Merge branch 'rmobile-latest' of git://github.com/pmundt/linux-sh
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 7 Nov 2011 01:28:13 +0000 (17:28 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 7 Nov 2011 01:28:13 +0000 (17:28 -0800)
* 'rmobile-latest' of git://github.com/pmundt/linux-sh: (21 commits)
  ARM: mach-shmobile: ag5evm needs CONFIG_I2C
  ARM: mach-shmobile: sh73a0 and AG5EVM PINT support
  ARM: mach-shmobile: Add support for PINT though INTC macros
  ARM: mach-shmobile: SDHI0 GPIO hotplug for AG5EVM
  ARM: mach-shmobile: Use common INTC IRQ code on sh73a0
  ARM: mach-shmobile: Use common INTC IRQ code on sh7372
  ARM: mach-shmobile: Use common INTC IRQ code on sh7377
  ARM: mach-shmobile: Use common INTC IRQ code on sh7367
  ARM: mach-shmobile: sh73a0 GPIO IRQ support
  ARM: sh7372 ap4evb NOR Flash USB boot fix
  ARM: mach-shmobile: sh7372 Mackerel NOR Flash USB boot fix
  sh: intc: Allow triggering on both edges for ARM SoCs
  ARM: mach-shmobile: Break out INTC IRQ code
  ARM: mach-shmobile: Kota2 SDHI0 and SDHI1 support
  ARM: mach-shmobile: Kota2 SCIFA4 and SCIFB support
  ARM: mach-shmobile: Kota2 MMCIF support
  ARM: mach-shmobile: Kota2 GPIO LEDs support
  ARM: mach-shmobile: Kota2 GPIO Keys support
  ARM: mach-shmobile: Kota2 KEYSC support
  ARM: mach-shmobile: Kota2 SCIFA2 and SMSC911X support
  ...

988 files changed:
Documentation/ABI/testing/sysfs-bus-pci-devices-cciss
Documentation/CodingStyle
Documentation/DocBook/media/v4l/compat.xml
Documentation/DocBook/media/v4l/controls.xml
Documentation/DocBook/media/v4l/io.xml
Documentation/DocBook/media/v4l/v4l2.xml
Documentation/DocBook/media/v4l/vidioc-create-bufs.xml [new file with mode: 0644]
Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml [new file with mode: 0644]
Documentation/block/switching-sched.txt
Documentation/blockdev/cciss.txt
Documentation/cgroups/cgroups.txt
Documentation/devicetree/bindings/ata/calxeda-sata.txt [new file with mode: 0644]
Documentation/devicetree/bindings/powerpc/fsl/board.txt
Documentation/devicetree/bindings/powerpc/fsl/dcsr.txt [new file with mode: 0644]
Documentation/devicetree/bindings/powerpc/fsl/msi-pic.txt
Documentation/filesystems/hfs.txt
Documentation/filesystems/inotify.txt
Documentation/hwmon/w83627ehf
Documentation/laptops/thinkpad-acpi.txt
Documentation/leds/leds-class.txt
Documentation/power/freezing-of-tasks.txt
Documentation/power/runtime_pm.txt
Documentation/serial/computone.txt
Documentation/watchdog/convert_drivers_to_kernel_api.txt [new file with mode: 0644]
MAINTAINERS
arch/arm/Kconfig
arch/arm/Makefile
arch/arm/configs/exynos4_defconfig
arch/arm/include/asm/hardware/pl080.h
arch/arm/mach-davinci/include/mach/gpio.h
arch/arm/mach-exynos/Kconfig [moved from arch/arm/mach-exynos4/Kconfig with 75% similarity]
arch/arm/mach-exynos/Makefile [moved from arch/arm/mach-exynos4/Makefile with 88% similarity]
arch/arm/mach-exynos/Makefile.boot [moved from arch/arm/mach-exynos4/Makefile.boot with 100% similarity]
arch/arm/mach-exynos/clock-exynos4210.c [moved from arch/arm/mach-exynos4/clock-exynos4210.c with 100% similarity]
arch/arm/mach-exynos/clock-exynos4212.c [moved from arch/arm/mach-exynos4/clock-exynos4212.c with 100% similarity]
arch/arm/mach-exynos/clock.c [moved from arch/arm/mach-exynos4/clock.c with 86% similarity]
arch/arm/mach-exynos/cpu.c [moved from arch/arm/mach-exynos4/cpu.c with 90% similarity]
arch/arm/mach-exynos/cpuidle.c [moved from arch/arm/mach-exynos4/cpuidle.c with 100% similarity]
arch/arm/mach-exynos/dev-ahci.c [moved from arch/arm/mach-exynos4/dev-ahci.c with 100% similarity]
arch/arm/mach-exynos/dev-audio.c [moved from arch/arm/mach-exynos4/dev-audio.c with 100% similarity]
arch/arm/mach-exynos/dev-dwmci.c [moved from arch/arm/mach-exynos4/dev-dwmci.c with 100% similarity]
arch/arm/mach-exynos/dev-pd.c [moved from arch/arm/mach-exynos4/dev-pd.c with 100% similarity]
arch/arm/mach-exynos/dev-sysmmu.c [moved from arch/arm/mach-exynos4/dev-sysmmu.c with 100% similarity]
arch/arm/mach-exynos/dma.c [new file with mode: 0644]
arch/arm/mach-exynos/headsmp.S [moved from arch/arm/mach-exynos4/headsmp.S with 100% similarity]
arch/arm/mach-exynos/hotplug.c [moved from arch/arm/mach-exynos4/hotplug.c with 100% similarity]
arch/arm/mach-exynos/include/mach/debug-macro.S [moved from arch/arm/mach-exynos4/include/mach/debug-macro.S with 100% similarity]
arch/arm/mach-exynos/include/mach/dma.h [moved from arch/arm/mach-exynos4/include/mach/dma.h with 90% similarity]
arch/arm/mach-exynos/include/mach/dwmci.h [moved from arch/arm/mach-exynos4/include/mach/dwmci.h with 100% similarity]
arch/arm/mach-exynos/include/mach/entry-macro.S [moved from arch/arm/mach-exynos4/include/mach/entry-macro.S with 100% similarity]
arch/arm/mach-exynos/include/mach/exynos4-clock.h [moved from arch/arm/mach-exynos4/include/mach/exynos4-clock.h with 100% similarity]
arch/arm/mach-exynos/include/mach/gpio.h [moved from arch/arm/mach-exynos4/include/mach/gpio.h with 100% similarity]
arch/arm/mach-exynos/include/mach/hardware.h [moved from arch/arm/mach-exynos4/include/mach/hardware.h with 100% similarity]
arch/arm/mach-exynos/include/mach/io.h [moved from arch/arm/mach-exynos4/include/mach/io.h with 100% similarity]
arch/arm/mach-exynos/include/mach/irqs.h [moved from arch/arm/mach-exynos4/include/mach/irqs.h with 97% similarity]
arch/arm/mach-exynos/include/mach/map.h [moved from arch/arm/mach-exynos4/include/mach/map.h with 87% similarity]
arch/arm/mach-exynos/include/mach/memory.h [moved from arch/arm/mach-exynos4/include/mach/memory.h with 100% similarity]
arch/arm/mach-exynos/include/mach/pm-core.h [moved from arch/arm/mach-exynos4/include/mach/pm-core.h with 89% similarity]
arch/arm/mach-exynos/include/mach/pmu.h [moved from arch/arm/mach-exynos4/include/mach/pmu.h with 84% similarity]
arch/arm/mach-exynos/include/mach/regs-audss.h [moved from arch/arm/mach-exynos4/include/mach/regs-audss.h with 100% similarity]
arch/arm/mach-exynos/include/mach/regs-clock.h [moved from arch/arm/mach-exynos4/include/mach/regs-clock.h with 100% similarity]
arch/arm/mach-exynos/include/mach/regs-gpio.h [moved from arch/arm/mach-exynos4/include/mach/regs-gpio.h with 100% similarity]
arch/arm/mach-exynos/include/mach/regs-irq.h [moved from arch/arm/mach-exynos4/include/mach/regs-irq.h with 100% similarity]
arch/arm/mach-exynos/include/mach/regs-mct.h [moved from arch/arm/mach-exynos4/include/mach/regs-mct.h with 100% similarity]
arch/arm/mach-exynos/include/mach/regs-mem.h [moved from arch/arm/mach-exynos4/include/mach/regs-mem.h with 100% similarity]
arch/arm/mach-exynos/include/mach/regs-pmu.h [moved from arch/arm/mach-exynos4/include/mach/regs-pmu.h with 69% similarity]
arch/arm/mach-exynos/include/mach/regs-sysmmu.h [moved from arch/arm/mach-exynos4/include/mach/regs-sysmmu.h with 100% similarity]
arch/arm/mach-exynos/include/mach/regs-usb-phy.h [moved from arch/arm/mach-exynos4/include/mach/regs-usb-phy.h with 100% similarity]
arch/arm/mach-exynos/include/mach/sysmmu.h [moved from arch/arm/mach-exynos4/include/mach/sysmmu.h with 100% similarity]
arch/arm/mach-exynos/include/mach/system.h [moved from arch/arm/mach-exynos4/include/mach/system.h with 100% similarity]
arch/arm/mach-exynos/include/mach/timex.h [moved from arch/arm/mach-exynos4/include/mach/timex.h with 100% similarity]
arch/arm/mach-exynos/include/mach/uncompress.h [moved from arch/arm/mach-exynos4/include/mach/uncompress.h with 100% similarity]
arch/arm/mach-exynos/include/mach/vmalloc.h [moved from arch/arm/mach-exynos4/include/mach/vmalloc.h with 100% similarity]
arch/arm/mach-exynos/init.c [moved from arch/arm/mach-exynos4/init.c with 100% similarity]
arch/arm/mach-exynos/irq-combiner.c [moved from arch/arm/mach-exynos4/irq-combiner.c with 100% similarity]
arch/arm/mach-exynos/irq-eint.c [moved from arch/arm/mach-exynos4/irq-eint.c with 100% similarity]
arch/arm/mach-exynos/mach-armlex4210.c [moved from arch/arm/mach-exynos4/mach-armlex4210.c with 100% similarity]
arch/arm/mach-exynos/mach-nuri.c [moved from arch/arm/mach-exynos4/mach-nuri.c with 85% similarity]
arch/arm/mach-exynos/mach-origen.c [new file with mode: 0644]
arch/arm/mach-exynos/mach-smdk4x12.c [moved from arch/arm/mach-exynos4/mach-smdk4x12.c with 100% similarity]
arch/arm/mach-exynos/mach-smdkv310.c [moved from arch/arm/mach-exynos4/mach-smdkv310.c with 88% similarity]
arch/arm/mach-exynos/mach-universal_c210.c [moved from arch/arm/mach-exynos4/mach-universal_c210.c with 67% similarity]
arch/arm/mach-exynos/mct.c [moved from arch/arm/mach-exynos4/mct.c with 91% similarity]
arch/arm/mach-exynos/platsmp.c [moved from arch/arm/mach-exynos4/platsmp.c with 99% similarity]
arch/arm/mach-exynos/pm.c [moved from arch/arm/mach-exynos4/pm.c with 98% similarity]
arch/arm/mach-exynos/pmu.c [new file with mode: 0644]
arch/arm/mach-exynos/setup-fimc.c [moved from arch/arm/mach-exynos4/setup-fimc.c with 100% similarity]
arch/arm/mach-exynos/setup-fimd0.c [moved from arch/arm/mach-exynos4/setup-fimd0.c with 100% similarity]
arch/arm/mach-exynos/setup-i2c0.c [moved from arch/arm/mach-exynos4/setup-i2c0.c with 100% similarity]
arch/arm/mach-exynos/setup-i2c1.c [moved from arch/arm/mach-exynos4/setup-i2c1.c with 100% similarity]
arch/arm/mach-exynos/setup-i2c2.c [moved from arch/arm/mach-exynos4/setup-i2c2.c with 100% similarity]
arch/arm/mach-exynos/setup-i2c3.c [moved from arch/arm/mach-exynos4/setup-i2c3.c with 100% similarity]
arch/arm/mach-exynos/setup-i2c4.c [moved from arch/arm/mach-exynos4/setup-i2c4.c with 100% similarity]
arch/arm/mach-exynos/setup-i2c5.c [moved from arch/arm/mach-exynos4/setup-i2c5.c with 100% similarity]
arch/arm/mach-exynos/setup-i2c6.c [moved from arch/arm/mach-exynos4/setup-i2c6.c with 100% similarity]
arch/arm/mach-exynos/setup-i2c7.c [moved from arch/arm/mach-exynos4/setup-i2c7.c with 100% similarity]
arch/arm/mach-exynos/setup-keypad.c [moved from arch/arm/mach-exynos4/setup-keypad.c with 100% similarity]
arch/arm/mach-exynos/setup-sdhci-gpio.c [moved from arch/arm/mach-exynos4/setup-sdhci-gpio.c with 100% similarity]
arch/arm/mach-exynos/setup-sdhci.c [new file with mode: 0644]
arch/arm/mach-exynos/setup-usb-phy.c [moved from arch/arm/mach-exynos4/setup-usb-phy.c with 100% similarity]
arch/arm/mach-exynos4/dma.c [deleted file]
arch/arm/mach-exynos4/include/mach/clkdev.h [deleted file]
arch/arm/mach-exynos4/mach-origen.c [deleted file]
arch/arm/mach-exynos4/pmu.c [deleted file]
arch/arm/mach-exynos4/setup-sdhci.c [deleted file]
arch/arm/mach-mmp/Makefile
arch/arm/mach-mmp/brownstone.c
arch/arm/mach-mmp/include/mach/mmp2.h
arch/arm/mach-mmp/include/mach/sram.h [new file with mode: 0644]
arch/arm/mach-mmp/mmp2.c
arch/arm/mach-mmp/sram.c [new file with mode: 0644]
arch/arm/mach-pxa/eseries.c
arch/arm/mach-pxa/eseries.h
arch/arm/mach-pxa/include/mach/gpio-pxa.h
arch/arm/mach-pxa/pcm990-baseboard.c
arch/arm/mach-s3c2410/Kconfig
arch/arm/mach-s3c2410/include/mach/dma.h
arch/arm/mach-s3c2410/include/mach/fb.h
arch/arm/mach-s3c2410/include/mach/gpio-fns.h
arch/arm/mach-s3c2410/include/mach/gpio-nrs.h
arch/arm/mach-s3c2410/include/mach/gpio-track.h
arch/arm/mach-s3c2410/include/mach/irqs.h
arch/arm/mach-s3c2410/include/mach/map.h
arch/arm/mach-s3c2410/include/mach/pm-core.h
arch/arm/mach-s3c2410/include/mach/regs-s3c2443-clock.h
arch/arm/mach-s3c2410/mach-h1940.c
arch/arm/mach-s3c2410/mach-qt2410.c
arch/arm/mach-s3c2410/s3c2410.c
arch/arm/mach-s3c2412/dma.c
arch/arm/mach-s3c2412/gpio.c [new file with mode: 0644]
arch/arm/mach-s3c2416/Kconfig
arch/arm/mach-s3c2416/clock.c
arch/arm/mach-s3c2416/s3c2416.c
arch/arm/mach-s3c2416/setup-sdhci.c
arch/arm/mach-s3c2440/Kconfig
arch/arm/mach-s3c2440/mach-rx1950.c
arch/arm/mach-s3c2440/s3c2440.c
arch/arm/mach-s3c2440/s3c2442.c
arch/arm/mach-s3c2443/Kconfig
arch/arm/mach-s3c2443/clock.c
arch/arm/mach-s3c2443/s3c2443.c
arch/arm/mach-s3c64xx/Kconfig
arch/arm/mach-s3c64xx/Makefile
arch/arm/mach-s3c64xx/clock.c
arch/arm/mach-s3c64xx/cpu.c
arch/arm/mach-s3c64xx/dev-onenand1.c [deleted file]
arch/arm/mach-s3c64xx/dma.c
arch/arm/mach-s3c64xx/gpiolib.c [deleted file]
arch/arm/mach-s3c64xx/include/mach/clkdev.h [deleted file]
arch/arm/mach-s3c64xx/include/mach/crag6410.h [new file with mode: 0644]
arch/arm/mach-s3c64xx/include/mach/dma.h
arch/arm/mach-s3c64xx/include/mach/pll.h [deleted file]
arch/arm/mach-s3c64xx/include/mach/pm-core.h
arch/arm/mach-s3c64xx/include/mach/pwm-clock.h [deleted file]
arch/arm/mach-s3c64xx/include/mach/regs-sys.h
arch/arm/mach-s3c64xx/mach-anw6410.c
arch/arm/mach-s3c64xx/mach-crag6410-module.c [new file with mode: 0644]
arch/arm/mach-s3c64xx/mach-crag6410.c
arch/arm/mach-s3c64xx/mach-hmt.c
arch/arm/mach-s3c64xx/mach-mini6410.c
arch/arm/mach-s3c64xx/mach-ncp.c
arch/arm/mach-s3c64xx/mach-real6410.c
arch/arm/mach-s3c64xx/mach-smartq5.c
arch/arm/mach-s3c64xx/mach-smartq7.c
arch/arm/mach-s3c64xx/mach-smdk6400.c
arch/arm/mach-s3c64xx/mach-smdk6410.c
arch/arm/mach-s3c64xx/pm.c
arch/arm/mach-s3c64xx/s3c6400.c
arch/arm/mach-s3c64xx/s3c6410.c
arch/arm/mach-s3c64xx/setup-sdhci.c
arch/arm/mach-s5p64x0/Kconfig
arch/arm/mach-s5p64x0/Makefile
arch/arm/mach-s5p64x0/clock-s5p6440.c
arch/arm/mach-s5p64x0/clock-s5p6450.c
arch/arm/mach-s5p64x0/cpu.c
arch/arm/mach-s5p64x0/dma.c
arch/arm/mach-s5p64x0/include/mach/clkdev.h [deleted file]
arch/arm/mach-s5p64x0/include/mach/dma.h
arch/arm/mach-s5p64x0/include/mach/irqs.h
arch/arm/mach-s5p64x0/include/mach/map.h
arch/arm/mach-s5p64x0/include/mach/pm-core.h [new file with mode: 0644]
arch/arm/mach-s5p64x0/include/mach/pwm-clock.h [deleted file]
arch/arm/mach-s5p64x0/include/mach/regs-clock.h
arch/arm/mach-s5p64x0/include/mach/regs-gpio.h
arch/arm/mach-s5p64x0/irq-eint.c
arch/arm/mach-s5p64x0/irq-pm.c [new file with mode: 0644]
arch/arm/mach-s5p64x0/mach-smdk6440.c
arch/arm/mach-s5p64x0/mach-smdk6450.c
arch/arm/mach-s5p64x0/pm.c [new file with mode: 0644]
arch/arm/mach-s5p64x0/setup-fb-24bpp.c [new file with mode: 0644]
arch/arm/mach-s5pc100/Kconfig
arch/arm/mach-s5pc100/clock.c
arch/arm/mach-s5pc100/dma.c
arch/arm/mach-s5pc100/include/mach/clkdev.h [deleted file]
arch/arm/mach-s5pc100/include/mach/dma.h
arch/arm/mach-s5pc100/include/mach/pwm-clock.h [deleted file]
arch/arm/mach-s5pc100/setup-sdhci.c
arch/arm/mach-s5pv210/Kconfig
arch/arm/mach-s5pv210/Makefile
arch/arm/mach-s5pv210/clock.c
arch/arm/mach-s5pv210/cpu.c
arch/arm/mach-s5pv210/dma.c
arch/arm/mach-s5pv210/include/mach/clkdev.h [deleted file]
arch/arm/mach-s5pv210/include/mach/dma.h
arch/arm/mach-s5pv210/include/mach/irqs.h
arch/arm/mach-s5pv210/include/mach/map.h
arch/arm/mach-s5pv210/include/mach/pm-core.h
arch/arm/mach-s5pv210/include/mach/pwm-clock.h [deleted file]
arch/arm/mach-s5pv210/include/mach/regs-clock.h
arch/arm/mach-s5pv210/mach-goni.c
arch/arm/mach-s5pv210/setup-sdhci.c
arch/arm/mach-s5pv210/sleep.S [deleted file]
arch/arm/mach-shmobile/board-ap4evb.c
arch/arm/mach-shmobile/board-mackerel.c
arch/arm/plat-s3c24xx/Kconfig
arch/arm/plat-s3c24xx/Makefile
arch/arm/plat-s3c24xx/dev-uart.c [new file with mode: 0644]
arch/arm/plat-s3c24xx/devs.c [deleted file]
arch/arm/plat-s3c24xx/dma.c
arch/arm/plat-s3c24xx/gpio.c [deleted file]
arch/arm/plat-s3c24xx/gpiolib.c [deleted file]
arch/arm/plat-s3c24xx/include/mach/clkdev.h [deleted file]
arch/arm/plat-s3c24xx/include/mach/pwm-clock.h [deleted file]
arch/arm/plat-s3c24xx/include/plat/pll.h [deleted file]
arch/arm/plat-s3c24xx/include/plat/regs-iis.h [deleted file]
arch/arm/plat-s3c24xx/include/plat/regs-spi.h [deleted file]
arch/arm/plat-s3c24xx/s3c2443-clock.c
arch/arm/plat-s5p/Kconfig
arch/arm/plat-s5p/Makefile
arch/arm/plat-s5p/cpu.c
arch/arm/plat-s5p/dev-csis0.c [deleted file]
arch/arm/plat-s5p/dev-csis1.c [deleted file]
arch/arm/plat-s5p/dev-ehci.c [deleted file]
arch/arm/plat-s5p/dev-fimc0.c [deleted file]
arch/arm/plat-s5p/dev-fimc1.c [deleted file]
arch/arm/plat-s5p/dev-fimc2.c [deleted file]
arch/arm/plat-s5p/dev-fimc3.c [deleted file]
arch/arm/plat-s5p/dev-fimd0.c [deleted file]
arch/arm/plat-s5p/dev-mfc.c
arch/arm/plat-s5p/dev-onenand.c [deleted file]
arch/arm/plat-s5p/dev-pmu.c [deleted file]
arch/arm/plat-s5p/irq-gpioint.c
arch/arm/plat-s5p/sleep.S [moved from arch/arm/mach-exynos4/sleep.S with 81% similarity]
arch/arm/plat-samsung/Kconfig
arch/arm/plat-samsung/Makefile
arch/arm/plat-samsung/adc.c
arch/arm/plat-samsung/dev-adc.c [deleted file]
arch/arm/plat-samsung/dev-asocdma.c [deleted file]
arch/arm/plat-samsung/dev-backlight.c
arch/arm/plat-samsung/dev-fb.c [deleted file]
arch/arm/plat-samsung/dev-hsmmc.c [deleted file]
arch/arm/plat-samsung/dev-hsmmc1.c [deleted file]
arch/arm/plat-samsung/dev-hsmmc2.c [deleted file]
arch/arm/plat-samsung/dev-hsmmc3.c [deleted file]
arch/arm/plat-samsung/dev-hwmon.c [deleted file]
arch/arm/plat-samsung/dev-i2c0.c [deleted file]
arch/arm/plat-samsung/dev-i2c1.c [deleted file]
arch/arm/plat-samsung/dev-i2c2.c [deleted file]
arch/arm/plat-samsung/dev-i2c3.c [deleted file]
arch/arm/plat-samsung/dev-i2c4.c [deleted file]
arch/arm/plat-samsung/dev-i2c5.c [deleted file]
arch/arm/plat-samsung/dev-i2c6.c [deleted file]
arch/arm/plat-samsung/dev-i2c7.c [deleted file]
arch/arm/plat-samsung/dev-ide.c [deleted file]
arch/arm/plat-samsung/dev-keypad.c [deleted file]
arch/arm/plat-samsung/dev-nand.c [deleted file]
arch/arm/plat-samsung/dev-onenand.c [deleted file]
arch/arm/plat-samsung/dev-pwm.c [deleted file]
arch/arm/plat-samsung/dev-rtc.c [deleted file]
arch/arm/plat-samsung/dev-ts.c [deleted file]
arch/arm/plat-samsung/dev-usb-hsotg.c [deleted file]
arch/arm/plat-samsung/dev-usb.c [deleted file]
arch/arm/plat-samsung/dev-wdt.c [deleted file]
arch/arm/plat-samsung/devs.c [new file with mode: 0644]
arch/arm/plat-samsung/dma-ops.c [new file with mode: 0644]
arch/arm/plat-samsung/gpio-config.c [deleted file]
arch/arm/plat-samsung/gpio.c [deleted file]
arch/arm/plat-samsung/include/plat/adc-core.h
arch/arm/plat-samsung/include/plat/audio-simtec.h [moved from arch/arm/plat-s3c24xx/include/plat/audio-simtec.h with 95% similarity]
arch/arm/plat-samsung/include/plat/camport.h [moved from arch/arm/plat-s5p/include/plat/camport.h with 86% similarity]
arch/arm/plat-samsung/include/plat/common-smdk.h [moved from arch/arm/plat-s3c24xx/include/plat/common-smdk.h with 87% similarity]
arch/arm/plat-samsung/include/plat/cpu-freq-core.h [moved from arch/arm/plat-s3c24xx/include/plat/cpu-freq-core.h with 98% similarity]
arch/arm/plat-samsung/include/plat/cpu.h
arch/arm/plat-samsung/include/plat/devs.h
arch/arm/plat-samsung/include/plat/dma-ops.h [new file with mode: 0644]
arch/arm/plat-samsung/include/plat/dma-pl330.h [moved from arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h with 84% similarity]
arch/arm/plat-samsung/include/plat/dma-s3c24xx.h
arch/arm/plat-samsung/include/plat/dma.h
arch/arm/plat-samsung/include/plat/ehci.h [moved from arch/arm/plat-s5p/include/plat/ehci.h with 84% similarity]
arch/arm/plat-samsung/include/plat/exynos4.h [moved from arch/arm/plat-s5p/include/plat/exynos4.h with 87% similarity]
arch/arm/plat-samsung/include/plat/fb-s3c2410.h [new file with mode: 0644]
arch/arm/plat-samsung/include/plat/fb.h
arch/arm/plat-samsung/include/plat/fiq.h [moved from arch/arm/plat-s3c24xx/include/plat/fiq.h with 88% similarity]
arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h
arch/arm/plat-samsung/include/plat/gpio-cfg.h
arch/arm/plat-samsung/include/plat/gpio-core.h
arch/arm/plat-samsung/include/plat/gpio-fns.h [new file with mode: 0644]
arch/arm/plat-samsung/include/plat/iic.h
arch/arm/plat-samsung/include/plat/irq.h [moved from arch/arm/plat-s3c24xx/include/plat/irq.h with 81% similarity]
arch/arm/plat-samsung/include/plat/irqs.h [moved from arch/arm/plat-s5p/include/plat/irqs.h with 93% similarity]
arch/arm/plat-samsung/include/plat/mci.h [moved from arch/arm/plat-s3c24xx/include/plat/mci.h with 90% similarity]
arch/arm/plat-samsung/include/plat/mfc.h [moved from arch/arm/plat-s5p/include/plat/mfc.h with 90% similarity]
arch/arm/plat-samsung/include/plat/mipi_csis.h [moved from arch/arm/plat-s5p/include/plat/mipi_csis.h with 90% similarity]
arch/arm/plat-samsung/include/plat/pll.h [moved from arch/arm/plat-s5p/include/plat/pll.h with 57% similarity]
arch/arm/plat-samsung/include/plat/pll6553x.h [deleted file]
arch/arm/plat-samsung/include/plat/pm.h
arch/arm/plat-samsung/include/plat/pwm-clock.h [moved from arch/arm/mach-exynos4/include/mach/pwm-clock.h with 68% similarity]
arch/arm/plat-samsung/include/plat/regs-adc.h
arch/arm/plat-samsung/include/plat/regs-dma.h [moved from arch/arm/plat-s3c24xx/include/plat/regs-dma.h with 58% similarity]
arch/arm/plat-samsung/include/plat/regs-iis.h [new file with mode: 0644]
arch/arm/plat-samsung/include/plat/regs-spi.h [new file with mode: 0644]
arch/arm/plat-samsung/include/plat/regs-srom.h [moved from arch/arm/plat-s5p/include/plat/regs-srom.h with 89% similarity]
arch/arm/plat-samsung/include/plat/regs-udc.h [moved from arch/arm/plat-s3c24xx/include/plat/regs-udc.h with 51% similarity]
arch/arm/plat-samsung/include/plat/reset.h [moved from arch/arm/plat-s5p/include/plat/reset.h with 66% similarity]
arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h [deleted file]
arch/arm/plat-samsung/include/plat/s3c2410.h [moved from arch/arm/plat-s3c24xx/include/plat/s3c2410.h with 93% similarity]
arch/arm/plat-samsung/include/plat/s3c2412.h [moved from arch/arm/plat-s3c24xx/include/plat/s3c2412.h with 92% similarity]
arch/arm/plat-samsung/include/plat/s3c2416.h [moved from arch/arm/plat-s3c24xx/include/plat/s3c2416.h with 92% similarity]
arch/arm/plat-samsung/include/plat/s3c2443.h [moved from arch/arm/plat-s3c24xx/include/plat/s3c2443.h with 87% similarity]
arch/arm/plat-samsung/include/plat/s3c244x.h [moved from arch/arm/plat-s3c24xx/include/plat/s3c244x.h with 94% similarity]
arch/arm/plat-samsung/include/plat/s3c6400.h [moved from arch/arm/mach-s3c64xx/include/mach/s3c6400.h with 94% similarity]
arch/arm/plat-samsung/include/plat/s3c6410.h [moved from arch/arm/mach-s3c64xx/include/mach/s3c6410.h with 93% similarity]
arch/arm/plat-samsung/include/plat/s5p-clock.h [moved from arch/arm/plat-s5p/include/plat/s5p-clock.h with 96% similarity]
arch/arm/plat-samsung/include/plat/s5p-time.h [moved from arch/arm/plat-s5p/include/plat/s5p-time.h with 94% similarity]
arch/arm/plat-samsung/include/plat/s5p6440.h [moved from arch/arm/plat-s5p/include/plat/s5p6440.h with 94% similarity]
arch/arm/plat-samsung/include/plat/s5p6450.h [moved from arch/arm/plat-s5p/include/plat/s5p6450.h with 94% similarity]
arch/arm/plat-samsung/include/plat/s5pc100.h [moved from arch/arm/plat-s5p/include/plat/s5pc100.h with 94% similarity]
arch/arm/plat-samsung/include/plat/s5pv210.h [moved from arch/arm/plat-s5p/include/plat/s5pv210.h with 94% similarity]
arch/arm/plat-samsung/include/plat/sdhci.h
arch/arm/plat-samsung/include/plat/sysmmu.h [moved from arch/arm/plat-s5p/include/plat/sysmmu.h with 96% similarity]
arch/arm/plat-samsung/include/plat/system-reset.h [moved from arch/arm/plat-s5p/include/plat/system-reset.h with 92% similarity]
arch/arm/plat-samsung/include/plat/tv-core.h [new file with mode: 0644]
arch/arm/plat-samsung/include/plat/udc.h [moved from arch/arm/plat-s3c24xx/include/plat/udc.h with 95% similarity]
arch/arm/plat-samsung/include/plat/usb-phy.h [moved from arch/arm/plat-s5p/include/plat/usb-phy.h with 83% similarity]
arch/arm/plat-samsung/platformdata.c
arch/arm/plat-samsung/pm-gpio.c
arch/arm/plat-samsung/pm.c
arch/arm/plat-samsung/pwm-clock.c
arch/arm/plat-samsung/pwm.c
arch/arm/plat-samsung/s3c-dma-ops.c [new file with mode: 0644]
arch/arm/plat-samsung/s3c-pl330.c [deleted file]
arch/ia64/include/asm/unistd.h
arch/ia64/kernel/entry.S
arch/m68k/emu/nfblock.c
arch/powerpc/Kconfig
arch/powerpc/Kconfig.debug
arch/powerpc/boot/Makefile
arch/powerpc/boot/dts/digsy_mtc.dts
arch/powerpc/boot/dts/gef_ppc9a.dts
arch/powerpc/boot/dts/gef_sbc310.dts
arch/powerpc/boot/dts/gef_sbc610.dts
arch/powerpc/boot/dts/hcu4.dts [deleted file]
arch/powerpc/boot/dts/ksi8560.dts
arch/powerpc/boot/dts/mgcoge.dts
arch/powerpc/boot/dts/mpc5200b.dtsi
arch/powerpc/boot/dts/mpc8349emitx.dts
arch/powerpc/boot/dts/p1022ds.dts
arch/powerpc/boot/dts/p2020ds.dts
arch/powerpc/boot/dts/p2041rdb.dts [moved from arch/powerpc/boot/dts/p2040rdb.dts with 95% similarity]
arch/powerpc/boot/dts/p2041si.dtsi [moved from arch/powerpc/boot/dts/p2040si.dtsi with 80% similarity]
arch/powerpc/boot/dts/p3041ds.dts
arch/powerpc/boot/dts/p3041si.dtsi
arch/powerpc/boot/dts/p3060qds.dts [new file with mode: 0644]
arch/powerpc/boot/dts/p3060si.dtsi [new file with mode: 0644]
arch/powerpc/boot/dts/p4080ds.dts
arch/powerpc/boot/dts/p4080si.dtsi
arch/powerpc/boot/dts/p5020ds.dts
arch/powerpc/boot/dts/p5020si.dtsi
arch/powerpc/boot/dts/sbc8560.dts
arch/powerpc/boot/dts/yosemite.dts
arch/powerpc/configs/40x/hcu4_defconfig [deleted file]
arch/powerpc/configs/85xx/p1023rds_defconfig
arch/powerpc/configs/85xx/xes_mpc85xx_defconfig
arch/powerpc/configs/corenet32_smp_defconfig
arch/powerpc/configs/corenet64_smp_defconfig
arch/powerpc/configs/mgcoge_defconfig
arch/powerpc/configs/mpc512x_defconfig
arch/powerpc/configs/mpc5200_defconfig
arch/powerpc/configs/mpc85xx_defconfig
arch/powerpc/configs/mpc85xx_smp_defconfig
arch/powerpc/configs/ppc40x_defconfig
arch/powerpc/configs/ppc6xx_defconfig
arch/powerpc/include/asm/device.h
arch/powerpc/include/asm/firmware.h
arch/powerpc/include/asm/hugetlb.h
arch/powerpc/include/asm/kexec.h
arch/powerpc/include/asm/machdep.h
arch/powerpc/include/asm/mmu-book3e.h
arch/powerpc/include/asm/mmu-hash64.h
arch/powerpc/include/asm/mmu.h
arch/powerpc/include/asm/mpic.h
arch/powerpc/include/asm/opal.h [new file with mode: 0644]
arch/powerpc/include/asm/paca.h
arch/powerpc/include/asm/page.h
arch/powerpc/include/asm/page_64.h
arch/powerpc/include/asm/pte-book3e.h
arch/powerpc/include/asm/reg_booke.h
arch/powerpc/include/asm/rtas.h
arch/powerpc/include/asm/smp.h
arch/powerpc/include/asm/sparsemem.h
arch/powerpc/include/asm/topology.h
arch/powerpc/include/asm/udbg.h
arch/powerpc/include/asm/xics.h
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/dma-iommu.c
arch/powerpc/kernel/dma-swiotlb.c
arch/powerpc/kernel/dma.c
arch/powerpc/kernel/exceptions-64s.S
arch/powerpc/kernel/head_32.S
arch/powerpc/kernel/head_40x.S
arch/powerpc/kernel/head_44x.S
arch/powerpc/kernel/head_64.S
arch/powerpc/kernel/head_8xx.S
arch/powerpc/kernel/head_fsl_booke.S
arch/powerpc/kernel/ibmebus.c
arch/powerpc/kernel/idle_e500.S
arch/powerpc/kernel/iommu.c
arch/powerpc/kernel/legacy_serial.c
arch/powerpc/kernel/machine_kexec_64.c
arch/powerpc/kernel/misc_32.S
arch/powerpc/kernel/pci-common.c
arch/powerpc/kernel/power6-pmu.c
arch/powerpc/kernel/power7-pmu.c
arch/powerpc/kernel/prom.c
arch/powerpc/kernel/prom_init.c
arch/powerpc/kernel/prom_init_check.sh
arch/powerpc/kernel/ptrace.c
arch/powerpc/kernel/setup_32.c
arch/powerpc/kernel/setup_64.c
arch/powerpc/kernel/smp.c
arch/powerpc/kernel/swsusp.c
arch/powerpc/kernel/traps.c
arch/powerpc/kernel/udbg.c
arch/powerpc/kernel/vio.c
arch/powerpc/math-emu/math_efp.c
arch/powerpc/mm/Makefile
arch/powerpc/mm/fsl_booke_mmu.c
arch/powerpc/mm/hash_utils_64.c
arch/powerpc/mm/hugetlbpage-book3e.c [new file with mode: 0644]
arch/powerpc/mm/hugetlbpage.c
arch/powerpc/mm/init_32.c
arch/powerpc/mm/mem.c
arch/powerpc/mm/mmu_context_hash64.c
arch/powerpc/mm/mmu_context_nohash.c
arch/powerpc/mm/mmu_decl.h
arch/powerpc/mm/numa.c
arch/powerpc/mm/pgtable.c
arch/powerpc/mm/tlb_low_64e.S
arch/powerpc/mm/tlb_nohash.c
arch/powerpc/platforms/40x/Kconfig
arch/powerpc/platforms/40x/Makefile
arch/powerpc/platforms/40x/hcu4.c [deleted file]
arch/powerpc/platforms/512x/Kconfig
arch/powerpc/platforms/82xx/km82xx.c
arch/powerpc/platforms/83xx/Kconfig
arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c
arch/powerpc/platforms/85xx/Kconfig
arch/powerpc/platforms/85xx/Makefile
arch/powerpc/platforms/85xx/p1022_ds.c
arch/powerpc/platforms/85xx/p2041_rdb.c [moved from arch/powerpc/platforms/85xx/p2040_rdb.c with 82% similarity]
arch/powerpc/platforms/85xx/p3060_qds.c [new file with mode: 0644]
arch/powerpc/platforms/85xx/sbc8560.c
arch/powerpc/platforms/85xx/smp.c
arch/powerpc/platforms/86xx/Kconfig
arch/powerpc/platforms/Kconfig
arch/powerpc/platforms/Kconfig.cputype
arch/powerpc/platforms/Makefile
arch/powerpc/platforms/cell/iommu.c
arch/powerpc/platforms/powernv/Kconfig [new file with mode: 0644]
arch/powerpc/platforms/powernv/Makefile [new file with mode: 0644]
arch/powerpc/platforms/powernv/opal-nvram.c [new file with mode: 0644]
arch/powerpc/platforms/powernv/opal-rtc.c [new file with mode: 0644]
arch/powerpc/platforms/powernv/opal-takeover.S [new file with mode: 0644]
arch/powerpc/platforms/powernv/opal-wrappers.S [new file with mode: 0644]
arch/powerpc/platforms/powernv/opal.c [new file with mode: 0644]
arch/powerpc/platforms/powernv/pci-p5ioc2.c [new file with mode: 0644]
arch/powerpc/platforms/powernv/pci.c [new file with mode: 0644]
arch/powerpc/platforms/powernv/pci.h [new file with mode: 0644]
arch/powerpc/platforms/powernv/powernv.h [new file with mode: 0644]
arch/powerpc/platforms/powernv/setup.c [new file with mode: 0644]
arch/powerpc/platforms/powernv/smp.c [new file with mode: 0644]
arch/powerpc/platforms/ps3/Kconfig
arch/powerpc/platforms/ps3/Makefile
arch/powerpc/platforms/ps3/gelic_udbg.c [new file with mode: 0644]
arch/powerpc/platforms/ps3/system-bus.c
arch/powerpc/platforms/pseries/Kconfig
arch/powerpc/platforms/pseries/dlpar.c
arch/powerpc/platforms/pseries/eeh.c
arch/powerpc/platforms/pseries/iommu.c
arch/powerpc/platforms/pseries/nvram.c
arch/powerpc/platforms/wsp/Kconfig
arch/powerpc/platforms/wsp/Makefile
arch/powerpc/platforms/wsp/ics.c
arch/powerpc/platforms/wsp/ics.h
arch/powerpc/platforms/wsp/msi.c [new file with mode: 0644]
arch/powerpc/platforms/wsp/msi.h [new file with mode: 0644]
arch/powerpc/platforms/wsp/psr2.c
arch/powerpc/platforms/wsp/wsp.h
arch/powerpc/platforms/wsp/wsp_pci.c [new file with mode: 0644]
arch/powerpc/platforms/wsp/wsp_pci.h [new file with mode: 0644]
arch/powerpc/sysdev/Makefile
arch/powerpc/sysdev/axonram.c
arch/powerpc/sysdev/cpm_common.c
arch/powerpc/sysdev/fsl_msi.c
arch/powerpc/sysdev/fsl_msi.h
arch/powerpc/sysdev/mpic.c
arch/powerpc/sysdev/ppc4xx_pci.c
arch/powerpc/sysdev/ppc4xx_pci.h
arch/powerpc/sysdev/xics/Makefile
arch/powerpc/sysdev/xics/icp-native.c
arch/powerpc/sysdev/xics/ics-opal.c [new file with mode: 0644]
arch/powerpc/sysdev/xics/xics-common.c
arch/powerpc/xmon/xmon.c
arch/sh/boards/mach-ap325rxa/setup.c
arch/sh/boards/mach-migor/setup.c
arch/tile/include/arch/Kbuild [new file with mode: 0644]
arch/tile/include/arch/abi.h
arch/tile/include/arch/opcode.h [moved from arch/tile/include/asm/opcode_constants.h with 62% similarity]
arch/tile/include/arch/opcode_tilegx.h [moved from arch/tile/include/asm/opcode_constants_64.h with 50% similarity]
arch/tile/include/arch/opcode_tilepro.h [new file with mode: 0644]
arch/tile/include/asm/Kbuild
arch/tile/include/asm/opcode-tile_32.h [deleted file]
arch/tile/include/asm/opcode-tile_64.h [deleted file]
arch/tile/include/asm/opcode_constants_32.h [deleted file]
arch/tile/include/asm/sigcontext.h
arch/tile/include/asm/tile-desc.h [moved from arch/tile/include/asm/opcode-tile.h with 56% similarity]
arch/tile/include/asm/tile-desc_32.h [new file with mode: 0644]
arch/tile/include/asm/tile-desc_64.h [new file with mode: 0644]
arch/tile/kernel/backtrace.c
arch/tile/kernel/module.c
arch/tile/kernel/single_step.c
arch/tile/kernel/tile-desc_32.c
arch/tile/kernel/tile-desc_64.c
arch/tile/kernel/traps.c
arch/tile/lib/exports.c
block/blk-cgroup.c
block/blk-cgroup.h
block/blk-core.c
block/blk-flush.c
block/blk-sysfs.c
block/blk-tag.c
block/blk-throttle.c
block/blk.h
block/elevator.c
block/genhd.c
block/ioctl.c
block/scsi_ioctl.c
drivers/acpi/sleep.c
drivers/ata/ahci_platform.c
drivers/base/power/runtime.c
drivers/block/aoe/aoeblk.c
drivers/block/brd.c
drivers/block/cciss.c
drivers/block/cciss.h
drivers/block/cpqarray.c
drivers/block/drbd/drbd_int.h
drivers/block/drbd/drbd_req.c
drivers/block/loop.c
drivers/block/nbd.c
drivers/block/pktcdvd.c
drivers/block/ps3vram.c
drivers/block/umem.c
drivers/block/xen-blkback/blkback.c
drivers/block/xen-blkback/common.h
drivers/block/xen-blkback/xenbus.c
drivers/block/xen-blkfront.c
drivers/dma/Kconfig
drivers/dma/amba-pl08x.c
drivers/dma/at_hdmac.c
drivers/dma/at_hdmac_regs.h
drivers/dma/dmatest.c
drivers/dma/dw_dmac.c
drivers/dma/ep93xx_dma.c
drivers/dma/imx-dma.c
drivers/dma/imx-sdma.c
drivers/dma/intel_mid_dma.c
drivers/dma/ipu/ipu_idmac.c
drivers/dma/mpc512x_dma.c
drivers/dma/mxs-dma.c
drivers/dma/pch_dma.c
drivers/dma/pl330.c
drivers/dma/shdma.c
drivers/dma/shdma.h
drivers/dma/timb_dma.c
drivers/edac/cpc925_edac.c
drivers/edac/ppc4xx_edac.c
drivers/firmware/edd.c
drivers/gpio/Kconfig
drivers/gpio/Makefile
drivers/gpio/gpio-exynos4.c [deleted file]
drivers/gpio/gpio-mpc8xxx.c [moved from arch/powerpc/sysdev/mpc8xxx_gpio.c with 98% similarity]
drivers/gpio/gpio-plat-samsung.c [deleted file]
drivers/gpio/gpio-s5pc100.c [deleted file]
drivers/gpio/gpio-s5pv210.c [deleted file]
drivers/gpio/gpio-samsung.c [new file with mode: 0644]
drivers/hwmon/Kconfig
drivers/hwmon/ad7414.c
drivers/hwmon/ad7418.c
drivers/hwmon/ads1015.c
drivers/hwmon/ads7828.c
drivers/hwmon/asb100.c
drivers/hwmon/coretemp.c
drivers/hwmon/ds1621.c
drivers/hwmon/ds620.c
drivers/hwmon/gl518sm.c
drivers/hwmon/gl520sm.c
drivers/hwmon/ibmaem.c
drivers/hwmon/jc42.c
drivers/hwmon/lm73.c
drivers/hwmon/lm75.c
drivers/hwmon/lm77.c
drivers/hwmon/lm90.c
drivers/hwmon/lm92.c
drivers/hwmon/max16065.c
drivers/hwmon/sht21.c
drivers/hwmon/smm665.c
drivers/hwmon/smsc47b397.c
drivers/hwmon/tmp102.c
drivers/hwmon/w83627ehf.c
drivers/hwmon/w83781d.c
drivers/infiniband/hw/mthca/mthca_mr.c
drivers/infiniband/hw/qib/qib_rc.c
drivers/infiniband/ulp/iser/iscsi_iser.c
drivers/infiniband/ulp/iser/iscsi_iser.h
drivers/infiniband/ulp/iser/iser_initiator.c
drivers/infiniband/ulp/iser/iser_verbs.c
drivers/md/dm.c
drivers/md/faulty.c
drivers/md/linear.c
drivers/md/md.c
drivers/md/md.h
drivers/md/multipath.c
drivers/md/raid0.c
drivers/md/raid1.c
drivers/md/raid10.c
drivers/md/raid5.c
drivers/media/dvb/ddbridge/Makefile
drivers/media/dvb/dvb-usb/Makefile
drivers/media/dvb/dvb-usb/dvb-usb-ids.h
drivers/media/dvb/dvb-usb/it913x.c
drivers/media/dvb/dvb-usb/mxl111sf-demod.c [new file with mode: 0644]
drivers/media/dvb/dvb-usb/mxl111sf-demod.h [new file with mode: 0644]
drivers/media/dvb/dvb-usb/mxl111sf.c
drivers/media/dvb/dvb-usb/mxl111sf.h
drivers/media/dvb/ngene/Makefile
drivers/media/radio/radio-tea5764.c
drivers/media/video/Kconfig
drivers/media/video/Makefile
drivers/media/video/atmel-isi.c
drivers/media/video/cx18/cx18-driver.c
drivers/media/video/cx25821/Kconfig [moved from drivers/staging/cx25821/Kconfig with 100% similarity]
drivers/media/video/cx25821/Makefile [moved from drivers/staging/cx25821/Makefile with 100% similarity]
drivers/media/video/cx25821/cx25821-alsa.c [moved from drivers/staging/cx25821/cx25821-alsa.c with 100% similarity]
drivers/media/video/cx25821/cx25821-audio-upstream.c [moved from drivers/staging/cx25821/cx25821-audio-upstream.c with 100% similarity]
drivers/media/video/cx25821/cx25821-audio-upstream.h [moved from drivers/staging/cx25821/cx25821-audio-upstream.h with 100% similarity]
drivers/media/video/cx25821/cx25821-audio.h [moved from drivers/staging/cx25821/cx25821-audio.h with 100% similarity]
drivers/media/video/cx25821/cx25821-biffuncs.h [moved from drivers/staging/cx25821/cx25821-biffuncs.h with 100% similarity]
drivers/media/video/cx25821/cx25821-cards.c [moved from drivers/staging/cx25821/cx25821-cards.c with 100% similarity]
drivers/media/video/cx25821/cx25821-core.c [moved from drivers/staging/cx25821/cx25821-core.c with 100% similarity]
drivers/media/video/cx25821/cx25821-gpio.c [moved from drivers/staging/cx25821/cx25821-gpio.c with 100% similarity]
drivers/media/video/cx25821/cx25821-i2c.c [moved from drivers/staging/cx25821/cx25821-i2c.c with 100% similarity]
drivers/media/video/cx25821/cx25821-medusa-defines.h [moved from drivers/staging/cx25821/cx25821-medusa-defines.h with 100% similarity]
drivers/media/video/cx25821/cx25821-medusa-reg.h [moved from drivers/staging/cx25821/cx25821-medusa-reg.h with 100% similarity]
drivers/media/video/cx25821/cx25821-medusa-video.c [moved from drivers/staging/cx25821/cx25821-medusa-video.c with 100% similarity]
drivers/media/video/cx25821/cx25821-medusa-video.h [moved from drivers/staging/cx25821/cx25821-medusa-video.h with 100% similarity]
drivers/media/video/cx25821/cx25821-reg.h [moved from drivers/staging/cx25821/cx25821-reg.h with 100% similarity]
drivers/media/video/cx25821/cx25821-sram.h [moved from drivers/staging/cx25821/cx25821-sram.h with 100% similarity]
drivers/media/video/cx25821/cx25821-video-upstream-ch2.c [moved from drivers/staging/cx25821/cx25821-video-upstream-ch2.c with 100% similarity]
drivers/media/video/cx25821/cx25821-video-upstream-ch2.h [moved from drivers/staging/cx25821/cx25821-video-upstream-ch2.h with 100% similarity]
drivers/media/video/cx25821/cx25821-video-upstream.c [moved from drivers/staging/cx25821/cx25821-video-upstream.c with 100% similarity]
drivers/media/video/cx25821/cx25821-video-upstream.h [moved from drivers/staging/cx25821/cx25821-video-upstream.h with 100% similarity]
drivers/media/video/cx25821/cx25821-video.c [moved from drivers/staging/cx25821/cx25821-video.c with 99% similarity]
drivers/media/video/cx25821/cx25821-video.h [moved from drivers/staging/cx25821/cx25821-video.h with 100% similarity]
drivers/media/video/cx25821/cx25821.h [moved from drivers/staging/cx25821/cx25821.h with 99% similarity]
drivers/media/video/em28xx/em28xx-cards.c
drivers/media/video/imx074.c
drivers/media/video/ivtv/ivtv-driver.c
drivers/media/video/marvell-ccic/mcam-core.c
drivers/media/video/mem2mem_testdev.c
drivers/media/video/mt9m001.c
drivers/media/video/mt9m111.c
drivers/media/video/mt9t031.c
drivers/media/video/mt9t112.c
drivers/media/video/mt9v022.c
drivers/media/video/mx1_camera.c
drivers/media/video/mx2_camera.c
drivers/media/video/mx3_camera.c
drivers/media/video/omap/omap_vout.c
drivers/media/video/omap1_camera.c
drivers/media/video/omap3isp/isp.c
drivers/media/video/omap3isp/ispccdc.c
drivers/media/video/omap3isp/ispccp2.c
drivers/media/video/omap3isp/ispcsi2.c
drivers/media/video/omap3isp/isph3a_aewb.c
drivers/media/video/omap3isp/isph3a_af.c
drivers/media/video/omap3isp/isphist.c
drivers/media/video/omap3isp/isppreview.c
drivers/media/video/omap3isp/isppreview.h
drivers/media/video/omap3isp/ispreg.h
drivers/media/video/omap3isp/ispresizer.c
drivers/media/video/omap3isp/ispstat.c
drivers/media/video/omap3isp/ispstat.h
drivers/media/video/omap3isp/ispvideo.c
drivers/media/video/omap3isp/ispvideo.h
drivers/media/video/ov2640.c
drivers/media/video/ov5642.c
drivers/media/video/ov6650.c
drivers/media/video/ov772x.c
drivers/media/video/ov9640.c
drivers/media/video/ov9640.h
drivers/media/video/ov9740.c
drivers/media/video/pwc/pwc-if.c
drivers/media/video/pxa_camera.c
drivers/media/video/rj54n1cb0c.c
drivers/media/video/s5k6aa.c [new file with mode: 0644]
drivers/media/video/s5p-fimc/fimc-capture.c
drivers/media/video/s5p-fimc/fimc-core.c
drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c
drivers/media/video/s5p-mfc/s5p_mfc_dec.c
drivers/media/video/s5p-mfc/s5p_mfc_enc.c
drivers/media/video/s5p-tv/mixer_video.c
drivers/media/video/saa7134/saa7134.h
drivers/media/video/sh_mobile_ceu_camera.c
drivers/media/video/sh_mobile_csi2.c
drivers/media/video/soc_camera.c
drivers/media/video/soc_camera_platform.c
drivers/media/video/soc_mediabus.c
drivers/media/video/tw9910.c
drivers/media/video/v4l2-compat-ioctl32.c
drivers/media/video/v4l2-ctrls.c
drivers/media/video/v4l2-device.c
drivers/media/video/v4l2-ioctl.c
drivers/media/video/videobuf2-core.c
drivers/media/video/vivi.c
drivers/mmc/host/s3cmci.c
drivers/net/ethernet/toshiba/ps3_gelic_net.c
drivers/net/ethernet/toshiba/ps3_gelic_net.h
drivers/of/fdt.c
drivers/of/platform.c
drivers/pcmcia/pxa2xx_base.c
drivers/pcmcia/pxa2xx_cm_x2xx.c
drivers/s390/block/dcssblk.c
drivers/s390/block/xpram.c
drivers/scsi/bnx2fc/bnx2fc.h
drivers/scsi/bnx2fc/bnx2fc_els.c
drivers/scsi/bnx2fc/bnx2fc_fcoe.c
drivers/scsi/bnx2fc/bnx2fc_io.c
drivers/scsi/device_handler/scsi_dh.c
drivers/scsi/device_handler/scsi_dh_alua.c
drivers/scsi/fcoe/fcoe.c
drivers/scsi/hosts.c
drivers/scsi/hpsa.c
drivers/scsi/hpsa.h
drivers/scsi/hpsa_cmd.h
drivers/scsi/ipr.c
drivers/scsi/ipr.h
drivers/scsi/isci/host.c
drivers/scsi/isci/init.c
drivers/scsi/isci/port.c
drivers/scsi/isci/port.h
drivers/scsi/isci/probe_roms.h
drivers/scsi/isci/remote_device.c
drivers/scsi/isci/remote_device.h
drivers/scsi/isci/request.c
drivers/scsi/isci/request.h
drivers/scsi/isci/task.c
drivers/scsi/isci/task.h
drivers/scsi/libfc/fc_exch.c
drivers/scsi/libfc/fc_lport.c
drivers/scsi/mpt2sas/mpi/mpi2.h
drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h
drivers/scsi/mpt2sas/mpi/mpi2_ioc.h
drivers/scsi/mpt2sas/mpt2sas_base.c
drivers/scsi/mpt2sas/mpt2sas_base.h
drivers/scsi/mpt2sas/mpt2sas_config.c
drivers/scsi/mpt2sas/mpt2sas_ctl.c
drivers/scsi/mpt2sas/mpt2sas_scsih.c
drivers/scsi/mvsas/mv_init.c
drivers/scsi/pmcraid.c
drivers/scsi/qla2xxx/qla_isr.c
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_scan.c
drivers/scsi/scsi_transport_iscsi.c
drivers/scsi/sd.c
drivers/scsi/sd.h
drivers/scsi/st.c
drivers/spi/spi-s3c64xx.c
drivers/staging/Kconfig
drivers/staging/Makefile
drivers/staging/cx25821/README [deleted file]
drivers/staging/media/Kconfig [new file with mode: 0644]
drivers/staging/media/Makefile [new file with mode: 0644]
drivers/staging/media/as102/Kconfig [new file with mode: 0644]
drivers/staging/media/as102/Makefile [new file with mode: 0644]
drivers/staging/media/as102/as102_drv.c [new file with mode: 0644]
drivers/staging/media/as102/as102_drv.h [new file with mode: 0644]
drivers/staging/media/as102/as102_fe.c [new file with mode: 0644]
drivers/staging/media/as102/as102_fw.c [new file with mode: 0644]
drivers/staging/media/as102/as102_fw.h [new file with mode: 0644]
drivers/staging/media/as102/as102_usb_drv.c [new file with mode: 0644]
drivers/staging/media/as102/as102_usb_drv.h [new file with mode: 0644]
drivers/staging/media/as102/as10x_cmd.c [new file with mode: 0644]
drivers/staging/media/as102/as10x_cmd.h [new file with mode: 0644]
drivers/staging/media/as102/as10x_cmd_cfg.c [new file with mode: 0644]
drivers/staging/media/as102/as10x_cmd_stream.c [new file with mode: 0644]
drivers/staging/media/as102/as10x_handle.h [new file with mode: 0644]
drivers/staging/media/as102/as10x_types.h [new file with mode: 0644]
drivers/staging/media/cxd2099/Kconfig [moved from drivers/staging/cxd2099/Kconfig with 100% similarity]
drivers/staging/media/cxd2099/Makefile [moved from drivers/staging/cxd2099/Makefile with 100% similarity]
drivers/staging/media/cxd2099/TODO [moved from drivers/staging/cxd2099/TODO with 100% similarity]
drivers/staging/media/cxd2099/cxd2099.c [moved from drivers/staging/cxd2099/cxd2099.c with 100% similarity]
drivers/staging/media/cxd2099/cxd2099.h [moved from drivers/staging/cxd2099/cxd2099.h with 100% similarity]
drivers/staging/media/dt3155v4l/Kconfig [moved from drivers/staging/dt3155v4l/Kconfig with 100% similarity]
drivers/staging/media/dt3155v4l/Makefile [moved from drivers/staging/dt3155v4l/Makefile with 100% similarity]
drivers/staging/media/dt3155v4l/dt3155v4l.c [moved from drivers/staging/dt3155v4l/dt3155v4l.c with 100% similarity]
drivers/staging/media/dt3155v4l/dt3155v4l.h [moved from drivers/staging/dt3155v4l/dt3155v4l.h with 100% similarity]
drivers/staging/media/easycap/Kconfig [moved from drivers/staging/easycap/Kconfig with 100% similarity]
drivers/staging/media/easycap/Makefile [moved from drivers/staging/easycap/Makefile with 100% similarity]
drivers/staging/media/easycap/README [moved from drivers/staging/easycap/README with 100% similarity]
drivers/staging/media/easycap/easycap.h [moved from drivers/staging/easycap/easycap.h with 100% similarity]
drivers/staging/media/easycap/easycap_ioctl.c [moved from drivers/staging/easycap/easycap_ioctl.c with 100% similarity]
drivers/staging/media/easycap/easycap_low.c [moved from drivers/staging/easycap/easycap_low.c with 100% similarity]
drivers/staging/media/easycap/easycap_main.c [moved from drivers/staging/easycap/easycap_main.c with 100% similarity]
drivers/staging/media/easycap/easycap_settings.c [moved from drivers/staging/easycap/easycap_settings.c with 100% similarity]
drivers/staging/media/easycap/easycap_sound.c [moved from drivers/staging/easycap/easycap_sound.c with 100% similarity]
drivers/staging/media/easycap/easycap_testcard.c [moved from drivers/staging/easycap/easycap_testcard.c with 100% similarity]
drivers/staging/media/go7007/Kconfig [moved from drivers/staging/go7007/Kconfig with 100% similarity]
drivers/staging/media/go7007/Makefile [moved from drivers/staging/go7007/Makefile with 100% similarity]
drivers/staging/media/go7007/README [moved from drivers/staging/go7007/README with 100% similarity]
drivers/staging/media/go7007/go7007-driver.c [moved from drivers/staging/go7007/go7007-driver.c with 100% similarity]
drivers/staging/media/go7007/go7007-fw.c [moved from drivers/staging/go7007/go7007-fw.c with 100% similarity]
drivers/staging/media/go7007/go7007-i2c.c [moved from drivers/staging/go7007/go7007-i2c.c with 100% similarity]
drivers/staging/media/go7007/go7007-priv.h [moved from drivers/staging/go7007/go7007-priv.h with 100% similarity]
drivers/staging/media/go7007/go7007-usb.c [moved from drivers/staging/go7007/go7007-usb.c with 100% similarity]
drivers/staging/media/go7007/go7007-v4l2.c [moved from drivers/staging/go7007/go7007-v4l2.c with 100% similarity]
drivers/staging/media/go7007/go7007.h [moved from drivers/staging/go7007/go7007.h with 100% similarity]
drivers/staging/media/go7007/go7007.txt [moved from drivers/staging/go7007/go7007.txt with 100% similarity]
drivers/staging/media/go7007/s2250-board.c [moved from drivers/staging/go7007/s2250-board.c with 100% similarity]
drivers/staging/media/go7007/s2250-loader.c [moved from drivers/staging/go7007/s2250-loader.c with 100% similarity]
drivers/staging/media/go7007/s2250-loader.h [moved from drivers/staging/go7007/s2250-loader.h with 100% similarity]
drivers/staging/media/go7007/saa7134-go7007.c [moved from drivers/staging/go7007/saa7134-go7007.c with 100% similarity]
drivers/staging/media/go7007/snd-go7007.c [moved from drivers/staging/go7007/snd-go7007.c with 100% similarity]
drivers/staging/media/go7007/wis-i2c.h [moved from drivers/staging/go7007/wis-i2c.h with 100% similarity]
drivers/staging/media/go7007/wis-ov7640.c [moved from drivers/staging/go7007/wis-ov7640.c with 100% similarity]
drivers/staging/media/go7007/wis-saa7113.c [moved from drivers/staging/go7007/wis-saa7113.c with 100% similarity]
drivers/staging/media/go7007/wis-saa7115.c [moved from drivers/staging/go7007/wis-saa7115.c with 100% similarity]
drivers/staging/media/go7007/wis-sony-tuner.c [moved from drivers/staging/go7007/wis-sony-tuner.c with 100% similarity]
drivers/staging/media/go7007/wis-tw2804.c [moved from drivers/staging/go7007/wis-tw2804.c with 100% similarity]
drivers/staging/media/go7007/wis-tw9903.c [moved from drivers/staging/go7007/wis-tw9903.c with 100% similarity]
drivers/staging/media/go7007/wis-uda1342.c [moved from drivers/staging/go7007/wis-uda1342.c with 100% similarity]
drivers/staging/media/lirc/Kconfig [moved from drivers/staging/lirc/Kconfig with 100% similarity]
drivers/staging/media/lirc/Makefile [moved from drivers/staging/lirc/Makefile with 100% similarity]
drivers/staging/media/lirc/TODO [moved from drivers/staging/lirc/TODO with 100% similarity]
drivers/staging/media/lirc/TODO.lirc_zilog [moved from drivers/staging/lirc/TODO.lirc_zilog with 100% similarity]
drivers/staging/media/lirc/lirc_bt829.c [moved from drivers/staging/lirc/lirc_bt829.c with 100% similarity]
drivers/staging/media/lirc/lirc_ene0100.h [moved from drivers/staging/lirc/lirc_ene0100.h with 100% similarity]
drivers/staging/media/lirc/lirc_igorplugusb.c [moved from drivers/staging/lirc/lirc_igorplugusb.c with 100% similarity]
drivers/staging/media/lirc/lirc_imon.c [moved from drivers/staging/lirc/lirc_imon.c with 100% similarity]
drivers/staging/media/lirc/lirc_parallel.c [moved from drivers/staging/lirc/lirc_parallel.c with 100% similarity]
drivers/staging/media/lirc/lirc_parallel.h [moved from drivers/staging/lirc/lirc_parallel.h with 100% similarity]
drivers/staging/media/lirc/lirc_sasem.c [moved from drivers/staging/lirc/lirc_sasem.c with 100% similarity]
drivers/staging/media/lirc/lirc_serial.c [moved from drivers/staging/lirc/lirc_serial.c with 100% similarity]
drivers/staging/media/lirc/lirc_sir.c [moved from drivers/staging/lirc/lirc_sir.c with 100% similarity]
drivers/staging/media/lirc/lirc_ttusbir.c [moved from drivers/staging/lirc/lirc_ttusbir.c with 100% similarity]
drivers/staging/media/lirc/lirc_zilog.c [moved from drivers/staging/lirc/lirc_zilog.c with 100% similarity]
drivers/staging/media/solo6x10/Kconfig [moved from drivers/staging/solo6x10/Kconfig with 100% similarity]
drivers/staging/media/solo6x10/Makefile [moved from drivers/staging/solo6x10/Makefile with 100% similarity]
drivers/staging/media/solo6x10/TODO [moved from drivers/staging/solo6x10/TODO with 100% similarity]
drivers/staging/media/solo6x10/core.c [moved from drivers/staging/solo6x10/core.c with 100% similarity]
drivers/staging/media/solo6x10/disp.c [moved from drivers/staging/solo6x10/disp.c with 100% similarity]
drivers/staging/media/solo6x10/enc.c [moved from drivers/staging/solo6x10/enc.c with 100% similarity]
drivers/staging/media/solo6x10/g723.c [moved from drivers/staging/solo6x10/g723.c with 100% similarity]
drivers/staging/media/solo6x10/gpio.c [moved from drivers/staging/solo6x10/gpio.c with 100% similarity]
drivers/staging/media/solo6x10/i2c.c [moved from drivers/staging/solo6x10/i2c.c with 100% similarity]
drivers/staging/media/solo6x10/jpeg.h [moved from drivers/staging/solo6x10/jpeg.h with 100% similarity]
drivers/staging/media/solo6x10/offsets.h [moved from drivers/staging/solo6x10/offsets.h with 100% similarity]
drivers/staging/media/solo6x10/osd-font.h [moved from drivers/staging/solo6x10/osd-font.h with 100% similarity]
drivers/staging/media/solo6x10/p2m.c [moved from drivers/staging/solo6x10/p2m.c with 100% similarity]
drivers/staging/media/solo6x10/registers.h [moved from drivers/staging/solo6x10/registers.h with 100% similarity]
drivers/staging/media/solo6x10/solo6x10.h [moved from drivers/staging/solo6x10/solo6x10.h with 100% similarity]
drivers/staging/media/solo6x10/tw28.c [moved from drivers/staging/solo6x10/tw28.c with 100% similarity]
drivers/staging/media/solo6x10/tw28.h [moved from drivers/staging/solo6x10/tw28.h with 100% similarity]
drivers/staging/media/solo6x10/v4l2-enc.c [moved from drivers/staging/solo6x10/v4l2-enc.c with 100% similarity]
drivers/staging/media/solo6x10/v4l2.c [moved from drivers/staging/solo6x10/v4l2.c with 100% similarity]
drivers/staging/zram/zram_drv.c
drivers/tty/hvc/Kconfig
drivers/tty/hvc/Makefile
drivers/tty/hvc/hvc_opal.c [new file with mode: 0644]
drivers/tty/hvc/hvcs.c
drivers/tty/hvc/hvsi_lib.c
drivers/tty/serial/8250.c
drivers/tty/serial/sh-sci.c
drivers/usb/core/driver.c
drivers/virt/fsl_hypervisor.c
drivers/watchdog/Kconfig
drivers/watchdog/coh901327_wdt.c
drivers/watchdog/eurotechwdt.c
drivers/watchdog/iTCO_wdt.c
drivers/watchdog/mpcore_wdt.c
drivers/watchdog/octeon-wdt-main.c
drivers/watchdog/s3c2410_wdt.c
drivers/watchdog/sb_wdog.c
drivers/watchdog/sc520_wdt.c
drivers/watchdog/w83627hf_wdt.c
drivers/watchdog/wdt.c
drivers/watchdog/wdt_pci.c
drivers/watchdog/wm831x_wdt.c
fs/bio.c
fs/block_dev.c
fs/exofs/Kconfig
fs/nfs/callback_xdr.c
fs/nfs/file.c
fs/nfs/nfs4filelayout.c
fs/nfs/nfs4proc.c
fs/nfs/nfs4xdr.c
fs/nfs/objlayout/objio_osd.c
fs/nfs/objlayout/objlayout.c
fs/nfs/objlayout/objlayout.h
fs/nfs/pagelist.c
fs/nfs/pnfs.c
fs/nfs/write.c
fs/nfsd/nfssvc.c
fs/squashfs/Kconfig
fs/squashfs/squashfs_fs.h
fs/squashfs/super.c
fs/statfs.c
include/linux/amba/pl08x.h
include/linux/amba/pl330.h
include/linux/bio.h
include/linux/blk_types.h
include/linux/blkdev.h
include/linux/cpu.h
include/linux/dma-mapping.h
include/linux/dmaengine.h
include/linux/elevator.h
include/linux/freezer.h
include/linux/genhd.h
include/linux/loop.h
include/linux/nfs_fs.h
include/linux/of.h
include/linux/opp.h
include/linux/pci_ids.h
include/linux/serial_sci.h
include/linux/sunrpc/clnt.h
include/linux/sunrpc/svc.h
include/linux/topology.h
include/linux/videodev2.h
include/media/ov772x.h
include/media/s5k6aa.h [new file with mode: 0644]
include/media/soc_camera.h
include/media/soc_camera_platform.h
include/media/soc_mediabus.h
include/media/v4l2-ioctl.h
include/media/v4l2-subdev.h
include/media/videobuf2-core.h
include/xen/interface/io/blkif.h
kernel/cpu.c
kernel/freezer.c
kernel/power/qos.c
kernel/sched.c
mm/bounce.c
net/sunrpc/auth_unix.c
net/sunrpc/rpcb_clnt.c
net/sunrpc/sunrpc_syms.c
net/sunrpc/svc.c
sound/core/control.c
sound/core/hwdep.c
sound/pci/hda/hda_hwdep.c
sound/pci/hda/hda_intel.c
sound/pci/hda/hda_local.h
sound/pci/hda/patch_hdmi.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/pci/hda/patch_via.c
sound/pci/intel8x0.c
sound/pci/rme9652/hdsp.c
sound/pci/rme9652/hdspm.c
sound/soc/codecs/tlv320aic23.c
sound/soc/codecs/tlv320aic3x.c
sound/soc/codecs/wm5100.c
sound/soc/codecs/wm8711.c
sound/soc/codecs/wm8904.c
sound/soc/codecs/wm8940.c
sound/soc/codecs/wm8962.c
sound/soc/samsung/ac97.c
sound/soc/samsung/dma.c
sound/soc/samsung/dma.h
sound/usb/misc/ua101.c

index f5bb0a3..53d99ed 100644 (file)
@@ -71,3 +71,10 @@ Description: Value of 1 indicates the controller can honor the reset_devices
                a dump device, as kdump requires resetting the device in order
                to work reliably.
 
+Where:         /sys/bus/pci/devices/<dev>/ccissX/transport_mode
+Date:          July 2011
+Kernel Version:        3.0
+Contact:       iss_storagedev@hp.com
+Description:   Value of "simple" indicates that the controller has been placed
+               in "simple mode". Value of "performant" indicates that the
+               controller has been placed in "performant mode".
index c940239..2b90d32 100644 (file)
@@ -166,8 +166,8 @@ if (condition)
 else
        do_that();
 
-This does not apply if one branch of a conditional statement is a single
-statement. Use braces in both branches.
+This does not apply if only one branch of a conditional statement is a single
+statement; in the latter case use braces in both branches:
 
 if (condition) {
        do_this();
index 91410b6..b68698f 100644 (file)
@@ -2486,6 +2486,9 @@ ioctls.</para>
         <listitem>
          <para>Flash API. <xref linkend="flash-controls" /></para>
         </listitem>
+        <listitem>
+         <para>&VIDIOC-CREATE-BUFS; and &VIDIOC-PREPARE-BUF; ioctls.</para>
+        </listitem>
       </itemizedlist>
     </section>
 
index 23fdf79..3bc5ee8 100644 (file)
@@ -232,8 +232,9 @@ control is deprecated. New drivers and applications should use the
            <entry>Enables a power line frequency filter to avoid
 flicker. Possible values for <constant>enum v4l2_power_line_frequency</constant> are:
 <constant>V4L2_CID_POWER_LINE_FREQUENCY_DISABLED</constant> (0),
-<constant>V4L2_CID_POWER_LINE_FREQUENCY_50HZ</constant> (1) and
-<constant>V4L2_CID_POWER_LINE_FREQUENCY_60HZ</constant> (2).</entry>
+<constant>V4L2_CID_POWER_LINE_FREQUENCY_50HZ</constant> (1),
+<constant>V4L2_CID_POWER_LINE_FREQUENCY_60HZ</constant> (2) and
+<constant>V4L2_CID_POWER_LINE_FREQUENCY_AUTO</constant> (3).</entry>
          </row>
          <row>
            <entry><constant>V4L2_CID_HUE_AUTO</constant></entry>
index c57d1ec..3f47df1 100644 (file)
@@ -927,6 +927,33 @@ ioctl is called.</entry>
 Applications set or clear this flag before calling the
 <constant>VIDIOC_QBUF</constant> ioctl.</entry>
          </row>
+         <row>
+           <entry><constant>V4L2_BUF_FLAG_PREPARED</constant></entry>
+           <entry>0x0400</entry>
+           <entry>The buffer has been prepared for I/O and can be queued by the
+application. Drivers set or clear this flag when the
+<link linkend="vidioc-querybuf">VIDIOC_QUERYBUF</link>, <link
+         linkend="vidioc-qbuf">VIDIOC_PREPARE_BUF</link>, <link
+         linkend="vidioc-qbuf">VIDIOC_QBUF</link> or <link
+         linkend="vidioc-qbuf">VIDIOC_DQBUF</link> ioctl is called.</entry>
+         </row>
+         <row>
+           <entry><constant>V4L2_BUF_FLAG_NO_CACHE_INVALIDATE</constant></entry>
+           <entry>0x0400</entry>
+           <entry>Caches do not have to be invalidated for this buffer.
+Typically applications shall use this flag if the data captured in the buffer
+is not going to be touched by the CPU, instead the buffer will, probably, be
+passed on to a DMA-capable hardware unit for further processing or output.
+</entry>
+         </row>
+         <row>
+           <entry><constant>V4L2_BUF_FLAG_NO_CACHE_CLEAN</constant></entry>
+           <entry>0x0800</entry>
+           <entry>Caches do not have to be cleaned for this buffer.
+Typically applications shall use this flag for output buffers if the data
+in this buffer has not been created by the CPU but by some DMA-capable unit,
+in which case caches have not been used.</entry>
+         </row>
        </tbody>
       </tgroup>
     </table>
index 40132c2..2ab365c 100644 (file)
@@ -469,6 +469,7 @@ and discussions on the V4L mailing list.</revremark>
     &sub-close;
     &sub-ioctl;
     <!-- All ioctls go here. -->
+    &sub-create-bufs;
     &sub-cropcap;
     &sub-dbg-g-chip-ident;
     &sub-dbg-g-register;
@@ -511,6 +512,7 @@ and discussions on the V4L mailing list.</revremark>
     &sub-queryctrl;
     &sub-query-dv-preset;
     &sub-querystd;
+    &sub-prepare-buf;
     &sub-reqbufs;
     &sub-s-hw-freq-seek;
     &sub-streamon;
diff --git a/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml b/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml
new file mode 100644 (file)
index 0000000..73ae8a6
--- /dev/null
@@ -0,0 +1,139 @@
+<refentry id="vidioc-create-bufs">
+  <refmeta>
+    <refentrytitle>ioctl VIDIOC_CREATE_BUFS</refentrytitle>
+    &manvol;
+  </refmeta>
+
+  <refnamediv>
+    <refname>VIDIOC_CREATE_BUFS</refname>
+    <refpurpose>Create buffers for Memory Mapped or User Pointer I/O</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcprototype>
+       <funcdef>int <function>ioctl</function></funcdef>
+       <paramdef>int <parameter>fd</parameter></paramdef>
+       <paramdef>int <parameter>request</parameter></paramdef>
+       <paramdef>struct v4l2_create_buffers *<parameter>argp</parameter></paramdef>
+      </funcprototype>
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Arguments</title>
+
+    <variablelist>
+      <varlistentry>
+       <term><parameter>fd</parameter></term>
+       <listitem>
+         <para>&fd;</para>
+       </listitem>
+      </varlistentry>
+      <varlistentry>
+       <term><parameter>request</parameter></term>
+       <listitem>
+         <para>VIDIOC_CREATE_BUFS</para>
+       </listitem>
+      </varlistentry>
+      <varlistentry>
+       <term><parameter>argp</parameter></term>
+       <listitem>
+         <para></para>
+       </listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>Description</title>
+
+    <para>This ioctl is used to create buffers for <link linkend="mmap">memory
+mapped</link> or <link linkend="userp">user pointer</link>
+I/O. It can be used as an alternative or in addition to the
+<constant>VIDIOC_REQBUFS</constant> ioctl, when a tighter control over buffers
+is required. This ioctl can be called multiple times to create buffers of
+different sizes.</para>
+
+    <para>To allocate device buffers applications initialize relevant fields of
+the <structname>v4l2_create_buffers</structname> structure. They set the
+<structfield>type</structfield> field in the
+<structname>v4l2_format</structname> structure, embedded in this
+structure, to the respective stream or buffer type.
+<structfield>count</structfield> must be set to the number of required buffers.
+<structfield>memory</structfield> specifies the required I/O method. The
+<structfield>format</structfield> field shall typically be filled in using
+either the <constant>VIDIOC_TRY_FMT</constant> or
+<constant>VIDIOC_G_FMT</constant> ioctl(). Additionally, applications can adjust
+<structfield>sizeimage</structfield> fields to fit their specific needs. The
+<structfield>reserved</structfield> array must be zeroed.</para>
+
+    <para>When the ioctl is called with a pointer to this structure the driver
+will attempt to allocate up to the requested number of buffers and store the
+actual number allocated and the starting index in the
+<structfield>count</structfield> and the <structfield>index</structfield> fields
+respectively. On return <structfield>count</structfield> can be smaller than
+the number requested. The driver may also increase buffer sizes if required,
+however, it will not update <structfield>sizeimage</structfield> field values.
+The user has to use <constant>VIDIOC_QUERYBUF</constant> to retrieve that
+information.</para>
+
+    <table pgwide="1" frame="none" id="v4l2-create-buffers">
+      <title>struct <structname>v4l2_create_buffers</structname></title>
+      <tgroup cols="3">
+       &cs-str;
+       <tbody valign="top">
+         <row>
+           <entry>__u32</entry>
+           <entry><structfield>index</structfield></entry>
+           <entry>The starting buffer index, returned by the driver.</entry>
+         </row>
+         <row>
+           <entry>__u32</entry>
+           <entry><structfield>count</structfield></entry>
+           <entry>The number of buffers requested or granted.</entry>
+         </row>
+         <row>
+           <entry>&v4l2-memory;</entry>
+           <entry><structfield>memory</structfield></entry>
+           <entry>Applications set this field to
+<constant>V4L2_MEMORY_MMAP</constant> or
+<constant>V4L2_MEMORY_USERPTR</constant>.</entry>
+         </row>
+         <row>
+           <entry>&v4l2-format;</entry>
+           <entry><structfield>format</structfield></entry>
+           <entry>Filled in by the application, preserved by the driver.</entry>
+         </row>
+         <row>
+           <entry>__u32</entry>
+           <entry><structfield>reserved</structfield>[8]</entry>
+           <entry>A place holder for future extensions.</entry>
+         </row>
+       </tbody>
+      </tgroup>
+    </table>
+  </refsect1>
+
+  <refsect1>
+    &return-value;
+
+    <variablelist>
+      <varlistentry>
+       <term><errorcode>ENOMEM</errorcode></term>
+       <listitem>
+         <para>No memory to allocate buffers for <link linkend="mmap">memory
+mapped</link> I/O.</para>
+       </listitem>
+      </varlistentry>
+      <varlistentry>
+       <term><errorcode>EINVAL</errorcode></term>
+       <listitem>
+         <para>The buffer type (<structfield>type</structfield> field) or the
+requested I/O method (<structfield>memory</structfield>) is not
+supported.</para>
+       </listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml b/Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml
new file mode 100644 (file)
index 0000000..7bde698
--- /dev/null
@@ -0,0 +1,88 @@
+<refentry id="vidioc-prepare-buf">
+  <refmeta>
+    <refentrytitle>ioctl VIDIOC_PREPARE_BUF</refentrytitle>
+    &manvol;
+  </refmeta>
+
+  <refnamediv>
+    <refname>VIDIOC_PREPARE_BUF</refname>
+    <refpurpose>Prepare a buffer for I/O</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcprototype>
+       <funcdef>int <function>ioctl</function></funcdef>
+       <paramdef>int <parameter>fd</parameter></paramdef>
+       <paramdef>int <parameter>request</parameter></paramdef>
+       <paramdef>struct v4l2_buffer *<parameter>argp</parameter></paramdef>
+      </funcprototype>
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Arguments</title>
+
+    <variablelist>
+      <varlistentry>
+       <term><parameter>fd</parameter></term>
+       <listitem>
+         <para>&fd;</para>
+       </listitem>
+      </varlistentry>
+      <varlistentry>
+       <term><parameter>request</parameter></term>
+       <listitem>
+         <para>VIDIOC_PREPARE_BUF</para>
+       </listitem>
+      </varlistentry>
+      <varlistentry>
+       <term><parameter>argp</parameter></term>
+       <listitem>
+         <para></para>
+       </listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>Description</title>
+
+    <para>Applications can optionally call the
+<constant>VIDIOC_PREPARE_BUF</constant> ioctl to pass ownership of the buffer
+to the driver before actually enqueuing it, using the
+<constant>VIDIOC_QBUF</constant> ioctl, and to prepare it for future I/O.
+Such preparations may include cache invalidation or cleaning. Performing them
+in advance saves time during the actual I/O. In case such cache operations are
+not required, the application can use one of
+<constant>V4L2_BUF_FLAG_NO_CACHE_INVALIDATE</constant> and
+<constant>V4L2_BUF_FLAG_NO_CACHE_CLEAN</constant> flags to skip the respective
+step.</para>
+
+    <para>The <structname>v4l2_buffer</structname> structure is
+specified in <xref linkend="buffer" />.</para>
+  </refsect1>
+
+  <refsect1>
+    &return-value;
+
+    <variablelist>
+      <varlistentry>
+       <term><errorcode>EBUSY</errorcode></term>
+       <listitem>
+         <para>File I/O is in progress.</para>
+       </listitem>
+      </varlistentry>
+      <varlistentry>
+       <term><errorcode>EINVAL</errorcode></term>
+       <listitem>
+         <para>The buffer <structfield>type</structfield> is not
+supported, or the <structfield>index</structfield> is out of bounds,
+or no buffers have been allocated yet, or the
+<structfield>userptr</structfield> or
+<structfield>length</structfield> are invalid.</para>
+       </listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+</refentry>
index 71cfbdc..3b2612e 100644 (file)
@@ -1,6 +1,6 @@
 To choose IO schedulers at boot time, use the argument 'elevator=deadline'.
-'noop', 'as' and 'cfq' (the default) are also available. IO schedulers are
-assigned globally at boot time only presently.
+'noop' and 'cfq' (the default) are also available. IO schedulers are assigned
+globally at boot time only presently.
 
 Each io queue has a set of io scheduler tunables associated with it. These
 tunables control how the io scheduler works. You can find these entries
index c00c6a5..71464e0 100644 (file)
@@ -78,6 +78,16 @@ The device naming scheme is:
 /dev/cciss/c1d1p2              Controller 1, disk 1, partition 2
 /dev/cciss/c1d1p3              Controller 1, disk 1, partition 3
 
+CCISS simple mode support
+-------------------------
+
+The "cciss_simple_mode=1" boot parameter may be used to prevent the driver
+from putting the controller into "performant" mode. The difference is that
+with simple mode, each command completion requires an interrupt, while with
+"performant mode" (the default, and ordinarily better performing) it is
+possible to have multiple command completions indicated by a single
+interrupt.
+
 SCSI tape drive and medium changer support
 ------------------------------------------
 
index cd67e90..9c452ef 100644 (file)
@@ -454,8 +454,8 @@ mounted hierarchy, to remove a task from its current cgroup you must
 move it into a new cgroup (possibly the root cgroup) by writing to the
 new cgroup's tasks file.
 
-Note: If the ns cgroup is active, moving a process to another cgroup can
-fail.
+Note: Due to some restrictions enforced by some cgroup subsystems, moving
+a process to another cgroup can fail.
 
 2.3 Mounting hierarchies by name
 --------------------------------
diff --git a/Documentation/devicetree/bindings/ata/calxeda-sata.txt b/Documentation/devicetree/bindings/ata/calxeda-sata.txt
new file mode 100644 (file)
index 0000000..79caa56
--- /dev/null
@@ -0,0 +1,17 @@
+* Calxeda SATA Controller
+
+SATA nodes are defined to describe on-chip Serial ATA controllers.
+Each SATA controller should have its own node.
+
+Required properties:
+- compatible        : compatible list, contains "calxeda,hb-ahci"
+- interrupts        : <interrupt mapping for SATA IRQ>
+- reg               : <registers mapping>
+
+Example:
+        sata@ffe08000 {
+               compatible = "calxeda,hb-ahci";
+                reg = <0xffe08000 0x1000>;
+                interrupts = <115>;
+        };
+
index 39e9415..380914e 100644 (file)
@@ -1,3 +1,8 @@
+Freescale Reference Board Bindings
+
+This document describes device tree bindings for various devices that
+exist on some Freescale reference boards.
+
 * Board Control and Status (BCSR)
 
 Required properties:
@@ -12,25 +17,26 @@ Example:
                reg = <f8000000 8000>;
        };
 
-* Freescale on board FPGA
+* Freescale on-board FPGA
 
 This is the memory-mapped registers for on board FPGA.
 
 Required properities:
-- compatible : should be "fsl,fpga-pixis".
-- reg : should contain the address and the length of the FPPGA register
-  set.
+- compatible: should be a board-specific string followed by a string
+  indicating the type of FPGA.  Example:
+       "fsl,<board>-fpga", "fsl,fpga-pixis"
+- reg: should contain the address and the length of the FPGA register set.
 - interrupt-parent: should specify phandle for the interrupt controller.
-- interrupts : should specify event (wakeup) IRQ.
+- interrupts: should specify event (wakeup) IRQ.
 
-Example (MPC8610HPCD):
+Example (P1022DS):
 
-       board-control@e8000000 {
-               compatible = "fsl,fpga-pixis";
-               reg = <0xe8000000 32>;
-               interrupt-parent = <&mpic>;
-               interrupts = <8 8>;
-       };
+        board-control@3,0 {
+                compatible = "fsl,p1022ds-fpga", "fsl,fpga-ngpixis";
+                reg = <3 0 0x30>;
+                interrupt-parent = <&mpic>;
+                interrupts = <8 8 0 0>;
+        };
 
 * Freescale BCSR GPIO banks
 
diff --git a/Documentation/devicetree/bindings/powerpc/fsl/dcsr.txt b/Documentation/devicetree/bindings/powerpc/fsl/dcsr.txt
new file mode 100644 (file)
index 0000000..9d54eb5
--- /dev/null
@@ -0,0 +1,395 @@
+===================================================================
+Debug Control and Status Register (DCSR) Binding
+Copyright 2011 Freescale Semiconductor Inc.
+
+NOTE: The bindings described in this document are preliminary and subject
+to change.  Some of the compatible strings that contain only generic names
+may turn out to be inappropriate, or need additional properties to describe
+the integration of the block with the rest of the chip.
+
+=====================================================================
+Debug Control and Status Register Memory Map
+
+Description
+
+This node defines the base address and range for the
+defined DCSR Memory Map. Child nodes will describe the individual
+debug blocks defined within this memory space.
+
+PROPERTIES
+
+       - compatible
+       Usage: required
+       Value type: <string>
+       Definition: Must include "fsl,dcsr" and "simple-bus".
+       The DCSR space exists in the memory-mapped bus.
+
+       - #address-cells
+       Usage: required
+       Value type: <u32>
+       Definition: A standard property.  Defines the number of cells
+       or representing physical addresses in child nodes.
+
+       - #size-cells
+       Usage: required
+       Value type: <u32>
+       Definition: A standard property.  Defines the number of cells
+       or representing the size of physical addresses in
+       child nodes.
+
+       - ranges
+       Usage: required
+       Value type: <prop-encoded-array>
+       Definition: A standard property. Specifies the physical address
+       range of the DCSR space.
+
+EXAMPLE
+       dcsr: dcsr@f00000000 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "fsl,dcsr", "simple-bus";
+               ranges = <0x00000000 0xf 0x00000000 0x01008000>;
+       };
+
+=====================================================================
+Event Processing Unit
+
+This node represents the region of DCSR space allocated to the EPU
+
+PROPERTIES
+
+       - compatible
+       Usage: required
+       Value type: <string>
+       Definition: Must include "fsl,dcsr-epu"
+
+       - interrupts
+       Usage: required
+       Value type: <prop_encoded-array>
+       Definition:  Specifies the interrupts generated by the EPU.
+       The value of the interrupts property consists of three
+       interrupt specifiers. The format of the specifier is defined
+       by the binding document describing the node's interrupt parent.
+
+       The EPU counters can be configured to assert the performance
+       monitor interrupt signal based on either counter overflow or value
+       match. Which counter asserted the interrupt is captured in an EPU
+       Counter Interrupt Status Register (EPCPUISR).
+
+       The EPU unit can also be configured to assert either or both of
+       two interrupt signals based on debug event sources within the SoC.
+       The interrupt signals are epu_xt_int0 and epu_xt_int1.
+       Which event source asserted the interrupt is captured in an EPU
+       Interrupt Status Register (EPISR0,EPISR1).
+
+       Interrupt numbers are lised in order (perfmon, event0, event1).
+
+       - interrupt-parent
+       Usage: required
+       Value type: <phandle>
+       Definition: A single <phandle> value that points
+       to the interrupt parent to which the child domain
+       is being mapped. Value must be "&mpic"
+
+       - reg
+       Usage: required
+       Value type: <prop-encoded-array>
+       Definition: A standard property.  Specifies the physical address
+       offset and length of the DCSR space registers of the device
+       configuration block.
+
+EXAMPLE
+       dcsr-epu@0 {
+               compatible = "fsl,dcsr-epu";
+               interrupts = <52 2 0 0
+                             84 2 0 0
+                             85 2 0 0>;
+               interrupt-parent = <&mpic>;
+               reg = <0x0 0x1000>;
+       };
+
+=======================================================================
+Nexus Port Controller
+
+This node represents the region of DCSR space allocated to the NPC
+
+PROPERTIES
+
+       - compatible
+       Usage: required
+       Value type: <string>
+       Definition: Must include "fsl,dcsr-npc"
+
+       - reg
+       Usage: required
+       Value type: <prop-encoded-array>
+       Definition: A standard property.  Specifies the physical address
+       offset and length of the DCSR space registers of the device
+       configuration block.
+       The Nexus Port controller occupies two regions in the DCSR space
+       with distinct functionality.
+
+       The first register range describes the Nexus Port Controller
+       control and status registers.
+
+       The second register range describes the Nexus Port Controller
+       internal trace buffer. The NPC trace buffer is a small memory buffer
+       which stages the nexus trace data for transmission via the Aurora port
+       or to a DDR based trace buffer. In some configurations the NPC trace
+       buffer can be the only trace buffer used.
+
+
+EXAMPLE
+               dcsr-npc {
+                       compatible = "fsl,dcsr-npc";
+                       reg = <0x1000 0x1000 0x1000000 0x8000>;
+               };
+
+=======================================================================
+Nexus Concentrator
+
+This node represents the region of DCSR space allocated to the NXC
+
+PROPERTIES
+
+       - compatible
+       Usage: required
+       Value type: <string>
+       Definition: Must include "fsl,dcsr-nxc"
+
+       - reg
+       Usage: required
+       Value type: <prop-encoded-array>
+       Definition: A standard property.  Specifies the physical address
+       offset and length of the DCSR space registers of the device
+       configuration block.
+
+EXAMPLE
+               dcsr-nxc@2000 {
+                       compatible = "fsl,dcsr-nxc";
+                       reg = <0x2000 0x1000>;
+               };
+=======================================================================
+CoreNet Debug Controller
+
+This node represents the region of DCSR space allocated to
+the CoreNet Debug controller.
+
+PROPERTIES
+
+       - compatible
+       Usage: required
+       Value type: <string>
+       Definition: Must include "fsl,dcsr-corenet"
+
+       - reg
+       Usage: required
+       Value type: <prop-encoded-array>
+       Definition: A standard property.  Specifies the physical address
+       offset and length of the DCSR space registers of the device
+       configuration block.
+       The CoreNet Debug controller occupies two regions in the DCSR space
+       with distinct functionality.
+
+       The first register range describes the CoreNet Debug Controller
+       functionalty to perform transaction and transaction attribute matches.
+
+       The second register range describes the CoreNet Debug Controller
+       functionalty to trigger event notifications and debug traces.
+
+EXAMPLE
+               dcsr-corenet {
+                       compatible = "fsl,dcsr-corenet";
+                       reg = <0x8000 0x1000 0xB0000 0x1000>;
+               };
+
+=======================================================================
+Data Path Debug controller
+
+This node represents the region of DCSR space allocated to
+the DPAA Debug Controller. This controller controls debug configuration
+for the QMAN and FMAN blocks.
+
+PROPERTIES
+
+       - compatible
+       Usage: required
+       Value type: <string>
+       Definition: Must include both an identifier specific to the SoC
+       or Debug IP of the form "fsl,<soc>-dcsr-dpaa" in addition to the
+       generic compatible string "fsl,dcsr-dpaa".
+
+       - reg
+       Usage: required
+       Value type: <prop-encoded-array>
+       Definition: A standard property.  Specifies the physical address
+       offset and length of the DCSR space registers of the device
+       configuration block.
+
+EXAMPLE
+               dcsr-dpaa@9000 {
+                       compatible = "fsl,p4080-dcsr-dpaa", "fsl,dcsr-dpaa";
+                       reg = <0x9000 0x1000>;
+               };
+
+=======================================================================
+OCeaN Debug controller
+
+This node represents the region of DCSR space allocated to
+the OCN Debug Controller.
+
+PROPERTIES
+
+       - compatible
+       Usage: required
+       Value type: <string>
+       Definition: Must include both an identifier specific to the SoC
+       or Debug IP of the form "fsl,<soc>-dcsr-ocn" in addition to the
+       generic compatible string "fsl,dcsr-ocn".
+
+       - reg
+       Usage: required
+       Value type: <prop-encoded-array>
+       Definition: A standard property.  Specifies the physical address
+       offset and length of the DCSR space registers of the device
+       configuration block.
+
+EXAMPLE
+               dcsr-ocn@11000 {
+                       compatible = "fsl,p4080-dcsr-ocn", "fsl,dcsr-ocn";
+                       reg = <0x11000 0x1000>;
+               };
+
+=======================================================================
+DDR Controller Debug controller
+
+This node represents the region of DCSR space allocated to
+the OCN Debug Controller.
+
+PROPERTIES
+
+       - compatible
+       Usage: required
+       Value type: <string>
+       Definition: Must include "fsl,dcsr-ddr"
+
+       - dev-handle
+       Usage: required
+       Definition: A phandle to associate this debug node with its
+       component controller.
+
+       - reg
+       Usage: required
+       Value type: <prop-encoded-array>
+       Definition: A standard property.  Specifies the physical address
+       offset and length of the DCSR space registers of the device
+       configuration block.
+
+EXAMPLE
+               dcsr-ddr@12000 {
+                       compatible = "fsl,dcsr-ddr";
+                       dev-handle = <&ddr1>;
+                       reg = <0x12000 0x1000>;
+               };
+
+=======================================================================
+Nexus Aurora Link Controller
+
+This node represents the region of DCSR space allocated to
+the NAL Controller.
+
+PROPERTIES
+
+       - compatible
+       Usage: required
+       Value type: <string>
+       Definition: Must include both an identifier specific to the SoC
+       or Debug IP of the form "fsl,<soc>-dcsr-nal" in addition to the
+       generic compatible string "fsl,dcsr-nal".
+
+       - reg
+       Usage: required
+       Value type: <prop-encoded-array>
+       Definition: A standard property.  Specifies the physical address
+       offset and length of the DCSR space registers of the device
+       configuration block.
+
+EXAMPLE
+               dcsr-nal@18000 {
+                       compatible = "fsl,p4080-dcsr-nal", "fsl,dcsr-nal";
+                       reg = <0x18000 0x1000>;
+               };
+
+
+=======================================================================
+Run Control and Power Management
+
+This node represents the region of DCSR space allocated to
+the RCPM Debug Controller. This functionlity is limited to the
+control the debug operations of the SoC and cores.
+
+PROPERTIES
+
+       - compatible
+       Usage: required
+       Value type: <string>
+       Definition: Must include both an identifier specific to the SoC
+       or Debug IP of the form "fsl,<soc>-dcsr-rcpm" in addition to the
+       generic compatible string "fsl,dcsr-rcpm".
+
+       - reg
+       Usage: required
+       Value type: <prop-encoded-array>
+       Definition: A standard property.  Specifies the physical address
+       offset and length of the DCSR space registers of the device
+       configuration block.
+
+EXAMPLE
+               dcsr-rcpm@22000 {
+                       compatible = "fsl,p4080-dcsr-rcpm", "fsl,dcsr-rcpm";
+                       reg = <0x22000 0x1000>;
+               };
+
+=======================================================================
+Core Service Bridge Proxy
+
+This node represents the region of DCSR space allocated to
+the Core Service Bridge Proxies.
+There is one Core Service Bridge Proxy device for each CPU in the system.
+This functionlity provides access to the debug operations of the CPU.
+
+PROPERTIES
+
+       - compatible
+       Usage: required
+       Value type: <string>
+       Definition: Must include both an identifier specific to the cpu
+       of the form "fsl,dcsr-<cpu>-sb-proxy" in addition to the
+       generic compatible string "fsl,dcsr-cpu-sb-proxy".
+
+       - cpu-handle
+       Usage: required
+       Definition: A phandle to associate this debug node with its cpu.
+
+       - reg
+       Usage: required
+       Value type: <prop-encoded-array>
+       Definition: A standard property.  Specifies the physical address
+       offset and length of the DCSR space registers of the device
+       configuration block.
+
+EXAMPLE
+               dcsr-cpu-sb-proxy@40000 {
+                       compatible = "fsl,dcsr-e500mc-sb-proxy",
+                                    "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu0>;
+                       reg = <0x40000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@41000 {
+                       compatible = "fsl,dcsr-e500mc-sb-proxy",
+                                    "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu1>;
+                       reg = <0x41000 0x1000>;
+               };
+
+=======================================================================
index 70558c3..5d586e1 100644 (file)
@@ -25,6 +25,16 @@ Required properties:
   are routed to IPIC, and for 85xx/86xx cpu the interrupts are routed
   to MPIC.
 
+Optional properties:
+- msi-address-64: 64-bit PCI address of the MSIIR register. The MSIIR register
+  is used for MSI messaging.  The address of MSIIR in PCI address space is
+  the MSI message address.
+
+  This property may be used in virtualized environments where the hypervisor
+  has created an alternate mapping for the MSIR block.  See below for an
+  explanation.
+
+
 Example:
        msi@41600 {
                compatible = "fsl,mpc8610-msi", "fsl,mpic-msi";
@@ -41,3 +51,35 @@ Example:
                        0xe7 0>;
                interrupt-parent = <&mpic>;
        };
+
+The Freescale hypervisor and msi-address-64
+-------------------------------------------
+Normally, PCI devices have access to all of CCSR via an ATMU mapping.  The
+Freescale MSI driver calculates the address of MSIIR (in the MSI register
+block) and sets that address as the MSI message address.
+
+In a virtualized environment, the hypervisor may need to create an IOMMU
+mapping for MSIIR.  The Freescale ePAPR hypervisor has this requirement
+because of hardware limitations of the Peripheral Access Management Unit
+(PAMU), which is currently the only IOMMU that the hypervisor supports.
+The ATMU is programmed with the guest physical address, and the PAMU
+intercepts transactions and reroutes them to the true physical address.
+
+In the PAMU, each PCI controller is given only one primary window.  The
+PAMU restricts DMA operations so that they can only occur within a window.
+Because PCI devices must be able to DMA to memory, the primary window must
+be used to cover all of the guest's memory space.
+
+PAMU primary windows can be divided into 256 subwindows, and each
+subwindow can have its own address mapping ("guest physical" to "true
+physical").  However, each subwindow has to have the same alignment, which
+means they cannot be located at just any address.  Because of these
+restrictions, it is usually impossible to create a 4KB subwindow that
+covers MSIIR where it's normally located.
+
+Therefore, the hypervisor has to create a subwindow inside the same
+primary window used for memory, but mapped to the MSIR block (where MSIIR
+lives).  The first subwindow after the end of guest memory is used for
+this.  The address specified in the msi-address-64 property is the PCI
+address of MSIIR.  The hypervisor configures the PAMU to map that address to
+the true physical address of MSIIR.
index bd0fa77..d096df6 100644 (file)
@@ -1,3 +1,4 @@
+Note: This filesystem doesn't have a maintainer.
 
 Macintosh HFS Filesystem for Linux
 ==================================
@@ -76,8 +77,6 @@ hformat that can be used to create HFS filesystem. See
 Credits
 =======
 
-The HFS drivers was written by Paul H. Hargrovea (hargrove@sccm.Stanford.EDU)
-and is now maintained by Roman Zippel (roman@ardistech.com) at Ardis
-Technologies.
-Roman rewrote large parts of the code and brought in btree routines derived
-from Brad Boyer's hfsplus driver (also maintained by Roman now).
+The HFS drivers was written by Paul H. Hargrovea (hargrove@sccm.Stanford.EDU).
+Roman Zippel (roman@ardistech.com) rewrote large parts of the code and brought
+in btree routines derived from Brad Boyer's hfsplus driver.
index 59a919f..cfd0271 100644 (file)
@@ -194,7 +194,8 @@ associated with the inotify_handle, and on which events are queued.
 Each watch is associated with an inotify_watch structure.  Watches are chained
 off of each associated inotify_handle and each associated inode.
 
-See fs/inotify.c and fs/inotify_user.c for the locking and lifetime rules.
+See fs/notify/inotify/inotify_fsnotify.c and fs/notify/inotify/inotify_user.c
+for the locking and lifetime rules.
 
 
 (vi) Rationale
index 76ffef9..3f44dbd 100644 (file)
@@ -14,6 +14,10 @@ Supported chips:
     Prefix: 'w83627dhg'
     Addresses scanned: ISA address retrieved from Super I/O registers
     Datasheet: not available
+  * Winbond W83627UHG
+    Prefix: 'w83627uhg'
+    Addresses scanned: ISA address retrieved from Super I/O registers
+    Datasheet: available from www.nuvoton.com
   * Winbond W83667HG
     Prefix: 'w83667hg'
     Addresses scanned: ISA address retrieved from Super I/O registers
@@ -42,14 +46,13 @@ Description
 -----------
 
 This driver implements support for the Winbond W83627EHF, W83627EHG,
-W83627DHG, W83627DHG-P, W83667HG, W83667HG-B, W83667HG-I (NCT6775F),
-and NCT6776F super I/O chips. We will refer to them collectively as
-Winbond chips.
-
-The chips implement three temperature sensors (up to four for 667HG-B, and nine
-for NCT6775F and NCT6776F), five fan rotation speed sensors, ten analog voltage
-sensors (only nine for the 627DHG), one VID (6 pins for the 627EHF/EHG, 8 pins
-for the 627DHG and 667HG), alarms with beep warnings (control unimplemented),
+W83627DHG, W83627DHG-P, W83627UHG, W83667HG, W83667HG-B, W83667HG-I
+(NCT6775F), and NCT6776F super I/O chips. We will refer to them collectively
+as Winbond chips.
+
+The chips implement 2 to 4 temperature sensors (9 for NCT6775F and NCT6776F),
+2 to 5 fan rotation speed sensors, 8 to 10 analog voltage sensors, one VID
+(except for 627UHG), alarms with beep warnings (control unimplemented),
 and some automatic fan regulation strategies (plus manual fan control mode).
 
 The temperature sensor sources on W82677HG-B, NCT6775F, and NCT6776F are
@@ -86,17 +89,16 @@ follows:
 
 temp1 -> pwm1
 temp2 -> pwm2
-temp3 -> pwm3
+temp3 -> pwm3 (not on 627UHG)
 prog  -> pwm4 (not on 667HG and 667HG-B; the programmable setting is not
               supported by the driver)
 
 /sys files
 ----------
 
-name - this is a standard hwmon device entry. For the W83627EHF and W83627EHG,
-       it is set to "w83627ehf", for the W83627DHG it is set to "w83627dhg",
-       for the W83667HG and W83667HG-B it is set to "w83667hg", for NCT6775F it
-       is set to "nct6775", and for NCT6776F it is set to "nct6776".
+name - this is a standard hwmon device entry, it contains the name of
+       the device (see the prefix in the list of supported devices at
+       the top of this file)
 
 pwm[1-4] - this file stores PWM duty cycle or DC value (fan speed) in range:
           0 (stop) to 255 (full)
index 3ff0dad..9d66682 100644 (file)
@@ -411,9 +411,9 @@ event       code    Key             Notes
 
 0x1004 0x03    FN+F4           Sleep button (ACPI sleep button
                                semantics, i.e. sleep-to-RAM).
-                               It is always generate some kind
+                               It always generates some kind
                                of event, either the hot key
-                               event or a ACPI sleep button
+                               event or an ACPI sleep button
                                event. The firmware may
                                refuse to generate further FN+F4
                                key presses until a S3 or S4 ACPI
index 4996586..79699c2 100644 (file)
@@ -61,8 +61,8 @@ Hardware accelerated blink of LEDs
 Some LEDs can be programmed to blink without any CPU interaction. To
 support this feature, a LED driver can optionally implement the
 blink_set() function (see <linux/leds.h>). To set an LED to blinking,
-however, it is better to use use the API function led_blink_set(),
-as it will check and implement software fallback if necessary.
+however, it is better to use the API function led_blink_set(), as it
+will check and implement software fallback if necessary.
 
 To turn off blinking again, use the API function led_brightness_set()
 as that will not just set the LED brightness but also stop any software
index 38b5724..316c2ba 100644 (file)
@@ -22,12 +22,12 @@ try_to_freeze_tasks() that sets TIF_FREEZE for all of the freezable tasks and
 either wakes them up, if they are kernel threads, or sends fake signals to them,
 if they are user space processes.  A task that has TIF_FREEZE set, should react
 to it by calling the function called refrigerator() (defined in
-kernel/power/process.c), which sets the task's PF_FROZEN flag, changes its state
+kernel/freezer.c), which sets the task's PF_FROZEN flag, changes its state
 to TASK_UNINTERRUPTIBLE and makes it loop until PF_FROZEN is cleared for it.
 Then, we say that the task is 'frozen' and therefore the set of functions
 handling this mechanism is referred to as 'the freezer' (these functions are
-defined in kernel/power/process.c and include/linux/freezer.h).  User space
-processes are generally frozen before kernel threads.
+defined in kernel/power/process.c, kernel/freezer.c & include/linux/freezer.h).
+User space processes are generally frozen before kernel threads.
 
 It is not recommended to call refrigerator() directly.  Instead, it is
 recommended to use the try_to_freeze() function (defined in
@@ -95,7 +95,7 @@ after the memory for the image has been freed, we don't want tasks to allocate
 additional memory and we prevent them from doing that by freezing them earlier.
 [Of course, this also means that device drivers should not allocate substantial
 amounts of memory from their .suspend() callbacks before hibernation, but this
-is e separate issue.]
+is a separate issue.]
 
 3. The third reason is to prevent user space processes and some kernel threads
 from interfering with the suspending and resuming of devices.  A user space
index 0e85608..5336149 100644 (file)
@@ -789,6 +789,16 @@ will behave normally, not taking the autosuspend delay into account.
 Similarly, if the power.use_autosuspend field isn't set then the autosuspend
 helper functions will behave just like the non-autosuspend counterparts.
 
+Under some circumstances a driver or subsystem may want to prevent a device
+from autosuspending immediately, even though the usage counter is zero and the
+autosuspend delay time has expired.  If the ->runtime_suspend() callback
+returns -EAGAIN or -EBUSY, and if the next autosuspend delay expiration time is
+in the future (as it normally would be if the callback invoked
+pm_runtime_mark_last_busy()), the PM core will automatically reschedule the
+autosuspend.  The ->runtime_suspend() callback can't do this rescheduling
+itself because no suspend requests of any kind are accepted while the device is
+suspending (i.e., while the callback is running).
+
 The implementation is well suited for asynchronous use in interrupt contexts.
 However such use inevitably involves races, because the PM core can't
 synchronize ->runtime_suspend() callbacks with the arrival of I/O requests.
index 60a6f65..39ddcdb 100644 (file)
@@ -20,8 +20,6 @@ Version: 1.2.14
 Date: 11/01/2001
 Historical Author: Andrew Manison <amanison@america.net>
 Primary Author: Doug McNash
-Support: support@computone.com
-Fixes and Updates: Mike Warfield <mhw@wittsend.com>
 
 This file assumes that you are using the Computone drivers which are
 integrated into the kernel sources.  For updating the drivers or installing
diff --git a/Documentation/watchdog/convert_drivers_to_kernel_api.txt b/Documentation/watchdog/convert_drivers_to_kernel_api.txt
new file mode 100644 (file)
index 0000000..ae1e900
--- /dev/null
@@ -0,0 +1,195 @@
+Converting old watchdog drivers to the watchdog framework
+by Wolfram Sang <w.sang@pengutronix.de>
+=========================================================
+
+Before the watchdog framework came into the kernel, every driver had to
+implement the API on its own. Now, as the framework factored out the common
+components, those drivers can be lightened making it a user of the framework.
+This document shall guide you for this task. The necessary steps are described
+as well as things to look out for.
+
+
+Remove the file_operations struct
+---------------------------------
+
+Old drivers define their own file_operations for actions like open(), write(),
+etc... These are now handled by the framework and just call the driver when
+needed. So, in general, the 'file_operations' struct and assorted functions can
+go. Only very few driver-specific details have to be moved to other functions.
+Here is a overview of the functions and probably needed actions:
+
+- open: Everything dealing with resource management (file-open checks, magic
+  close preparations) can simply go. Device specific stuff needs to go to the
+  driver specific start-function. Note that for some drivers, the start-function
+  also serves as the ping-function. If that is the case and you need start/stop
+  to be balanced (clocks!), you are better off refactoring a separate start-function.
+
+- close: Same hints as for open apply.
+
+- write: Can simply go, all defined behaviour is taken care of by the framework,
+  i.e. ping on write and magic char ('V') handling.
+
+- ioctl: While the driver is allowed to have extensions to the IOCTL interface,
+  the most common ones are handled by the framework, supported by some assistance
+  from the driver:
+
+       WDIOC_GETSUPPORT:
+               Returns the mandatory watchdog_info struct from the driver
+
+       WDIOC_GETSTATUS:
+               Needs the status-callback defined, otherwise returns 0
+
+       WDIOC_GETBOOTSTATUS:
+               Needs the bootstatus member properly set. Make sure it is 0 if you
+               don't have further support!
+
+       WDIOC_SETOPTIONS:
+               No preparations needed
+
+       WDIOC_KEEPALIVE:
+               If wanted, options in watchdog_info need to have WDIOF_KEEPALIVEPING
+               set
+
+       WDIOC_SETTIMEOUT:
+               Options in watchdog_info need to have WDIOF_SETTIMEOUT set
+               and a set_timeout-callback has to be defined. The core will also
+               do limit-checking, if min_timeout and max_timeout in the watchdog
+               device are set. All is optional.
+
+       WDIOC_GETTIMEOUT:
+               No preparations needed
+
+  Other IOCTLs can be served using the ioctl-callback. Note that this is mainly
+  intended for porting old drivers; new drivers should not invent private IOCTLs.
+  Private IOCTLs are processed first. When the callback returns with
+  -ENOIOCTLCMD, the IOCTLs of the framework will be tried, too. Any other error
+  is directly given to the user.
+
+Example conversion:
+
+-static const struct file_operations s3c2410wdt_fops = {
+-       .owner          = THIS_MODULE,
+-       .llseek         = no_llseek,
+-       .write          = s3c2410wdt_write,
+-       .unlocked_ioctl = s3c2410wdt_ioctl,
+-       .open           = s3c2410wdt_open,
+-       .release        = s3c2410wdt_release,
+-};
+
+Check the functions for device-specific stuff and keep it for later
+refactoring. The rest can go.
+
+
+Remove the miscdevice
+---------------------
+
+Since the file_operations are gone now, you can also remove the 'struct
+miscdevice'. The framework will create it on watchdog_dev_register() called by
+watchdog_register_device().
+
+-static struct miscdevice s3c2410wdt_miscdev = {
+-       .minor          = WATCHDOG_MINOR,
+-       .name           = "watchdog",
+-       .fops           = &s3c2410wdt_fops,
+-};
+
+
+Remove obsolete includes and defines
+------------------------------------
+
+Because of the simplifications, a few defines are probably unused now. Remove
+them. Includes can be removed, too. For example:
+
+- #include <linux/fs.h>
+- #include <linux/miscdevice.h> (if MODULE_ALIAS_MISCDEV is not used)
+- #include <linux/uaccess.h> (if no custom IOCTLs are used)
+
+
+Add the watchdog operations
+---------------------------
+
+All possible callbacks are defined in 'struct watchdog_ops'. You can find it
+explained in 'watchdog-kernel-api.txt' in this directory. start(), stop() and
+owner must be set, the rest are optional. You will easily find corresponding
+functions in the old driver. Note that you will now get a pointer to the
+watchdog_device as a parameter to these functions, so you probably have to
+change the function header. Other changes are most likely not needed, because
+here simply happens the direct hardware access. If you have device-specific
+code left from the above steps, it should be refactored into these callbacks.
+
+Here is a simple example:
+
++static struct watchdog_ops s3c2410wdt_ops = {
++       .owner = THIS_MODULE,
++       .start = s3c2410wdt_start,
++       .stop = s3c2410wdt_stop,
++       .ping = s3c2410wdt_keepalive,
++       .set_timeout = s3c2410wdt_set_heartbeat,
++};
+
+A typical function-header change looks like:
+
+-static void s3c2410wdt_keepalive(void)
++static int s3c2410wdt_keepalive(struct watchdog_device *wdd)
+ {
+...
++
++       return 0;
+ }
+
+...
+
+-       s3c2410wdt_keepalive();
++       s3c2410wdt_keepalive(&s3c2410_wdd);
+
+
+Add the watchdog device
+-----------------------
+
+Now we need to create a 'struct watchdog_device' and populate it with the
+necessary information for the framework. The struct is also explained in detail
+in 'watchdog-kernel-api.txt' in this directory. We pass it the mandatory
+watchdog_info struct and the newly created watchdog_ops. Often, old drivers
+have their own record-keeping for things like bootstatus and timeout using
+static variables. Those have to be converted to use the members in
+watchdog_device. Note that the timeout values are unsigned int. Some drivers
+use signed int, so this has to be converted, too.
+
+Here is a simple example for a watchdog device:
+
++static struct watchdog_device s3c2410_wdd = {
++       .info = &s3c2410_wdt_ident,
++       .ops = &s3c2410wdt_ops,
++};
+
+
+Register the watchdog device
+----------------------------
+
+Replace misc_register(&miscdev) with watchdog_register_device(&watchdog_dev).
+Make sure the return value gets checked and the error message, if present,
+still fits. Also convert the unregister case.
+
+-       ret = misc_register(&s3c2410wdt_miscdev);
++       ret = watchdog_register_device(&s3c2410_wdd);
+
+...
+
+-       misc_deregister(&s3c2410wdt_miscdev);
++       watchdog_unregister_device(&s3c2410_wdd);
+
+
+Update the Kconfig-entry
+------------------------
+
+The entry for the driver now needs to select WATCHDOG_CORE:
+
++       select WATCHDOG_CORE
+
+
+Create a patch and send it to upstream
+--------------------------------------
+
+Make sure you understood Documentation/SubmittingPatches and send your patch to
+linux-watchdog@vger.kernel.org. We are looking forward to it :)
+
index a6afe34..6388a96 100644 (file)
@@ -2387,7 +2387,7 @@ F:        include/linux/netfilter_bridge/ebt_*.h
 F:     net/bridge/netfilter/ebt*.c
 
 ECRYPT FILE SYSTEM
-M:     Tyler Hicks <tyhicks@linux.vnet.ibm.com>
+M:     Tyler Hicks <tyhicks@canonical.com>
 M:     Dustin Kirkland <kirkland@canonical.com>
 L:     ecryptfs@vger.kernel.org
 W:     https://launchpad.net/ecryptfs
index fe6b052..44789ef 100644 (file)
@@ -595,6 +595,7 @@ config ARCH_MMP
        select TICK_ONESHOT
        select PLAT_PXA
        select SPARSE_IRQ
+       select GENERIC_ALLOCATOR
        help
          Support for Marvell's PXA168/PXA910(MMP) and MMP2 processor line.
 
@@ -769,6 +770,7 @@ config ARCH_S3C64XX
        select CPU_V6
        select ARM_VIC
        select HAVE_CLK
+       select HAVE_TCM
        select CLKDEV_LOOKUP
        select NO_IOPORT
        select ARCH_USES_GETTIMEOFFSET
@@ -777,9 +779,6 @@ config ARCH_S3C64XX
        select SAMSUNG_CLKSRC
        select SAMSUNG_IRQ_VIC_TIMER
        select S3C_GPIO_TRACK
-       select S3C_GPIO_PULL_UPDOWN
-       select S3C_GPIO_CFG_S3C24XX
-       select S3C_GPIO_CFG_S3C64XX
        select S3C_DEV_NAND
        select USB_ARCH_HAS_OHCI
        select SAMSUNG_GPIOLIB_4BIT
@@ -838,8 +837,8 @@ config ARCH_S5PV210
        help
          Samsung S5PV210/S5PC110 series based systems
 
-config ARCH_EXYNOS4
-       bool "Samsung EXYNOS4"
+config ARCH_EXYNOS
+       bool "SAMSUNG EXYNOS"
        select CPU_V7
        select ARCH_SPARSEMEM_ENABLE
        select ARCH_HAS_HOLES_MEMORYMODEL
@@ -853,7 +852,7 @@ config ARCH_EXYNOS4
        select HAVE_S3C2410_WATCHDOG if WATCHDOG
        select NEED_MACH_MEMORY_H
        help
-         Samsung EXYNOS4 series based systems
+         Support for SAMSUNG's EXYNOS SoCs (EXYNOS4/5)
 
 config ARCH_SHARK
        bool "Shark"
@@ -1080,7 +1079,7 @@ source "arch/arm/mach-s5pc100/Kconfig"
 
 source "arch/arm/mach-s5pv210/Kconfig"
 
-source "arch/arm/mach-exynos4/Kconfig"
+source "arch/arm/mach-exynos/Kconfig"
 
 source "arch/arm/mach-shmobile/Kconfig"
 
@@ -2212,7 +2211,7 @@ menu "Power management options"
 source "kernel/power/Kconfig"
 
 config ARCH_SUSPEND_POSSIBLE
-       depends on !ARCH_S5P64X0 && !ARCH_S5PC100
+       depends on !ARCH_S5PC100
        depends on CPU_ARM920T || CPU_ARM926T || CPU_SA1100 || \
                CPU_V6 || CPU_V6K || CPU_V7 || CPU_XSC3 || CPU_XSCALE
        def_bool y
index b7c2d37..dfcf3b0 100644 (file)
@@ -180,7 +180,7 @@ machine-$(CONFIG_ARCH_S3C64XX)              := s3c64xx
 machine-$(CONFIG_ARCH_S5P64X0)         := s5p64x0
 machine-$(CONFIG_ARCH_S5PC100)         := s5pc100
 machine-$(CONFIG_ARCH_S5PV210)         := s5pv210
-machine-$(CONFIG_ARCH_EXYNOS4)         := exynos4
+machine-$(CONFIG_ARCH_EXYNOS4)         := exynos
 machine-$(CONFIG_ARCH_SA1100)          := sa1100
 machine-$(CONFIG_ARCH_SHARK)           := shark
 machine-$(CONFIG_ARCH_SHMOBILE)        := shmobile
index cd40bb5..bffe68e 100644 (file)
@@ -4,19 +4,18 @@ CONFIG_KALLSYMS_ALL=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_EXYNOS4=y
+CONFIG_ARCH_EXYNOS=y
 CONFIG_S3C_LOWLEVEL_UART_PORT=1
 CONFIG_MACH_SMDKC210=y
-CONFIG_MACH_SMDKV310=y
 CONFIG_MACH_ARMLEX4210=y
 CONFIG_MACH_UNIVERSAL_C210=y
 CONFIG_MACH_NURI=y
 CONFIG_MACH_ORIGEN=y
+CONFIG_MACH_SMDK4412=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 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC1,115200 init=/linuxrc mem=256M"
@@ -61,13 +60,9 @@ CONFIG_DETECT_HUNG_TASK=y
 CONFIG_DEBUG_RT_MUTEXES=y
 CONFIG_DEBUG_SPINLOCK=y
 CONFIG_DEBUG_MUTEXES=y
-CONFIG_DEBUG_SPINLOCK_SLEEP=y
 CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 CONFIG_SYSCTL_SYSCALL_CHECK=y
 CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_ERRORS=y
 CONFIG_DEBUG_LL=y
 CONFIG_EARLY_PRINTK=y
-CONFIG_DEBUG_S3C_UART=1
 CONFIG_CRC_CCITT=y
index e4a04e4..33c78d7 100644 (file)
@@ -21,6 +21,9 @@
  * OneNAND features.
 */
 
+#ifndef ASM_PL080_H
+#define ASM_PL080_H
+
 #define PL080_INT_STATUS                       (0x00)
 #define PL080_TC_STATUS                                (0x04)
 #define PL080_TC_CLEAR                         (0x08)
@@ -138,3 +141,4 @@ struct pl080s_lli {
        u32     control1;
 };
 
+#endif /* ASM_PL080_H */
index fbaae47..960e9de 100644 (file)
@@ -15,6 +15,8 @@
 
 #include <asm-generic/gpio.h>
 
+#define __ARM_GPIOLIB_COMPLEX
+
 /* The inline versions use the static inlines in the driver header */
 #include "gpio-davinci.h"
 
similarity index 75%
rename from arch/arm/mach-exynos4/Kconfig
rename to arch/arm/mach-exynos/Kconfig
index a652735..724ec0f 100644 (file)
@@ -1,4 +1,4 @@
-# arch/arm/mach-exynos4/Kconfig
+# arch/arm/mach-exynos/Kconfig
 #
 # Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
 #              http://www.samsung.com/
@@ -7,22 +7,47 @@
 
 # Configuration options for the EXYNOS4
 
-if ARCH_EXYNOS4
+if ARCH_EXYNOS
+
+menu "SAMSUNG EXYNOS SoCs Support"
+
+choice
+       prompt "EXYNOS System Type"
+       default ARCH_EXYNOS4
+
+config ARCH_EXYNOS4
+       bool "SAMSUNG EXYNOS4"
+       help
+         Samsung EXYNOS4 SoCs based systems
+
+endchoice
+
+comment "EXYNOS SoCs"
 
 config CPU_EXYNOS4210
-       bool
-       select S3C_PL330_DMA
+       bool "SAMSUNG EXYNOS4210"
+       default y
+       depends on ARCH_EXYNOS4
+       select SAMSUNG_DMADEV
        select ARM_CPU_SUSPEND if PM
+       select S5P_PM if PM
+       select S5P_SLEEP if PM
        help
          Enable EXYNOS4210 CPU support
 
 config SOC_EXYNOS4212
-       bool
+       bool "SAMSUNG EXYNOS4212"
+       default y
+       depends on ARCH_EXYNOS4
+       select S5P_PM if PM
+       select S5P_SLEEP if PM
        help
          Enable EXYNOS4212 SoC support
 
 config SOC_EXYNOS4412
-       bool
+       bool "SAMSUNG EXYNOS4412"
+       default y
+       depends on ARCH_EXYNOS4
        help
          Enable EXYNOS4412 SoC support
 
@@ -120,7 +145,7 @@ config EXYNOS4_SETUP_USB_PHY
 
 # machine support
 
-menu "EXYNOS4 Machines"
+if ARCH_EXYNOS4
 
 comment "EXYNOS4210 Boards"
 
@@ -137,6 +162,14 @@ config MACH_SMDKV310
        select S3C_DEV_RTC
        select S3C_DEV_WDT
        select S3C_DEV_I2C1
+       select S5P_DEV_FIMC0
+       select S5P_DEV_FIMC1
+       select S5P_DEV_FIMC2
+       select S5P_DEV_FIMC3
+       select S5P_DEV_I2C_HDMIPHY
+       select S5P_DEV_MFC
+       select S5P_DEV_TV
+       select S5P_DEV_USB_EHCI
        select S3C_DEV_HSMMC
        select S3C_DEV_HSMMC1
        select S3C_DEV_HSMMC2
@@ -151,6 +184,7 @@ config MACH_SMDKV310
        select EXYNOS4_SETUP_I2C1
        select EXYNOS4_SETUP_KEYPAD
        select EXYNOS4_SETUP_SDHCI
+       select EXYNOS4_SETUP_USB_PHY
        help
          Machine support for Samsung SMDKV310
 
@@ -176,19 +210,26 @@ config MACH_UNIVERSAL_C210
        select S5P_DEV_FIMC1
        select S5P_DEV_FIMC2
        select S5P_DEV_FIMC3
+       select S5P_DEV_CSIS0
+       select S5P_DEV_FIMD0
        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_I2C_HDMIPHY
        select S5P_DEV_MFC
        select S5P_DEV_ONENAND
+       select S5P_DEV_TV
        select EXYNOS4_DEV_PD
+       select EXYNOS4_SETUP_FIMD0
        select EXYNOS4_SETUP_I2C1
        select EXYNOS4_SETUP_I2C3
        select EXYNOS4_SETUP_I2C5
        select EXYNOS4_SETUP_SDHCI
+       select EXYNOS4_SETUP_FIMC
+       select S5P_SETUP_MIPIPHY
        help
          Machine support for Samsung Mobile Universal S5PC210 Reference
          Board.
@@ -196,21 +237,33 @@ config MACH_UNIVERSAL_C210
 config MACH_NURI
        bool "Mobile NURI Board"
        select CPU_EXYNOS4210
+       select S5P_GPIO_INT
        select S3C_DEV_WDT
+       select S3C_DEV_RTC
+       select S5P_DEV_FIMD0
        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_CSIS0
+       select S5P_DEV_FIMC0
+       select S5P_DEV_FIMC1
+       select S5P_DEV_FIMC2
+       select S5P_DEV_FIMC3
        select S5P_DEV_MFC
        select S5P_DEV_USB_EHCI
+       select S5P_SETUP_MIPIPHY
        select EXYNOS4_DEV_PD
+       select EXYNOS4_SETUP_FIMC
+       select EXYNOS4_SETUP_FIMD0
        select EXYNOS4_SETUP_I2C1
        select EXYNOS4_SETUP_I2C3
        select EXYNOS4_SETUP_I2C5
        select EXYNOS4_SETUP_SDHCI
        select EXYNOS4_SETUP_USB_PHY
+       select S5P_SETUP_MIPIPHY
        select SAMSUNG_DEV_PWM
        select SAMSUNG_DEV_ADC
        help
@@ -221,8 +274,23 @@ config MACH_ORIGEN
        select CPU_EXYNOS4210
        select S3C_DEV_RTC
        select S3C_DEV_WDT
+       select S3C_DEV_HSMMC
        select S3C_DEV_HSMMC2
+       select S5P_DEV_FIMC0
+       select S5P_DEV_FIMC1
+       select S5P_DEV_FIMC2
+       select S5P_DEV_FIMC3
+       select S5P_DEV_FIMD0
+       select S5P_DEV_I2C_HDMIPHY
+       select S5P_DEV_MFC
+       select S5P_DEV_TV
+       select S5P_DEV_USB_EHCI
+       select SAMSUNG_DEV_BACKLIGHT
+       select SAMSUNG_DEV_PWM
+       select EXYNOS4_DEV_PD
+       select EXYNOS4_SETUP_FIMD0
        select EXYNOS4_SETUP_SDHCI
+       select EXYNOS4_SETUP_USB_PHY
        help
          Machine support for ORIGEN based on Samsung EXYNOS4210
 
@@ -257,12 +325,11 @@ config MACH_SMDK4412
        select MACH_SMDK4212
        help
          Machine support for Samsung SMDK4412
+endif
 
-endmenu
-
-comment "Configuration for HSMMC bus width"
+if ARCH_EXYNOS4
 
-menu "Use 8-bit bus width"
+comment "Configuration for HSMMC 8-bit bus width"
 
 config EXYNOS4_SDHCI_CH0_8BIT
        bool "Channel 0 with 8-bit bus"
@@ -275,6 +342,7 @@ config EXYNOS4_SDHCI_CH2_8BIT
        help
          Support HSMMC Channel 2 8-bit bus.
          If selected, Channel 3 is disabled.
+endif
 
 endmenu
 
similarity index 88%
rename from arch/arm/mach-exynos4/Makefile
rename to arch/arm/mach-exynos/Makefile
index c9b2e1f..59069a3 100644 (file)
@@ -1,4 +1,4 @@
-# arch/arm/mach-exynos4/Makefile
+# arch/arm/mach-exynos/Makefile
 #
 # Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
 #              http://www.samsung.com/
@@ -12,11 +12,11 @@ obj-                                :=
 
 # Core support for EXYNOS4 system
 
-obj-$(CONFIG_ARCH_EXYNOS4)     += cpu.o init.o clock.o irq-combiner.o
-obj-$(CONFIG_ARCH_EXYNOS4)     += setup-i2c0.o irq-eint.o dma.o pmu.o
+obj-$(CONFIG_ARCH_EXYNOS4)     += cpu.o init.o clock.o irq-combiner.o setup-i2c0.o
+obj-$(CONFIG_ARCH_EXYNOS4)     += irq-eint.o dma.o pmu.o
 obj-$(CONFIG_CPU_EXYNOS4210)   += clock-exynos4210.o
 obj-$(CONFIG_SOC_EXYNOS4212)   += clock-exynos4212.o
-obj-$(CONFIG_PM)               += pm.o sleep.o
+obj-$(CONFIG_PM)               += pm.o
 obj-$(CONFIG_CPU_IDLE)         += cpuidle.o
 
 obj-$(CONFIG_SMP)              += platsmp.o headsmp.o
@@ -39,11 +39,11 @@ obj-$(CONFIG_MACH_SMDK4412)         += mach-smdk4x12.o
 
 # device support
 
-obj-y                                  += dev-audio.o
+obj-$(CONFIG_ARCH_EXYNOS4)             += 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_DEV_DWMCI)                += dev-dwmci.o
 
 obj-$(CONFIG_EXYNOS4_SETUP_FIMC)       += setup-fimc.o
 obj-$(CONFIG_EXYNOS4_SETUP_FIMD0)      += setup-fimd0.o
@@ -57,5 +57,4 @@ obj-$(CONFIG_EXYNOS4_SETUP_I2C7)      += setup-i2c7.o
 obj-$(CONFIG_EXYNOS4_SETUP_KEYPAD)     += setup-keypad.o
 obj-$(CONFIG_EXYNOS4_SETUP_SDHCI)      += setup-sdhci.o
 obj-$(CONFIG_EXYNOS4_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o
-
 obj-$(CONFIG_EXYNOS4_SETUP_USB_PHY)    += setup-usb-phy.o
similarity index 86%
rename from arch/arm/mach-exynos4/clock.c
rename to arch/arm/mach-exynos/clock.c
index 0d59be3..2894f0a 100644 (file)
@@ -111,6 +111,11 @@ struct clk clk_sclk_usbphy1 = {
        .name           = "sclk_usbphy1",
 };
 
+static struct clk dummy_apb_pclk = {
+       .name           = "apb_pclk",
+       .id             = -1,
+};
+
 static int exynos4_clksrc_mask_top_ctrl(struct clk *clk, int enable)
 {
        return s5p_gatectrl(S5P_CLKSRC_MASK_TOP, clk, enable);
@@ -146,6 +151,11 @@ static int exynos4_clk_ip_mfc_ctrl(struct clk *clk, int enable)
        return s5p_gatectrl(S5P_CLKGATE_IP_MFC, clk, enable);
 }
 
+static int exynos4_clksrc_mask_tv_ctrl(struct clk *clk, int enable)
+{
+       return s5p_gatectrl(S5P_CLKSRC_MASK_TV, clk, enable);
+}
+
 static int exynos4_clk_ip_cam_ctrl(struct clk *clk, int enable)
 {
        return s5p_gatectrl(S5P_CLKGATE_IP_CAM, clk, enable);
@@ -186,6 +196,16 @@ static int exynos4_clk_ip_perir_ctrl(struct clk *clk, int enable)
        return s5p_gatectrl(S5P_CLKGATE_IP_PERIR, clk, enable);
 }
 
+static int exynos4_clk_hdmiphy_ctrl(struct clk *clk, int enable)
+{
+       return s5p_gatectrl(S5P_HDMI_PHY_CONTROL, clk, enable);
+}
+
+static int exynos4_clk_dac_ctrl(struct clk *clk, int enable)
+{
+       return s5p_gatectrl(S5P_DAC_PHY_CONTROL, clk, enable);
+}
+
 /* Core list of CMU_CPU side */
 
 static struct clksrc_clk clk_mout_apll = {
@@ -503,13 +523,43 @@ static struct clk init_clocks_off[] = {
                .enable         = exynos4_clk_ip_fsys_ctrl,
                .ctrlbit        = (1 << 9),
        }, {
-               .name           = "pdma",
-               .devname        = "s3c-pl330.0",
+               .name           = "dac",
+               .devname        = "s5p-sdo",
+               .enable         = exynos4_clk_ip_tv_ctrl,
+               .ctrlbit        = (1 << 2),
+       }, {
+               .name           = "mixer",
+               .devname        = "s5p-mixer",
+               .enable         = exynos4_clk_ip_tv_ctrl,
+               .ctrlbit        = (1 << 1),
+       }, {
+               .name           = "vp",
+               .devname        = "s5p-mixer",
+               .enable         = exynos4_clk_ip_tv_ctrl,
+               .ctrlbit        = (1 << 0),
+       }, {
+               .name           = "hdmi",
+               .devname        = "exynos4-hdmi",
+               .enable         = exynos4_clk_ip_tv_ctrl,
+               .ctrlbit        = (1 << 3),
+       }, {
+               .name           = "hdmiphy",
+               .devname        = "exynos4-hdmi",
+               .enable         = exynos4_clk_hdmiphy_ctrl,
+               .ctrlbit        = (1 << 0),
+       }, {
+               .name           = "dacphy",
+               .devname        = "s5p-sdo",
+               .enable         = exynos4_clk_dac_ctrl,
+               .ctrlbit        = (1 << 0),
+       }, {
+               .name           = "dma",
+               .devname        = "dma-pl330.0",
                .enable         = exynos4_clk_ip_fsys_ctrl,
                .ctrlbit        = (1 << 0),
        }, {
-               .name           = "pdma",
-               .devname        = "s3c-pl330.1",
+               .name           = "dma",
+               .devname        = "dma-pl330.1",
                .enable         = exynos4_clk_ip_fsys_ctrl,
                .ctrlbit        = (1 << 1),
        }, {
@@ -630,6 +680,12 @@ static struct clk init_clocks_off[] = {
                .enable         = exynos4_clk_ip_peril_ctrl,
                .ctrlbit        = (1 << 13),
        }, {
+               .name           = "i2c",
+               .devname        = "s3c2440-hdmiphy-i2c",
+               .parent         = &clk_aclk_100.clk,
+               .enable         = exynos4_clk_ip_peril_ctrl,
+               .ctrlbit        = (1 << 14),
+       }, {
                .name           = "SYSMMU_MDMA",
                .enable         = exynos4_clk_ip_image_ctrl,
                .ctrlbit        = (1 << 5),
@@ -831,6 +887,81 @@ static struct clksrc_sources clkset_mout_mfc = {
        .nr_sources     = ARRAY_SIZE(clkset_mout_mfc_list),
 };
 
+static struct clk *clkset_sclk_dac_list[] = {
+       [0] = &clk_sclk_vpll.clk,
+       [1] = &clk_sclk_hdmiphy,
+};
+
+static struct clksrc_sources clkset_sclk_dac = {
+       .sources        = clkset_sclk_dac_list,
+       .nr_sources     = ARRAY_SIZE(clkset_sclk_dac_list),
+};
+
+static struct clksrc_clk clk_sclk_dac = {
+       .clk            = {
+               .name           = "sclk_dac",
+               .enable         = exynos4_clksrc_mask_tv_ctrl,
+               .ctrlbit        = (1 << 8),
+       },
+       .sources = &clkset_sclk_dac,
+       .reg_src = { .reg = S5P_CLKSRC_TV, .shift = 8, .size = 1 },
+};
+
+static struct clksrc_clk clk_sclk_pixel = {
+       .clk            = {
+               .name           = "sclk_pixel",
+               .parent = &clk_sclk_vpll.clk,
+       },
+       .reg_div = { .reg = S5P_CLKDIV_TV, .shift = 0, .size = 4 },
+};
+
+static struct clk *clkset_sclk_hdmi_list[] = {
+       [0] = &clk_sclk_pixel.clk,
+       [1] = &clk_sclk_hdmiphy,
+};
+
+static struct clksrc_sources clkset_sclk_hdmi = {
+       .sources        = clkset_sclk_hdmi_list,
+       .nr_sources     = ARRAY_SIZE(clkset_sclk_hdmi_list),
+};
+
+static struct clksrc_clk clk_sclk_hdmi = {
+       .clk            = {
+               .name           = "sclk_hdmi",
+               .enable         = exynos4_clksrc_mask_tv_ctrl,
+               .ctrlbit        = (1 << 0),
+       },
+       .sources = &clkset_sclk_hdmi,
+       .reg_src = { .reg = S5P_CLKSRC_TV, .shift = 0, .size = 1 },
+};
+
+static struct clk *clkset_sclk_mixer_list[] = {
+       [0] = &clk_sclk_dac.clk,
+       [1] = &clk_sclk_hdmi.clk,
+};
+
+static struct clksrc_sources clkset_sclk_mixer = {
+       .sources        = clkset_sclk_mixer_list,
+       .nr_sources     = ARRAY_SIZE(clkset_sclk_mixer_list),
+};
+
+static struct clksrc_clk clk_sclk_mixer = {
+       .clk            = {
+               .name           = "sclk_mixer",
+               .enable         = exynos4_clksrc_mask_tv_ctrl,
+               .ctrlbit        = (1 << 4),
+       },
+       .sources = &clkset_sclk_mixer,
+       .reg_src = { .reg = S5P_CLKSRC_TV, .shift = 4, .size = 1 },
+};
+
+static struct clksrc_clk *sclk_tv[] = {
+       &clk_sclk_dac,
+       &clk_sclk_pixel,
+       &clk_sclk_hdmi,
+       &clk_sclk_mixer,
+};
+
 static struct clksrc_clk clk_dout_mmc0 = {
        .clk            = {
                .name           = "dout_mmc0",
@@ -1157,6 +1288,71 @@ static struct clk_ops exynos4_fout_apll_ops = {
        .get_rate = exynos4_fout_apll_get_rate,
 };
 
+static u32 vpll_div[][8] = {
+       {  54000000, 3, 53, 3, 1024, 0, 17, 0 },
+       { 108000000, 3, 53, 2, 1024, 0, 17, 0 },
+};
+
+static unsigned long exynos4_vpll_get_rate(struct clk *clk)
+{
+       return clk->rate;
+}
+
+static int exynos4_vpll_set_rate(struct clk *clk, unsigned long rate)
+{
+       unsigned int vpll_con0, vpll_con1 = 0;
+       unsigned int i;
+
+       /* Return if nothing changed */
+       if (clk->rate == rate)
+               return 0;
+
+       vpll_con0 = __raw_readl(S5P_VPLL_CON0);
+       vpll_con0 &= ~(0x1 << 27 |                                      \
+                       PLL90XX_MDIV_MASK << PLL46XX_MDIV_SHIFT |       \
+                       PLL90XX_PDIV_MASK << PLL46XX_PDIV_SHIFT |       \
+                       PLL90XX_SDIV_MASK << PLL46XX_SDIV_SHIFT);
+
+       vpll_con1 = __raw_readl(S5P_VPLL_CON1);
+       vpll_con1 &= ~(PLL46XX_MRR_MASK << PLL46XX_MRR_SHIFT |  \
+                       PLL46XX_MFR_MASK << PLL46XX_MFR_SHIFT | \
+                       PLL4650C_KDIV_MASK << PLL46XX_KDIV_SHIFT);
+
+       for (i = 0; i < ARRAY_SIZE(vpll_div); i++) {
+               if (vpll_div[i][0] == rate) {
+                       vpll_con0 |= vpll_div[i][1] << PLL46XX_PDIV_SHIFT;
+                       vpll_con0 |= vpll_div[i][2] << PLL46XX_MDIV_SHIFT;
+                       vpll_con0 |= vpll_div[i][3] << PLL46XX_SDIV_SHIFT;
+                       vpll_con1 |= vpll_div[i][4] << PLL46XX_KDIV_SHIFT;
+                       vpll_con1 |= vpll_div[i][5] << PLL46XX_MFR_SHIFT;
+                       vpll_con1 |= vpll_div[i][6] << PLL46XX_MRR_SHIFT;
+                       vpll_con0 |= vpll_div[i][7] << 27;
+                       break;
+               }
+       }
+
+       if (i == ARRAY_SIZE(vpll_div)) {
+               printk(KERN_ERR "%s: Invalid Clock VPLL Frequency\n",
+                               __func__);
+               return -EINVAL;
+       }
+
+       __raw_writel(vpll_con0, S5P_VPLL_CON0);
+       __raw_writel(vpll_con1, S5P_VPLL_CON1);
+
+       /* Wait for VPLL lock */
+       while (!(__raw_readl(S5P_VPLL_CON0) & (1 << PLL46XX_LOCKED_SHIFT)))
+               continue;
+
+       clk->rate = rate;
+       return 0;
+}
+
+static struct clk_ops exynos4_vpll_ops = {
+       .get_rate = exynos4_vpll_get_rate,
+       .set_rate = exynos4_vpll_set_rate,
+};
+
 void __init_or_cpufreq exynos4_setup_clocks(void)
 {
        struct clk *xtal_clk;
@@ -1214,6 +1410,7 @@ void __init_or_cpufreq exynos4_setup_clocks(void)
        clk_fout_apll.ops = &exynos4_fout_apll_ops;
        clk_fout_mpll.rate = mpll;
        clk_fout_epll.rate = epll;
+       clk_fout_vpll.ops = &exynos4_vpll_ops;
        clk_fout_vpll.rate = vpll;
 
        printk(KERN_INFO "EXYNOS4: PLL settings, A=%ld, M=%ld, E=%ld V=%ld",
@@ -1241,7 +1438,10 @@ void __init_or_cpufreq exynos4_setup_clocks(void)
 }
 
 static struct clk *clks[] __initdata = {
-       /* Nothing here yet */
+       &clk_sclk_hdmi27m,
+       &clk_sclk_hdmiphy,
+       &clk_sclk_usbphy0,
+       &clk_sclk_usbphy1,
 };
 
 #ifdef CONFIG_PM_SLEEP
@@ -1275,6 +1475,9 @@ void __init exynos4_register_clocks(void)
        for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
                s3c_register_clksrc(sysclks[ptr], 1);
 
+       for (ptr = 0; ptr < ARRAY_SIZE(sclk_tv); ptr++)
+               s3c_register_clksrc(sclk_tv[ptr], 1);
+
        s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
        s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
 
@@ -1282,5 +1485,7 @@ void __init exynos4_register_clocks(void)
        s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 
        register_syscore_ops(&exynos4_clock_syscore_ops);
+       s3c24xx_register_clock(&dummy_apb_pclk);
+
        s3c_pwmclk_init();
 }
similarity index 90%
rename from arch/arm/mach-exynos4/cpu.c
rename to arch/arm/mach-exynos/cpu.c
index a348434..90ec247 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-exynos4/cpu.c
+/* linux/arch/arm/mach-exynos/cpu.c
  *
  * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com
@@ -28,6 +28,7 @@
 #include <plat/fimc-core.h>
 #include <plat/iic-core.h>
 #include <plat/reset.h>
+#include <plat/tv-core.h>
 
 #include <mach/regs-irq.h>
 #include <mach/regs-pmu.h>
@@ -39,28 +40,47 @@ extern int combiner_init(unsigned int combiner_nr, void __iomem *base,
 extern void combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq);
 
 /* Initial IO mappings */
-static struct map_desc exynos4_iodesc[] __initdata = {
+static struct map_desc exynos_iodesc[] __initdata = {
        {
                .virtual        = (unsigned long)S5P_VA_SYSTIMER,
-               .pfn            = __phys_to_pfn(EXYNOS4_PA_SYSTIMER),
+               .pfn            = __phys_to_pfn(EXYNOS_PA_SYSTIMER),
                .length         = SZ_4K,
-               .type           = MT_DEVICE,
-       }, {
-               .virtual        = (unsigned long)S5P_VA_CMU,
-               .pfn            = __phys_to_pfn(EXYNOS4_PA_CMU),
-               .length         = SZ_128K,
                .type           = MT_DEVICE,
        }, {
                .virtual        = (unsigned long)S5P_VA_PMU,
-               .pfn            = __phys_to_pfn(EXYNOS4_PA_PMU),
+               .pfn            = __phys_to_pfn(EXYNOS_PA_PMU),
                .length         = SZ_64K,
                .type           = MT_DEVICE,
        }, {
                .virtual        = (unsigned long)S5P_VA_COMBINER_BASE,
-               .pfn            = __phys_to_pfn(EXYNOS4_PA_COMBINER),
+               .pfn            = __phys_to_pfn(EXYNOS_PA_COMBINER),
                .length         = SZ_4K,
                .type           = MT_DEVICE,
        }, {
+               .virtual        = (unsigned long)S5P_VA_GIC_CPU,
+               .pfn            = __phys_to_pfn(EXYNOS_PA_GIC_CPU),
+               .length         = SZ_64K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = (unsigned long)S5P_VA_GIC_DIST,
+               .pfn            = __phys_to_pfn(EXYNOS_PA_GIC_DIST),
+               .length         = SZ_64K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = (unsigned long)S3C_VA_UART,
+               .pfn            = __phys_to_pfn(S3C_PA_UART),
+               .length         = SZ_512K,
+               .type           = MT_DEVICE,
+       },
+};
+
+static struct map_desc exynos4_iodesc[] __initdata = {
+       {
+               .virtual        = (unsigned long)S5P_VA_CMU,
+               .pfn            = __phys_to_pfn(EXYNOS4_PA_CMU),
+               .length         = SZ_128K,
+               .type           = MT_DEVICE,
+       }, {
                .virtual        = (unsigned long)S5P_VA_COREPERI_BASE,
                .pfn            = __phys_to_pfn(EXYNOS4_PA_COREPERI),
                .length         = SZ_8K,
@@ -91,11 +111,6 @@ static struct map_desc exynos4_iodesc[] __initdata = {
                .length         = SZ_4K,
                .type           = MT_DEVICE,
        }, {
-               .virtual        = (unsigned long)S3C_VA_UART,
-               .pfn            = __phys_to_pfn(S3C_PA_UART),
-               .length         = SZ_512K,
-               .type           = MT_DEVICE,
-       }, {
                .virtual        = (unsigned long)S5P_VA_SROMC,
                .pfn            = __phys_to_pfn(EXYNOS4_PA_SROMC),
                .length         = SZ_4K,
@@ -105,16 +120,6 @@ 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,
        },
 };
 
@@ -136,7 +141,7 @@ static struct map_desc exynos4_iodesc1[] __initdata = {
        },
 };
 
-static void exynos4_idle(void)
+static void exynos_idle(void)
 {
        if (!need_resched())
                cpu_do_idle();
@@ -150,12 +155,13 @@ static void exynos4_sw_reset(void)
 }
 
 /*
- * exynos4_map_io
+ * exynos_map_io
  *
  * register the standard cpu IO areas
  */
 void __init exynos4_map_io(void)
 {
+       iotable_init(exynos_iodesc, ARRAY_SIZE(exynos_iodesc));
        iotable_init(exynos4_iodesc, ARRAY_SIZE(exynos4_iodesc));
 
        if (soc_is_exynos4210() && samsung_rev() == EXYNOS4210_REV_0)
@@ -182,6 +188,7 @@ void __init exynos4_map_io(void)
        s3c_i2c2_setname("s3c2440-i2c");
 
        s5p_fb_setname(0, "exynos4-fb");
+       s5p_hdmi_setname("exynos4-hdmi");
 }
 
 void __init exynos4_init_clocks(int xtal)
@@ -248,7 +255,6 @@ static int __init exynos4_core_init(void)
 {
        return sysdev_class_register(&exynos4_sysclass);
 }
-
 core_initcall(exynos4_core_init);
 
 #ifdef CONFIG_CACHE_L2X0
@@ -277,15 +283,16 @@ static int __init exynos4_l2x0_cache_init(void)
 early_initcall(exynos4_l2x0_cache_init);
 #endif
 
-int __init exynos4_init(void)
+int __init exynos_init(void)
 {
-       printk(KERN_INFO "EXYNOS4: Initializing architecture\n");
+       printk(KERN_INFO "EXYNOS: Initializing architecture\n");
 
        /* set idle function */
-       pm_idle = exynos4_idle;
+       pm_idle = exynos_idle;
 
        /* set sw_reset function */
-       s5p_reset_hook = exynos4_sw_reset;
+       if (soc_is_exynos4210() || soc_is_exynos4212() || soc_is_exynos4412())
+               s5p_reset_hook = exynos4_sw_reset;
 
        return sysdev_register(&exynos4_sysdev);
 }
diff --git a/arch/arm/mach-exynos/dma.c b/arch/arm/mach-exynos/dma.c
new file mode 100644 (file)
index 0000000..9667c61
--- /dev/null
@@ -0,0 +1,250 @@
+/* linux/arch/arm/mach-exynos4/dma.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Copyright (C) 2010 Samsung Electronics Co. Ltd.
+ *     Jaswinder Singh <jassi.brar@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License 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/dma-mapping.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/pl330.h>
+
+#include <asm/irq.h>
+#include <plat/devs.h>
+#include <plat/irqs.h>
+
+#include <mach/map.h>
+#include <mach/irqs.h>
+#include <mach/dma.h>
+
+static u64 dma_dmamask = DMA_BIT_MASK(32);
+
+struct dma_pl330_peri pdma0_peri[28] = {
+       {
+               .peri_id = (u8)DMACH_PCM0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_PCM0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_PCM2_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_PCM2_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_MSM_REQ0,
+       }, {
+               .peri_id = (u8)DMACH_MSM_REQ2,
+       }, {
+               .peri_id = (u8)DMACH_SPI0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_SPI0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_SPI2_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_SPI2_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_I2S0S_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_I2S0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_I2S0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART2_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART2_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART4_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART4_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_SLIMBUS0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_SLIMBUS0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_SLIMBUS2_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_SLIMBUS2_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_SLIMBUS4_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_SLIMBUS4_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_AC97_MICIN,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_AC97_PCMIN,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_AC97_PCMOUT,
+               .rqtype = MEMTODEV,
+       },
+};
+
+struct dma_pl330_platdata exynos4_pdma0_pdata = {
+       .nr_valid_peri = ARRAY_SIZE(pdma0_peri),
+       .peri = pdma0_peri,
+};
+
+struct amba_device exynos4_device_pdma0 = {
+       .dev = {
+               .init_name = "dma-pl330.0",
+               .dma_mask = &dma_dmamask,
+               .coherent_dma_mask = DMA_BIT_MASK(32),
+               .platform_data = &exynos4_pdma0_pdata,
+       },
+       .res = {
+               .start = EXYNOS4_PA_PDMA0,
+               .end = EXYNOS4_PA_PDMA0 + SZ_4K,
+               .flags = IORESOURCE_MEM,
+       },
+       .irq = {IRQ_PDMA0, NO_IRQ},
+       .periphid = 0x00041330,
+};
+
+struct dma_pl330_peri pdma1_peri[25] = {
+       {
+               .peri_id = (u8)DMACH_PCM0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_PCM0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_PCM1_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_PCM1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_MSM_REQ1,
+       }, {
+               .peri_id = (u8)DMACH_MSM_REQ3,
+       }, {
+               .peri_id = (u8)DMACH_SPI1_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_SPI1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_I2S0S_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_I2S0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_I2S0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_I2S1_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_I2S1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART1_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART3_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART3_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_SLIMBUS1_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_SLIMBUS1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_SLIMBUS3_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_SLIMBUS3_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_SLIMBUS5_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_SLIMBUS5_TX,
+               .rqtype = MEMTODEV,
+       },
+};
+
+struct dma_pl330_platdata exynos4_pdma1_pdata = {
+       .nr_valid_peri = ARRAY_SIZE(pdma1_peri),
+       .peri = pdma1_peri,
+};
+
+struct amba_device exynos4_device_pdma1 = {
+       .dev = {
+               .init_name = "dma-pl330.1",
+               .dma_mask = &dma_dmamask,
+               .coherent_dma_mask = DMA_BIT_MASK(32),
+               .platform_data = &exynos4_pdma1_pdata,
+       },
+       .res = {
+               .start = EXYNOS4_PA_PDMA1,
+               .end = EXYNOS4_PA_PDMA1 + SZ_4K,
+               .flags = IORESOURCE_MEM,
+       },
+       .irq = {IRQ_PDMA1, NO_IRQ},
+       .periphid = 0x00041330,
+};
+
+static int __init exynos4_dma_init(void)
+{
+       amba_device_register(&exynos4_device_pdma0, &iomem_resource);
+       amba_device_register(&exynos4_device_pdma1, &iomem_resource);
+
+       return 0;
+}
+arch_initcall(exynos4_dma_init);
similarity index 90%
rename from arch/arm/mach-exynos4/include/mach/dma.h
rename to arch/arm/mach-exynos/include/mach/dma.h
index 81209eb..201842a 100644 (file)
@@ -20,7 +20,7 @@
 #ifndef __MACH_DMA_H
 #define __MACH_DMA_H
 
-/* This platform uses the common S3C DMA API driver for PL330 */
-#include <plat/s3c-dma-pl330.h>
+/* This platform uses the common DMA API driver for PL330 */
+#include <plat/dma-pl330.h>
 
 #endif /* __MACH_DMA_H */
similarity index 97%
rename from arch/arm/mach-exynos4/include/mach/irqs.h
rename to arch/arm/mach-exynos/include/mach/irqs.h
index 2d3f6bc..dfd4b7e 100644 (file)
 #define IRQ_2D                 IRQ_SPI(89)
 #define IRQ_PCIE               IRQ_SPI(90)
 
+#define IRQ_MIXER              IRQ_SPI(91)
+#define IRQ_HDMI               IRQ_SPI(92)
+#define IRQ_IIC_HDMIPHY                IRQ_SPI(93)
 #define IRQ_MFC                        IRQ_SPI(94)
+#define IRQ_SDO                        IRQ_SPI(95)
 
 #define IRQ_AUDIO_SS           IRQ_SPI(96)
 #define IRQ_I2S0               IRQ_SPI(97)
similarity index 87%
rename from arch/arm/mach-exynos4/include/mach/map.h
rename to arch/arm/mach-exynos/include/mach/map.h
index 9f97eb8..058541d 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-exynos4/include/mach/map.h
+/* linux/arch/arm/mach-exynos/include/mach/map.h
  *
  * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com/
 
 #define EXYNOS4_PA_UART                        0x13800000
 
+#define EXYNOS4_PA_VP                  0x12C00000
+#define EXYNOS4_PA_MIXER               0x12C10000
+#define EXYNOS4_PA_SDO                 0x12C20000
+#define EXYNOS4_PA_HDMI                        0x12D00000
+#define EXYNOS4_PA_IIC_HDMIPHY         0x138E0000
+
 #define EXYNOS4_PA_IIC(x)              (0x13860000 + ((x) * 0x10000))
 
 #define EXYNOS4_PA_ADC                 0x13910000
 #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 S3C_PA_UART                    EXYNOS4_PA_UART
 
 #define S5P_PA_CHIPID                  EXYNOS4_PA_CHIPID
+#define S5P_PA_EHCI                    EXYNOS4_PA_EHCI
 #define S5P_PA_FIMC0                   EXYNOS4_PA_FIMC0
 #define S5P_PA_FIMC1                   EXYNOS4_PA_FIMC1
 #define S5P_PA_FIMC2                   EXYNOS4_PA_FIMC2
 #define S5P_PA_FIMC3                   EXYNOS4_PA_FIMC3
+#define S5P_PA_FIMD0                   EXYNOS4_PA_FIMD0
+#define S5P_PA_HDMI                    EXYNOS4_PA_HDMI
+#define S5P_PA_IIC_HDMIPHY             EXYNOS4_PA_IIC_HDMIPHY
+#define S5P_PA_MFC                     EXYNOS4_PA_MFC
 #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_MIXER                   EXYNOS4_PA_MIXER
 #define S5P_PA_ONENAND                 EXYNOS4_PA_ONENAND
 #define S5P_PA_ONENAND_DMA             EXYNOS4_PA_ONENAND_DMA
+#define S5P_PA_SDO                     EXYNOS4_PA_SDO
 #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
+#define S5P_PA_VP                      EXYNOS4_PA_VP
 
+#define SAMSUNG_PA_ADC                 EXYNOS4_PA_ADC
+#define SAMSUNG_PA_ADC1                        EXYNOS4_PA_ADC1
 #define SAMSUNG_PA_KEYPAD              EXYNOS4_PA_KEYPAD
 
-/* UART */
+#define EXYNOS_PA_COMBINER             EXYNOS4_PA_COMBINER
+#define EXYNOS_PA_GIC_CPU              EXYNOS4_PA_GIC_CPU
+#define EXYNOS_PA_GIC_DIST             EXYNOS4_PA_GIC_DIST
+#define EXYNOS_PA_PMU                  EXYNOS4_PA_PMU
+#define EXYNOS_PA_SYSTIMER             EXYNOS4_PA_SYSTIMER
 
-#define S3C_PA_UART                    EXYNOS4_PA_UART
+/* Compatibility UART */
+
+#define S3C_VA_UARTx(x)                        (S3C_VA_UART + ((x) * S3C_UART_OFFSET))
 
 #define S5P_PA_UART(x)                 (S3C_PA_UART + ((x) * S3C_UART_OFFSET))
 #define S5P_PA_UART0                   S5P_PA_UART(0)
similarity index 89%
rename from arch/arm/mach-exynos4/include/mach/pm-core.h
rename to arch/arm/mach-exynos/include/mach/pm-core.h
index 1df3b81..9d8da51 100644 (file)
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
 */
+
+#ifndef __ASM_ARCH_PM_CORE_H
+#define __ASM_ARCH_PM_CORE_H __FILE__
+
 #include <mach/regs-pmu.h>
 
 static inline void s3c_pm_debug_init_uart(void)
@@ -53,7 +57,9 @@ static inline void s3c_pm_restored_gpios(void)
        /* nothing here yet */
 }
 
-static inline void s3c_pm_saved_gpios(void)
+static inline void samsung_pm_saved_gpios(void)
 {
        /* nothing here yet */
 }
+
+#endif /* __ASM_ARCH_PM_CORE_H */
similarity index 84%
rename from arch/arm/mach-exynos4/include/mach/pmu.h
rename to arch/arm/mach-exynos/include/mach/pmu.h
index a952904..632dd56 100644 (file)
@@ -13,6 +13,8 @@
 #ifndef __ASM_ARCH_PMU_H
 #define __ASM_ARCH_PMU_H __FILE__
 
+#define PMU_TABLE_END  NULL
+
 enum sys_powerdown {
        SYS_AFTR,
        SYS_LPA,
@@ -20,6 +22,11 @@ enum sys_powerdown {
        NUM_SYS_POWERDOWN,
 };
 
+struct exynos4_pmu_conf {
+       void __iomem *reg;
+       unsigned int val[NUM_SYS_POWERDOWN];
+};
+
 extern void exynos4_sys_powerdown_conf(enum sys_powerdown mode);
 
 #endif /* __ASM_ARCH_PMU_H */
similarity index 69%
rename from arch/arm/mach-exynos4/include/mach/regs-pmu.h
rename to arch/arm/mach-exynos/include/mach/regs-pmu.h
index cdf9b47..4fff8e9 100644 (file)
 
 #define S5P_USE_STANDBY_WFI0                   (1 << 16)
 #define S5P_USE_STANDBY_WFI1                   (1 << 17)
+#define S5P_USE_STANDBYWFI_ISP_ARM             (1 << 18)
 #define S5P_USE_STANDBY_WFE0                   (1 << 24)
 #define S5P_USE_STANDBY_WFE1                   (1 << 25)
-#define S5P_USE_MASK                           ((0x3 << 16) | (0x3 << 24))
+#define S5P_USE_STANDBYWFE_ISP_ARM             (1 << 26)
 
 #define S5P_SWRESET                            S5P_PMUREG(0x0400)
 
 #define S5P_EINT_WAKEUP_MASK                   S5P_PMUREG(0x0604)
 #define S5P_WAKEUP_MASK                                S5P_PMUREG(0x0608)
 
-#define S5P_USBHOST_PHY_CONTROL                        S5P_PMUREG(0x0708)
-#define S5P_USBHOST_PHY_ENABLE                 (1 << 0)
+#define S5P_HDMI_PHY_CONTROL                   S5P_PMUREG(0x0700)
+#define S5P_HDMI_PHY_ENABLE                    (1 << 0)
+
+#define S5P_DAC_PHY_CONTROL                    S5P_PMUREG(0x070C)
+#define S5P_DAC_PHY_ENABLE                     (1 << 0)
 
 #define S5P_MIPI_DPHY_CONTROL(n)               S5P_PMUREG(0x0710 + (n) * 4)
 #define S5P_MIPI_DPHY_ENABLE                   (1 << 0)
 #define S5P_MIPI_DPHY_SRESETN                  (1 << 1)
 #define S5P_MIPI_DPHY_MRESETN                  (1 << 2)
 
-#define S5P_PMU_SATA_PHY_CONTROL               S5P_PMUREG(0x0720)
 #define S5P_INFORM0                            S5P_PMUREG(0x0800)
 #define S5P_INFORM1                            S5P_PMUREG(0x0804)
 #define S5P_INFORM2                            S5P_PMUREG(0x0808)
@@ -76,7 +79,6 @@
 #define S5P_CMU_CLKSTOP_MFC_LOWPWR             S5P_PMUREG(0x1148)
 #define S5P_CMU_CLKSTOP_G3D_LOWPWR             S5P_PMUREG(0x114C)
 #define S5P_CMU_CLKSTOP_LCD0_LOWPWR            S5P_PMUREG(0x1150)
-#define S5P_CMU_CLKSTOP_LCD1_LOWPWR            S5P_PMUREG(0x1154)
 #define S5P_CMU_CLKSTOP_MAUDIO_LOWPWR          S5P_PMUREG(0x1158)
 #define S5P_CMU_CLKSTOP_GPS_LOWPWR             S5P_PMUREG(0x115C)
 #define S5P_CMU_RESET_CAM_LOWPWR               S5P_PMUREG(0x1160)
@@ -84,7 +86,6 @@
 #define S5P_CMU_RESET_MFC_LOWPWR               S5P_PMUREG(0x1168)
 #define S5P_CMU_RESET_G3D_LOWPWR               S5P_PMUREG(0x116C)
 #define S5P_CMU_RESET_LCD0_LOWPWR              S5P_PMUREG(0x1170)
-#define S5P_CMU_RESET_LCD1_LOWPWR              S5P_PMUREG(0x1174)
 #define S5P_CMU_RESET_MAUDIO_LOWPWR            S5P_PMUREG(0x1178)
 #define S5P_CMU_RESET_GPS_LOWPWR               S5P_PMUREG(0x117C)
 #define S5P_TOP_BUS_LOWPWR                     S5P_PMUREG(0x1180)
 #define S5P_TOP_PWR_LOWPWR                     S5P_PMUREG(0x1188)
 #define S5P_LOGIC_RESET_LOWPWR                 S5P_PMUREG(0x11A0)
 #define S5P_ONENAND_MEM_LOWPWR                 S5P_PMUREG(0x11C0)
-#define S5P_MODIMIF_MEM_LOWPWR                 S5P_PMUREG(0x11C4)
 #define S5P_G2D_ACP_MEM_LOWPWR                 S5P_PMUREG(0x11C8)
 #define S5P_USBOTG_MEM_LOWPWR                  S5P_PMUREG(0x11CC)
 #define S5P_HSMMC_MEM_LOWPWR                   S5P_PMUREG(0x11D0)
 #define S5P_CSSYS_MEM_LOWPWR                   S5P_PMUREG(0x11D4)
 #define S5P_SECSS_MEM_LOWPWR                   S5P_PMUREG(0x11D8)
-#define S5P_PCIE_MEM_LOWPWR                    S5P_PMUREG(0x11E0)
-#define S5P_SATA_MEM_LOWPWR                    S5P_PMUREG(0x11E4)
 #define S5P_PAD_RETENTION_DRAM_LOWPWR          S5P_PMUREG(0x1200)
 #define S5P_PAD_RETENTION_MAUDIO_LOWPWR                S5P_PMUREG(0x1204)
 #define S5P_PAD_RETENTION_GPIO_LOWPWR          S5P_PMUREG(0x1220)
 #define S5P_MFC_LOWPWR                         S5P_PMUREG(0x1388)
 #define S5P_G3D_LOWPWR                         S5P_PMUREG(0x138C)
 #define S5P_LCD0_LOWPWR                                S5P_PMUREG(0x1390)
-#define S5P_LCD1_LOWPWR                                S5P_PMUREG(0x1394)
 #define S5P_MAUDIO_LOWPWR                      S5P_PMUREG(0x1398)
 #define S5P_GPS_LOWPWR                         S5P_PMUREG(0x139C)
 #define S5P_GPS_ALIVE_LOWPWR                   S5P_PMUREG(0x13A0)
 #define S5P_PMU_MFC_CONF                       S5P_PMUREG(0x3C40)
 #define S5P_PMU_G3D_CONF                       S5P_PMUREG(0x3C60)
 #define S5P_PMU_LCD0_CONF                      S5P_PMUREG(0x3C80)
-#define S5P_PMU_LCD1_CONF                      S5P_PMUREG(0x3CA0)
 #define S5P_PMU_GPS_CONF                       S5P_PMUREG(0x3CE0)
 
 #define S5P_PMU_SATA_PHY_CONTROL_EN            0x1
 
 #define S5P_CHECK_SLEEP                                0x00000BAD
 
+/* Only for EXYNOS4210 */
+#define S5P_USBHOST_PHY_CONTROL                S5P_PMUREG(0x0708)
+#define S5P_USBHOST_PHY_ENABLE         (1 << 0)
+
+#define S5P_PMU_SATA_PHY_CONTROL       S5P_PMUREG(0x0720)
+
+#define S5P_CMU_CLKSTOP_LCD1_LOWPWR    S5P_PMUREG(0x1154)
+#define S5P_CMU_RESET_LCD1_LOWPWR      S5P_PMUREG(0x1174)
+#define S5P_MODIMIF_MEM_LOWPWR         S5P_PMUREG(0x11C4)
+#define S5P_PCIE_MEM_LOWPWR            S5P_PMUREG(0x11E0)
+#define S5P_SATA_MEM_LOWPWR            S5P_PMUREG(0x11E4)
+#define S5P_LCD1_LOWPWR                        S5P_PMUREG(0x1394)
+
+#define S5P_PMU_LCD1_CONF              S5P_PMUREG(0x3CA0)
+
+/* Only for EXYNOS4212 */
+#define S5P_ISP_ARM_LOWPWR                     S5P_PMUREG(0x1050)
+#define S5P_DIS_IRQ_ISP_ARM_LOCAL_LOWPWR       S5P_PMUREG(0x1054)
+#define S5P_DIS_IRQ_ISP_ARM_CENTRAL_LOWPWR     S5P_PMUREG(0x1058)
+#define S5P_CMU_ACLKSTOP_COREBLK_LOWPWR                S5P_PMUREG(0x1110)
+#define S5P_CMU_SCLKSTOP_COREBLK_LOWPWR                S5P_PMUREG(0x1114)
+#define S5P_CMU_RESET_COREBLK_LOWPWR           S5P_PMUREG(0x111C)
+#define S5P_MPLLUSER_SYSCLK_LOWPWR             S5P_PMUREG(0x1130)
+#define S5P_CMU_CLKSTOP_ISP_LOWPWR             S5P_PMUREG(0x1154)
+#define S5P_CMU_RESET_ISP_LOWPWR               S5P_PMUREG(0x1174)
+#define S5P_TOP_BUS_COREBLK_LOWPWR             S5P_PMUREG(0x1190)
+#define S5P_TOP_RETENTION_COREBLK_LOWPWR       S5P_PMUREG(0x1194)
+#define S5P_TOP_PWR_COREBLK_LOWPWR             S5P_PMUREG(0x1198)
+#define S5P_OSCCLK_GATE_LOWPWR                 S5P_PMUREG(0x11A4)
+#define S5P_LOGIC_RESET_COREBLK_LOWPWR         S5P_PMUREG(0x11B0)
+#define S5P_OSCCLK_GATE_COREBLK_LOWPWR         S5P_PMUREG(0x11B4)
+#define S5P_HSI_MEM_LOWPWR                     S5P_PMUREG(0x11C4)
+#define S5P_ROTATOR_MEM_LOWPWR                 S5P_PMUREG(0x11DC)
+#define S5P_PAD_RETENTION_GPIO_COREBLK_LOWPWR  S5P_PMUREG(0x123C)
+#define S5P_PAD_ISOLATION_COREBLK_LOWPWR       S5P_PMUREG(0x1250)
+#define S5P_GPIO_MODE_COREBLK_LOWPWR           S5P_PMUREG(0x1320)
+#define S5P_TOP_ASB_RESET_LOWPWR               S5P_PMUREG(0x1344)
+#define S5P_TOP_ASB_ISOLATION_LOWPWR           S5P_PMUREG(0x1348)
+#define S5P_ISP_LOWPWR                         S5P_PMUREG(0x1394)
+#define S5P_DRAM_FREQ_DOWN_LOWPWR              S5P_PMUREG(0x13B0)
+#define S5P_DDRPHY_DLLOFF_LOWPWR               S5P_PMUREG(0x13B4)
+#define S5P_CMU_SYSCLK_ISP_LOWPWR              S5P_PMUREG(0x13B8)
+#define S5P_CMU_SYSCLK_GPS_LOWPWR              S5P_PMUREG(0x13BC)
+#define S5P_LPDDR_PHY_DLL_LOCK_LOWPWR          S5P_PMUREG(0x13C0)
+
+#define S5P_ARM_L2_0_OPTION                    S5P_PMUREG(0x2608)
+#define S5P_ARM_L2_1_OPTION                    S5P_PMUREG(0x2628)
+#define S5P_ONENAND_MEM_OPTION                 S5P_PMUREG(0x2E08)
+#define S5P_HSI_MEM_OPTION                     S5P_PMUREG(0x2E28)
+#define S5P_G2D_ACP_MEM_OPTION                 S5P_PMUREG(0x2E48)
+#define S5P_USBOTG_MEM_OPTION                  S5P_PMUREG(0x2E68)
+#define S5P_HSMMC_MEM_OPTION                   S5P_PMUREG(0x2E88)
+#define S5P_CSSYS_MEM_OPTION                   S5P_PMUREG(0x2EA8)
+#define S5P_SECSS_MEM_OPTION                   S5P_PMUREG(0x2EC8)
+#define S5P_ROTATOR_MEM_OPTION                 S5P_PMUREG(0x2F48)
+
 #endif /* __ASM_ARCH_REGS_PMU_H */
similarity index 85%
rename from arch/arm/mach-exynos4/mach-nuri.c
rename to arch/arm/mach-exynos/mach-nuri.c
index 6e05368..236bbe1 100644 (file)
 #include <linux/pwm_backlight.h>
 
 #include <video/platform_lcd.h>
+#include <media/m5mols.h>
+#include <media/s5p_fimc.h>
+#include <media/v4l2-mediabus.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 
 #include <plat/adc.h>
+#include <plat/regs-fb-v4.h>
 #include <plat/regs-serial.h>
 #include <plat/exynos4.h>
 #include <plat/cpu.h>
 #include <plat/devs.h>
+#include <plat/fb.h>
 #include <plat/sdhci.h>
 #include <plat/ehci.h>
 #include <plat/clock.h>
@@ -43,6 +48,9 @@
 #include <plat/iic.h>
 #include <plat/mfc.h>
 #include <plat/pd.h>
+#include <plat/fimc-core.h>
+#include <plat/camport.h>
+#include <plat/mipi_csis.h>
 
 #include <mach/map.h>
 
@@ -63,6 +71,8 @@
 enum fixed_regulator_id {
        FIXED_REG_ID_MMC = 0,
        FIXED_REG_ID_MAX8903,
+       FIXED_REG_ID_CAM_A28V,
+       FIXED_REG_ID_CAM_12V,
 };
 
 static struct s3c2410_uartcfg nuri_uartcfgs[] __initdata = {
@@ -199,6 +209,33 @@ static struct platform_device nuri_gpio_keys = {
        },
 };
 
+/* Frame Buffer */
+static struct s3c_fb_pd_win nuri_fb_win0 = {
+       .win_mode = {
+               .left_margin    = 64,
+               .right_margin   = 16,
+               .upper_margin   = 64,
+               .lower_margin   = 1,
+               .hsync_len      = 48,
+               .vsync_len      = 3,
+               .xres           = 1280,
+               .yres           = 800,
+               .refresh        = 60,
+       },
+       .max_bpp        = 24,
+       .default_bpp    = 16,
+       .virtual_x      = 1280,
+       .virtual_y      = 800,
+};
+
+static struct s3c_fb_platdata nuri_fb_pdata __initdata = {
+       .win[0]         = &nuri_fb_win0,
+       .vidcon0        = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB |
+                         VIDCON0_CLKSEL_LCD,
+       .vidcon1        = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
+       .setup_gpio     = exynos4_fimd0_gpio_setup_24bpp,
+};
+
 static void nuri_lcd_power_on(struct plat_lcd_data *pd, unsigned int power)
 {
        int gpio = EXYNOS4_GPE1(5);
@@ -1037,13 +1074,6 @@ static struct platform_device nuri_max8903_device = {
        },
 };
 
-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;
@@ -1088,10 +1118,141 @@ static void __init nuri_ehci_init(void)
        s5p_ehci_set_platdata(pdata);
 }
 
+/* CAMERA */
+static struct regulator_consumer_supply cam_vdda_supply[] = {
+       REGULATOR_SUPPLY("a_sensor", "0-001f"),
+};
+
+static struct regulator_init_data cam_vdda_reg_init_data = {
+       .constraints = { .valid_ops_mask = REGULATOR_CHANGE_STATUS },
+       .num_consumer_supplies = ARRAY_SIZE(cam_vdda_supply),
+       .consumer_supplies = cam_vdda_supply,
+};
+
+static struct fixed_voltage_config cam_vdda_fixed_voltage_cfg = {
+       .supply_name    = "CAM_IO_EN",
+       .microvolts     = 2800000,
+       .gpio           = EXYNOS4_GPE2(1), /* CAM_IO_EN */
+       .enable_high    = 1,
+       .init_data      = &cam_vdda_reg_init_data,
+};
+
+static struct platform_device cam_vdda_fixed_rdev = {
+       .name = "reg-fixed-voltage", .id = FIXED_REG_ID_CAM_A28V,
+       .dev = { .platform_data = &cam_vdda_fixed_voltage_cfg },
+};
+
+static struct regulator_consumer_supply camera_8m_12v_supply =
+       REGULATOR_SUPPLY("dig_12", "0-001f");
+
+static struct regulator_init_data cam_8m_12v_reg_init_data = {
+       .num_consumer_supplies  = 1,
+       .consumer_supplies      = &camera_8m_12v_supply,
+       .constraints = {
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS
+       },
+};
+
+static struct fixed_voltage_config cam_8m_12v_fixed_voltage_cfg = {
+       .supply_name    = "8M_1.2V",
+       .microvolts     = 1200000,
+       .gpio           = EXYNOS4_GPE2(5), /* 8M_1.2V_EN */
+       .enable_high    = 1,
+       .init_data      = &cam_8m_12v_reg_init_data,
+};
+
+static struct platform_device cam_8m_12v_fixed_rdev = {
+       .name = "reg-fixed-voltage", .id = FIXED_REG_ID_CAM_12V,
+       .dev = { .platform_data = &cam_8m_12v_fixed_voltage_cfg },
+};
+
+static struct s5p_platform_mipi_csis mipi_csis_platdata = {
+       .clk_rate       = 166000000UL,
+       .lanes          = 2,
+       .alignment      = 32,
+       .hs_settle      = 12,
+       .phy_enable     = s5p_csis_phy_enable,
+};
+
+#define GPIO_CAM_MEGA_RST      EXYNOS4_GPY3(7) /* ISP_RESET */
+#define GPIO_CAM_8M_ISP_INT    EXYNOS4_GPL2(5)
+
+static struct m5mols_platform_data m5mols_platdata = {
+       .gpio_reset = GPIO_CAM_MEGA_RST,
+};
+
+static struct i2c_board_info m5mols_board_info = {
+       I2C_BOARD_INFO("M5MOLS", 0x1F),
+       .platform_data  = &m5mols_platdata,
+};
+
+static struct s5p_fimc_isp_info nuri_camera_sensors[] = {
+       {
+               .flags          = V4L2_MBUS_PCLK_SAMPLE_FALLING |
+                                 V4L2_MBUS_VSYNC_ACTIVE_LOW,
+               .bus_type       = FIMC_MIPI_CSI2,
+               .board_info     = &m5mols_board_info,
+               .clk_frequency  = 24000000UL,
+               .csi_data_align = 32,
+       },
+};
+
+static struct s5p_platform_fimc fimc_md_platdata = {
+       .isp_info       = nuri_camera_sensors,
+       .num_clients    = ARRAY_SIZE(nuri_camera_sensors),
+};
+
+static struct gpio nuri_camera_gpios[] = {
+       { GPIO_CAM_8M_ISP_INT,  GPIOF_IN,           "8M_ISP_INT"  },
+       { GPIO_CAM_MEGA_RST,    GPIOF_OUT_INIT_LOW, "CAM_8M_NRST" },
+};
+
+static void nuri_camera_init(void)
+{
+       s3c_set_platdata(&mipi_csis_platdata, sizeof(mipi_csis_platdata),
+                        &s5p_device_mipi_csis0);
+       s3c_set_platdata(&fimc_md_platdata,  sizeof(fimc_md_platdata),
+                        &s5p_device_fimc_md);
+
+       if (gpio_request_array(nuri_camera_gpios,
+                              ARRAY_SIZE(nuri_camera_gpios))) {
+               pr_err("%s: GPIO request failed\n", __func__);
+               return;
+       }
+
+       m5mols_board_info.irq = s5p_register_gpio_interrupt(GPIO_CAM_8M_ISP_INT);
+       if (!IS_ERR_VALUE(m5mols_board_info.irq))
+               s3c_gpio_cfgpin(GPIO_CAM_8M_ISP_INT, S3C_GPIO_SFN(0xF));
+       else
+               pr_err("%s: Failed to configure 8M_ISP_INT GPIO\n", __func__);
+
+       /* Free GPIOs controlled directly by the sensor drivers. */
+       gpio_free(GPIO_CAM_MEGA_RST);
+
+       if (exynos4_fimc_setup_gpio(S5P_CAMPORT_A)) {
+               pr_err("%s: Camera port A setup failed\n", __func__);
+               return;
+       }
+       /* Increase drive strength of the sensor clock output */
+       s5p_gpio_set_drvstr(EXYNOS4_GPJ1(3), S5P_GPIO_DRVSTR_LV4);
+}
+
+static struct s3c2410_platform_i2c nuri_i2c0_platdata __initdata = {
+       .frequency      = 400000U,
+       .sda_delay      = 200,
+};
+
 static struct platform_device *nuri_devices[] __initdata = {
        /* Samsung Platform Devices */
        &s3c_device_i2c5, /* PMIC should initialize first */
+       &s3c_device_i2c0,
        &emmc_fixed_voltage,
+       &s5p_device_mipi_csis0,
+       &s5p_device_fimc0,
+       &s5p_device_fimc1,
+       &s5p_device_fimc2,
+       &s5p_device_fimc3,
+       &s5p_device_fimd0,
        &s3c_device_hsmmc0,
        &s3c_device_hsmmc2,
        &s3c_device_hsmmc3,
@@ -1106,6 +1267,9 @@ static struct platform_device *nuri_devices[] __initdata = {
        &s5p_device_mfc_l,
        &s5p_device_mfc_r,
        &exynos4_device_pd[PD_MFC],
+       &exynos4_device_pd[PD_LCD0],
+       &exynos4_device_pd[PD_CAM],
+       &s5p_device_fimc_md,
 
        /* NURI Devices */
        &nuri_gpio_keys,
@@ -1113,6 +1277,8 @@ static struct platform_device *nuri_devices[] __initdata = {
        &nuri_backlight_device,
        &max8903_fixed_reg_dev,
        &nuri_max8903_device,
+       &cam_vdda_fixed_rdev,
+       &cam_8m_12v_fixed_rdev,
 };
 
 static void __init nuri_map_io(void)
@@ -1133,6 +1299,7 @@ static void __init nuri_machine_init(void)
        nuri_tsp_init();
        nuri_power_init();
 
+       s3c_i2c0_set_platdata(&nuri_i2c0_platdata);
        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));
@@ -1142,12 +1309,23 @@ static void __init nuri_machine_init(void)
        i2c9_devs[I2C9_MAX17042].irq = gpio_to_irq(EXYNOS4_GPX2(3));
        i2c_register_board_info(9, i2c9_devs, ARRAY_SIZE(i2c9_devs));
 
+       s5p_fimd0_set_platdata(&nuri_fb_pdata);
+
+       nuri_camera_init();
+
        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;
+       s5p_device_fimd0.dev.parent = &exynos4_device_pd[PD_LCD0].dev;
+
+       s5p_device_fimc0.dev.parent = &exynos4_device_pd[PD_CAM].dev;
+       s5p_device_fimc1.dev.parent = &exynos4_device_pd[PD_CAM].dev;
+       s5p_device_fimc2.dev.parent = &exynos4_device_pd[PD_CAM].dev;
+       s5p_device_fimc3.dev.parent = &exynos4_device_pd[PD_CAM].dev;
+       s5p_device_mipi_csis0.dev.parent = &exynos4_device_pd[PD_CAM].dev;
 }
 
 MACHINE_START(NURI, "NURI")
diff --git a/arch/arm/mach-exynos/mach-origen.c b/arch/arm/mach-exynos/mach-origen.c
new file mode 100644 (file)
index 0000000..f80b563
--- /dev/null
@@ -0,0 +1,700 @@
+/* linux/arch/arm/mach-exynos4/mach-origen.c
+ *
+ * Copyright (c) 2011 Insignal Co., Ltd.
+ *             http://www.insignal.co.kr/
+ *
+ * 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/serial_core.h>
+#include <linux/gpio.h>
+#include <linux/mmc/host.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/input.h>
+#include <linux/pwm_backlight.h>
+#include <linux/gpio_keys.h>
+#include <linux/i2c.h>
+#include <linux/regulator/machine.h>
+#include <linux/mfd/max8997.h>
+#include <linux/lcd.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include <video/platform_lcd.h>
+
+#include <plat/regs-serial.h>
+#include <plat/regs-fb-v4.h>
+#include <plat/exynos4.h>
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/sdhci.h>
+#include <plat/iic.h>
+#include <plat/ehci.h>
+#include <plat/clock.h>
+#include <plat/gpio-cfg.h>
+#include <plat/backlight.h>
+#include <plat/pd.h>
+#include <plat/fb.h>
+#include <plat/mfc.h>
+
+#include <mach/map.h>
+
+/* Following are default values for UCON, ULCON and UFCON UART registers */
+#define ORIGEN_UCON_DEFAULT    (S3C2410_UCON_TXILEVEL |        \
+                                S3C2410_UCON_RXILEVEL |        \
+                                S3C2410_UCON_TXIRQMODE |       \
+                                S3C2410_UCON_RXIRQMODE |       \
+                                S3C2410_UCON_RXFIFO_TOI |      \
+                                S3C2443_UCON_RXERR_IRQEN)
+
+#define ORIGEN_ULCON_DEFAULT   S3C2410_LCON_CS8
+
+#define ORIGEN_UFCON_DEFAULT   (S3C2410_UFCON_FIFOMODE |       \
+                                S5PV210_UFCON_TXTRIG4 |        \
+                                S5PV210_UFCON_RXTRIG4)
+
+static struct s3c2410_uartcfg origen_uartcfgs[] __initdata = {
+       [0] = {
+               .hwport         = 0,
+               .flags          = 0,
+               .ucon           = ORIGEN_UCON_DEFAULT,
+               .ulcon          = ORIGEN_ULCON_DEFAULT,
+               .ufcon          = ORIGEN_UFCON_DEFAULT,
+       },
+       [1] = {
+               .hwport         = 1,
+               .flags          = 0,
+               .ucon           = ORIGEN_UCON_DEFAULT,
+               .ulcon          = ORIGEN_ULCON_DEFAULT,
+               .ufcon          = ORIGEN_UFCON_DEFAULT,
+       },
+       [2] = {
+               .hwport         = 2,
+               .flags          = 0,
+               .ucon           = ORIGEN_UCON_DEFAULT,
+               .ulcon          = ORIGEN_ULCON_DEFAULT,
+               .ufcon          = ORIGEN_UFCON_DEFAULT,
+       },
+       [3] = {
+               .hwport         = 3,
+               .flags          = 0,
+               .ucon           = ORIGEN_UCON_DEFAULT,
+               .ulcon          = ORIGEN_ULCON_DEFAULT,
+               .ufcon          = ORIGEN_UFCON_DEFAULT,
+       },
+};
+
+static struct regulator_consumer_supply __initdata ldo3_consumer[] = {
+       REGULATOR_SUPPLY("vdd11", "s5p-mipi-csis.0"), /* MIPI */
+       REGULATOR_SUPPLY("vdd", "exynos4-hdmi"), /* HDMI */
+       REGULATOR_SUPPLY("vdd_pll", "exynos4-hdmi"), /* HDMI */
+};
+static struct regulator_consumer_supply __initdata ldo6_consumer[] = {
+       REGULATOR_SUPPLY("vdd18", "s5p-mipi-csis.0"), /* MIPI */
+};
+static struct regulator_consumer_supply __initdata ldo7_consumer[] = {
+       REGULATOR_SUPPLY("avdd", "alc5625"), /* Realtek ALC5625 */
+};
+static struct regulator_consumer_supply __initdata ldo8_consumer[] = {
+       REGULATOR_SUPPLY("vdd", "s5p-adc"), /* ADC */
+       REGULATOR_SUPPLY("vdd_osc", "exynos4-hdmi"), /* HDMI */
+};
+static struct regulator_consumer_supply __initdata ldo9_consumer[] = {
+       REGULATOR_SUPPLY("dvdd", "swb-a31"), /* AR6003 WLAN & CSR 8810 BT */
+};
+static struct regulator_consumer_supply __initdata ldo11_consumer[] = {
+       REGULATOR_SUPPLY("dvdd", "alc5625"), /* Realtek ALC5625 */
+};
+static struct regulator_consumer_supply __initdata ldo14_consumer[] = {
+       REGULATOR_SUPPLY("avdd18", "swb-a31"), /* AR6003 WLAN & CSR 8810 BT */
+};
+static struct regulator_consumer_supply __initdata ldo17_consumer[] = {
+       REGULATOR_SUPPLY("vdd33", "swb-a31"), /* AR6003 WLAN & CSR 8810 BT */
+};
+static struct regulator_consumer_supply __initdata buck1_consumer[] = {
+       REGULATOR_SUPPLY("vdd_arm", NULL), /* CPUFREQ */
+};
+static struct regulator_consumer_supply __initdata buck2_consumer[] = {
+       REGULATOR_SUPPLY("vdd_int", NULL), /* CPUFREQ */
+};
+static struct regulator_consumer_supply __initdata buck3_consumer[] = {
+       REGULATOR_SUPPLY("vdd_g3d", "mali_drm"), /* G3D */
+};
+static struct regulator_consumer_supply __initdata buck7_consumer[] = {
+       REGULATOR_SUPPLY("vcc", "platform-lcd"), /* LCD */
+};
+
+static struct regulator_init_data __initdata max8997_ldo1_data = {
+       .constraints    = {
+               .name           = "VDD_ABB_3.3V",
+               .min_uV         = 3300000,
+               .max_uV         = 3300000,
+               .apply_uV       = 1,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+};
+
+static struct regulator_init_data __initdata max8997_ldo2_data = {
+       .constraints    = {
+               .name           = "VDD_ALIVE_1.1V",
+               .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           = "VMIPI_1.1V",
+               .min_uV         = 1100000,
+               .max_uV         = 1100000,
+               .apply_uV       = 1,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+       .num_consumer_supplies  = ARRAY_SIZE(ldo3_consumer),
+       .consumer_supplies      = ldo3_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_ldo4_data = {
+       .constraints    = {
+               .name           = "VDD_RTC_1.8V",
+               .min_uV         = 1800000,
+               .max_uV         = 1800000,
+               .apply_uV       = 1,
+               .always_on      = 1,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+};
+
+static struct regulator_init_data __initdata max8997_ldo6_data = {
+       .constraints    = {
+               .name           = "VMIPI_1.8V",
+               .min_uV         = 1800000,
+               .max_uV         = 1800000,
+               .apply_uV       = 1,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+       .num_consumer_supplies  = ARRAY_SIZE(ldo6_consumer),
+       .consumer_supplies      = ldo6_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_ldo7_data = {
+       .constraints    = {
+               .name           = "VDD_AUD_1.8V",
+               .min_uV         = 1800000,
+               .max_uV         = 1800000,
+               .apply_uV       = 1,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+       .num_consumer_supplies  = ARRAY_SIZE(ldo7_consumer),
+       .consumer_supplies      = ldo7_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_ldo8_data = {
+       .constraints    = {
+               .name           = "VADC_3.3V",
+               .min_uV         = 3300000,
+               .max_uV         = 3300000,
+               .apply_uV       = 1,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+       .num_consumer_supplies  = ARRAY_SIZE(ldo8_consumer),
+       .consumer_supplies      = ldo8_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_ldo9_data = {
+       .constraints    = {
+               .name           = "DVDD_SWB_2.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(ldo9_consumer),
+       .consumer_supplies      = ldo9_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_ldo10_data = {
+       .constraints    = {
+               .name           = "VDD_PLL_1.1V",
+               .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           = "VDD_AUD_3V",
+               .min_uV         = 3000000,
+               .max_uV         = 3000000,
+               .apply_uV       = 1,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+       .num_consumer_supplies  = ARRAY_SIZE(ldo11_consumer),
+       .consumer_supplies      = ldo11_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_ldo14_data = {
+       .constraints    = {
+               .name           = "AVDD18_SWB_1.8V",
+               .min_uV         = 1800000,
+               .max_uV         = 1800000,
+               .apply_uV       = 1,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+       .num_consumer_supplies  = ARRAY_SIZE(ldo14_consumer),
+       .consumer_supplies      = ldo14_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_ldo17_data = {
+       .constraints    = {
+               .name           = "VDD_SWB_3.3V",
+               .min_uV         = 3300000,
+               .max_uV         = 3300000,
+               .apply_uV       = 1,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+       .num_consumer_supplies  = ARRAY_SIZE(ldo17_consumer),
+       .consumer_supplies      = ldo17_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_ldo21_data = {
+       .constraints    = {
+               .name           = "VDD_MIF_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           = "VDD_ARM_1.2V",
+               .min_uV         = 950000,
+               .max_uV         = 1350000,
+               .always_on      = 1,
+               .boot_on        = 1,
+               .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+       .num_consumer_supplies  = ARRAY_SIZE(buck1_consumer),
+       .consumer_supplies      = buck1_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_buck2_data = {
+       .constraints    = {
+               .name           = "VDD_INT_1.1V",
+               .min_uV         = 900000,
+               .max_uV         = 1100000,
+               .always_on      = 1,
+               .boot_on        = 1,
+               .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+       .num_consumer_supplies  = ARRAY_SIZE(buck2_consumer),
+       .consumer_supplies      = buck2_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_buck3_data = {
+       .constraints    = {
+               .name           = "VDD_G3D_1.1V",
+               .min_uV         = 900000,
+               .max_uV         = 1100000,
+               .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+                                       REGULATOR_CHANGE_STATUS,
+               .state_mem      = {
+                       .disabled       = 1,
+               },
+       },
+       .num_consumer_supplies  = ARRAY_SIZE(buck3_consumer),
+       .consumer_supplies      = buck3_consumer,
+};
+
+static struct regulator_init_data __initdata max8997_buck5_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_buck7_data = {
+       .constraints    = {
+               .name           = "VDD_LCD_3.3V",
+               .min_uV         = 3300000,
+               .max_uV         = 3300000,
+               .boot_on        = 1,
+               .apply_uV       = 1,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+               .state_mem      = {
+                       .disabled       = 1
+               },
+       },
+       .num_consumer_supplies  = ARRAY_SIZE(buck7_consumer),
+       .consumer_supplies      = buck7_consumer,
+};
+
+static struct max8997_regulator_data __initdata origen_max8997_regulators[] = {
+       { MAX8997_LDO1,         &max8997_ldo1_data },
+       { MAX8997_LDO2,         &max8997_ldo2_data },
+       { MAX8997_LDO3,         &max8997_ldo3_data },
+       { MAX8997_LDO4,         &max8997_ldo4_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_LDO14,        &max8997_ldo14_data },
+       { MAX8997_LDO17,        &max8997_ldo17_data },
+       { MAX8997_LDO21,        &max8997_ldo21_data },
+       { MAX8997_BUCK1,        &max8997_buck1_data },
+       { MAX8997_BUCK2,        &max8997_buck2_data },
+       { MAX8997_BUCK3,        &max8997_buck3_data },
+       { MAX8997_BUCK5,        &max8997_buck5_data },
+       { MAX8997_BUCK7,        &max8997_buck7_data },
+};
+
+struct max8997_platform_data __initdata origen_max8997_pdata = {
+       .num_regulators = ARRAY_SIZE(origen_max8997_regulators),
+       .regulators     = origen_max8997_regulators,
+
+       .wakeup = true,
+       .buck1_gpiodvs  = false,
+       .buck2_gpiodvs  = false,
+       .buck5_gpiodvs  = false,
+       .irq_base       = IRQ_GPIO_END + 1,
+
+       .ignore_gpiodvs_side_effect = true,
+       .buck125_default_idx = 0x0,
+
+       .buck125_gpios[0]       = EXYNOS4_GPX0(0),
+       .buck125_gpios[1]       = EXYNOS4_GPX0(1),
+       .buck125_gpios[2]       = EXYNOS4_GPX0(2),
+
+       .buck1_voltage[0]       = 1350000,
+       .buck1_voltage[1]       = 1300000,
+       .buck1_voltage[2]       = 1250000,
+       .buck1_voltage[3]       = 1200000,
+       .buck1_voltage[4]       = 1150000,
+       .buck1_voltage[5]       = 1100000,
+       .buck1_voltage[6]       = 1000000,
+       .buck1_voltage[7]       = 950000,
+
+       .buck2_voltage[0]       = 1100000,
+       .buck2_voltage[1]       = 1100000,
+       .buck2_voltage[2]       = 1100000,
+       .buck2_voltage[3]       = 1100000,
+       .buck2_voltage[4]       = 1000000,
+       .buck2_voltage[5]       = 1000000,
+       .buck2_voltage[6]       = 1000000,
+       .buck2_voltage[7]       = 1000000,
+
+       .buck5_voltage[0]       = 1200000,
+       .buck5_voltage[1]       = 1200000,
+       .buck5_voltage[2]       = 1200000,
+       .buck5_voltage[3]       = 1200000,
+       .buck5_voltage[4]       = 1200000,
+       .buck5_voltage[5]       = 1200000,
+       .buck5_voltage[6]       = 1200000,
+       .buck5_voltage[7]       = 1200000,
+};
+
+/* I2C0 */
+static struct i2c_board_info i2c0_devs[] __initdata = {
+       {
+               I2C_BOARD_INFO("max8997", (0xCC >> 1)),
+               .platform_data  = &origen_max8997_pdata,
+               .irq            = IRQ_EINT(4),
+       },
+};
+
+static struct s3c_sdhci_platdata origen_hsmmc0_pdata __initdata = {
+       .cd_type                = S3C_SDHCI_CD_INTERNAL,
+       .clk_type               = S3C_SDHCI_CLK_DIV_EXTERNAL,
+};
+
+static struct s3c_sdhci_platdata origen_hsmmc2_pdata __initdata = {
+       .cd_type                = S3C_SDHCI_CD_INTERNAL,
+       .clk_type               = S3C_SDHCI_CLK_DIV_EXTERNAL,
+};
+
+/* USB EHCI */
+static struct s5p_ehci_platdata origen_ehci_pdata;
+
+static void __init origen_ehci_init(void)
+{
+       struct s5p_ehci_platdata *pdata = &origen_ehci_pdata;
+
+       s5p_ehci_set_platdata(pdata);
+}
+
+static struct gpio_keys_button origen_gpio_keys_table[] = {
+       {
+               .code                   = KEY_MENU,
+               .gpio                   = EXYNOS4_GPX1(5),
+               .desc                   = "gpio-keys: KEY_MENU",
+               .type                   = EV_KEY,
+               .active_low             = 1,
+               .wakeup                 = 1,
+               .debounce_interval      = 1,
+       }, {
+               .code                   = KEY_HOME,
+               .gpio                   = EXYNOS4_GPX1(6),
+               .desc                   = "gpio-keys: KEY_HOME",
+               .type                   = EV_KEY,
+               .active_low             = 1,
+               .wakeup                 = 1,
+               .debounce_interval      = 1,
+       }, {
+               .code                   = KEY_BACK,
+               .gpio                   = EXYNOS4_GPX1(7),
+               .desc                   = "gpio-keys: KEY_BACK",
+               .type                   = EV_KEY,
+               .active_low             = 1,
+               .wakeup                 = 1,
+               .debounce_interval      = 1,
+       }, {
+               .code                   = KEY_UP,
+               .gpio                   = EXYNOS4_GPX2(0),
+               .desc                   = "gpio-keys: KEY_UP",
+               .type                   = EV_KEY,
+               .active_low             = 1,
+               .wakeup                 = 1,
+               .debounce_interval      = 1,
+       }, {
+               .code                   = KEY_DOWN,
+               .gpio                   = EXYNOS4_GPX2(1),
+               .desc                   = "gpio-keys: KEY_DOWN",
+               .type                   = EV_KEY,
+               .active_low             = 1,
+               .wakeup                 = 1,
+               .debounce_interval      = 1,
+       },
+};
+
+static struct gpio_keys_platform_data origen_gpio_keys_data = {
+       .buttons        = origen_gpio_keys_table,
+       .nbuttons       = ARRAY_SIZE(origen_gpio_keys_table),
+};
+
+static struct platform_device origen_device_gpiokeys = {
+       .name           = "gpio-keys",
+       .dev            = {
+               .platform_data  = &origen_gpio_keys_data,
+       },
+};
+
+static void lcd_hv070wsa_set_power(struct plat_lcd_data *pd, unsigned int power)
+{
+       int ret;
+
+       if (power)
+               ret = gpio_request_one(EXYNOS4_GPE3(4),
+                                       GPIOF_OUT_INIT_HIGH, "GPE3_4");
+       else
+               ret = gpio_request_one(EXYNOS4_GPE3(4),
+                                       GPIOF_OUT_INIT_LOW, "GPE3_4");
+
+       gpio_free(EXYNOS4_GPE3(4));
+
+       if (ret)
+               pr_err("failed to request gpio for LCD power: %d\n", ret);
+}
+
+static struct plat_lcd_data origen_lcd_hv070wsa_data = {
+       .set_power = lcd_hv070wsa_set_power,
+};
+
+static struct platform_device origen_lcd_hv070wsa = {
+       .name                   = "platform-lcd",
+       .dev.parent             = &s5p_device_fimd0.dev,
+       .dev.platform_data      = &origen_lcd_hv070wsa_data,
+};
+
+static struct s3c_fb_pd_win origen_fb_win0 = {
+       .win_mode = {
+               .left_margin    = 64,
+               .right_margin   = 16,
+               .upper_margin   = 64,
+               .lower_margin   = 16,
+               .hsync_len      = 48,
+               .vsync_len      = 3,
+               .xres           = 1024,
+               .yres           = 600,
+       },
+       .max_bpp                = 32,
+       .default_bpp            = 24,
+};
+
+static struct s3c_fb_platdata origen_lcd_pdata __initdata = {
+       .win[0]         = &origen_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 platform_device *origen_devices[] __initdata = {
+       &s3c_device_hsmmc2,
+       &s3c_device_hsmmc0,
+       &s3c_device_i2c0,
+       &s3c_device_rtc,
+       &s3c_device_wdt,
+       &s5p_device_ehci,
+       &s5p_device_fimc0,
+       &s5p_device_fimc1,
+       &s5p_device_fimc2,
+       &s5p_device_fimc3,
+       &s5p_device_fimd0,
+       &s5p_device_hdmi,
+       &s5p_device_i2c_hdmiphy,
+       &s5p_device_mfc,
+       &s5p_device_mfc_l,
+       &s5p_device_mfc_r,
+       &s5p_device_mixer,
+       &exynos4_device_pd[PD_LCD0],
+       &exynos4_device_pd[PD_TV],
+       &exynos4_device_pd[PD_G3D],
+       &exynos4_device_pd[PD_LCD1],
+       &exynos4_device_pd[PD_CAM],
+       &exynos4_device_pd[PD_GPS],
+       &exynos4_device_pd[PD_MFC],
+       &origen_device_gpiokeys,
+       &origen_lcd_hv070wsa,
+};
+
+/* LCD Backlight data */
+static struct samsung_bl_gpio_info origen_bl_gpio_info = {
+       .no             = EXYNOS4_GPD0(0),
+       .func           = S3C_GPIO_SFN(2),
+};
+
+static struct platform_pwm_backlight_data origen_bl_data = {
+       .pwm_id         = 0,
+       .pwm_period_ns  = 1000,
+};
+
+static void s5p_tv_setup(void)
+{
+       /* Direct HPD to HDMI chip */
+       gpio_request_one(EXYNOS4_GPX3(7), GPIOF_IN, "hpd-plug");
+       s3c_gpio_cfgpin(EXYNOS4_GPX3(7), S3C_GPIO_SFN(0x3));
+       s3c_gpio_setpull(EXYNOS4_GPX3(7), S3C_GPIO_PULL_NONE);
+}
+
+static void __init origen_map_io(void)
+{
+       s5p_init_io(NULL, 0, S5P_VA_CHIPID);
+       s3c24xx_init_clocks(24000000);
+       s3c24xx_init_uarts(origen_uartcfgs, ARRAY_SIZE(origen_uartcfgs));
+}
+
+static void __init origen_power_init(void)
+{
+       gpio_request(EXYNOS4_GPX0(4), "PMIC_IRQ");
+       s3c_gpio_cfgpin(EXYNOS4_GPX0(4), S3C_GPIO_SFN(0xf));
+       s3c_gpio_setpull(EXYNOS4_GPX0(4), S3C_GPIO_PULL_NONE);
+}
+
+static void __init origen_reserve(void)
+{
+       s5p_mfc_reserve_mem(0x43000000, 8 << 20, 0x51000000, 8 << 20);
+}
+
+static void __init origen_machine_init(void)
+{
+       origen_power_init();
+
+       s3c_i2c0_set_platdata(NULL);
+       i2c_register_board_info(0, i2c0_devs, ARRAY_SIZE(i2c0_devs));
+
+       /*
+        * Since sdhci instance 2 can contain a bootable media,
+        * sdhci instance 0 is registered after instance 2.
+        */
+       s3c_sdhci2_set_platdata(&origen_hsmmc2_pdata);
+       s3c_sdhci0_set_platdata(&origen_hsmmc0_pdata);
+
+       origen_ehci_init();
+       clk_xusbxti.rate = 24000000;
+
+       s5p_tv_setup();
+       s5p_i2c_hdmiphy_set_platdata(NULL);
+
+       s5p_fimd0_set_platdata(&origen_lcd_pdata);
+
+       platform_add_devices(origen_devices, ARRAY_SIZE(origen_devices));
+
+       s5p_device_fimd0.dev.parent = &exynos4_device_pd[PD_LCD0].dev;
+
+       s5p_device_hdmi.dev.parent = &exynos4_device_pd[PD_TV].dev;
+       s5p_device_mixer.dev.parent = &exynos4_device_pd[PD_TV].dev;
+
+       s5p_device_mfc.dev.parent = &exynos4_device_pd[PD_MFC].dev;
+
+       samsung_bl_set(&origen_bl_gpio_info, &origen_bl_data);
+}
+
+MACHINE_START(ORIGEN, "ORIGEN")
+       /* Maintainer: JeongHyeon Kim <jhkim@insignal.co.kr> */
+       .atag_offset    = 0x100,
+       .init_irq       = exynos4_init_irq,
+       .map_io         = origen_map_io,
+       .init_machine   = origen_machine_init,
+       .timer          = &exynos4_timer,
+       .reserve        = &origen_reserve,
+MACHINE_END
similarity index 88%
rename from arch/arm/mach-exynos4/mach-smdkv310.c
rename to arch/arm/mach-exynos/mach-smdkv310.c
index 2c1a076..cec2afa 100644 (file)
@@ -37,6 +37,9 @@
 #include <plat/pd.h>
 #include <plat/gpio-cfg.h>
 #include <plat/backlight.h>
+#include <plat/mfc.h>
+#include <plat/ehci.h>
+#include <plat/clock.h>
 
 #include <mach/map.h>
 
@@ -232,17 +235,36 @@ static struct i2c_board_info i2c_devs1[] __initdata = {
        {I2C_BOARD_INFO("wm8994", 0x1a),},
 };
 
+/* USB EHCI */
+static struct s5p_ehci_platdata smdkv310_ehci_pdata;
+
+static void __init smdkv310_ehci_init(void)
+{
+       struct s5p_ehci_platdata *pdata = &smdkv310_ehci_pdata;
+
+       s5p_ehci_set_platdata(pdata);
+}
+
 static struct platform_device *smdkv310_devices[] __initdata = {
        &s3c_device_hsmmc0,
        &s3c_device_hsmmc1,
        &s3c_device_hsmmc2,
        &s3c_device_hsmmc3,
        &s3c_device_i2c1,
+       &s5p_device_i2c_hdmiphy,
        &s3c_device_rtc,
        &s3c_device_wdt,
+       &s5p_device_ehci,
+       &s5p_device_fimc0,
+       &s5p_device_fimc1,
+       &s5p_device_fimc2,
+       &s5p_device_fimc3,
        &exynos4_device_ac97,
        &exynos4_device_i2s0,
        &samsung_device_keypad,
+       &s5p_device_mfc,
+       &s5p_device_mfc_l,
+       &s5p_device_mfc_r,
        &exynos4_device_pd[PD_MFC],
        &exynos4_device_pd[PD_G3D],
        &exynos4_device_pd[PD_LCD0],
@@ -258,6 +280,8 @@ static struct platform_device *smdkv310_devices[] __initdata = {
        &smdkv310_lcd_lte480wv,
        &smdkv310_smsc911x,
        &exynos4_device_ahci,
+       &s5p_device_hdmi,
+       &s5p_device_mixer,
 };
 
 static void __init smdkv310_smsc911x_init(void)
@@ -294,6 +318,18 @@ static struct platform_pwm_backlight_data smdkv310_bl_data = {
        .pwm_period_ns  = 1000,
 };
 
+static void s5p_tv_setup(void)
+{
+       /* direct HPD to HDMI chip */
+       WARN_ON(gpio_request_one(EXYNOS4_GPX3(7), GPIOF_IN, "hpd-plug"));
+       s3c_gpio_cfgpin(EXYNOS4_GPX3(7), S3C_GPIO_SFN(0x3));
+       s3c_gpio_setpull(EXYNOS4_GPX3(7), S3C_GPIO_PULL_NONE);
+
+       /* setup dependencies between TV devices */
+       s5p_device_hdmi.dev.parent = &exynos4_device_pd[PD_TV].dev;
+       s5p_device_mixer.dev.parent = &exynos4_device_pd[PD_TV].dev;
+}
+
 static void __init smdkv310_map_io(void)
 {
        s5p_init_io(NULL, 0, S5P_VA_CHIPID);
@@ -301,6 +337,11 @@ static void __init smdkv310_map_io(void)
        s3c24xx_init_uarts(smdkv310_uartcfgs, ARRAY_SIZE(smdkv310_uartcfgs));
 }
 
+static void __init smdkv310_reserve(void)
+{
+       s5p_mfc_reserve_mem(0x43000000, 8 << 20, 0x51000000, 8 << 20);
+}
+
 static void __init smdkv310_machine_init(void)
 {
        s3c_i2c1_set_platdata(NULL);
@@ -313,12 +354,19 @@ static void __init smdkv310_machine_init(void)
        s3c_sdhci2_set_platdata(&smdkv310_hsmmc2_pdata);
        s3c_sdhci3_set_platdata(&smdkv310_hsmmc3_pdata);
 
+       s5p_tv_setup();
+       s5p_i2c_hdmiphy_set_platdata(NULL);
+
        samsung_keypad_set_platdata(&smdkv310_keypad_data);
 
        samsung_bl_set(&smdkv310_bl_gpio_info, &smdkv310_bl_data);
        s5p_fimd0_set_platdata(&smdkv310_lcd0_pdata);
 
+       smdkv310_ehci_init();
+       clk_xusbxti.rate = 24000000;
+
        platform_add_devices(smdkv310_devices, ARRAY_SIZE(smdkv310_devices));
+       s5p_device_mfc.dev.parent = &exynos4_device_pd[PD_MFC].dev;
 }
 
 MACHINE_START(SMDKV310, "SMDKV310")
@@ -329,6 +377,7 @@ MACHINE_START(SMDKV310, "SMDKV310")
        .map_io         = smdkv310_map_io,
        .init_machine   = smdkv310_machine_init,
        .timer          = &exynos4_timer,
+       .reserve        = &smdkv310_reserve,
 MACHINE_END
 
 MACHINE_START(SMDKC210, "SMDKC210")
similarity index 67%
rename from arch/arm/mach-exynos4/mach-universal_c210.c
rename to arch/arm/mach-exynos/mach-universal_c210.c
index 2aac6f7..a2a177f 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/i2c.h>
 #include <linux/gpio_keys.h>
 #include <linux/gpio.h>
+#include <linux/fb.h>
 #include <linux/mfd/max8998.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/fixed.h>
 #include <plat/devs.h>
 #include <plat/iic.h>
 #include <plat/gpio-cfg.h>
+#include <plat/fb.h>
 #include <plat/mfc.h>
 #include <plat/sdhci.h>
 #include <plat/pd.h>
+#include <plat/regs-fb-v4.h>
+#include <plat/fimc-core.h>
+#include <plat/camport.h>
+#include <plat/mipi_csis.h>
 
 #include <mach/map.h>
 
+#include <media/v4l2-mediabus.h>
+#include <media/s5p_fimc.h>
+#include <media/m5mols.h>
+
 /* Following are default values for UCON, ULCON and UFCON UART registers */
 #define UNIVERSAL_UCON_DEFAULT (S3C2410_UCON_TXILEVEL |        \
                                 S3C2410_UCON_RXILEVEL |        \
@@ -110,6 +120,9 @@ static struct regulator_consumer_supply lp3974_buck1_consumer =
 static struct regulator_consumer_supply lp3974_buck2_consumer =
        REGULATOR_SUPPLY("vddg3d", NULL);
 
+static struct regulator_consumer_supply lp3974_buck3_consumer =
+       REGULATOR_SUPPLY("vdet", "s5p-sdo");
+
 static struct regulator_init_data lp3974_buck1_data = {
        .constraints    = {
                .name           = "VINT_1.1V",
@@ -153,6 +166,8 @@ static struct regulator_init_data lp3974_buck3_data = {
                        .enabled        = 1,
                },
        },
+       .num_consumer_supplies = 1,
+       .consumer_supplies = &lp3974_buck3_consumer,
 };
 
 static struct regulator_init_data lp3974_buck4_data = {
@@ -181,6 +196,12 @@ static struct regulator_init_data lp3974_ldo2_data = {
        },
 };
 
+static struct regulator_consumer_supply lp3974_ldo3_consumer[] = {
+       REGULATOR_SUPPLY("vdd", "exynos4-hdmi"),
+       REGULATOR_SUPPLY("vdd_pll", "exynos4-hdmi"),
+       REGULATOR_SUPPLY("vdd11", "s5p-mipi-csis.0"),
+};
+
 static struct regulator_init_data lp3974_ldo3_data = {
        .constraints    = {
                .name           = "VUSB+MIPI_1.1V",
@@ -192,6 +213,12 @@ static struct regulator_init_data lp3974_ldo3_data = {
                        .disabled       = 1,
                },
        },
+       .num_consumer_supplies = ARRAY_SIZE(lp3974_ldo3_consumer),
+       .consumer_supplies = lp3974_ldo3_consumer,
+};
+
+static struct regulator_consumer_supply lp3974_ldo4_consumer[] = {
+       REGULATOR_SUPPLY("vdd_osc", "exynos4-hdmi"),
 };
 
 static struct regulator_init_data lp3974_ldo4_data = {
@@ -205,6 +232,8 @@ static struct regulator_init_data lp3974_ldo4_data = {
                        .disabled       = 1,
                },
        },
+       .num_consumer_supplies = ARRAY_SIZE(lp3974_ldo4_consumer),
+       .consumer_supplies = lp3974_ldo4_consumer,
 };
 
 static struct regulator_init_data lp3974_ldo5_data = {
@@ -233,6 +262,10 @@ static struct regulator_init_data lp3974_ldo6_data = {
        },
 };
 
+static struct regulator_consumer_supply lp3974_ldo7_consumer[] = {
+       REGULATOR_SUPPLY("vdd18", "s5p-mipi-csis.0"),
+};
+
 static struct regulator_init_data lp3974_ldo7_data = {
        .constraints    = {
                .name           = "VLCD+VMIPI_1.8V",
@@ -244,6 +277,12 @@ static struct regulator_init_data lp3974_ldo7_data = {
                        .disabled       = 1,
                },
        },
+       .num_consumer_supplies  = ARRAY_SIZE(lp3974_ldo7_consumer),
+       .consumer_supplies      = lp3974_ldo7_consumer,
+};
+
+static struct regulator_consumer_supply lp3974_ldo8_consumer[] = {
+       REGULATOR_SUPPLY("vdd33a_dac", "s5p-sdo"),
 };
 
 static struct regulator_init_data lp3974_ldo8_data = {
@@ -257,6 +296,8 @@ static struct regulator_init_data lp3974_ldo8_data = {
                        .disabled       = 1,
                },
        },
+       .num_consumer_supplies = ARRAY_SIZE(lp3974_ldo8_consumer),
+       .consumer_supplies = lp3974_ldo8_consumer,
 };
 
 static struct regulator_init_data lp3974_ldo9_data = {
@@ -286,6 +327,9 @@ static struct regulator_init_data lp3974_ldo10_data = {
        },
 };
 
+static struct regulator_consumer_supply lp3974_ldo11_consumer =
+       REGULATOR_SUPPLY("dig_28", "0-001f");
+
 static struct regulator_init_data lp3974_ldo11_data = {
        .constraints    = {
                .name           = "CAM_AF_3.3V",
@@ -297,6 +341,8 @@ static struct regulator_init_data lp3974_ldo11_data = {
                        .disabled       = 1,
                },
        },
+       .num_consumer_supplies  = 1,
+       .consumer_supplies      = &lp3974_ldo11_consumer,
 };
 
 static struct regulator_init_data lp3974_ldo12_data = {
@@ -325,6 +371,9 @@ static struct regulator_init_data lp3974_ldo13_data = {
        },
 };
 
+static struct regulator_consumer_supply lp3974_ldo14_consumer =
+       REGULATOR_SUPPLY("dig_18", "0-001f");
+
 static struct regulator_init_data lp3974_ldo14_data = {
        .constraints    = {
                .name           = "CAM_I_HOST_1.8V",
@@ -336,8 +385,14 @@ static struct regulator_init_data lp3974_ldo14_data = {
                        .disabled       = 1,
                },
        },
+       .num_consumer_supplies  = 1,
+       .consumer_supplies      = &lp3974_ldo14_consumer,
 };
 
+
+static struct regulator_consumer_supply lp3974_ldo15_consumer =
+       REGULATOR_SUPPLY("dig_12", "0-001f");
+
 static struct regulator_init_data lp3974_ldo15_data = {
        .constraints    = {
                .name           = "CAM_S_DIG+FM33_CORE_1.2V",
@@ -349,6 +404,12 @@ static struct regulator_init_data lp3974_ldo15_data = {
                        .disabled       = 1,
                },
        },
+       .num_consumer_supplies  = 1,
+       .consumer_supplies      = &lp3974_ldo15_consumer,
+};
+
+static struct regulator_consumer_supply lp3974_ldo16_consumer[] = {
+       REGULATOR_SUPPLY("a_sensor", "0-001f"),
 };
 
 static struct regulator_init_data lp3974_ldo16_data = {
@@ -362,6 +423,8 @@ static struct regulator_init_data lp3974_ldo16_data = {
                        .disabled       = 1,
                },
        },
+       .num_consumer_supplies  = ARRAY_SIZE(lp3974_ldo16_consumer),
+       .consumer_supplies      = lp3974_ldo16_consumer,
 };
 
 static struct regulator_init_data lp3974_ldo17_data = {
@@ -472,6 +535,43 @@ static struct max8998_platform_data universal_lp3974_pdata = {
        .wakeup                 = true,
 };
 
+
+enum fixed_regulator_id {
+       FIXED_REG_ID_MMC0,
+       FIXED_REG_ID_HDMI_5V,
+       FIXED_REG_ID_CAM_S_IF,
+       FIXED_REG_ID_CAM_I_CORE,
+       FIXED_REG_ID_CAM_VT_DIO,
+};
+
+static struct regulator_consumer_supply hdmi_fixed_consumer =
+       REGULATOR_SUPPLY("hdmi-en", "exynos4-hdmi");
+
+static struct regulator_init_data hdmi_fixed_voltage_init_data = {
+       .constraints            = {
+               .name           = "HDMI_5V",
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+       },
+       .num_consumer_supplies  = 1,
+       .consumer_supplies      = &hdmi_fixed_consumer,
+};
+
+static struct fixed_voltage_config hdmi_fixed_voltage_config = {
+       .supply_name            = "HDMI_EN1",
+       .microvolts             = 5000000,
+       .gpio                   = EXYNOS4_GPE0(1),
+       .enable_high            = true,
+       .init_data              = &hdmi_fixed_voltage_init_data,
+};
+
+static struct platform_device hdmi_fixed_voltage = {
+       .name                   = "reg-fixed-voltage",
+       .id                     = FIXED_REG_ID_HDMI_5V,
+       .dev                    = {
+               .platform_data  = &hdmi_fixed_voltage_config,
+       },
+};
+
 /* GPIO I2C 5 (PMIC) */
 static struct i2c_board_info i2c5_devs[] __initdata = {
        {
@@ -573,6 +673,11 @@ static void __init universal_touchkey_init(void)
        gpio_direction_output(gpio, 1);
 }
 
+static struct s3c2410_platform_i2c universal_i2c0_platdata __initdata = {
+       .frequency      = 300 * 1000,
+       .sda_delay      = 200,
+};
+
 /* GPIO KEYS */
 static struct gpio_keys_button universal_gpio_keys_tables[] = {
        {
@@ -658,7 +763,7 @@ static struct fixed_voltage_config mmc0_fixed_voltage_config = {
 
 static struct platform_device mmc0_fixed_voltage = {
        .name                   = "reg-fixed-voltage",
-       .id                     = 0,
+       .id                     = FIXED_REG_ID_MMC0,
        .dev                    = {
                .platform_data  = &mmc0_fixed_voltage_config,
        },
@@ -692,18 +797,165 @@ static void __init universal_sdhci_init(void)
        s3c_sdhci3_set_platdata(&universal_hsmmc3_data);
 }
 
-/* I2C0 */
-static struct i2c_board_info i2c0_devs[] __initdata = {
-       /* Camera, To be updated */
-};
-
 /* I2C1 */
 static struct i2c_board_info i2c1_devs[] __initdata = {
        /* Gyro, To be updated */
 };
 
+/* Frame Buffer */
+static struct s3c_fb_pd_win universal_fb_win0 = {
+       .win_mode = {
+               .left_margin    = 16,
+               .right_margin   = 16,
+               .upper_margin   = 2,
+               .lower_margin   = 28,
+               .hsync_len      = 2,
+               .vsync_len      = 1,
+               .xres           = 480,
+               .yres           = 800,
+               .refresh        = 55,
+       },
+       .max_bpp        = 32,
+       .default_bpp    = 16,
+};
+
+static struct s3c_fb_platdata universal_lcd_pdata __initdata = {
+       .win[0]         = &universal_fb_win0,
+       .vidcon0        = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB |
+                         VIDCON0_CLKSEL_LCD,
+       .vidcon1        = VIDCON1_INV_VCLK | VIDCON1_INV_VDEN
+                         | VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
+       .setup_gpio     = exynos4_fimd0_gpio_setup_24bpp,
+};
+
+static struct regulator_consumer_supply cam_i_core_supply =
+       REGULATOR_SUPPLY("core", "0-001f");
+
+static struct regulator_init_data cam_i_core_reg_init_data = {
+       .constraints = { .valid_ops_mask = REGULATOR_CHANGE_STATUS },
+       .num_consumer_supplies = 1,
+       .consumer_supplies = &cam_i_core_supply,
+};
+
+static struct fixed_voltage_config cam_i_core_fixed_voltage_cfg = {
+       .supply_name    = "CAM_I_CORE_1.2V",
+       .microvolts     = 1200000,
+       .gpio           = EXYNOS4_GPE2(2),      /* CAM_8M_CORE_EN */
+       .enable_high    = 1,
+       .init_data      = &cam_i_core_reg_init_data,
+};
+
+static struct platform_device cam_i_core_fixed_reg_dev = {
+       .name = "reg-fixed-voltage", .id = FIXED_REG_ID_CAM_I_CORE,
+       .dev = { .platform_data = &cam_i_core_fixed_voltage_cfg },
+};
+
+static struct regulator_consumer_supply cam_s_if_supply =
+       REGULATOR_SUPPLY("d_sensor", "0-001f");
+
+static struct regulator_init_data cam_s_if_reg_init_data = {
+       .constraints = { .valid_ops_mask = REGULATOR_CHANGE_STATUS },
+       .num_consumer_supplies = 1,
+       .consumer_supplies = &cam_s_if_supply,
+};
+
+static struct fixed_voltage_config cam_s_if_fixed_voltage_cfg = {
+       .supply_name    = "CAM_S_IF_1.8V",
+       .microvolts     = 1800000,
+       .gpio           = EXYNOS4_GPE3(0),      /* CAM_PWR_EN1 */
+       .enable_high    = 1,
+       .init_data      = &cam_s_if_reg_init_data,
+};
+
+static struct platform_device cam_s_if_fixed_reg_dev = {
+       .name = "reg-fixed-voltage", .id = FIXED_REG_ID_CAM_S_IF,
+       .dev = { .platform_data = &cam_s_if_fixed_voltage_cfg },
+};
+
+static struct s5p_platform_mipi_csis mipi_csis_platdata = {
+       .clk_rate       = 166000000UL,
+       .lanes          = 2,
+       .alignment      = 32,
+       .hs_settle      = 12,
+       .phy_enable     = s5p_csis_phy_enable,
+};
+
+#define GPIO_CAM_LEVEL_EN(n)   EXYNOS4_GPE4(n + 3)
+#define GPIO_CAM_8M_ISP_INT    EXYNOS4_GPX1(5) /* XEINT_13 */
+#define GPIO_CAM_MEGA_nRST     EXYNOS4_GPE2(5)
+
+static int m5mols_set_power(struct device *dev, int on)
+{
+       gpio_set_value(GPIO_CAM_LEVEL_EN(1), !on);
+       gpio_set_value(GPIO_CAM_LEVEL_EN(2), !!on);
+       return 0;
+}
+
+static struct m5mols_platform_data m5mols_platdata = {
+       .gpio_reset     = GPIO_CAM_MEGA_nRST,
+       .reset_polarity = 0,
+       .set_power      = m5mols_set_power,
+};
+
+static struct i2c_board_info m5mols_board_info = {
+       I2C_BOARD_INFO("M5MOLS", 0x1F),
+       .platform_data = &m5mols_platdata,
+};
+
+static struct s5p_fimc_isp_info universal_camera_sensors[] = {
+       {
+               .mux_id         = 0,
+               .flags          = V4L2_MBUS_PCLK_SAMPLE_FALLING |
+                                 V4L2_MBUS_VSYNC_ACTIVE_LOW,
+               .bus_type       = FIMC_MIPI_CSI2,
+               .board_info     = &m5mols_board_info,
+               .i2c_bus_num    = 0,
+               .clk_frequency  = 21600000UL,
+               .csi_data_align = 32,
+       },
+};
+
+static struct s5p_platform_fimc fimc_md_platdata = {
+       .isp_info       = universal_camera_sensors,
+       .num_clients    = ARRAY_SIZE(universal_camera_sensors),
+};
+
+static struct gpio universal_camera_gpios[] = {
+       { GPIO_CAM_LEVEL_EN(1), GPIOF_OUT_INIT_HIGH, "CAM_LVL_EN1" },
+       { GPIO_CAM_LEVEL_EN(2), GPIOF_OUT_INIT_LOW,  "CAM_LVL_EN2" },
+       { GPIO_CAM_8M_ISP_INT,  GPIOF_IN,            "8M_ISP_INT"  },
+       { GPIO_CAM_MEGA_nRST,   GPIOF_OUT_INIT_LOW,  "CAM_8M_NRST" },
+};
+
+static void universal_camera_init(void)
+{
+       s3c_set_platdata(&mipi_csis_platdata, sizeof(mipi_csis_platdata),
+                        &s5p_device_mipi_csis0);
+       s3c_set_platdata(&fimc_md_platdata,  sizeof(fimc_md_platdata),
+                        &s5p_device_fimc_md);
+
+       if (gpio_request_array(universal_camera_gpios,
+                              ARRAY_SIZE(universal_camera_gpios))) {
+               pr_err("%s: GPIO request failed\n", __func__);
+               return;
+       }
+
+       if (!s3c_gpio_cfgpin(GPIO_CAM_8M_ISP_INT, S3C_GPIO_SFN(0xf)))
+               m5mols_board_info.irq = gpio_to_irq(GPIO_CAM_8M_ISP_INT);
+       else
+               pr_err("Failed to configure 8M_ISP_INT GPIO\n");
+
+       /* Free GPIOs controlled directly by the sensor drivers. */
+       gpio_free(GPIO_CAM_MEGA_nRST);
+       gpio_free(GPIO_CAM_8M_ISP_INT);
+
+       if (exynos4_fimc_setup_gpio(S5P_CAMPORT_A))
+               pr_err("Camera port A setup failed\n");
+}
+
 static struct platform_device *universal_devices[] __initdata = {
        /* Samsung Platform Devices */
+       &s5p_device_mipi_csis0,
        &s5p_device_fimc0,
        &s5p_device_fimc1,
        &s5p_device_fimc2,
@@ -712,17 +964,30 @@ static struct platform_device *universal_devices[] __initdata = {
        &s3c_device_hsmmc0,
        &s3c_device_hsmmc2,
        &s3c_device_hsmmc3,
+       &s3c_device_i2c0,
        &s3c_device_i2c3,
        &s3c_device_i2c5,
+       &s5p_device_i2c_hdmiphy,
+       &hdmi_fixed_voltage,
+       &exynos4_device_pd[PD_TV],
+       &s5p_device_hdmi,
+       &s5p_device_sdo,
+       &s5p_device_mixer,
 
        /* Universal Devices */
        &i2c_gpio12,
        &universal_gpio_keys,
        &s5p_device_onenand,
+       &s5p_device_fimd0,
        &s5p_device_mfc,
        &s5p_device_mfc_l,
        &s5p_device_mfc_r,
        &exynos4_device_pd[PD_MFC],
+       &exynos4_device_pd[PD_LCD0],
+       &exynos4_device_pd[PD_CAM],
+       &cam_i_core_fixed_reg_dev,
+       &cam_s_if_fixed_reg_dev,
+       &s5p_device_fimc_md,
 };
 
 static void __init universal_map_io(void)
@@ -732,6 +997,20 @@ static void __init universal_map_io(void)
        s3c24xx_init_uarts(universal_uartcfgs, ARRAY_SIZE(universal_uartcfgs));
 }
 
+void s5p_tv_setup(void)
+{
+       /* direct HPD to HDMI chip */
+       gpio_request(EXYNOS4_GPX3(7), "hpd-plug");
+
+       gpio_direction_input(EXYNOS4_GPX3(7));
+       s3c_gpio_cfgpin(EXYNOS4_GPX3(7), S3C_GPIO_SFN(0x3));
+       s3c_gpio_setpull(EXYNOS4_GPX3(7), S3C_GPIO_PULL_NONE);
+
+       /* setup dependencies between TV devices */
+       s5p_device_hdmi.dev.parent = &exynos4_device_pd[PD_TV].dev;
+       s5p_device_mixer.dev.parent = &exynos4_device_pd[PD_TV].dev;
+}
+
 static void __init universal_reserve(void)
 {
        s5p_mfc_reserve_mem(0x43000000, 8 << 20, 0x51000000, 8 << 20);
@@ -740,8 +1019,9 @@ static void __init universal_reserve(void)
 static void __init universal_machine_init(void)
 {
        universal_sdhci_init();
+       s5p_tv_setup();
 
-       i2c_register_board_info(0, i2c0_devs, ARRAY_SIZE(i2c0_devs));
+       s3c_i2c0_set_platdata(&universal_i2c0_platdata);
        i2c_register_board_info(1, i2c1_devs, ARRAY_SIZE(i2c1_devs));
 
        universal_tsp_init();
@@ -749,15 +1029,28 @@ static void __init universal_machine_init(void)
        i2c_register_board_info(3, i2c3_devs, ARRAY_SIZE(i2c3_devs));
 
        s3c_i2c5_set_platdata(NULL);
+       s5p_i2c_hdmiphy_set_platdata(NULL);
        i2c_register_board_info(5, i2c5_devs, ARRAY_SIZE(i2c5_devs));
 
+       s5p_fimd0_set_platdata(&universal_lcd_pdata);
+
        universal_touchkey_init();
        i2c_register_board_info(I2C_GPIO_BUS_12, i2c_gpio12_devs,
                        ARRAY_SIZE(i2c_gpio12_devs));
 
+       universal_camera_init();
+
        /* Last */
        platform_add_devices(universal_devices, ARRAY_SIZE(universal_devices));
+
        s5p_device_mfc.dev.parent = &exynos4_device_pd[PD_MFC].dev;
+       s5p_device_fimd0.dev.parent = &exynos4_device_pd[PD_LCD0].dev;
+
+       s5p_device_fimc0.dev.parent = &exynos4_device_pd[PD_CAM].dev;
+       s5p_device_fimc1.dev.parent = &exynos4_device_pd[PD_CAM].dev;
+       s5p_device_fimc2.dev.parent = &exynos4_device_pd[PD_CAM].dev;
+       s5p_device_fimc3.dev.parent = &exynos4_device_pd[PD_CAM].dev;
+       s5p_device_mipi_csis0.dev.parent = &exynos4_device_pd[PD_CAM].dev;
 }
 
 MACHINE_START(UNIVERSAL_C210, "UNIVERSAL_C210")
similarity index 91%
rename from arch/arm/mach-exynos4/mct.c
rename to arch/arm/mach-exynos/mct.c
index f191608..97343df 100644 (file)
@@ -44,7 +44,7 @@ struct mct_clock_event_device {
        char name[10];
 };
 
-struct mct_clock_event_device mct_tick[NR_CPUS];
+static DEFINE_PER_CPU(struct mct_clock_event_device, percpu_mct_tick);
 
 static void exynos4_mct_write(unsigned int value, void *addr)
 {
@@ -302,7 +302,7 @@ static void exynos4_mct_tick_start(unsigned long cycles,
 static int exynos4_tick_set_next_event(unsigned long cycles,
                                       struct clock_event_device *evt)
 {
-       struct mct_clock_event_device *mevt = &mct_tick[smp_processor_id()];
+       struct mct_clock_event_device *mevt = this_cpu_ptr(&percpu_mct_tick);
 
        exynos4_mct_tick_start(cycles, mevt);
 
@@ -312,7 +312,7 @@ static int exynos4_tick_set_next_event(unsigned long cycles,
 static inline void exynos4_tick_set_mode(enum clock_event_mode mode,
                                         struct clock_event_device *evt)
 {
-       struct mct_clock_event_device *mevt = &mct_tick[smp_processor_id()];
+       struct mct_clock_event_device *mevt = this_cpu_ptr(&percpu_mct_tick);
 
        exynos4_mct_tick_stop(mevt);
 
@@ -376,14 +376,16 @@ static struct irqaction mct_tick1_event_irq = {
 
 static void exynos4_mct_tick_init(struct clock_event_device *evt)
 {
+       struct mct_clock_event_device *mevt;
        unsigned int cpu = smp_processor_id();
 
-       mct_tick[cpu].evt = evt;
+       mevt = this_cpu_ptr(&percpu_mct_tick);
+       mevt->evt = evt;
 
-       mct_tick[cpu].base = EXYNOS4_MCT_L_BASE(cpu);
-       sprintf(mct_tick[cpu].name, "mct_tick%d", cpu);
+       mevt->base = EXYNOS4_MCT_L_BASE(cpu);
+       sprintf(mevt->name, "mct_tick%d", cpu);
 
-       evt->name = mct_tick[cpu].name;
+       evt->name = mevt->name;
        evt->cpumask = cpumask_of(cpu);
        evt->set_next_event = exynos4_tick_set_next_event;
        evt->set_mode = exynos4_tick_set_mode;
@@ -398,21 +400,21 @@ static void exynos4_mct_tick_init(struct clock_event_device *evt)
 
        clockevents_register_device(evt);
 
-       exynos4_mct_write(0x1, mct_tick[cpu].base + MCT_L_TCNTB_OFFSET);
+       exynos4_mct_write(0x1, mevt->base + MCT_L_TCNTB_OFFSET);
 
        if (mct_int_type == MCT_INT_SPI) {
                if (cpu == 0) {
-                       mct_tick0_event_irq.dev_id = &mct_tick[cpu];
+                       mct_tick0_event_irq.dev_id = mevt;
                        evt->irq = IRQ_MCT_L0;
                        setup_irq(IRQ_MCT_L0, &mct_tick0_event_irq);
                } else {
-                       mct_tick1_event_irq.dev_id = &mct_tick[cpu];
+                       mct_tick1_event_irq.dev_id = mevt;
                        evt->irq = IRQ_MCT_L1;
                        setup_irq(IRQ_MCT_L1, &mct_tick1_event_irq);
                        irq_set_affinity(IRQ_MCT_L1, cpumask_of(1));
                }
        } else {
-               gic_enable_ppi(IRQ_MCT_LOCALTIMER);
+               enable_percpu_irq(IRQ_MCT_LOCALTIMER, 0);
        }
 }
 
@@ -427,9 +429,11 @@ int __cpuinit local_timer_setup(struct clock_event_device *evt)
 void local_timer_stop(struct clock_event_device *evt)
 {
        evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);
-       disable_irq(evt->irq);
+       if (mct_int_type == MCT_INT_SPI)
+               disable_irq(evt->irq);
+       else
+               disable_percpu_irq(IRQ_MCT_LOCALTIMER);
 }
-
 #endif /* CONFIG_LOCAL_TIMERS */
 
 static void __init exynos4_timer_resources(void)
@@ -438,6 +442,16 @@ static void __init exynos4_timer_resources(void)
        mct_clk = clk_get(NULL, "xtal");
 
        clk_rate = clk_get_rate(mct_clk);
+
+       if (mct_int_type == MCT_INT_PPI) {
+               int err;
+
+               err = request_percpu_irq(IRQ_MCT_LOCALTIMER,
+                                        exynos4_mct_tick_isr, "MCT",
+                                        &percpu_mct_tick);
+               WARN(err, "MCT: can't request IRQ %d (%d)\n",
+                    IRQ_MCT_LOCALTIMER, err);
+       }
 }
 
 static void __init exynos4_timer_init(void)
similarity index 99%
rename from arch/arm/mach-exynos4/platsmp.c
rename to arch/arm/mach-exynos/platsmp.c
index 0559540..69ffb2f 100644 (file)
@@ -110,8 +110,6 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
         */
        spin_lock(&boot_lock);
        spin_unlock(&boot_lock);
-
-       set_cpu_online(cpu, true);
 }
 
 int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
similarity index 98%
rename from arch/arm/mach-exynos4/pm.c
rename to arch/arm/mach-exynos/pm.c
index 62e4f43..509a435 100644 (file)
@@ -339,6 +339,13 @@ static int exynos4_pm_suspend(void)
        tmp &= ~S5P_CENTRAL_LOWPWR_CFG;
        __raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
 
+       if (soc_is_exynos4212()) {
+               tmp = __raw_readl(S5P_CENTRAL_SEQ_OPTION);
+               tmp &= ~(S5P_USE_STANDBYWFI_ISP_ARM |
+                        S5P_USE_STANDBYWFE_ISP_ARM);
+               __raw_writel(tmp, S5P_CENTRAL_SEQ_OPTION);
+       }
+
        /* Save Power control register */
        asm ("mrc p15, 0, %0, c15, c0, 0"
             : "=r" (tmp) : : "cc");
diff --git a/arch/arm/mach-exynos/pmu.c b/arch/arm/mach-exynos/pmu.c
new file mode 100644 (file)
index 0000000..bba48f5
--- /dev/null
@@ -0,0 +1,230 @@
+/* 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 struct exynos4_pmu_conf *exynos4_pmu_config;
+
+static struct exynos4_pmu_conf exynos4210_pmu_config[] = {
+       /* { .reg = address, .val = { AFTR, LPA, SLEEP } */
+       { S5P_ARM_CORE0_LOWPWR,                 { 0x0, 0x0, 0x2 } },
+       { S5P_DIS_IRQ_CORE0,                    { 0x0, 0x0, 0x0 } },
+       { S5P_DIS_IRQ_CENTRAL0,                 { 0x0, 0x0, 0x0 } },
+       { S5P_ARM_CORE1_LOWPWR,                 { 0x0, 0x0, 0x2 } },
+       { S5P_DIS_IRQ_CORE1,                    { 0x0, 0x0, 0x0 } },
+       { S5P_DIS_IRQ_CENTRAL1,                 { 0x0, 0x0, 0x0 } },
+       { S5P_ARM_COMMON_LOWPWR,                { 0x0, 0x0, 0x2 } },
+       { S5P_L2_0_LOWPWR,                      { 0x2, 0x2, 0x3 } },
+       { S5P_L2_1_LOWPWR,                      { 0x2, 0x2, 0x3 } },
+       { S5P_CMU_ACLKSTOP_LOWPWR,              { 0x1, 0x0, 0x0 } },
+       { S5P_CMU_SCLKSTOP_LOWPWR,              { 0x1, 0x0, 0x0 } },
+       { S5P_CMU_RESET_LOWPWR,                 { 0x1, 0x1, 0x0 } },
+       { S5P_APLL_SYSCLK_LOWPWR,               { 0x1, 0x0, 0x0 } },
+       { S5P_MPLL_SYSCLK_LOWPWR,               { 0x1, 0x0, 0x0 } },
+       { S5P_VPLL_SYSCLK_LOWPWR,               { 0x1, 0x0, 0x0 } },
+       { S5P_EPLL_SYSCLK_LOWPWR,               { 0x1, 0x1, 0x0 } },
+       { S5P_CMU_CLKSTOP_GPS_ALIVE_LOWPWR,     { 0x1, 0x1, 0x0 } },
+       { S5P_CMU_RESET_GPSALIVE_LOWPWR,        { 0x1, 0x1, 0x0 } },
+       { S5P_CMU_CLKSTOP_CAM_LOWPWR,           { 0x1, 0x1, 0x0 } },
+       { S5P_CMU_CLKSTOP_TV_LOWPWR,            { 0x1, 0x1, 0x0 } },
+       { S5P_CMU_CLKSTOP_MFC_LOWPWR,           { 0x1, 0x1, 0x0 } },
+       { S5P_CMU_CLKSTOP_G3D_LOWPWR,           { 0x1, 0x1, 0x0 } },
+       { S5P_CMU_CLKSTOP_LCD0_LOWPWR,          { 0x1, 0x1, 0x0 } },
+       { S5P_CMU_CLKSTOP_LCD1_LOWPWR,          { 0x1, 0x1, 0x0 } },
+       { S5P_CMU_CLKSTOP_MAUDIO_LOWPWR,        { 0x1, 0x1, 0x0 } },
+       { S5P_CMU_CLKSTOP_GPS_LOWPWR,           { 0x1, 0x1, 0x0 } },
+       { S5P_CMU_RESET_CAM_LOWPWR,             { 0x1, 0x1, 0x0 } },
+       { S5P_CMU_RESET_TV_LOWPWR,              { 0x1, 0x1, 0x0 } },
+       { S5P_CMU_RESET_MFC_LOWPWR,             { 0x1, 0x1, 0x0 } },
+       { S5P_CMU_RESET_G3D_LOWPWR,             { 0x1, 0x1, 0x0 } },
+       { S5P_CMU_RESET_LCD0_LOWPWR,            { 0x1, 0x1, 0x0 } },
+       { S5P_CMU_RESET_LCD1_LOWPWR,            { 0x1, 0x1, 0x0 } },
+       { S5P_CMU_RESET_MAUDIO_LOWPWR,          { 0x1, 0x1, 0x0 } },
+       { S5P_CMU_RESET_GPS_LOWPWR,             { 0x1, 0x1, 0x0 } },
+       { S5P_TOP_BUS_LOWPWR,                   { 0x3, 0x0, 0x0 } },
+       { S5P_TOP_RETENTION_LOWPWR,             { 0x1, 0x0, 0x1 } },
+       { S5P_TOP_PWR_LOWPWR,                   { 0x3, 0x0, 0x3 } },
+       { S5P_LOGIC_RESET_LOWPWR,               { 0x1, 0x1, 0x0 } },
+       { S5P_ONENAND_MEM_LOWPWR,               { 0x3, 0x0, 0x0 } },
+       { S5P_MODIMIF_MEM_LOWPWR,               { 0x3, 0x0, 0x0 } },
+       { S5P_G2D_ACP_MEM_LOWPWR,               { 0x3, 0x0, 0x0 } },
+       { S5P_USBOTG_MEM_LOWPWR,                { 0x3, 0x0, 0x0 } },
+       { S5P_HSMMC_MEM_LOWPWR,                 { 0x3, 0x0, 0x0 } },
+       { S5P_CSSYS_MEM_LOWPWR,                 { 0x3, 0x0, 0x0 } },
+       { S5P_SECSS_MEM_LOWPWR,                 { 0x3, 0x0, 0x0 } },
+       { S5P_PCIE_MEM_LOWPWR,                  { 0x3, 0x0, 0x0 } },
+       { S5P_SATA_MEM_LOWPWR,                  { 0x3, 0x0, 0x0 } },
+       { S5P_PAD_RETENTION_DRAM_LOWPWR,        { 0x1, 0x0, 0x0 } },
+       { S5P_PAD_RETENTION_MAUDIO_LOWPWR,      { 0x1, 0x1, 0x0 } },
+       { S5P_PAD_RETENTION_GPIO_LOWPWR,        { 0x1, 0x0, 0x0 } },
+       { S5P_PAD_RETENTION_UART_LOWPWR,        { 0x1, 0x0, 0x0 } },
+       { S5P_PAD_RETENTION_MMCA_LOWPWR,        { 0x1, 0x0, 0x0 } },
+       { S5P_PAD_RETENTION_MMCB_LOWPWR,        { 0x1, 0x0, 0x0 } },
+       { S5P_PAD_RETENTION_EBIA_LOWPWR,        { 0x1, 0x0, 0x0 } },
+       { S5P_PAD_RETENTION_EBIB_LOWPWR,        { 0x1, 0x0, 0x0 } },
+       { S5P_PAD_RETENTION_ISOLATION_LOWPWR,   { 0x1, 0x0, 0x0 } },
+       { S5P_PAD_RETENTION_ALV_SEL_LOWPWR,     { 0x1, 0x0, 0x0 } },
+       { S5P_XUSBXTI_LOWPWR,                   { 0x1, 0x1, 0x0 } },
+       { S5P_XXTI_LOWPWR,                      { 0x1, 0x1, 0x0 } },
+       { S5P_EXT_REGULATOR_LOWPWR,             { 0x1, 0x1, 0x0 } },
+       { S5P_GPIO_MODE_LOWPWR,                 { 0x1, 0x0, 0x0 } },
+       { S5P_GPIO_MODE_MAUDIO_LOWPWR,          { 0x1, 0x1, 0x0 } },
+       { S5P_CAM_LOWPWR,                       { 0x7, 0x0, 0x0 } },
+       { S5P_TV_LOWPWR,                        { 0x7, 0x0, 0x0 } },
+       { S5P_MFC_LOWPWR,                       { 0x7, 0x0, 0x0 } },
+       { S5P_G3D_LOWPWR,                       { 0x7, 0x0, 0x0 } },
+       { S5P_LCD0_LOWPWR,                      { 0x7, 0x0, 0x0 } },
+       { S5P_LCD1_LOWPWR,                      { 0x7, 0x0, 0x0 } },
+       { S5P_MAUDIO_LOWPWR,                    { 0x7, 0x7, 0x0 } },
+       { S5P_GPS_LOWPWR,                       { 0x7, 0x0, 0x0 } },
+       { S5P_GPS_ALIVE_LOWPWR,                 { 0x7, 0x0, 0x0 } },
+       { PMU_TABLE_END,},
+};
+
+static struct exynos4_pmu_conf exynos4212_pmu_config[] = {
+       { S5P_ARM_CORE0_LOWPWR,                 { 0x0, 0x0, 0x2 } },
+       { S5P_DIS_IRQ_CORE0,                    { 0x0, 0x0, 0x0 } },
+       { S5P_DIS_IRQ_CENTRAL0,                 { 0x0, 0x0, 0x0 } },
+       { S5P_ARM_CORE1_LOWPWR,                 { 0x0, 0x0, 0x2 } },
+       { S5P_DIS_IRQ_CORE1,                    { 0x0, 0x0, 0x0 } },
+       { S5P_DIS_IRQ_CENTRAL1,                 { 0x0, 0x0, 0x0 } },
+       { S5P_ISP_ARM_LOWPWR,                   { 0x1, 0x0, 0x0 } },
+       { S5P_DIS_IRQ_ISP_ARM_LOCAL_LOWPWR,     { 0x0, 0x0, 0x0 } },
+       { S5P_DIS_IRQ_ISP_ARM_CENTRAL_LOWPWR,   { 0x0, 0x0, 0x0 } },
+       { S5P_ARM_COMMON_LOWPWR,                { 0x0, 0x0, 0x2 } },
+       { S5P_L2_0_LOWPWR,                      { 0x0, 0x0, 0x3 } },
+       /* XXX_OPTION register should be set other field */
+       { S5P_ARM_L2_0_OPTION,                  { 0x10, 0x10, 0x0 } },
+       { S5P_L2_1_LOWPWR,                      { 0x0, 0x0, 0x3 } },
+       { S5P_ARM_L2_1_OPTION,                  { 0x10, 0x10, 0x0 } },
+       { S5P_CMU_ACLKSTOP_LOWPWR,              { 0x1, 0x0, 0x0 } },
+       { S5P_CMU_SCLKSTOP_LOWPWR,              { 0x1, 0x0, 0x0 } },
+       { S5P_CMU_RESET_LOWPWR,                 { 0x1, 0x1, 0x0 } },
+       { S5P_DRAM_FREQ_DOWN_LOWPWR,            { 0x1, 0x1, 0x1 } },
+       { S5P_DDRPHY_DLLOFF_LOWPWR,             { 0x1, 0x1, 0x1 } },
+       { S5P_LPDDR_PHY_DLL_LOCK_LOWPWR,        { 0x1, 0x1, 0x1 } },
+       { S5P_CMU_ACLKSTOP_COREBLK_LOWPWR,      { 0x1, 0x0, 0x0 } },
+       { S5P_CMU_SCLKSTOP_COREBLK_LOWPWR,      { 0x1, 0x0, 0x0 } },
+       { S5P_CMU_RESET_COREBLK_LOWPWR,         { 0x1, 0x1, 0x0 } },
+       { S5P_APLL_SYSCLK_LOWPWR,               { 0x1, 0x0, 0x0 } },
+       { S5P_MPLL_SYSCLK_LOWPWR,               { 0x1, 0x0, 0x0 } },
+       { S5P_VPLL_SYSCLK_LOWPWR,               { 0x1, 0x0, 0x0 } },
+       { S5P_EPLL_SYSCLK_LOWPWR,               { 0x1, 0x1, 0x0 } },
+       { S5P_MPLLUSER_SYSCLK_LOWPWR,           { 0x1, 0x0, 0x0 } },
+       { S5P_CMU_CLKSTOP_GPS_ALIVE_LOWPWR,     { 0x1, 0x0, 0x0 } },
+       { S5P_CMU_RESET_GPSALIVE_LOWPWR,        { 0x1, 0x0, 0x0 } },
+       { S5P_CMU_CLKSTOP_CAM_LOWPWR,           { 0x1, 0x0, 0x0 } },
+       { S5P_CMU_CLKSTOP_TV_LOWPWR,            { 0x1, 0x0, 0x0 } },
+       { S5P_CMU_CLKSTOP_MFC_LOWPWR,           { 0x1, 0x0, 0x0 } },
+       { S5P_CMU_CLKSTOP_G3D_LOWPWR,           { 0x1, 0x0, 0x0 } },
+       { S5P_CMU_CLKSTOP_LCD0_LOWPWR,          { 0x1, 0x0, 0x0 } },
+       { S5P_CMU_CLKSTOP_ISP_LOWPWR,           { 0x1, 0x0, 0x0 } },
+       { S5P_CMU_CLKSTOP_MAUDIO_LOWPWR,        { 0x1, 0x0, 0x0 } },
+       { S5P_CMU_CLKSTOP_GPS_LOWPWR,           { 0x1, 0x0, 0x0 } },
+       { S5P_CMU_RESET_CAM_LOWPWR,             { 0x1, 0x0, 0x0 } },
+       { S5P_CMU_RESET_TV_LOWPWR,              { 0x1, 0x0, 0x0 } },
+       { S5P_CMU_RESET_MFC_LOWPWR,             { 0x1, 0x0, 0x0 } },
+       { S5P_CMU_RESET_G3D_LOWPWR,             { 0x1, 0x0, 0x0 } },
+       { S5P_CMU_RESET_LCD0_LOWPWR,            { 0x1, 0x0, 0x0 } },
+       { S5P_CMU_RESET_ISP_LOWPWR,             { 0x1, 0x0, 0x0 } },
+       { S5P_CMU_RESET_MAUDIO_LOWPWR,          { 0x1, 0x1, 0x0 } },
+       { S5P_CMU_RESET_GPS_LOWPWR,             { 0x1, 0x0, 0x0 } },
+       { S5P_TOP_BUS_LOWPWR,                   { 0x3, 0x0, 0x0 } },
+       { S5P_TOP_RETENTION_LOWPWR,             { 0x1, 0x0, 0x1 } },
+       { S5P_TOP_PWR_LOWPWR,                   { 0x3, 0x0, 0x3 } },
+       { S5P_TOP_BUS_COREBLK_LOWPWR,           { 0x3, 0x0, 0x0 } },
+       { S5P_TOP_RETENTION_COREBLK_LOWPWR,     { 0x1, 0x0, 0x1 } },
+       { S5P_TOP_PWR_COREBLK_LOWPWR,           { 0x3, 0x0, 0x3 } },
+       { S5P_LOGIC_RESET_LOWPWR,               { 0x1, 0x1, 0x0 } },
+       { S5P_OSCCLK_GATE_LOWPWR,               { 0x1, 0x0, 0x1 } },
+       { S5P_LOGIC_RESET_COREBLK_LOWPWR,       { 0x1, 0x1, 0x0 } },
+       { S5P_OSCCLK_GATE_COREBLK_LOWPWR,       { 0x1, 0x0, 0x1 } },
+       { S5P_ONENAND_MEM_LOWPWR,               { 0x3, 0x0, 0x0 } },
+       { S5P_ONENAND_MEM_OPTION,               { 0x10, 0x10, 0x0 } },
+       { S5P_HSI_MEM_LOWPWR,                   { 0x3, 0x0, 0x0 } },
+       { S5P_HSI_MEM_OPTION,                   { 0x10, 0x10, 0x0 } },
+       { S5P_G2D_ACP_MEM_LOWPWR,               { 0x3, 0x0, 0x0 } },
+       { S5P_G2D_ACP_MEM_OPTION,               { 0x10, 0x10, 0x0 } },
+       { S5P_USBOTG_MEM_LOWPWR,                { 0x3, 0x0, 0x0 } },
+       { S5P_USBOTG_MEM_OPTION,                { 0x10, 0x10, 0x0 } },
+       { S5P_HSMMC_MEM_LOWPWR,                 { 0x3, 0x0, 0x0 } },
+       { S5P_HSMMC_MEM_OPTION,                 { 0x10, 0x10, 0x0 } },
+       { S5P_CSSYS_MEM_LOWPWR,                 { 0x3, 0x0, 0x0 } },
+       { S5P_CSSYS_MEM_OPTION,                 { 0x10, 0x10, 0x0 } },
+       { S5P_SECSS_MEM_LOWPWR,                 { 0x3, 0x0, 0x0 } },
+       { S5P_SECSS_MEM_OPTION,                 { 0x10, 0x10, 0x0 } },
+       { S5P_ROTATOR_MEM_LOWPWR,               { 0x3, 0x0, 0x0 } },
+       { S5P_ROTATOR_MEM_OPTION,               { 0x10, 0x10, 0x0 } },
+       { S5P_PAD_RETENTION_DRAM_LOWPWR,        { 0x1, 0x0, 0x0 } },
+       { S5P_PAD_RETENTION_MAUDIO_LOWPWR,      { 0x1, 0x1, 0x0 } },
+       { S5P_PAD_RETENTION_GPIO_LOWPWR,        { 0x1, 0x0, 0x0 } },
+       { S5P_PAD_RETENTION_UART_LOWPWR,        { 0x1, 0x0, 0x0 } },
+       { S5P_PAD_RETENTION_MMCA_LOWPWR,        { 0x1, 0x0, 0x0 } },
+       { S5P_PAD_RETENTION_MMCB_LOWPWR,        { 0x1, 0x0, 0x0 } },
+       { S5P_PAD_RETENTION_EBIA_LOWPWR,        { 0x1, 0x0, 0x0 } },
+       { S5P_PAD_RETENTION_EBIB_LOWPWR,        { 0x1, 0x0, 0x0 } },
+       { S5P_PAD_RETENTION_GPIO_COREBLK_LOWPWR,{ 0x1, 0x0, 0x0 } },
+       { S5P_PAD_RETENTION_ISOLATION_LOWPWR,   { 0x1, 0x0, 0x0 } },
+       { S5P_PAD_ISOLATION_COREBLK_LOWPWR,     { 0x1, 0x0, 0x0 } },
+       { S5P_PAD_RETENTION_ALV_SEL_LOWPWR,     { 0x1, 0x0, 0x0 } },
+       { S5P_XUSBXTI_LOWPWR,                   { 0x1, 0x1, 0x0 } },
+       { S5P_XXTI_LOWPWR,                      { 0x1, 0x1, 0x0 } },
+       { S5P_EXT_REGULATOR_LOWPWR,             { 0x1, 0x1, 0x0 } },
+       { S5P_GPIO_MODE_LOWPWR,                 { 0x1, 0x0, 0x0 } },
+       { S5P_GPIO_MODE_COREBLK_LOWPWR,         { 0x1, 0x0, 0x0 } },
+       { S5P_GPIO_MODE_MAUDIO_LOWPWR,          { 0x1, 0x1, 0x0 } },
+       { S5P_TOP_ASB_RESET_LOWPWR,             { 0x1, 0x1, 0x1 } },
+       { S5P_TOP_ASB_ISOLATION_LOWPWR,         { 0x1, 0x0, 0x1 } },
+       { S5P_CAM_LOWPWR,                       { 0x7, 0x0, 0x0 } },
+       { S5P_TV_LOWPWR,                        { 0x7, 0x0, 0x0 } },
+       { S5P_MFC_LOWPWR,                       { 0x7, 0x0, 0x0 } },
+       { S5P_G3D_LOWPWR,                       { 0x7, 0x0, 0x0 } },
+       { S5P_LCD0_LOWPWR,                      { 0x7, 0x0, 0x0 } },
+       { S5P_ISP_LOWPWR,                       { 0x7, 0x0, 0x0 } },
+       { S5P_MAUDIO_LOWPWR,                    { 0x7, 0x7, 0x0 } },
+       { S5P_GPS_LOWPWR,                       { 0x7, 0x0, 0x0 } },
+       { S5P_GPS_ALIVE_LOWPWR,                 { 0x7, 0x0, 0x0 } },
+       { S5P_CMU_SYSCLK_ISP_LOWPWR,            { 0x1, 0x0, 0x0 } },
+       { S5P_CMU_SYSCLK_GPS_LOWPWR,            { 0x1, 0x0, 0x0 } },
+       { PMU_TABLE_END,},
+};
+
+void exynos4_sys_powerdown_conf(enum sys_powerdown mode)
+{
+       unsigned int i;
+
+       for (i = 0; (exynos4_pmu_config[i].reg != PMU_TABLE_END) ; i++)
+               __raw_writel(exynos4_pmu_config[i].val[mode],
+                               exynos4_pmu_config[i].reg);
+}
+
+static int __init exynos4_pmu_init(void)
+{
+       exynos4_pmu_config = exynos4210_pmu_config;
+
+       if (soc_is_exynos4210()) {
+               exynos4_pmu_config = exynos4210_pmu_config;
+               pr_info("EXYNOS4210 PMU Initialize\n");
+       } else if (soc_is_exynos4212()) {
+               exynos4_pmu_config = exynos4212_pmu_config;
+               pr_info("EXYNOS4212 PMU Initialize\n");
+       } else {
+               pr_info("EXYNOS4: PMU not supported\n");
+       }
+
+       return 0;
+}
+arch_initcall(exynos4_pmu_init);
diff --git a/arch/arm/mach-exynos/setup-sdhci.c b/arch/arm/mach-exynos/setup-sdhci.c
new file mode 100644 (file)
index 0000000..92937b4
--- /dev/null
@@ -0,0 +1,22 @@
+/* linux/arch/arm/mach-exynos4/setup-sdhci.c
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * EXYNOS4 - Helper functions for settign up SDHCI device(s) (HSMMC)
+ *
+ * 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/types.h>
+
+/* clock sources for the mmc bus clock, order as for the ctrl2[5..4] */
+
+char *exynos4_hsmmc_clksrcs[4] = {
+       [0] = NULL,
+       [1] = NULL,
+       [2] = "sclk_mmc",       /* mmc_bus */
+       [3] = NULL,
+};
diff --git a/arch/arm/mach-exynos4/dma.c b/arch/arm/mach-exynos4/dma.c
deleted file mode 100644 (file)
index 564bb53..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-/* linux/arch/arm/mach-exynos4/dma.c
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com
- *
- * Copyright (C) 2010 Samsung Electronics Co. Ltd.
- *     Jaswinder Singh <jassi.brar@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License 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/platform_device.h>
-#include <linux/dma-mapping.h>
-
-#include <plat/devs.h>
-#include <plat/irqs.h>
-
-#include <mach/map.h>
-#include <mach/irqs.h>
-
-#include <plat/s3c-pl330-pdata.h>
-
-static u64 dma_dmamask = DMA_BIT_MASK(32);
-
-static struct resource exynos4_pdma0_resource[] = {
-       [0] = {
-               .start  = EXYNOS4_PA_PDMA0,
-               .end    = EXYNOS4_PA_PDMA0 + SZ_4K,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = IRQ_PDMA0,
-               .end    = IRQ_PDMA0,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct s3c_pl330_platdata exynos4_pdma0_pdata = {
-       .peri = {
-               [0] = DMACH_PCM0_RX,
-               [1] = DMACH_PCM0_TX,
-               [2] = DMACH_PCM2_RX,
-               [3] = DMACH_PCM2_TX,
-               [4] = DMACH_MSM_REQ0,
-               [5] = DMACH_MSM_REQ2,
-               [6] = DMACH_SPI0_RX,
-               [7] = DMACH_SPI0_TX,
-               [8] = DMACH_SPI2_RX,
-               [9] = DMACH_SPI2_TX,
-               [10] = DMACH_I2S0S_TX,
-               [11] = DMACH_I2S0_RX,
-               [12] = DMACH_I2S0_TX,
-               [13] = DMACH_I2S2_RX,
-               [14] = DMACH_I2S2_TX,
-               [15] = DMACH_UART0_RX,
-               [16] = DMACH_UART0_TX,
-               [17] = DMACH_UART2_RX,
-               [18] = DMACH_UART2_TX,
-               [19] = DMACH_UART4_RX,
-               [20] = DMACH_UART4_TX,
-               [21] = DMACH_SLIMBUS0_RX,
-               [22] = DMACH_SLIMBUS0_TX,
-               [23] = DMACH_SLIMBUS2_RX,
-               [24] = DMACH_SLIMBUS2_TX,
-               [25] = DMACH_SLIMBUS4_RX,
-               [26] = DMACH_SLIMBUS4_TX,
-               [27] = DMACH_AC97_MICIN,
-               [28] = DMACH_AC97_PCMIN,
-               [29] = DMACH_AC97_PCMOUT,
-               [30] = DMACH_MAX,
-               [31] = DMACH_MAX,
-       },
-};
-
-static struct platform_device exynos4_device_pdma0 = {
-       .name           = "s3c-pl330",
-       .id             = 0,
-       .num_resources  = ARRAY_SIZE(exynos4_pdma0_resource),
-       .resource       = exynos4_pdma0_resource,
-       .dev            = {
-               .dma_mask = &dma_dmamask,
-               .coherent_dma_mask = DMA_BIT_MASK(32),
-               .platform_data = &exynos4_pdma0_pdata,
-       },
-};
-
-static struct resource exynos4_pdma1_resource[] = {
-       [0] = {
-               .start  = EXYNOS4_PA_PDMA1,
-               .end    = EXYNOS4_PA_PDMA1 + SZ_4K,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = IRQ_PDMA1,
-               .end    = IRQ_PDMA1,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct s3c_pl330_platdata exynos4_pdma1_pdata = {
-       .peri = {
-               [0] = DMACH_PCM0_RX,
-               [1] = DMACH_PCM0_TX,
-               [2] = DMACH_PCM1_RX,
-               [3] = DMACH_PCM1_TX,
-               [4] = DMACH_MSM_REQ1,
-               [5] = DMACH_MSM_REQ3,
-               [6] = DMACH_SPI1_RX,
-               [7] = DMACH_SPI1_TX,
-               [8] = DMACH_I2S0S_TX,
-               [9] = DMACH_I2S0_RX,
-               [10] = DMACH_I2S0_TX,
-               [11] = DMACH_I2S1_RX,
-               [12] = DMACH_I2S1_TX,
-               [13] = DMACH_UART0_RX,
-               [14] = DMACH_UART0_TX,
-               [15] = DMACH_UART1_RX,
-               [16] = DMACH_UART1_TX,
-               [17] = DMACH_UART3_RX,
-               [18] = DMACH_UART3_TX,
-               [19] = DMACH_SLIMBUS1_RX,
-               [20] = DMACH_SLIMBUS1_TX,
-               [21] = DMACH_SLIMBUS3_RX,
-               [22] = DMACH_SLIMBUS3_TX,
-               [23] = DMACH_SLIMBUS5_RX,
-               [24] = DMACH_SLIMBUS5_TX,
-               [25] = DMACH_SLIMBUS0AUX_RX,
-               [26] = DMACH_SLIMBUS0AUX_TX,
-               [27] = DMACH_SPDIF,
-               [28] = DMACH_MAX,
-               [29] = DMACH_MAX,
-               [30] = DMACH_MAX,
-               [31] = DMACH_MAX,
-       },
-};
-
-static struct platform_device exynos4_device_pdma1 = {
-       .name           = "s3c-pl330",
-       .id             = 1,
-       .num_resources  = ARRAY_SIZE(exynos4_pdma1_resource),
-       .resource       = exynos4_pdma1_resource,
-       .dev            = {
-               .dma_mask = &dma_dmamask,
-               .coherent_dma_mask = DMA_BIT_MASK(32),
-               .platform_data = &exynos4_pdma1_pdata,
-       },
-};
-
-static struct platform_device *exynos4_dmacs[] __initdata = {
-       &exynos4_device_pdma0,
-       &exynos4_device_pdma1,
-};
-
-static int __init exynos4_dma_init(void)
-{
-       platform_add_devices(exynos4_dmacs, ARRAY_SIZE(exynos4_dmacs));
-
-       return 0;
-}
-arch_initcall(exynos4_dma_init);
diff --git a/arch/arm/mach-exynos4/include/mach/clkdev.h b/arch/arm/mach-exynos4/include/mach/clkdev.h
deleted file mode 100644 (file)
index 7dffa83..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#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-exynos4/mach-origen.c b/arch/arm/mach-exynos4/mach-origen.c
deleted file mode 100644 (file)
index b5f6f38..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-/* linux/arch/arm/mach-exynos4/mach-origen.c
- *
- * Copyright (c) 2011 Insignal Co., Ltd.
- *             http://www.insignal.co.kr/
- *
- * 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/serial_core.h>
-#include <linux/gpio.h>
-#include <linux/mmc/host.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/input.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach-types.h>
-
-#include <plat/regs-serial.h>
-#include <plat/exynos4.h>
-#include <plat/cpu.h>
-#include <plat/devs.h>
-#include <plat/sdhci.h>
-#include <plat/iic.h>
-
-#include <mach/map.h>
-
-/* Following are default values for UCON, ULCON and UFCON UART registers */
-#define ORIGEN_UCON_DEFAULT    (S3C2410_UCON_TXILEVEL |        \
-                                S3C2410_UCON_RXILEVEL |        \
-                                S3C2410_UCON_TXIRQMODE |       \
-                                S3C2410_UCON_RXIRQMODE |       \
-                                S3C2410_UCON_RXFIFO_TOI |      \
-                                S3C2443_UCON_RXERR_IRQEN)
-
-#define ORIGEN_ULCON_DEFAULT   S3C2410_LCON_CS8
-
-#define ORIGEN_UFCON_DEFAULT   (S3C2410_UFCON_FIFOMODE |       \
-                                S5PV210_UFCON_TXTRIG4 |        \
-                                S5PV210_UFCON_RXTRIG4)
-
-static struct s3c2410_uartcfg origen_uartcfgs[] __initdata = {
-       [0] = {
-               .hwport         = 0,
-               .flags          = 0,
-               .ucon           = ORIGEN_UCON_DEFAULT,
-               .ulcon          = ORIGEN_ULCON_DEFAULT,
-               .ufcon          = ORIGEN_UFCON_DEFAULT,
-       },
-       [1] = {
-               .hwport         = 1,
-               .flags          = 0,
-               .ucon           = ORIGEN_UCON_DEFAULT,
-               .ulcon          = ORIGEN_ULCON_DEFAULT,
-               .ufcon          = ORIGEN_UFCON_DEFAULT,
-       },
-       [2] = {
-               .hwport         = 2,
-               .flags          = 0,
-               .ucon           = ORIGEN_UCON_DEFAULT,
-               .ulcon          = ORIGEN_ULCON_DEFAULT,
-               .ufcon          = ORIGEN_UFCON_DEFAULT,
-       },
-       [3] = {
-               .hwport         = 3,
-               .flags          = 0,
-               .ucon           = ORIGEN_UCON_DEFAULT,
-               .ulcon          = ORIGEN_ULCON_DEFAULT,
-               .ufcon          = ORIGEN_UFCON_DEFAULT,
-       },
-};
-
-static struct s3c_sdhci_platdata origen_hsmmc2_pdata __initdata = {
-       .cd_type                = S3C_SDHCI_CD_GPIO,
-       .ext_cd_gpio            = EXYNOS4_GPK2(2),
-       .ext_cd_gpio_invert     = 1,
-       .clk_type               = S3C_SDHCI_CLK_DIV_EXTERNAL,
-};
-
-static struct platform_device *origen_devices[] __initdata = {
-       &s3c_device_hsmmc2,
-       &s3c_device_rtc,
-       &s3c_device_wdt,
-};
-
-static void __init origen_map_io(void)
-{
-       s5p_init_io(NULL, 0, S5P_VA_CHIPID);
-       s3c24xx_init_clocks(24000000);
-       s3c24xx_init_uarts(origen_uartcfgs, ARRAY_SIZE(origen_uartcfgs));
-}
-
-static void __init origen_machine_init(void)
-{
-       s3c_sdhci2_set_platdata(&origen_hsmmc2_pdata);
-       platform_add_devices(origen_devices, ARRAY_SIZE(origen_devices));
-}
-
-MACHINE_START(ORIGEN, "ORIGEN")
-       /* Maintainer: JeongHyeon Kim <jhkim@insignal.co.kr> */
-       .atag_offset    = 0x100,
-       .init_irq       = exynos4_init_irq,
-       .map_io         = origen_map_io,
-       .init_machine   = origen_machine_init,
-       .timer          = &exynos4_timer,
-MACHINE_END
diff --git a/arch/arm/mach-exynos4/pmu.c b/arch/arm/mach-exynos4/pmu.c
deleted file mode 100644 (file)
index 7ea9eb2..0000000
+++ /dev/null
@@ -1,175 +0,0 @@
-/* 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-sdhci.c b/arch/arm/mach-exynos4/setup-sdhci.c
deleted file mode 100644 (file)
index 1e83f8c..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/* linux/arch/arm/mach-exynos4/setup-sdhci.c
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com
- *
- * EXYNOS4 - Helper functions for settign up SDHCI device(s) (HSMMC)
- *
- * 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/types.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-
-#include <linux/mmc/card.h>
-#include <linux/mmc/host.h>
-
-#include <plat/regs-sdhci.h>
-
-/* clock sources for the mmc bus clock, order as for the ctrl2[5..4] */
-
-char *exynos4_hsmmc_clksrcs[4] = {
-       [0] = NULL,
-       [1] = NULL,
-       [2] = "sclk_mmc",       /* mmc_bus */
-       [3] = NULL,
-};
-
-void exynos4_setup_sdhci_cfg_card(struct platform_device *dev, void __iomem *r,
-                                 struct mmc_ios *ios, struct mmc_card *card)
-{
-       u32 ctrl2, ctrl3;
-
-       /* don't need to alter anything according to card-type */
-
-       ctrl2 = readl(r + S3C_SDHCI_CONTROL2);
-
-       /* select base clock source to HCLK */
-
-       ctrl2 &= S3C_SDHCI_CTRL2_SELBASECLK_MASK;
-
-       /*
-        * clear async mode, enable conflict mask, rx feedback ctrl, SD
-        * clk hold and no use debounce count
-        */
-
-       ctrl2 |= (S3C64XX_SDHCI_CTRL2_ENSTAASYNCCLR |
-                 S3C64XX_SDHCI_CTRL2_ENCMDCNFMSK |
-                 S3C_SDHCI_CTRL2_ENFBCLKRX |
-                 S3C_SDHCI_CTRL2_DFCNT_NONE |
-                 S3C_SDHCI_CTRL2_ENCLKOUTHOLD);
-
-       /* Tx and Rx feedback clock delay control */
-
-       if (ios->clock < 25 * 1000000)
-               ctrl3 = (S3C_SDHCI_CTRL3_FCSEL3 |
-                        S3C_SDHCI_CTRL3_FCSEL2 |
-                        S3C_SDHCI_CTRL3_FCSEL1 |
-                        S3C_SDHCI_CTRL3_FCSEL0);
-       else
-               ctrl3 = (S3C_SDHCI_CTRL3_FCSEL1 | S3C_SDHCI_CTRL3_FCSEL0);
-
-       writel(ctrl2, r + S3C_SDHCI_CONTROL2);
-       writel(ctrl3, r + S3C_SDHCI_CONTROL3);
-}
index 8f948f9..ba254a7 100644 (file)
@@ -7,7 +7,7 @@ obj-y                           += common.o clock.o devices.o time.o
 # SoC support
 obj-$(CONFIG_CPU_PXA168)       += pxa168.o irq-pxa168.o
 obj-$(CONFIG_CPU_PXA910)       += pxa910.o irq-pxa168.o
-obj-$(CONFIG_CPU_MMP2)         += mmp2.o irq-mmp2.o
+obj-$(CONFIG_CPU_MMP2)         += mmp2.o irq-mmp2.o sram.o
 
 # board support
 obj-$(CONFIG_MACH_ASPENITE)    += aspenite.o
index e411252..983cfb1 100644 (file)
@@ -185,6 +185,15 @@ static struct sdhci_pxa_platdata mmp2_sdh_platdata_mmc2 = {
                | PXA_FLAG_SD_8_BIT_CAPABLE_SLOT,
 };
 
+static struct sram_platdata mmp2_asram_platdata = {
+       .pool_name      = "asram",
+       .granularity    = SRAM_GRANULARITY,
+};
+
+static struct sram_platdata mmp2_isram_platdata = {
+       .pool_name      = "isram",
+       .granularity    = SRAM_GRANULARITY,
+};
 
 static void __init brownstone_init(void)
 {
@@ -196,6 +205,8 @@ static void __init brownstone_init(void)
        mmp2_add_twsi(1, NULL, ARRAY_AND_SIZE(brownstone_twsi1_info));
        mmp2_add_sdhost(0, &mmp2_sdh_platdata_mmc0); /* SD/MMC */
        mmp2_add_sdhost(2, &mmp2_sdh_platdata_mmc2); /* eMMC */
+       mmp2_add_asram(&mmp2_asram_platdata);
+       mmp2_add_isram(&mmp2_isram_platdata);
 
        /* enable 5v regulator */
        platform_device_register(&brownstone_v_5vp_device);
index de7b888..2f7b2d3 100644 (file)
@@ -13,6 +13,7 @@ extern void mmp2_clear_pmic_int(void);
 #include <linux/i2c.h>
 #include <linux/i2c/pxa-i2c.h>
 #include <mach/devices.h>
+#include <mach/sram.h>
 
 extern struct pxa_device_desc mmp2_device_uart1;
 extern struct pxa_device_desc mmp2_device_uart2;
@@ -28,6 +29,8 @@ extern struct pxa_device_desc mmp2_device_sdh0;
 extern struct pxa_device_desc mmp2_device_sdh1;
 extern struct pxa_device_desc mmp2_device_sdh2;
 extern struct pxa_device_desc mmp2_device_sdh3;
+extern struct pxa_device_desc mmp2_device_asram;
+extern struct pxa_device_desc mmp2_device_isram;
 
 static inline int mmp2_add_uart(int id)
 {
@@ -85,5 +88,15 @@ static inline int mmp2_add_sdhost(int id, struct sdhci_pxa_platdata *data)
        return pxa_register_device(d, data, sizeof(*data));
 }
 
+static inline int mmp2_add_asram(struct sram_platdata *data)
+{
+       return pxa_register_device(&mmp2_device_asram, data, sizeof(*data));
+}
+
+static inline int mmp2_add_isram(struct sram_platdata *data)
+{
+       return pxa_register_device(&mmp2_device_isram, data, sizeof(*data));
+}
+
 #endif /* __ASM_MACH_MMP2_H */
 
diff --git a/arch/arm/mach-mmp/include/mach/sram.h b/arch/arm/mach-mmp/include/mach/sram.h
new file mode 100644 (file)
index 0000000..239e0fc
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ *  linux/arch/arm/mach-mmp/include/mach/sram.h
+ *
+ *  SRAM Memory Management
+ *
+ *  Copyright (c) 2011 Marvell Semiconductors 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.
+ *
+ */
+
+#ifndef __ASM_ARCH_SRAM_H
+#define __ASM_ARCH_SRAM_H
+
+#include <linux/genalloc.h>
+
+/* ARBITRARY:  SRAM allocations are multiples of this 2^N size */
+#define SRAM_GRANULARITY       512
+
+enum sram_type {
+       MMP_SRAM_UNDEFINED = 0,
+       MMP_ASRAM,
+       MMP_ISRAM,
+};
+
+struct sram_platdata {
+       char *pool_name;
+       int granularity;
+};
+
+extern struct gen_pool *sram_get_gpool(char *pool_name);
+
+#endif /* __ASM_ARCH_SRAM_H */
index 7a7e8e4..5dd1d4a 100644 (file)
@@ -226,4 +226,7 @@ MMP2_DEVICE(sdh0, "sdhci-pxav3", 0, MMC, 0xd4280000, 0x120);
 MMP2_DEVICE(sdh1, "sdhci-pxav3", 1, MMC2, 0xd4280800, 0x120);
 MMP2_DEVICE(sdh2, "sdhci-pxav3", 2, MMC3, 0xd4281000, 0x120);
 MMP2_DEVICE(sdh3, "sdhci-pxav3", 3, MMC4, 0xd4281800, 0x120);
+MMP2_DEVICE(asram, "asram", -1, NONE, 0xe0000000, 0x4000);
+/* 0xd1000000 ~ 0xd101ffff is reserved for secure processor */
+MMP2_DEVICE(isram, "isram", -1, NONE, 0xd1020000, 0x18000);
 
diff --git a/arch/arm/mach-mmp/sram.c b/arch/arm/mach-mmp/sram.c
new file mode 100644 (file)
index 0000000..4304f95
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ *  linux/arch/arm/mach-mmp/sram.c
+ *
+ *  based on mach-davinci/sram.c - DaVinci simple SRAM allocator
+ *
+ *  Copyright (c) 2011 Marvell Semiconductors Inc.
+ *  All Rights Reserved
+ *
+ *  Add for mmp sram support - Leo Yan <leoy@marvell.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/genalloc.h>
+
+#include <mach/sram.h>
+
+struct sram_bank_info {
+       char *pool_name;
+       struct gen_pool *gpool;
+       int granularity;
+
+       phys_addr_t sram_phys;
+       void __iomem *sram_virt;
+       u32 sram_size;
+
+       struct list_head node;
+};
+
+static DEFINE_MUTEX(sram_lock);
+static LIST_HEAD(sram_bank_list);
+
+struct gen_pool *sram_get_gpool(char *pool_name)
+{
+       struct sram_bank_info *info = NULL;
+
+       if (!pool_name)
+               return NULL;
+
+       mutex_lock(&sram_lock);
+
+       list_for_each_entry(info, &sram_bank_list, node)
+               if (!strcmp(pool_name, info->pool_name))
+                       break;
+
+       mutex_unlock(&sram_lock);
+
+       if (&info->node == &sram_bank_list)
+               return NULL;
+
+       return info->gpool;
+}
+EXPORT_SYMBOL(sram_get_gpool);
+
+static int __devinit sram_probe(struct platform_device *pdev)
+{
+       struct sram_platdata *pdata = pdev->dev.platform_data;
+       struct sram_bank_info *info;
+       struct resource *res;
+       int ret = 0;
+
+       if (!pdata && !pdata->pool_name)
+               return -ENODEV;
+
+       info = kzalloc(sizeof(*info), GFP_KERNEL);
+       if (!info)
+               return -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (res == NULL) {
+               dev_err(&pdev->dev, "no memory resource defined\n");
+               ret = -ENODEV;
+               goto out;
+       }
+
+       if (!resource_size(res))
+               return 0;
+
+       info->sram_phys   = (phys_addr_t)res->start;
+       info->sram_size   = resource_size(res);
+       info->sram_virt   = ioremap(info->sram_phys, info->sram_size);
+       info->pool_name   = kstrdup(pdata->pool_name, GFP_KERNEL);
+       info->granularity = pdata->granularity;
+
+       info->gpool = gen_pool_create(ilog2(info->granularity), -1);
+       if (!info->gpool) {
+               dev_err(&pdev->dev, "create pool failed\n");
+               ret = -ENOMEM;
+               goto create_pool_err;
+       }
+
+       ret = gen_pool_add_virt(info->gpool, (unsigned long)info->sram_virt,
+                               info->sram_phys, info->sram_size, -1);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "add new chunk failed\n");
+               ret = -ENOMEM;
+               goto add_chunk_err;
+       }
+
+       mutex_lock(&sram_lock);
+       list_add(&info->node, &sram_bank_list);
+       mutex_unlock(&sram_lock);
+
+       platform_set_drvdata(pdev, info);
+
+       dev_info(&pdev->dev, "initialized\n");
+       return 0;
+
+add_chunk_err:
+       gen_pool_destroy(info->gpool);
+create_pool_err:
+       iounmap(info->sram_virt);
+       kfree(info->pool_name);
+out:
+       kfree(info);
+       return ret;
+}
+
+static int __devexit sram_remove(struct platform_device *pdev)
+{
+       struct sram_bank_info *info;
+
+       info = platform_get_drvdata(pdev);
+       if (info == NULL)
+               return -ENODEV;
+
+       mutex_lock(&sram_lock);
+       list_del(&info->node);
+       mutex_unlock(&sram_lock);
+
+       gen_pool_destroy(info->gpool);
+       iounmap(info->sram_virt);
+       kfree(info->pool_name);
+       kfree(info);
+       return 0;
+}
+
+static const struct platform_device_id sram_id_table[] = {
+       { "asram", MMP_ASRAM },
+       { "isram", MMP_ISRAM },
+       { }
+};
+
+static struct platform_driver sram_driver = {
+       .probe          = sram_probe,
+       .remove         = sram_remove,
+       .driver         = {
+               .name   = "mmp-sram",
+       },
+       .id_table       = sram_id_table,
+};
+
+static int __init sram_init(void)
+{
+       return platform_driver_register(&sram_driver);
+}
+core_initcall(sram_init);
+
+MODULE_LICENSE("GPL");
index 8e697dd..d82b7aa 100644 (file)
@@ -144,7 +144,7 @@ static struct clk_lookup eseries_clkregs[] = {
        INIT_CLKREG(&tmio_dummy_clk, NULL, "CLK_CK32K"),
 };
 
-void eseries_register_clks(void)
+static void __init eseries_register_clks(void)
 {
        clkdev_add_table(eseries_clkregs, ARRAY_SIZE(eseries_clkregs));
 }
index be92196..b96949d 100644 (file)
@@ -11,5 +11,4 @@ extern int eseries_tmio_resume(struct platform_device *dev);
 extern void eseries_get_tmio_gpios(void);
 extern struct resource eseries_tmio_resources[];
 extern struct platform_device e300_tc6387xb_device;
-extern void eseries_register_clks(void);
 
index 576868f..41b4c93 100644 (file)
@@ -25,7 +25,7 @@
 #define GPIO_REGS_VIRT io_p2v(0x40E00000)
 
 #define BANK_OFF(n)    (((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2))
-#define GPIO_REG(x)    (GPIO_REGS_VIRT + (x))
+#define GPIO_REG(x)    (*(volatile u32 *)(GPIO_REGS_VIRT + (x)))
 
 /* GPIO Pin Level Registers */
 #define GPLR0          GPIO_REG(BANK_OFF(0) + 0x00)
index 9a9c539..6d38c65 100644 (file)
@@ -394,9 +394,9 @@ static int pcm990_camera_set_bus_param(struct soc_camera_link *link,
        }
 
        if (flags & SOCAM_DATAWIDTH_8)
-               gpio_set_value(gpio_bus_switch, 1);
+               gpio_set_value_cansleep(gpio_bus_switch, 1);
        else
-               gpio_set_value(gpio_bus_switch, 0);
+               gpio_set_value_cansleep(gpio_bus_switch, 0);
 
        return 0;
 }
index 3700cf3..5261a7e 100644 (file)
@@ -6,7 +6,6 @@ config CPU_S3C2410
        bool
        depends on ARCH_S3C2410
        select CPU_ARM920T
-       select S3C_GPIO_PULL_UP
        select S3C2410_CLOCK
        select CPU_LLSERIAL_S3C2410
        select S3C2410_PM if PM
index b2b2a5b..ae8e482 100644 (file)
@@ -13,7 +13,6 @@
 #ifndef __ASM_ARCH_DMA_H
 #define __ASM_ARCH_DMA_H __FILE__
 
-#include <plat/dma.h>
 #include <linux/sysdev.h>
 
 #define MAX_DMA_TRANSFER_SIZE   0x100000 /* Data Unit is half word  */
@@ -51,6 +50,18 @@ enum dma_ch {
        DMACH_MAX,              /* the end entry */
 };
 
+static inline bool samsung_dma_has_circular(void)
+{
+       return false;
+}
+
+static inline bool samsung_dma_is_dmadev(void)
+{
+       return false;
+}
+
+#include <plat/dma.h>
+
 #define DMACH_LOW_LEVEL        (1<<28) /* use this to specifiy hardware ch no */
 
 /* we have 4 dma channels */
@@ -163,7 +174,7 @@ struct s3c2410_dma_chan {
        struct s3c2410_dma_client *client;
 
        /* channel configuration */
-       enum s3c2410_dmasrc      source;
+       enum dma_data_direction  source;
        enum dma_ch              req_ch;
        unsigned long            dev_addr;
        unsigned long            load_timeout;
@@ -196,9 +207,4 @@ struct s3c2410_dma_chan {
 
 typedef unsigned long dma_device_t;
 
-static inline bool s3c_dma_has_circular(void)
-{
-       return false;
-}
-
 #endif /* __ASM_ARCH_DMA_H */
index eee0654..a957bc8 100644 (file)
@@ -1,74 +1 @@
-/* arch/arm/mach-s3c2410/include/mach/fb.h
- *
- * Copyright (c) 2004 Arnaud Patard <arnaud.patard@rtp-net.org>
- *
- * Inspired by pxafb.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARM_FB_H
-#define __ASM_ARM_FB_H
-
-#include <mach/regs-lcd.h>
-
-struct s3c2410fb_hw {
-       unsigned long   lcdcon1;
-       unsigned long   lcdcon2;
-       unsigned long   lcdcon3;
-       unsigned long   lcdcon4;
-       unsigned long   lcdcon5;
-};
-
-/* LCD description */
-struct s3c2410fb_display {
-       /* LCD type */
-       unsigned type;
-
-       /* Screen size */
-       unsigned short width;
-       unsigned short height;
-
-       /* Screen info */
-       unsigned short xres;
-       unsigned short yres;
-       unsigned short bpp;
-
-       unsigned pixclock;              /* pixclock in picoseconds */
-       unsigned short left_margin;  /* value in pixels (TFT) or HCLKs (STN) */
-       unsigned short right_margin; /* value in pixels (TFT) or HCLKs (STN) */
-       unsigned short hsync_len;    /* value in pixels (TFT) or HCLKs (STN) */
-       unsigned short upper_margin;    /* value in lines (TFT) or 0 (STN) */
-       unsigned short lower_margin;    /* value in lines (TFT) or 0 (STN) */
-       unsigned short vsync_len;       /* value in lines (TFT) or 0 (STN) */
-
-       /* lcd configuration registers */
-       unsigned long   lcdcon5;
-};
-
-struct s3c2410fb_mach_info {
-
-       struct s3c2410fb_display *displays;     /* attached diplays info */
-       unsigned num_displays;                  /* number of defined displays */
-       unsigned default_display;
-
-       /* GPIOs */
-
-       unsigned long   gpcup;
-       unsigned long   gpcup_mask;
-       unsigned long   gpccon;
-       unsigned long   gpccon_mask;
-       unsigned long   gpdup;
-       unsigned long   gpdup_mask;
-       unsigned long   gpdcon;
-       unsigned long   gpdcon_mask;
-
-       /* lpc3600 control register */
-       unsigned long   lpcsel;
-};
-
-extern void __init s3c24xx_fb_set_platdata(struct s3c2410fb_mach_info *);
-
-#endif /* __ASM_ARM_FB_H */
+#include <plat/fb-s3c2410.h>
index bab1392..c53ad34 100644 (file)
@@ -1,98 +1 @@
-/* arch/arm/mach-s3c2410/include/mach/gpio-fns.h
- *
- * Copyright (c) 2003-2009 Simtec Electronics
- *     Ben Dooks <ben@simtec.co.uk>
- *
- * S3C2410 - hardware
- *
- * 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_GPIO_FNS_H
-#define __MACH_GPIO_FNS_H __FILE__
-
-/* These functions are in the to-be-removed category and it is strongly
- * encouraged not to use these in new code. They will be marked deprecated
- * very soon.
- *
- * Most of the functionality can be either replaced by the gpiocfg calls
- * for the s3c platform or by the generic GPIOlib API.
- *
- * As of 2.6.35-rc, these will be removed, with the few drivers using them
- * either replaced or given a wrapper until the calls can be removed.
-*/
-
-#include <plat/gpio-cfg.h>
-
-static inline void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int cfg)
-{
-       /* 1:1 mapping between cfgpin and setcfg calls at the moment */
-       s3c_gpio_cfgpin(pin, cfg);
-}
-
-/* external functions for GPIO support
- *
- * These allow various different clients to access the same GPIO
- * registers without conflicting. If your driver only owns the entire
- * GPIO register, then it is safe to ioremap/__raw_{read|write} to it.
-*/
-
-extern unsigned int s3c2410_gpio_getcfg(unsigned int pin);
-
-/* s3c2410_gpio_getirq
- *
- * turn the given pin number into the corresponding IRQ number
- *
- * returns:
- *     < 0 = no interrupt for this pin
- *     >=0 = interrupt number for the pin
-*/
-
-extern int s3c2410_gpio_getirq(unsigned int pin);
-
-/* s3c2410_gpio_irqfilter
- *
- * set the irq filtering on the given pin
- *
- * on = 0 => disable filtering
- *      1 => enable filtering
- *
- * config = S3C2410_EINTFLT_PCLK or S3C2410_EINTFLT_EXTCLK orred with
- *          width of filter (0 through 63)
- *
- *
-*/
-
-extern int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
-                                 unsigned int config);
-
-/* s3c2410_gpio_pullup
- *
- * This call should be replaced with s3c_gpio_setpull().
- *
- * As a note, there is currently no distinction between pull-up and pull-down
- * in the s3c24xx series devices with only an on/off configuration.
- */
-
-/* s3c2410_gpio_pullup
- *
- * configure the pull-up control on the given pin
- *
- * to = 1 => disable the pull-up
- *      0 => enable the pull-up
- *
- * eg;
- *
- *   s3c2410_gpio_pullup(S3C2410_GPB(0), 0);
- *   s3c2410_gpio_pullup(S3C2410_GPE(8), 0);
-*/
-
-extern void s3c2410_gpio_pullup(unsigned int pin, unsigned int to);
-
-extern void s3c2410_gpio_setpin(unsigned int pin, unsigned int to);
-
-extern unsigned int s3c2410_gpio_getpin(unsigned int pin);
-
-#endif /* __MACH_GPIO_FNS_H */
+#include <plat/gpio-fns.h>
index 4f7bf32..019ea86 100644 (file)
@@ -53,7 +53,7 @@
 #define S3C2410_GPIO_M_NR      (32)    /* technically 2. */
 
 #if CONFIG_S3C_GPIO_SPACE != 0
-#error CONFIG_S3C_GPIO_SPACE cannot be zero at the moment
+#error CONFIG_S3C_GPIO_SPACE cannot be nonzero at the moment
 #endif
 
 #define S3C2410_GPIO_NEXT(__gpio) \
index d67819d..c410a07 100644 (file)
 
 #include <mach/regs-gpio.h>
 
-extern struct s3c_gpio_chip s3c24xx_gpios[];
+extern struct samsung_gpio_chip s3c24xx_gpios[];
 
-static inline struct s3c_gpio_chip *s3c_gpiolib_getchip(unsigned int pin)
+static inline struct samsung_gpio_chip *samsung_gpiolib_getchip(unsigned int pin)
 {
-       struct s3c_gpio_chip *chip;
+       struct samsung_gpio_chip *chip;
 
        if (pin > S3C_GPIO_END)
                return NULL;
index e5a68ea..e53b217 100644 (file)
 #define IRQ_LCD_SYSTEM         IRQ_S3C2443_LCD2
 
 #ifdef CONFIG_CPU_S3C2440
-#define IRQ_S3C244x_AC97 IRQ_S3C2440_AC97
+#define IRQ_S3C244X_AC97 IRQ_S3C2440_AC97
 #else
-#define IRQ_S3C244x_AC97 IRQ_S3C2443_AC97
+#define IRQ_S3C244X_AC97 IRQ_S3C2443_AC97
 #endif
 
 /* Our FIQs are routable from IRQ_EINT0 to IRQ_ADCPARENT */
index 4cf495f..78ae807 100644 (file)
 #define S3C24XX_PA_RTC      S3C2410_PA_RTC
 #define S3C24XX_PA_ADC      S3C2410_PA_ADC
 #define S3C24XX_PA_SPI      S3C2410_PA_SPI
+#define S3C24XX_PA_SPI1                (S3C2410_PA_SPI + S3C2410_SPI1)
 #define S3C24XX_PA_SDI      S3C2410_PA_SDI
 #define S3C24XX_PA_NAND            S3C2410_PA_NAND
 
index 45eea52..2eef7e6 100644 (file)
@@ -64,4 +64,4 @@ static inline void s3c_pm_arch_update_uart(void __iomem *regs,
 }
 
 static inline void s3c_pm_restored_gpios(void) { }
-static inline void s3c_pm_saved_gpios(void) { }
+static inline void samsung_pm_saved_gpios(void) { }
index 5e06c72..c3feff3 100644 (file)
@@ -65,6 +65,7 @@
 #define S3C2443_CLKDIV0_PREDIV_MASK    (3<<4)
 #define S3C2443_CLKDIV0_PREDIV_SHIFT   (4)
 
+#define S3C2416_CLKDIV0_ARMDIV_MASK    (7 << 9)
 #define S3C2443_CLKDIV0_ARMDIV_MASK    (15<<9)
 #define S3C2443_CLKDIV0_ARMDIV_SHIFT   (9)
 #define S3C2443_CLKDIV0_ARMDIV_1       (0<<9)
 #define S3C2443_PCLKCON_UART3          (1<<3)
 #define S3C2443_PCLKCON_IIC            (1<<4)
 #define S3C2443_PCLKCON_SDI            (1<<5)
+#define S3C2443_PCLKCON_HSSPI          (1<<6)
 #define S3C2443_PCLKCON_ADC            (1<<7)
 #define S3C2443_PCLKCON_AC97           (1<<8)
 #define S3C2443_PCLKCON_IIS            (1<<9)
index 556c535..caa4ae2 100644 (file)
@@ -696,9 +696,9 @@ static void __init h1940_init(void)
                              S3C2410_MISCCR_USBSUSPND0 |
                              S3C2410_MISCCR_USBSUSPND1, 0x0);
 
-       tmp =   (0x78 << S3C24XX_PLLCON_MDIVSHIFT)
-             | (0x02 << S3C24XX_PLLCON_PDIVSHIFT)
-             | (0x03 << S3C24XX_PLLCON_SDIVSHIFT);
+       tmp =   (0x78 << S3C24XX_PLL_MDIV_SHIFT)
+             | (0x02 << S3C24XX_PLL_PDIV_SHIFT)
+             | (0x03 << S3C24XX_PLL_SDIV_SHIFT);
        writel(tmp, S3C2410_UPLLCON);
 
        gpio_request(S3C2410_GPC(0), "LCD power");
index 367d376..4518521 100644 (file)
@@ -49,6 +49,7 @@
 
 #include <mach/regs-gpio.h>
 #include <mach/leds-gpio.h>
+#include <mach/regs-lcd.h>
 #include <plat/regs-serial.h>
 #include <mach/fb.h>
 #include <plat/nand.h>
index 343a540..3d7ebc5 100644 (file)
@@ -72,8 +72,8 @@ void __init s3c2410_init_uarts(struct s3c2410_uartcfg *cfg, int no)
 
 void __init s3c2410_map_io(void)
 {
-       s3c24xx_gpiocfg_default.set_pull = s3c_gpio_setpull_1up;
-       s3c24xx_gpiocfg_default.get_pull = s3c_gpio_getpull_1up;
+       s3c24xx_gpiocfg_default.set_pull = s3c24xx_gpio_setpull_1up;
+       s3c24xx_gpiocfg_default.get_pull = s3c24xx_gpio_getpull_1up;
 
        iotable_init(s3c2410_iodesc, ARRAY_SIZE(s3c2410_iodesc));
 }
index c61e326..d2a7d5e 100644 (file)
@@ -130,11 +130,11 @@ static struct s3c24xx_dma_map __initdata s3c2412_dma_mappings[] = {
 
 static void s3c2412_dma_direction(struct s3c2410_dma_chan *chan,
                                  struct s3c24xx_dma_map *map,
-                                 enum s3c2410_dmasrc dir)
+                                 enum dma_data_direction dir)
 {
        unsigned long chsel;
 
-       if (dir == S3C2410_DMASRC_HW)
+       if (dir == DMA_FROM_DEVICE)
                chsel = map->channels_rx[0];
        else
                chsel = map->channels[0];
diff --git a/arch/arm/mach-s3c2412/gpio.c b/arch/arm/mach-s3c2412/gpio.c
new file mode 100644 (file)
index 0000000..4526f6b
--- /dev/null
@@ -0,0 +1,62 @@
+/* linux/arch/arm/mach-s3c2412/gpio.c
+ *
+ * Copyright (c) 2007 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * http://armlinux.simtec.co.uk/.
+ *
+ * S3C2412/S3C2413 specific GPIO 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/kernel.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/gpio.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <mach/regs-gpio.h>
+#include <mach/hardware.h>
+
+#include <plat/gpio-core.h>
+
+int s3c2412_gpio_set_sleepcfg(unsigned int pin, unsigned int state)
+{
+       struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
+       unsigned long offs = pin - chip->chip.base;
+       unsigned long flags;
+       unsigned long slpcon;
+
+       offs *= 2;
+
+       if (pin < S3C2410_GPB(0))
+               return -EINVAL;
+
+       if (pin >= S3C2410_GPF(0) &&
+           pin <= S3C2410_GPG(16))
+               return -EINVAL;
+
+       if (pin > S3C2410_GPH(16))
+               return -EINVAL;
+
+       local_irq_save(flags);
+
+       slpcon = __raw_readl(chip->base + 0x0C);
+
+       slpcon &= ~(3 << offs);
+       slpcon |= state << offs;
+
+       __raw_writel(slpcon, chip->base + 0x0C);
+
+       local_irq_restore(flags);
+
+       return 0;
+}
+
+EXPORT_SYMBOL(s3c2412_gpio_set_sleepcfg);
index 69b48a7..84c7b03 100644 (file)
@@ -13,7 +13,6 @@ config CPU_S3C2416
        select CPU_ARM926T
        select S3C2416_DMA if S3C2410_DMA
        select CPU_LLSERIAL_S3C2440
-       select S3C_GPIO_PULL_UPDOWN
        select SAMSUNG_CLKSRC
        select S3C2443_CLOCK
        help
index 21a5e81..afbbe8b 100644 (file)
@@ -21,7 +21,6 @@
 #include <plat/cpu.h>
 
 #include <plat/cpu-freq.h>
-#include <plat/pll6553x.h>
 #include <plat/pll.h>
 
 #include <asm/mach/map.h>
 #include <mach/regs-clock.h>
 #include <mach/regs-s3c2443-clock.h>
 
+/* armdiv
+ *
+ * this clock is sourced from msysclk and can have a number of
+ * divider values applied to it to then be fed into armclk.
+ * The real clock definition is done in s3c2443-clock.c,
+ * only the armdiv divisor table must be defined here.
+*/
+
 static unsigned int armdiv[8] = {
        [0] = 1,
        [1] = 2,
@@ -38,6 +45,32 @@ static unsigned int armdiv[8] = {
        [7] = 8,
 };
 
+static struct clksrc_clk hsspi_eplldiv = {
+       .clk = {
+               .name   = "hsspi-eplldiv",
+               .parent = &clk_esysclk.clk,
+               .ctrlbit = (1 << 14),
+               .enable = s3c2443_clkcon_enable_s,
+       },
+       .reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 24 },
+};
+
+static struct clk *hsspi_sources[] = {
+       [0] = &hsspi_eplldiv.clk,
+       [1] = NULL, /* to fix */
+};
+
+static struct clksrc_clk hsspi_mux = {
+       .clk    = {
+               .name   = "hsspi-if",
+       },
+       .sources = &(struct clksrc_sources) {
+               .sources = hsspi_sources,
+               .nr_sources = ARRAY_SIZE(hsspi_sources),
+       },
+       .reg_src = { .reg = S3C2443_CLKSRC, .size = 1, .shift = 18 },
+};
+
 static struct clksrc_clk hsmmc_div[] = {
        [0] = {
                .clk = {
@@ -100,20 +133,15 @@ static struct clk hsmmc0_clk = {
        .ctrlbit        = S3C2416_HCLKCON_HSMMC0,
 };
 
-static inline unsigned int s3c2416_fclk_div(unsigned long clkcon0)
-{
-       clkcon0 &= 7 << S3C2443_CLKDIV0_ARMDIV_SHIFT;
-
-       return armdiv[clkcon0 >> S3C2443_CLKDIV0_ARMDIV_SHIFT];
-}
-
 void __init_or_cpufreq s3c2416_setup_clocks(void)
 {
-       s3c2443_common_setup_clocks(s3c2416_get_pll, s3c2416_fclk_div);
+       s3c2443_common_setup_clocks(s3c2416_get_pll);
 }
 
 
 static struct clksrc_clk *clksrcs[] __initdata = {
+       &hsspi_eplldiv,
+       &hsspi_mux,
        &hsmmc_div[0],
        &hsmmc_div[1],
        &hsmmc_mux[0],
@@ -131,7 +159,9 @@ void __init s3c2416_init_clocks(int xtal)
 
        clk_epll.parent = &clk_epllref.clk;
 
-       s3c2443_common_init_clocks(xtal, s3c2416_get_pll, s3c2416_fclk_div);
+       s3c2443_common_init_clocks(xtal, s3c2416_get_pll,
+                                  armdiv, ARRAY_SIZE(armdiv),
+                                  S3C2416_CLKDIV0_ARMDIV_MASK);
 
        for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
                s3c_register_clksrc(clksrcs[ptr], 1);
index 20b3fdf..ee214bc 100644 (file)
@@ -60,6 +60,7 @@
 #include <plat/iic-core.h>
 #include <plat/fb-core.h>
 #include <plat/nand-core.h>
+#include <plat/adc-core.h>
 
 static struct map_desc s3c2416_iodesc[] __initdata = {
        IODESC_ENT(WATCHDOG),
@@ -97,6 +98,8 @@ int __init s3c2416_init(void)
 
        s3c_fb_setname("s3c2443-fb");
 
+       s3c_adc_setname("s3c2416-adc");
+
 #ifdef CONFIG_PM
        register_syscore_ops(&s3c2416_pm_syscore_ops);
 #endif
@@ -120,8 +123,8 @@ void __init s3c2416_init_uarts(struct s3c2410_uartcfg *cfg, int no)
 
 void __init s3c2416_map_io(void)
 {
-       s3c24xx_gpiocfg_default.set_pull = s3c_gpio_setpull_updown;
-       s3c24xx_gpiocfg_default.get_pull = s3c_gpio_getpull_updown;
+       s3c24xx_gpiocfg_default.set_pull = samsung_gpio_setpull_updown;
+       s3c24xx_gpiocfg_default.get_pull = samsung_gpio_getpull_updown;
 
        /* initialize device information early */
        s3c2416_default_sdhci0();
index ed34fad..cee5395 100644 (file)
  * published by the Free Software Foundation.
 */
 
-#include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-
-#include <linux/mmc/card.h>
-#include <linux/mmc/host.h>
-
-#include <plat/regs-sdhci.h>
-#include <plat/sdhci.h>
 
 /* clock sources for the mmc bus clock, order as for the ctrl2[5..4] */
 
@@ -32,30 +22,3 @@ char *s3c2416_hsmmc_clksrcs[4] = {
        [2] = "hsmmc-if",
        /* [3] = "48m", - note not successfully used yet */
 };
-
-void s3c2416_setup_sdhci_cfg_card(struct platform_device *dev,
-                                 void __iomem *r,
-                                 struct mmc_ios *ios,
-                                 struct mmc_card *card)
-{
-       u32 ctrl2, ctrl3;
-
-       ctrl2 = __raw_readl(r + S3C_SDHCI_CONTROL2);
-       ctrl2 &= S3C_SDHCI_CTRL2_SELBASECLK_MASK;
-       ctrl2 |= (S3C64XX_SDHCI_CTRL2_ENSTAASYNCCLR |
-                 S3C64XX_SDHCI_CTRL2_ENCMDCNFMSK |
-                 S3C_SDHCI_CTRL2_ENFBCLKRX |
-                 S3C_SDHCI_CTRL2_DFCNT_NONE |
-                 S3C_SDHCI_CTRL2_ENCLKOUTHOLD);
-
-       if (ios->clock < 25 * 1000000)
-               ctrl3 = (S3C_SDHCI_CTRL3_FCSEL3 |
-                        S3C_SDHCI_CTRL3_FCSEL2 |
-                        S3C_SDHCI_CTRL3_FCSEL1 |
-                        S3C_SDHCI_CTRL3_FCSEL0);
-       else
-               ctrl3 = (S3C_SDHCI_CTRL3_FCSEL1 | S3C_SDHCI_CTRL3_FCSEL0);
-
-       __raw_writel(ctrl2, r + S3C_SDHCI_CONTROL2);
-       __raw_writel(ctrl3, r + S3C_SDHCI_CONTROL3);
-}
index c461fb8..914e620 100644 (file)
@@ -5,7 +5,6 @@
 config CPU_S3C2440
        bool
        select CPU_ARM920T
-       select S3C_GPIO_PULL_UP
        select S3C2410_CLOCK
        select S3C2410_PM if PM
        select S3C2440_DMA if S3C2410_DMA
@@ -17,7 +16,6 @@ config CPU_S3C2440
 config CPU_S3C2442
        bool
        select CPU_ARM920T
-       select S3C_GPIO_PULL_DOWN
        select S3C2410_CLOCK
        select S3C2410_PM if PM
        select CPU_S3C244X
index 684dbb3..0d3453b 100644 (file)
@@ -43,6 +43,7 @@
 
 #include <mach/regs-gpio.h>
 #include <mach/regs-gpioj.h>
+#include <mach/regs-lcd.h>
 #include <mach/h1940.h>
 #include <mach/fb.h>
 
index 2270d33..37f8cc6 100644 (file)
@@ -70,6 +70,6 @@ void __init s3c2440_map_io(void)
 {
        s3c244x_map_io();
 
-       s3c24xx_gpiocfg_default.set_pull = s3c_gpio_setpull_1up;
-       s3c24xx_gpiocfg_default.get_pull = s3c_gpio_getpull_1up;
+       s3c24xx_gpiocfg_default.set_pull = s3c24xx_gpio_setpull_1up;
+       s3c24xx_gpiocfg_default.get_pull = s3c24xx_gpio_getpull_1up;
 }
index 6f2b65e..2c822e0 100644 (file)
@@ -182,6 +182,6 @@ void __init s3c2442_map_io(void)
 {
        s3c244x_map_io();
 
-       s3c24xx_gpiocfg_default.set_pull = s3c_gpio_setpull_1down;
-       s3c24xx_gpiocfg_default.get_pull = s3c_gpio_getpull_1down;
+       s3c24xx_gpiocfg_default.set_pull = s3c24xx_gpio_setpull_1down;
+       s3c24xx_gpiocfg_default.get_pull = s3c24xx_gpio_getpull_1down;
 }
index d8eb868..8814031 100644 (file)
@@ -10,7 +10,6 @@ config CPU_S3C2443
        select CPU_LLSERIAL_S3C2440
        select SAMSUNG_CLKSRC
        select S3C2443_CLOCK
-       select S3C_GPIO_PULL_S3C2443
        help
          Support for the S3C2443 SoC from the S3C24XX line
 
index 38058af..1c2c088 100644 (file)
 
 /* clock selections */
 
-static struct clk clk_i2s_ext = {
-       .name           = "i2s-ext",
-};
-
 /* armdiv
  *
  * this clock is sourced from msysclk and can have a number of
  * divider values applied to it to then be fed into armclk.
+ * The real clock definition is done in s3c2443-clock.c,
+ * only the armdiv divisor table must be defined here.
 */
 
-/* armdiv divisor table */
-
 static unsigned int armdiv[16] = {
        [S3C2443_CLKDIV0_ARMDIV_1 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]      = 1,
        [S3C2443_CLKDIV0_ARMDIV_2 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]      = 2,
@@ -80,92 +76,6 @@ static unsigned int armdiv[16] = {
        [S3C2443_CLKDIV0_ARMDIV_16 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]     = 16,
 };
 
-static inline unsigned int s3c2443_fclk_div(unsigned long clkcon0)
-{
-       clkcon0 &= S3C2443_CLKDIV0_ARMDIV_MASK;
-
-       return armdiv[clkcon0 >> S3C2443_CLKDIV0_ARMDIV_SHIFT];
-}
-
-static unsigned long s3c2443_armclk_roundrate(struct clk *clk,
-                                             unsigned long rate)
-{
-       unsigned long parent = clk_get_rate(clk->parent);
-       unsigned long calc;
-       unsigned best = 256; /* bigger than any value */
-       unsigned div;
-       int ptr;
-
-       for (ptr = 0; ptr < ARRAY_SIZE(armdiv); ptr++) {
-               div = armdiv[ptr];
-               calc = parent / div;
-               if (calc <= rate && div < best)
-                       best = div;
-       }
-
-       return parent / best;
-}
-
-static int s3c2443_armclk_setrate(struct clk *clk, unsigned long rate)
-{
-       unsigned long parent = clk_get_rate(clk->parent);
-       unsigned long calc;
-       unsigned div;
-       unsigned best = 256; /* bigger than any value */
-       int ptr;
-       int val = -1;
-
-       for (ptr = 0; ptr < ARRAY_SIZE(armdiv); ptr++) {
-               div = armdiv[ptr];
-               calc = parent / div;
-               if (calc <= rate && div < best) {
-                       best = div;
-                       val = ptr;
-               }
-       }
-
-       if (val >= 0) {
-               unsigned long clkcon0;
-
-               clkcon0 = __raw_readl(S3C2443_CLKDIV0);
-               clkcon0 &= ~S3C2443_CLKDIV0_ARMDIV_MASK;
-               clkcon0 |= val << S3C2443_CLKDIV0_ARMDIV_SHIFT;
-               __raw_writel(clkcon0, S3C2443_CLKDIV0);
-       }
-
-       return (val == -1) ? -EINVAL : 0;
-}
-
-static struct clk clk_armdiv = {
-       .name           = "armdiv",
-       .parent         = &clk_msysclk.clk,
-       .ops            = &(struct clk_ops) {
-               .round_rate = s3c2443_armclk_roundrate,
-               .set_rate = s3c2443_armclk_setrate,
-       },
-};
-
-/* armclk
- *
- * this is the clock fed into the ARM core itself, from armdiv or from hclk.
- */
-
-static struct clk *clk_arm_sources[] = {
-       [0] = &clk_armdiv,
-       [1] = &clk_h,
-};
-
-static struct clksrc_clk clk_arm = {
-       .clk    = {
-               .name           = "armclk",
-       },
-       .sources = &(struct clksrc_sources) {
-               .sources = clk_arm_sources,
-               .nr_sources = ARRAY_SIZE(clk_arm_sources),
-       },
-       .reg_src = { .reg = S3C2443_CLKDIV0, .size = 1, .shift = 13 },
-};
-
 /* hsspi
  *
  * high-speed spi clock, sourced from esysclk
@@ -173,7 +83,7 @@ static struct clksrc_clk clk_arm = {
 
 static struct clksrc_clk clk_hsspi = {
        .clk    = {
-               .name           = "hsspi",
+               .name           = "hsspi-if",
                .parent         = &clk_esysclk.clk,
                .ctrlbit        = S3C2443_SCLKCON_HSSPICLK,
                .enable         = s3c2443_clkcon_enable_s,
@@ -235,48 +145,6 @@ static struct clk clk_hsmmc = {
        },
 };
 
-/* i2s_eplldiv
- *
- * This clock is the output from the I2S divisor of ESYSCLK, and is separate
- * from the mux that comes after it (cannot merge into one single clock)
-*/
-
-static struct clksrc_clk clk_i2s_eplldiv = {
-       .clk    = {
-               .name           = "i2s-eplldiv",
-               .parent         = &clk_esysclk.clk,
-       },
-       .reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 12, },
-};
-
-/* i2s-ref
- *
- * i2s bus reference clock, selectable from external, esysclk or epllref
- *
- * Note, this used to be two clocks, but was compressed into one.
-*/
-
-struct clk *clk_i2s_srclist[] = {
-       [0] = &clk_i2s_eplldiv.clk,
-       [1] = &clk_i2s_ext,
-       [2] = &clk_epllref.clk,
-       [3] = &clk_epllref.clk,
-};
-
-static struct clksrc_clk clk_i2s = {
-       .clk    = {
-               .name           = "i2s-if",
-               .ctrlbit        = S3C2443_SCLKCON_I2SCLK,
-               .enable         = s3c2443_clkcon_enable_s,
-
-       },
-       .sources = &(struct clksrc_sources) {
-               .sources = clk_i2s_srclist,
-               .nr_sources = ARRAY_SIZE(clk_i2s_srclist),
-       },
-       .reg_src = { .reg = S3C2443_CLKSRC, .size = 2, .shift = 14 },
-};
-
 /* standard clock definitions */
 
 static struct clk init_clocks_off[] = {
@@ -286,11 +154,6 @@ static struct clk init_clocks_off[] = {
                .enable         = s3c2443_clkcon_enable_p,
                .ctrlbit        = S3C2443_PCLKCON_SDI,
        }, {
-               .name           = "iis",
-               .parent         = &clk_p,
-               .enable         = s3c2443_clkcon_enable_p,
-               .ctrlbit        = S3C2443_PCLKCON_IIS,
-       }, {
                .name           = "spi",
                .devname        = "s3c2410-spi.0",
                .parent         = &clk_p,
@@ -305,27 +168,20 @@ static struct clk init_clocks_off[] = {
        }
 };
 
-static struct clk init_clocks[] = {
-};
-
 /* clocks to add straight away */
 
 static struct clksrc_clk *clksrcs[] __initdata = {
-       &clk_arm,
-       &clk_i2s_eplldiv,
-       &clk_i2s,
        &clk_hsspi,
        &clk_hsmmc_div,
 };
 
 static struct clk *clks[] __initdata = {
        &clk_hsmmc,
-       &clk_armdiv,
 };
 
 void __init_or_cpufreq s3c2443_setup_clocks(void)
 {
-       s3c2443_common_setup_clocks(s3c2443_get_mpll, s3c2443_fclk_div);
+       s3c2443_common_setup_clocks(s3c2443_get_mpll);
 }
 
 void __init s3c2443_init_clocks(int xtal)
@@ -336,7 +192,9 @@ void __init s3c2443_init_clocks(int xtal)
        clk_epll.rate = s3c2443_get_epll(epllcon, xtal);
        clk_epll.parent = &clk_epllref.clk;
 
-       s3c2443_common_init_clocks(xtal, s3c2443_get_mpll, s3c2443_fclk_div);
+       s3c2443_common_init_clocks(xtal, s3c2443_get_mpll,
+                                  armdiv, ARRAY_SIZE(armdiv),
+                                  S3C2443_CLKDIV0_ARMDIV_MASK);
 
        s3c2443_setup_clocks();
 
@@ -345,10 +203,6 @@ void __init s3c2443_init_clocks(int xtal)
        for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
                s3c_register_clksrc(clksrcs[ptr], 1);
 
-       /* register clocks from clock array */
-
-       s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
-
        /* We must be careful disabling the clocks we are not intending to
         * be using at boot time, as subsystems such as the LCD which do
         * their own DMA requests to the bus can cause the system to lockup
index e6a28ba..a22b771 100644 (file)
@@ -41,6 +41,7 @@
 #include <plat/cpu.h>
 #include <plat/fb-core.h>
 #include <plat/nand-core.h>
+#include <plat/adc-core.h>
 
 static struct map_desc s3c2443_iodesc[] __initdata = {
        IODESC_ENT(WATCHDOG),
@@ -70,6 +71,8 @@ int __init s3c2443_init(void)
        s3c_nand_setname("s3c2412-nand");
        s3c_fb_setname("s3c2443-fb");
 
+       s3c_adc_setname("s3c2443-adc");
+
        /* change WDT IRQ number */
        s3c_device_wdt.resource[1].start = IRQ_S3C2443_WDT;
        s3c_device_wdt.resource[1].end   = IRQ_S3C2443_WDT;
@@ -90,8 +93,8 @@ void __init s3c2443_init_uarts(struct s3c2410_uartcfg *cfg, int no)
 
 void __init s3c2443_map_io(void)
 {
-       s3c24xx_gpiocfg_default.set_pull = s3c_gpio_setpull_s3c2443;
-       s3c24xx_gpiocfg_default.get_pull = s3c_gpio_getpull_s3c2443;
+       s3c24xx_gpiocfg_default.set_pull = s3c2443_gpio_setpull;
+       s3c24xx_gpiocfg_default.get_pull = s3c2443_gpio_getpull;
 
        iotable_init(s3c2443_iodesc, ARRAY_SIZE(s3c2443_iodesc));
 }
index f057b6a..5552e04 100644 (file)
@@ -288,5 +288,6 @@ config MACH_WLF_CRAGG_6410
        select S3C_DEV_RTC
        select S3C64XX_DEV_SPI
        select S3C24XX_GPIO_EXTRA128
+       select I2C
        help
          Machine support for the Wolfson Cragganmore S3C6410 variant.
index 61b4034..cfc0b99 100644 (file)
@@ -13,7 +13,6 @@ obj-                          :=
 # Core files
 obj-y                          += cpu.o
 obj-y                          += clock.o
-obj-y                          += gpiolib.o
 
 # Core support for S3C6400 system
 
@@ -55,12 +54,10 @@ 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
+obj-$(CONFIG_MACH_WLF_CRAGG_6410) += mach-crag6410.o mach-crag6410-module.o
 
 # device support
 
 obj-y                          += dev-uart.o
 obj-y                          += dev-audio.o
 obj-$(CONFIG_S3C64XX_DEV_SPI)  += dev-spi.o
-obj-$(CONFIG_S3C64XX_DEV_TS)   += dev-ts.o
-obj-$(CONFIG_S3C64XX_DEV_ONENAND1)     += dev-onenand1.o
index 8cf39e3..39c238d 100644 (file)
 
 #include <mach/regs-sys.h>
 #include <mach/regs-clock.h>
-#include <mach/pll.h>
 
 #include <plat/cpu.h>
 #include <plat/devs.h>
 #include <plat/cpu-freq.h>
 #include <plat/clock.h>
 #include <plat/clock-clksrc.h>
+#include <plat/pll.h>
 
 /* fin_apll, fin_mpll and fin_epll are all the same clock, which we call
  * ext_xtal_mux for want of an actual name from the manual.
@@ -735,7 +735,8 @@ void __init_or_cpufreq s3c6400_setup_clocks(void)
        /* For now assume the mux always selects the crystal */
        clk_ext_xtal_mux.parent = xtal_clk;
 
-       epll = s3c6400_get_epll(xtal);
+       epll = s3c_get_pll6553x(xtal, __raw_readl(S3C_EPLL_CON0),
+                               __raw_readl(S3C_EPLL_CON1));
        mpll = s3c6400_get_pll(xtal, __raw_readl(S3C_MPLL_CON));
        apll = s3c6400_get_pll(xtal, __raw_readl(S3C_APLL_CON));
 
@@ -744,7 +745,13 @@ void __init_or_cpufreq s3c6400_setup_clocks(void)
        printk(KERN_INFO "S3C64XX: PLL settings, A=%ld, M=%ld, E=%ld\n",
               apll, mpll, epll);
 
-       hclk2 = mpll / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK2);
+       if(__raw_readl(S3C64XX_OTHERS) & S3C64XX_OTHERS_SYNCMUXSEL)
+               /* Synchronous mode */
+               hclk2 = apll / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK2);
+       else
+               /* Asynchronous mode */
+               hclk2 = mpll / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK2);
+
        hclk = hclk2 / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK);
        pclk = hclk2 / GET_DIV(clkdiv0, S3C6400_CLKDIV0_PCLK);
 
index c704783..de085b7 100644 (file)
@@ -34,8 +34,8 @@
 #include <plat/devs.h>
 #include <plat/clock.h>
 
-#include <mach/s3c6400.h>
-#include <mach/s3c6410.h>
+#include <plat/s3c6400.h>
+#include <plat/s3c6410.h>
 
 /* table of supported CPUs */
 
diff --git a/arch/arm/mach-s3c64xx/dev-onenand1.c b/arch/arm/mach-s3c64xx/dev-onenand1.c
deleted file mode 100644 (file)
index 999f9e1..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * linux/arch/arm/mach-s3c64xx/dev-onenand1.c
- *
- *  Copyright (c) 2008-2010 Samsung Electronics
- *  Kyungmin Park <kyungmin.park@samsung.com>
- *
- * S3C64XX series device definition for OneNAND devices
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/onenand.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/devs.h>
-
-static struct resource s3c64xx_onenand1_resources[] = {
-       [0] = {
-               .start  = S3C64XX_PA_ONENAND1,
-               .end    = S3C64XX_PA_ONENAND1 + 0x400 - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = S3C64XX_PA_ONENAND1_BUF,
-               .end    = S3C64XX_PA_ONENAND1_BUF + S3C64XX_SZ_ONENAND1_BUF - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [2] = {
-               .start  = IRQ_ONENAND1,
-               .end    = IRQ_ONENAND1,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-struct platform_device s3c64xx_device_onenand1 = {
-       .name           = "samsung-onenand",
-       .id             = 1,
-       .num_resources  = ARRAY_SIZE(s3c64xx_onenand1_resources),
-       .resource       = s3c64xx_onenand1_resources,
-};
-
-void s3c64xx_onenand1_set_platdata(struct onenand_platform_data *pdata)
-{
-       s3c_set_platdata(pdata, sizeof(struct onenand_platform_data),
-                        &s3c64xx_device_onenand1);
-}
index 204bfaf..17d62f4 100644 (file)
@@ -147,14 +147,14 @@ static void s3c64xx_dma_fill_lli(struct s3c2410_dma_chan *chan,
        u32 control0, control1;
 
        switch (chan->source) {
-       case S3C2410_DMASRC_HW:
+       case DMA_FROM_DEVICE:
                src = chan->dev_addr;
                dst = data;
                control0 = PL080_CONTROL_SRC_AHB2;
                control0 |= PL080_CONTROL_DST_INCR;
                break;
 
-       case S3C2410_DMASRC_MEM:
+       case DMA_TO_DEVICE:
                src = data;
                dst = chan->dev_addr;
                control0 = PL080_CONTROL_DST_AHB2;
@@ -416,7 +416,7 @@ EXPORT_SYMBOL(s3c2410_dma_enqueue);
 
 
 int s3c2410_dma_devconfig(enum dma_ch channel,
-                         enum s3c2410_dmasrc source,
+                         enum dma_data_direction source,
                          unsigned long devaddr)
 {
        struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
@@ -437,11 +437,11 @@ int s3c2410_dma_devconfig(enum dma_ch channel,
        pr_debug("%s: peripheral %d\n", __func__, peripheral);
 
        switch (source) {
-       case S3C2410_DMASRC_HW:
+       case DMA_FROM_DEVICE:
                config = 2 << PL080_CONFIG_FLOW_CONTROL_SHIFT;
                config |= peripheral << PL080_CONFIG_SRC_SEL_SHIFT;
                break;
-       case S3C2410_DMASRC_MEM:
+       case DMA_TO_DEVICE:
                config = 1 << PL080_CONFIG_FLOW_CONTROL_SHIFT;
                config |= peripheral << PL080_CONFIG_DST_SEL_SHIFT;
                break;
@@ -740,7 +740,7 @@ static int __init s3c64xx_dma_init(void)
        }
 
        /* Set all DMA configuration to be DMA, not SDMA */
-       writel(0xffffff, S3C_SYSREG(0x110));
+       writel(0xffffff, S3C64XX_SDMA_SEL);
 
        /* Register standard DMA controllers */
        s3c64xx_dma_init1(0, DMACH_UART0, IRQ_DMA0, 0x75000000);
diff --git a/arch/arm/mach-s3c64xx/gpiolib.c b/arch/arm/mach-s3c64xx/gpiolib.c
deleted file mode 100644 (file)
index 92b0908..0000000
+++ /dev/null
@@ -1,290 +0,0 @@
-/* arch/arm/plat-s3c64xx/gpiolib.c
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *      Ben Dooks <ben@simtec.co.uk>
- *      http://armlinux.simtec.co.uk/
- *
- * S3C64XX - GPIOlib 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/kernel.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-
-#include <mach/map.h>
-
-#include <plat/gpio-core.h>
-#include <plat/gpio-cfg.h>
-#include <plat/gpio-cfg-helpers.h>
-#include <mach/regs-gpio.h>
-
-/* GPIO bank summary:
- *
- * Bank        GPIOs   Style   SlpCon  ExtInt Group
- * A   8       4Bit    Yes     1
- * B   7       4Bit    Yes     1
- * C   8       4Bit    Yes     2
- * D   5       4Bit    Yes     3
- * E   5       4Bit    Yes     None
- * F   16      2Bit    Yes     4 [1]
- * G   7       4Bit    Yes     5
- * H   10      4Bit[2] Yes     6
- * I   16      2Bit    Yes     None
- * J   12      2Bit    Yes     None
- * K   16      4Bit[2] No      None
- * L   15      4Bit[2] No      None
- * M   6       4Bit    No      IRQ_EINT
- * N   16      2Bit    No      IRQ_EINT
- * O   16      2Bit    Yes     7
- * P   15      2Bit    Yes     8
- * Q   9       2Bit    Yes     9
- *
- * [1] BANKF pins 14,15 do not form part of the external interrupt sources
- * [2] BANK has two control registers, GPxCON0 and GPxCON1
- */
-
-static struct s3c_gpio_cfg gpio_4bit_cfg_noint = {
-       .set_config     = s3c_gpio_setcfg_s3c64xx_4bit,
-       .get_config     = s3c_gpio_getcfg_s3c64xx_4bit,
-       .set_pull       = s3c_gpio_setpull_updown,
-       .get_pull       = s3c_gpio_getpull_updown,
-};
-
-static struct s3c_gpio_cfg gpio_4bit_cfg_eint0111 = {
-       .cfg_eint       = 7,
-       .set_config     = s3c_gpio_setcfg_s3c64xx_4bit,
-       .get_config     = s3c_gpio_getcfg_s3c64xx_4bit,
-       .set_pull       = s3c_gpio_setpull_updown,
-       .get_pull       = s3c_gpio_getpull_updown,
-};
-
-static struct s3c_gpio_cfg gpio_4bit_cfg_eint0011 = {
-       .cfg_eint       = 3,
-       .get_config     = s3c_gpio_getcfg_s3c64xx_4bit,
-       .set_config     = s3c_gpio_setcfg_s3c64xx_4bit,
-       .set_pull       = s3c_gpio_setpull_updown,
-       .get_pull       = s3c_gpio_getpull_updown,
-};
-
-static int s3c64xx_gpio2int_gpm(struct gpio_chip *chip, unsigned pin)
-{
-       return pin < 5 ? IRQ_EINT(23) + pin : -ENXIO;
-}
-
-static struct s3c_gpio_chip gpio_4bit[] = {
-       {
-               .base   = S3C64XX_GPA_BASE,
-               .config = &gpio_4bit_cfg_eint0111,
-               .chip   = {
-                       .base   = S3C64XX_GPA(0),
-                       .ngpio  = S3C64XX_GPIO_A_NR,
-                       .label  = "GPA",
-               },
-       }, {
-               .base   = S3C64XX_GPB_BASE,
-               .config = &gpio_4bit_cfg_eint0111,
-               .chip   = {
-                       .base   = S3C64XX_GPB(0),
-                       .ngpio  = S3C64XX_GPIO_B_NR,
-                       .label  = "GPB",
-               },
-       }, {
-               .base   = S3C64XX_GPC_BASE,
-               .config = &gpio_4bit_cfg_eint0111,
-               .chip   = {
-                       .base   = S3C64XX_GPC(0),
-                       .ngpio  = S3C64XX_GPIO_C_NR,
-                       .label  = "GPC",
-               },
-       }, {
-               .base   = S3C64XX_GPD_BASE,
-               .config = &gpio_4bit_cfg_eint0111,
-               .chip   = {
-                       .base   = S3C64XX_GPD(0),
-                       .ngpio  = S3C64XX_GPIO_D_NR,
-                       .label  = "GPD",
-               },
-       }, {
-               .base   = S3C64XX_GPE_BASE,
-               .config = &gpio_4bit_cfg_noint,
-               .chip   = {
-                       .base   = S3C64XX_GPE(0),
-                       .ngpio  = S3C64XX_GPIO_E_NR,
-                       .label  = "GPE",
-               },
-       }, {
-               .base   = S3C64XX_GPG_BASE,
-               .config = &gpio_4bit_cfg_eint0111,
-               .chip   = {
-                       .base   = S3C64XX_GPG(0),
-                       .ngpio  = S3C64XX_GPIO_G_NR,
-                       .label  = "GPG",
-               },
-       }, {
-               .base   = S3C64XX_GPM_BASE,
-               .config = &gpio_4bit_cfg_eint0011,
-               .chip   = {
-                       .base   = S3C64XX_GPM(0),
-                       .ngpio  = S3C64XX_GPIO_M_NR,
-                       .label  = "GPM",
-                       .to_irq = s3c64xx_gpio2int_gpm,
-               },
-       },
-};
-
-static int s3c64xx_gpio2int_gpl(struct gpio_chip *chip, unsigned pin)
-{
-       return pin >= 8 ? IRQ_EINT(16) + pin - 8 : -ENXIO;
-}
-
-static struct s3c_gpio_chip gpio_4bit2[] = {
-       {
-               .base   = S3C64XX_GPH_BASE + 0x4,
-               .config = &gpio_4bit_cfg_eint0111,
-               .chip   = {
-                       .base   = S3C64XX_GPH(0),
-                       .ngpio  = S3C64XX_GPIO_H_NR,
-                       .label  = "GPH",
-               },
-       }, {
-               .base   = S3C64XX_GPK_BASE + 0x4,
-               .config = &gpio_4bit_cfg_noint,
-               .chip   = {
-                       .base   = S3C64XX_GPK(0),
-                       .ngpio  = S3C64XX_GPIO_K_NR,
-                       .label  = "GPK",
-               },
-       }, {
-               .base   = S3C64XX_GPL_BASE + 0x4,
-               .config = &gpio_4bit_cfg_eint0011,
-               .chip   = {
-                       .base   = S3C64XX_GPL(0),
-                       .ngpio  = S3C64XX_GPIO_L_NR,
-                       .label  = "GPL",
-                       .to_irq = s3c64xx_gpio2int_gpl,
-               },
-       },
-};
-
-static struct s3c_gpio_cfg gpio_2bit_cfg_noint = {
-       .set_config     = s3c_gpio_setcfg_s3c24xx,
-       .get_config     = s3c_gpio_getcfg_s3c24xx,
-       .set_pull       = s3c_gpio_setpull_updown,
-       .get_pull       = s3c_gpio_getpull_updown,
-};
-
-static struct s3c_gpio_cfg gpio_2bit_cfg_eint10 = {
-       .cfg_eint       = 2,
-       .set_config     = s3c_gpio_setcfg_s3c24xx,
-       .get_config     = s3c_gpio_getcfg_s3c24xx,
-       .set_pull       = s3c_gpio_setpull_updown,
-       .get_pull       = s3c_gpio_getpull_updown,
-};
-
-static struct s3c_gpio_cfg gpio_2bit_cfg_eint11 = {
-       .cfg_eint       = 3,
-       .set_config     = s3c_gpio_setcfg_s3c24xx,
-       .get_config     = s3c_gpio_getcfg_s3c24xx,
-       .set_pull       = s3c_gpio_setpull_updown,
-       .get_pull       = s3c_gpio_getpull_updown,
-};
-
-static struct s3c_gpio_chip gpio_2bit[] = {
-       {
-               .base   = S3C64XX_GPF_BASE,
-               .config = &gpio_2bit_cfg_eint11,
-               .chip   = {
-                       .base   = S3C64XX_GPF(0),
-                       .ngpio  = S3C64XX_GPIO_F_NR,
-                       .label  = "GPF",
-               },
-       }, {
-               .base   = S3C64XX_GPI_BASE,
-               .config = &gpio_2bit_cfg_noint,
-               .chip   = {
-                       .base   = S3C64XX_GPI(0),
-                       .ngpio  = S3C64XX_GPIO_I_NR,
-                       .label  = "GPI",
-               },
-       }, {
-               .base   = S3C64XX_GPJ_BASE,
-               .config = &gpio_2bit_cfg_noint,
-               .chip   = {
-                       .base   = S3C64XX_GPJ(0),
-                       .ngpio  = S3C64XX_GPIO_J_NR,
-                       .label  = "GPJ",
-               },
-       }, {
-               .base   = S3C64XX_GPN_BASE,
-               .irq_base = IRQ_EINT(0),
-               .config = &gpio_2bit_cfg_eint10,
-               .chip   = {
-                       .base   = S3C64XX_GPN(0),
-                       .ngpio  = S3C64XX_GPIO_N_NR,
-                       .label  = "GPN",
-                       .to_irq = samsung_gpiolib_to_irq,
-               },
-       }, {
-               .base   = S3C64XX_GPO_BASE,
-               .config = &gpio_2bit_cfg_eint11,
-               .chip   = {
-                       .base   = S3C64XX_GPO(0),
-                       .ngpio  = S3C64XX_GPIO_O_NR,
-                       .label  = "GPO",
-               },
-       }, {
-               .base   = S3C64XX_GPP_BASE,
-               .config = &gpio_2bit_cfg_eint11,
-               .chip   = {
-                       .base   = S3C64XX_GPP(0),
-                       .ngpio  = S3C64XX_GPIO_P_NR,
-                       .label  = "GPP",
-               },
-       }, {
-               .base   = S3C64XX_GPQ_BASE,
-               .config = &gpio_2bit_cfg_eint11,
-               .chip   = {
-                       .base   = S3C64XX_GPQ(0),
-                       .ngpio  = S3C64XX_GPIO_Q_NR,
-                       .label  = "GPQ",
-               },
-       },
-};
-
-static __init void s3c64xx_gpiolib_add_2bit(struct s3c_gpio_chip *chip)
-{
-       chip->pm = __gpio_pm(&s3c_gpio_pm_2bit);
-}
-
-static __init void s3c64xx_gpiolib_add(struct s3c_gpio_chip *chips,
-                                      int nr_chips,
-                                      void (*fn)(struct s3c_gpio_chip *))
-{
-       for (; nr_chips > 0; nr_chips--, chips++) {
-               if (fn)
-                       (fn)(chips);
-               s3c_gpiolib_add(chips);
-       }
-}
-
-static __init int s3c64xx_gpiolib_init(void)
-{
-       s3c64xx_gpiolib_add(gpio_4bit, ARRAY_SIZE(gpio_4bit),
-                           samsung_gpiolib_add_4bit);
-
-       s3c64xx_gpiolib_add(gpio_4bit2, ARRAY_SIZE(gpio_4bit2),
-                           samsung_gpiolib_add_4bit2);
-
-       s3c64xx_gpiolib_add(gpio_2bit, ARRAY_SIZE(gpio_2bit),
-                           s3c64xx_gpiolib_add_2bit);
-
-       return 0;
-}
-
-core_initcall(s3c64xx_gpiolib_init);
diff --git a/arch/arm/mach-s3c64xx/include/mach/clkdev.h b/arch/arm/mach-s3c64xx/include/mach/clkdev.h
deleted file mode 100644 (file)
index 7dffa83..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#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-s3c64xx/include/mach/crag6410.h b/arch/arm/mach-s3c64xx/include/mach/crag6410.h
new file mode 100644 (file)
index 0000000..be9074e
--- /dev/null
@@ -0,0 +1,23 @@
+/* Cragganmore 6410 shared definitions
+ *
+ * Copyright 2011 Wolfson Microelectronics plc
+ *     Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef MACH_CRAG6410_H
+#define MACH_CRAG6410_H
+
+#include <linux/gpio.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)
+
+#endif
index 0a5d926..fe1a98c 100644 (file)
@@ -58,11 +58,15 @@ enum dma_ch {
        DMACH_MAX               /* the end */
 };
 
-static __inline__ bool s3c_dma_has_circular(void)
+static inline bool samsung_dma_has_circular(void)
 {
        return true;
 }
 
+static inline bool samsung_dma_is_dmadev(void)
+{
+       return false;
+}
 #define S3C2410_DMAF_CIRCULAR          (1 << 0)
 
 #include <plat/dma.h>
@@ -95,7 +99,7 @@ struct s3c2410_dma_chan {
        unsigned char            peripheral;
 
        unsigned int             flags;
-       enum s3c2410_dmasrc      source;
+       enum dma_data_direction  source;
 
 
        dma_addr_t              dev_addr;
diff --git a/arch/arm/mach-s3c64xx/include/mach/pll.h b/arch/arm/mach-s3c64xx/include/mach/pll.h
deleted file mode 100644 (file)
index 5ef0bb6..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/* arch/arm/plat-s3c64xx/include/plat/pll.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *     Ben Dooks <ben@simtec.co.uk>
- *     http://armlinux.simtec.co.uk/
- *
- * S3C64XX PLL code
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#define S3C6400_PLL_MDIV_MASK  ((1 << (25-16+1)) - 1)
-#define S3C6400_PLL_PDIV_MASK  ((1 << (13-8+1)) - 1)
-#define S3C6400_PLL_SDIV_MASK  ((1 << (2-0+1)) - 1)
-#define S3C6400_PLL_MDIV_SHIFT (16)
-#define S3C6400_PLL_PDIV_SHIFT (8)
-#define S3C6400_PLL_SDIV_SHIFT (0)
-
-#include <asm/div64.h>
-#include <plat/pll6553x.h>
-
-static inline unsigned long s3c6400_get_pll(unsigned long baseclk,
-                                           u32 pllcon)
-{
-       u32 mdiv, pdiv, sdiv;
-       u64 fvco = baseclk;
-
-       mdiv = (pllcon >> S3C6400_PLL_MDIV_SHIFT) & S3C6400_PLL_MDIV_MASK;
-       pdiv = (pllcon >> S3C6400_PLL_PDIV_SHIFT) & S3C6400_PLL_PDIV_MASK;
-       sdiv = (pllcon >> S3C6400_PLL_SDIV_SHIFT) & S3C6400_PLL_SDIV_MASK;
-
-       fvco *= mdiv;
-       do_div(fvco, (pdiv << sdiv));
-
-       return (unsigned long)fvco;
-}
-
-static inline unsigned long s3c6400_get_epll(unsigned long baseclk)
-{
-       return s3c_get_pll6553x(baseclk, __raw_readl(S3C_EPLL_CON0),
-                               __raw_readl(S3C_EPLL_CON1));
-}
index 38659be..fcf3dca 100644 (file)
@@ -104,7 +104,7 @@ static inline void s3c_pm_restored_gpios(void)
        __raw_writel(0, S3C64XX_SLPEN);
 }
 
-static inline void s3c_pm_saved_gpios(void)
+static inline void samsung_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
diff --git a/arch/arm/mach-s3c64xx/include/mach/pwm-clock.h b/arch/arm/mach-s3c64xx/include/mach/pwm-clock.h
deleted file mode 100644 (file)
index b25bede..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/* linux/arch/arm/mach-s3c6400/include/mach/pwm-clock.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *      Ben Dooks <ben@simtec.co.uk>
- *      http://armlinux.simtec.co.uk/
- *
- * S3C64xx - pwm clock and timer support
- */
-
-/**
- * pwm_cfg_src_is_tclk() - return whether the given mux config is a tclk
- * @tcfg: The timer TCFG1 register bits shifted down to 0.
- *
- * Return true if the given configuration from TCFG1 is a TCLK instead
- * any of the TDIV clocks.
- */
-static inline int pwm_cfg_src_is_tclk(unsigned long tcfg)
-{
-       return tcfg >= S3C64XX_TCFG1_MUX_TCLK;
-}
-
-/**
- * tcfg_to_divisor() - convert tcfg1 setting to a divisor
- * @tcfg1: The tcfg1 setting, shifted down.
- *
- * Get the divisor value for the given tcfg1 setting. We assume the
- * caller has already checked to see if this is not a TCLK source.
- */
-static inline unsigned long tcfg_to_divisor(unsigned long tcfg1)
-{
-       return 1 << tcfg1;
-}
-
-/**
- * pwm_tdiv_has_div1() - does the tdiv setting have a /1
- *
- * Return true if we have a /1 in the tdiv setting.
- */
-static inline unsigned int pwm_tdiv_has_div1(void)
-{
-       return 1;
-}
-
-/**
- * pwm_tdiv_div_bits() - calculate TCFG1 divisor value.
- * @div: The divisor to calculate the bit information for.
- *
- * Turn a divisor into the necessary bit field for TCFG1.
- */
-static inline unsigned long pwm_tdiv_div_bits(unsigned int div)
-{
-       return ilog2(div);
-}
-
-#define S3C_TCFG1_MUX_TCLK S3C64XX_TCFG1_MUX_TCLK
index 69b78d9..b91e020 100644 (file)
 #define S3C64XX_AHB_CON1       S3C_SYSREG(0x104)
 #define S3C64XX_AHB_CON2       S3C_SYSREG(0x108)
 
+#define S3C64XX_SDMA_SEL       S3C_SYSREG(0x110)
+
 #define S3C64XX_OTHERS         S3C_SYSREG(0x900)
 
 #define S3C64XX_OTHERS_USBMASK (1 << 16)
+#define S3C64XX_OTHERS_SYNCMUXSEL      (1 << 6)
 
 #endif /* _PLAT_REGS_SYS_H */
index d164a28..8eba88e 100644 (file)
@@ -45,7 +45,7 @@
 #include <plat/fb.h>
 #include <plat/regs-fb-v4.h>
 
-#include <mach/s3c6410.h>
+#include <plat/s3c6410.h>
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
diff --git a/arch/arm/mach-s3c64xx/mach-crag6410-module.c b/arch/arm/mach-s3c64xx/mach-crag6410-module.c
new file mode 100644 (file)
index 0000000..6666856
--- /dev/null
@@ -0,0 +1,182 @@
+/* Speyside modules for Cragganmore - board data probing
+ *
+ * Copyright 2011 Wolfson Microelectronics plc
+ *     Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+
+#include <linux/mfd/wm831x/irq.h>
+#include <linux/mfd/wm831x/gpio.h>
+
+#include <sound/wm8996.h>
+#include <sound/wm8962.h>
+#include <sound/wm9081.h>
+
+#include <mach/crag6410.h>
+
+static struct wm8996_retune_mobile_config wm8996_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 wm8996_pdata wm8996_pdata __initdata = {
+       .ldo_ena = S3C64XX_GPN(7),
+       .gpio_base = CODEC_GPIO_BASE,
+       .micdet_def = 1,
+       .inl_mode = WM8996_DIFFERRENTIAL_1,
+       .inr_mode = WM8996_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 = wm8996_retune,
+       .num_retune_mobile_cfgs = ARRAY_SIZE(wm8996_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 const struct i2c_board_info wm1254_devs[] = {
+       { I2C_BOARD_INFO("wm8996", 0x1a),
+         .platform_data = &wm8996_pdata,
+         .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
+       },
+       { I2C_BOARD_INFO("wm9081", 0x6c),
+         .platform_data = &wm9081_pdata, },
+};
+
+static const struct i2c_board_info wm1255_devs[] = {
+       { I2C_BOARD_INFO("wm5100", 0x1a),
+         .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
+       },
+       { I2C_BOARD_INFO("wm9081", 0x6c),
+         .platform_data = &wm9081_pdata, },
+};
+
+static const struct i2c_board_info wm1259_devs[] = {
+       { I2C_BOARD_INFO("wm8962", 0x1a),
+         .platform_data = &wm8962_pdata,
+         .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
+       },
+};
+
+
+static __devinitdata const struct {
+       u8 id;
+       const char *name;
+       const struct i2c_board_info *i2c_devs;
+       int num_i2c_devs;
+} gf_mods[] = {
+       { .id = 0x01, .name = "1250-EV1 Springbank" },
+       { .id = 0x02, .name = "1251-EV1 Jura" },
+       { .id = 0x03, .name = "1252-EV1 Glenlivet" },
+       { .id = 0x11, .name = "6249-EV2 Glenfarclas", },
+       { .id = 0x21, .name = "1275-EV1 Mortlach" },
+       { .id = 0x25, .name = "1274-EV1 Glencadam" },
+       { .id = 0x31, .name = "1253-EV1 Tomatin", },
+       { .id = 0x39, .name = "1254-EV1 Dallas Dhu",
+         .i2c_devs = wm1254_devs, .num_i2c_devs = ARRAY_SIZE(wm1254_devs) },
+       { .id = 0x3a, .name = "1259-EV1 Tobermory",
+         .i2c_devs = wm1259_devs, .num_i2c_devs = ARRAY_SIZE(wm1259_devs) },
+       { .id = 0x3b, .name = "1255-EV1 Kilchoman",
+         .i2c_devs = wm1255_devs, .num_i2c_devs = ARRAY_SIZE(wm1255_devs) },
+       { .id = 0x3c, .name = "1273-EV1 Longmorn" },
+};
+
+static __devinit int wlf_gf_module_probe(struct i2c_client *i2c,
+                                        const struct i2c_device_id *i2c_id)
+{
+       int ret, i, j, id, rev;
+
+       ret = i2c_smbus_read_byte_data(i2c, 0);
+       if (ret < 0) {
+               dev_err(&i2c->dev, "Failed to read ID: %d\n", ret);
+               return ret;
+       }
+
+       id = (ret & 0xfe) >> 2;
+       rev = ret & 0x3;
+       for (i = 0; i < ARRAY_SIZE(gf_mods); i++)
+               if (id == gf_mods[i].id)
+                       break;
+
+       if (i < ARRAY_SIZE(gf_mods)) {
+               dev_info(&i2c->dev, "%s revision %d\n",
+                        gf_mods[i].name, rev + 1);
+               for (j = 0; j < gf_mods[i].num_i2c_devs; j++) {
+                       if (!i2c_new_device(i2c->adapter,
+                                           &(gf_mods[i].i2c_devs[j])))
+                               dev_err(&i2c->dev,
+                                       "Failed to register dev: %d\n", ret);
+               }
+       } else {
+               dev_warn(&i2c->dev, "Unknown module ID %d revision %d\n",
+                        id, rev);
+       }
+
+       return 0;
+}
+
+static const struct i2c_device_id wlf_gf_module_id[] = {
+       { "wlf-gf-module", 0 },
+       { }
+};
+
+static struct i2c_driver wlf_gf_module_driver = {
+       .driver = {
+               .name = "wlf-gf-module",
+               .owner = THIS_MODULE,
+       },
+       .probe = wlf_gf_module_probe,
+       .id_table = wlf_gf_module_id,
+};
+
+static int __init wlf_gf_module_register(void)
+{
+       return i2c_add_driver(&wlf_gf_module_driver);
+}
+module_init(wlf_gf_module_register);
index 8065803..d04b654 100644 (file)
 #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/crag6410.h>
 
 #include <mach/regs-gpio-memport.h>
 
+#include <plat/s3c6410.h>
 #include <plat/regs-serial.h>
 #include <plat/regs-fb-v4.h>
 #include <plat/fb.h>
 #include <plat/iic.h>
 #include <plat/pm.h>
 
-#include <sound/wm8996.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)
@@ -287,6 +277,11 @@ static struct platform_device speyside_device = {
        .id             = -1,
 };
 
+static struct platform_device lowland_device = {
+       .name           = "lowland",
+       .id             = -1,
+};
+
 static struct platform_device speyside_wm8962_device = {
        .name           = "speyside-wm8962",
        .id             = -1,
@@ -295,6 +290,8 @@ static struct platform_device speyside_wm8962_device = {
 static struct regulator_consumer_supply wallvdd_consumers[] = {
        REGULATOR_SUPPLY("SPKVDD1", "1-001a"),
        REGULATOR_SUPPLY("SPKVDD2", "1-001a"),
+       REGULATOR_SUPPLY("SPKVDDL", "1-001a"),
+       REGULATOR_SUPPLY("SPKVDDR", "1-001a"),
 };
 
 static struct regulator_init_data wallvdd_data = {
@@ -342,6 +339,7 @@ static struct platform_device *crag6410_devices[] __initdata = {
        &crag6410_backlight_device,
        &speyside_device,
        &speyside_wm8962_device,
+       &lowland_device,
        &wallvdd_device,
 };
 
@@ -350,6 +348,12 @@ static struct pca953x_platform_data crag6410_pca_data = {
        .irq_base       = 0,
 };
 
+/* VDDARM is controlled by DVS1 connected to GPK(0) */
+static struct wm831x_buckv_pdata vddarm_pdata = {
+       .dvs_control_src = 1,
+       .dvs_gpio = S3C64XX_GPK(0),
+};
+
 static struct regulator_consumer_supply vddarm_consumers[] __initdata = {
        REGULATOR_SUPPLY("vddarm", NULL),
 };
@@ -365,6 +369,7 @@ static struct regulator_init_data vddarm __initdata = {
        .num_consumer_supplies = ARRAY_SIZE(vddarm_consumers),
        .consumer_supplies = vddarm_consumers,
        .supply_regulator = "WALLVDD",
+       .driver_data = &vddarm_pdata,
 };
 
 static struct regulator_init_data vddint __initdata = {
@@ -500,6 +505,8 @@ static struct wm831x_pdata crag_pmic_pdata __initdata = {
        .backup = &banff_backup_pdata,
 
        .gpio_defaults = {
+               /* GPIO5: DVS1_REQ - CMOS, DBVDD, active high */
+               [4] = WM831X_GPN_DIR | WM831X_GPN_POL | WM831X_GPN_ENA | 0x8,
                /* GPIO11: Touchscreen data - CMOS, DBVDD, active high*/
                [10] = WM831X_GPN_POL | WM831X_GPN_ENA | 0x6,
                /* GPIO12: Touchscreen pen down - CMOS, DBVDD, active high*/
@@ -557,8 +564,12 @@ static struct regulator_init_data pvdd_1v2 __initdata = {
 };
 
 static struct regulator_consumer_supply pvdd_1v8_consumers[] __initdata = {
+       REGULATOR_SUPPLY("LDOVDD", "1-001a"),
        REGULATOR_SUPPLY("PLLVDD", "1-001a"),
        REGULATOR_SUPPLY("DBVDD", "1-001a"),
+       REGULATOR_SUPPLY("DBVDD1", "1-001a"),
+       REGULATOR_SUPPLY("DBVDD2", "1-001a"),
+       REGULATOR_SUPPLY("DBVDD3", "1-001a"),
        REGULATOR_SUPPLY("CPVDD", "1-001a"),
        REGULATOR_SUPPLY("AVDD2", "1-001a"),
        REGULATOR_SUPPLY("DCVDD", "1-001a"),
@@ -611,81 +622,16 @@ static struct wm831x_pdata glenfarclas_pmic_pdata __initdata = {
        .disable_touch = true,
 };
 
-static struct wm8996_retune_mobile_config wm8996_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 wm8996_pdata wm8996_pdata __initdata = {
-       .ldo_ena = S3C64XX_GPN(7),
-       .gpio_base = CODEC_GPIO_BASE,
-       .micdet_def = 1,
-       .inl_mode = WM8996_DIFFERRENTIAL_1,
-       .inr_mode = WM8996_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 = wm8996_retune,
-       .num_retune_mobile_cfgs = ARRAY_SIZE(wm8996_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("wlf-gf-module", 0x24) },
+       { I2C_BOARD_INFO("wlf-gf-module", 0x25) },
+       { I2C_BOARD_INFO("wlf-gf-module", 0x26) },
+
        { I2C_BOARD_INFO("wm1250-ev1", 0x27) },
-       { I2C_BOARD_INFO("wm8996", 0x1a),
-         .platform_data = &wm8996_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)
index 19a0887..952f75f 100644 (file)
@@ -37,7 +37,7 @@
 #include <plat/fb.h>
 #include <plat/nand.h>
 
-#include <mach/s3c6410.h>
+#include <plat/s3c6410.h>
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
index fb8969a..1bc85c3 100644 (file)
@@ -32,8 +32,8 @@
 #include <mach/regs-gpio.h>
 #include <mach/regs-modem.h>
 #include <mach/regs-srom.h>
-#include <mach/s3c6410.h>
 
+#include <plat/s3c6410.h>
 #include <plat/adc.h>
 #include <plat/cpu.h>
 #include <plat/devs.h>
index c30f2e5..cb13cba 100644 (file)
@@ -39,7 +39,7 @@
 #include <plat/iic.h>
 #include <plat/fb.h>
 
-#include <mach/s3c6410.h>
+#include <plat/s3c6410.h>
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
index 93170d4..87281e4 100644 (file)
@@ -33,8 +33,8 @@
 #include <mach/regs-gpio.h>
 #include <mach/regs-modem.h>
 #include <mach/regs-srom.h>
-#include <mach/s3c6410.h>
 
+#include <plat/s3c6410.h>
 #include <plat/adc.h>
 #include <plat/cpu.h>
 #include <plat/devs.h>
index cbb57de..94c831d 100644 (file)
@@ -22,8 +22,8 @@
 
 #include <mach/map.h>
 #include <mach/regs-gpio.h>
-#include <mach/s3c6410.h>
 
+#include <plat/s3c6410.h>
 #include <plat/cpu.h>
 #include <plat/devs.h>
 #include <plat/fb.h>
index 04f914b..f112547 100644 (file)
@@ -22,8 +22,8 @@
 
 #include <mach/map.h>
 #include <mach/regs-gpio.h>
-#include <mach/s3c6410.h>
 
+#include <plat/s3c6410.h>
 #include <plat/cpu.h>
 #include <plat/devs.h>
 #include <plat/fb.h>
index 6fd5e95..73450c2 100644 (file)
@@ -31,7 +31,7 @@
 
 #include <plat/regs-serial.h>
 
-#include <mach/s3c6400.h>
+#include <plat/s3c6400.h>
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
index 5f147c3..8bc8edd 100644 (file)
@@ -63,7 +63,7 @@
 #include <plat/fb.h>
 #include <plat/gpio-cfg.h>
 
-#include <mach/s3c6410.h>
+#include <plat/s3c6410.h>
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
index 055e285..b375cd5 100644 (file)
@@ -29,6 +29,7 @@
 #include <mach/regs-clock.h>
 #include <mach/regs-syscon-power.h>
 #include <mach/regs-gpio-memport.h>
+#include <mach/regs-modem.h>
 
 #ifdef CONFIG_S3C_PM_DEBUG_LED_SMDK
 void s3c_pm_debug_smdkled(u32 set, u32 clear)
@@ -85,6 +86,9 @@ static struct sleep_save misc_save[] = {
        SAVE_ITEM(S3C64XX_MEM0CONSLP0),
        SAVE_ITEM(S3C64XX_MEM0CONSLP1),
        SAVE_ITEM(S3C64XX_MEM1CONSLP),
+
+       SAVE_ITEM(S3C64XX_SDMA_SEL),
+       SAVE_ITEM(S3C64XX_MODEM_MIFPCON),
 };
 
 void s3c_pm_configure_extint(void)
index 5e93fe3..7a3bc32 100644 (file)
@@ -38,7 +38,7 @@
 #include <plat/sdhci.h>
 #include <plat/iic-core.h>
 #include <plat/onenand-core.h>
-#include <mach/s3c6400.h>
+#include <plat/s3c6400.h>
 
 void __init s3c6400_map_io(void)
 {
index 312aa6b..4117003 100644 (file)
@@ -41,8 +41,8 @@
 #include <plat/adc-core.h>
 #include <plat/iic-core.h>
 #include <plat/onenand-core.h>
-#include <mach/s3c6400.h>
-#include <mach/s3c6410.h>
+#include <plat/s3c6400.h>
+#include <plat/s3c6410.h>
 
 void __init s3c6410_map_io(void)
 {
index f344a22..c75a71b 100644 (file)
  * published by the Free Software Foundation.
 */
 
-#include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-
-#include <linux/mmc/card.h>
-#include <linux/mmc/host.h>
-
-#include <plat/regs-sdhci.h>
-#include <plat/sdhci.h>
 
 /* clock sources for the mmc bus clock, order as for the ctrl2[5..4] */
 
@@ -32,41 +22,3 @@ char *s3c64xx_hsmmc_clksrcs[4] = {
        [2] = "mmc_bus",
        /* [3] = "48m", - note not successfully used yet */
 };
-
-void s3c6400_setup_sdhci_cfg_card(struct platform_device *dev,
-                                 void __iomem *r,
-                                 struct mmc_ios *ios,
-                                 struct mmc_card *card)
-{
-       u32 ctrl2, ctrl3;
-
-       ctrl2 = readl(r + S3C_SDHCI_CONTROL2);
-       ctrl2 &= S3C_SDHCI_CTRL2_SELBASECLK_MASK;
-       ctrl2 |= (S3C64XX_SDHCI_CTRL2_ENSTAASYNCCLR |
-                 S3C64XX_SDHCI_CTRL2_ENCMDCNFMSK |
-                 S3C_SDHCI_CTRL2_ENFBCLKRX |
-                 S3C_SDHCI_CTRL2_DFCNT_NONE |
-                 S3C_SDHCI_CTRL2_ENCLKOUTHOLD);
-
-       if (ios->clock < 25 * 1000000)
-               ctrl3 = (S3C_SDHCI_CTRL3_FCSEL3 |
-                        S3C_SDHCI_CTRL3_FCSEL2 |
-                        S3C_SDHCI_CTRL3_FCSEL1 |
-                        S3C_SDHCI_CTRL3_FCSEL0);
-       else
-               ctrl3 = (S3C_SDHCI_CTRL3_FCSEL1 | S3C_SDHCI_CTRL3_FCSEL0);
-
-       pr_debug("%s: CTRL 2=%08x, 3=%08x\n", __func__, ctrl2, ctrl3);
-       writel(ctrl2, r + S3C_SDHCI_CONTROL2);
-       writel(ctrl3, r + S3C_SDHCI_CONTROL3);
-}
-
-void s3c6410_setup_sdhci_cfg_card(struct platform_device *dev,
-                                 void __iomem *r,
-                                 struct mmc_ios *ios,
-                                 struct mmc_card *card)
-{
-       writel(S3C64XX_SDHCI_CONTROL4_DRIVE_9mA, r + S3C64XX_SDHCI_CONTROL4);
-
-       s3c6400_setup_sdhci_cfg_card(dev, r, ios, card);
-}
index 65c7518..18690c5 100644 (file)
@@ -9,18 +9,28 @@ if ARCH_S5P64X0
 
 config CPU_S5P6440
        bool
-       select S3C_PL330_DMA
+       select SAMSUNG_DMADEV
        select S5P_HRT
+       select S5P_SLEEP if PM
+       select SAMSUNG_WAKEMASK if PM
        help
          Enable S5P6440 CPU support
 
 config CPU_S5P6450
        bool
-       select S3C_PL330_DMA
+       select SAMSUNG_DMADEV
        select S5P_HRT
+       select S5P_SLEEP if PM
+       select SAMSUNG_WAKEMASK if PM
        help
          Enable S5P6450 CPU support
 
+config S5P64X0_SETUP_FB_24BPP
+       bool
+       help
+         Common setup code for S5P64X0 based boards with a LCD display
+         through RGB interface.
+
 config S5P64X0_SETUP_I2C1
        bool
        help
@@ -31,6 +41,7 @@ config S5P64X0_SETUP_I2C1
 config MACH_SMDK6440
        bool "SMDK6440"
        select CPU_S5P6440
+       select S3C_DEV_FB
        select S3C_DEV_I2C1
        select S3C_DEV_RTC
        select S3C_DEV_WDT
@@ -39,6 +50,7 @@ config MACH_SMDK6440
        select SAMSUNG_DEV_BACKLIGHT
        select SAMSUNG_DEV_PWM
        select SAMSUNG_DEV_TS
+       select S5P64X0_SETUP_FB_24BPP
        select S5P64X0_SETUP_I2C1
        help
          Machine support for the Samsung SMDK6440
@@ -46,6 +58,7 @@ config MACH_SMDK6440
 config MACH_SMDK6450
        bool "SMDK6450"
        select CPU_S5P6450
+       select S3C_DEV_FB
        select S3C_DEV_I2C1
        select S3C_DEV_RTC
        select S3C_DEV_WDT
@@ -54,6 +67,7 @@ config MACH_SMDK6450
        select SAMSUNG_DEV_BACKLIGHT
        select SAMSUNG_DEV_PWM
        select SAMSUNG_DEV_TS
+       select S5P64X0_SETUP_FB_24BPP
        select S5P64X0_SETUP_I2C1
        help
          Machine support for the Samsung SMDK6450
index 5f6afdf..a1324d8 100644 (file)
@@ -12,10 +12,11 @@ obj-                                :=
 
 # Core support for S5P64X0 system
 
-obj-$(CONFIG_ARCH_S5P64X0)     += cpu.o init.o clock.o dma.o gpiolib.o
+obj-$(CONFIG_ARCH_S5P64X0)     += cpu.o init.o clock.o dma.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
+obj-$(CONFIG_PM)               += pm.o irq-pm.o
 
 # machine support
 
@@ -28,3 +29,4 @@ obj-y                         += dev-audio.o
 obj-$(CONFIG_S3C64XX_DEV_SPI)  += dev-spi.o
 
 obj-$(CONFIG_S5P64X0_SETUP_I2C1)       += setup-i2c1.o
+obj-$(CONFIG_S5P64X0_SETUP_FB_24BPP)   += setup-fb-24bpp.o
index 0e9cd30..c54c65d 100644 (file)
@@ -146,7 +146,8 @@ static struct clk init_clocks_off[] = {
                .enable         = s5p64x0_hclk0_ctrl,
                .ctrlbit        = (1 << 8),
        }, {
-               .name           = "pdma",
+               .name           = "dma",
+               .devname        = "dma-pl330",
                .parent         = &clk_hclk_low.clk,
                .enable         = s5p64x0_hclk0_ctrl,
                .ctrlbit        = (1 << 12),
@@ -499,6 +500,11 @@ static struct clksrc_clk *sysclks[] = {
        &clk_pclk_low,
 };
 
+static struct clk dummy_apb_pclk = {
+       .name           = "apb_pclk",
+       .id             = -1,
+};
+
 void __init_or_cpufreq s5p6440_setup_clocks(void)
 {
        struct clk *xtal_clk;
@@ -581,5 +587,7 @@ void __init s5p6440_register_clocks(void)
        s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
        s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 
+       s3c24xx_register_clock(&dummy_apb_pclk);
+
        s3c_pwmclk_init();
 }
index d9dc16c..2d04abf 100644 (file)
@@ -179,7 +179,8 @@ static struct clk init_clocks_off[] = {
                .enable         = s5p64x0_hclk0_ctrl,
                .ctrlbit        = (1 << 3),
        }, {
-               .name           = "pdma",
+               .name           = "dma",
+               .devname        = "dma-pl330",
                .parent         = &clk_hclk_low.clk,
                .enable         = s5p64x0_hclk0_ctrl,
                .ctrlbit        = (1 << 12),
@@ -553,6 +554,11 @@ static struct clksrc_clk *sysclks[] = {
        &clk_sclk_audio0,
 };
 
+static struct clk dummy_apb_pclk = {
+       .name           = "apb_pclk",
+       .id             = -1,
+};
+
 void __init_or_cpufreq s5p6450_setup_clocks(void)
 {
        struct clk *xtal_clk;
@@ -632,5 +638,7 @@ void __init s5p6450_register_clocks(void)
        s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
        s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 
+       s3c24xx_register_clock(&dummy_apb_pclk);
+
        s3c_pwmclk_init();
 }
index 8a93854..ecab40c 100644 (file)
@@ -39,6 +39,7 @@
 #include <plat/s5p6440.h>
 #include <plat/s5p6450.h>
 #include <plat/adc-core.h>
+#include <plat/fb-core.h>
 
 /* Initial IO mappings */
 
@@ -109,6 +110,7 @@ void __init s5p6440_map_io(void)
 {
        /* initialize any device information early */
        s3c_adc_setname("s3c64xx-adc");
+       s3c_fb_setname("s5p64x0-fb");
 
        iotable_init(s5p64x0_iodesc, ARRAY_SIZE(s5p64x0_iodesc));
        iotable_init(s5p6440_iodesc, ARRAY_SIZE(s5p6440_iodesc));
@@ -119,6 +121,7 @@ void __init s5p6450_map_io(void)
 {
        /* initialize any device information early */
        s3c_adc_setname("s3c64xx-adc");
+       s3c_fb_setname("s5p64x0-fb");
 
        iotable_init(s5p64x0_iodesc, ARRAY_SIZE(s5p64x0_iodesc));
        iotable_init(s5p6450_iodesc, ARRAY_SIZE(s5p6450_iodesc));
index 0e5b3e6..442dd4a 100644 (file)
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-#include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/pl330.h>
+
+#include <asm/irq.h>
 
 #include <mach/map.h>
 #include <mach/irqs.h>
 #include <mach/regs-clock.h>
+#include <mach/dma.h>
 
 #include <plat/cpu.h>
 #include <plat/devs.h>
-#include <plat/s3c-pl330-pdata.h>
+#include <plat/irqs.h>
 
 static u64 dma_dmamask = DMA_BIT_MASK(32);
 
-static struct resource s5p64x0_pdma_resource[] = {
-       [0] = {
-               .start  = S5P64X0_PA_PDMA,
-               .end    = S5P64X0_PA_PDMA + SZ_4K,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = IRQ_DMA0,
-               .end    = IRQ_DMA0,
-               .flags  = IORESOURCE_IRQ,
+struct dma_pl330_peri s5p6440_pdma_peri[22] = {
+       {
+               .peri_id = (u8)DMACH_UART0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART1_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART2_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART2_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART3_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART3_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = DMACH_MAX,
+       }, {
+               .peri_id = DMACH_MAX,
+       }, {
+               .peri_id = (u8)DMACH_PCM0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_PCM0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_I2S0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_I2S0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_SPI0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_SPI0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_MAX,
+       }, {
+               .peri_id = (u8)DMACH_MAX,
+       }, {
+               .peri_id = (u8)DMACH_MAX,
+       }, {
+               .peri_id = (u8)DMACH_MAX,
+       }, {
+               .peri_id = (u8)DMACH_SPI1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_SPI1_RX,
+               .rqtype = DEVTOMEM,
        },
 };
 
-static struct s3c_pl330_platdata s5p6440_pdma_pdata = {
-       .peri = {
-               [0] = DMACH_UART0_RX,
-               [1] = DMACH_UART0_TX,
-               [2] = DMACH_UART1_RX,
-               [3] = DMACH_UART1_TX,
-               [4] = DMACH_UART2_RX,
-               [5] = DMACH_UART2_TX,
-               [6] = DMACH_UART3_RX,
-               [7] = DMACH_UART3_TX,
-               [8] = DMACH_MAX,
-               [9] = DMACH_MAX,
-               [10] = DMACH_PCM0_TX,
-               [11] = DMACH_PCM0_RX,
-               [12] = DMACH_I2S0_TX,
-               [13] = DMACH_I2S0_RX,
-               [14] = DMACH_SPI0_TX,
-               [15] = DMACH_SPI0_RX,
-               [16] = DMACH_MAX,
-               [17] = DMACH_MAX,
-               [18] = DMACH_MAX,
-               [19] = DMACH_MAX,
-               [20] = DMACH_SPI1_TX,
-               [21] = DMACH_SPI1_RX,
-               [22] = DMACH_MAX,
-               [23] = DMACH_MAX,
-               [24] = DMACH_MAX,
-               [25] = DMACH_MAX,
-               [26] = DMACH_MAX,
-               [27] = DMACH_MAX,
-               [28] = DMACH_MAX,
-               [29] = DMACH_PWM,
-               [30] = DMACH_MAX,
-               [31] = DMACH_MAX,
-       },
+struct dma_pl330_platdata s5p6440_pdma_pdata = {
+       .nr_valid_peri = ARRAY_SIZE(s5p6440_pdma_peri),
+       .peri = s5p6440_pdma_peri,
 };
 
-static struct s3c_pl330_platdata s5p6450_pdma_pdata = {
-       .peri = {
-               [0] = DMACH_UART0_RX,
-               [1] = DMACH_UART0_TX,
-               [2] = DMACH_UART1_RX,
-               [3] = DMACH_UART1_TX,
-               [4] = DMACH_UART2_RX,
-               [5] = DMACH_UART2_TX,
-               [6] = DMACH_UART3_RX,
-               [7] = DMACH_UART3_TX,
-               [8] = DMACH_UART4_RX,
-               [9] = DMACH_UART4_TX,
-               [10] = DMACH_PCM0_TX,
-               [11] = DMACH_PCM0_RX,
-               [12] = DMACH_I2S0_TX,
-               [13] = DMACH_I2S0_RX,
-               [14] = DMACH_SPI0_TX,
-               [15] = DMACH_SPI0_RX,
-               [16] = DMACH_PCM1_TX,
-               [17] = DMACH_PCM1_RX,
-               [18] = DMACH_PCM2_TX,
-               [19] = DMACH_PCM2_RX,
-               [20] = DMACH_SPI1_TX,
-               [21] = DMACH_SPI1_RX,
-               [22] = DMACH_USI_TX,
-               [23] = DMACH_USI_RX,
-               [24] = DMACH_MAX,
-               [25] = DMACH_I2S1_TX,
-               [26] = DMACH_I2S1_RX,
-               [27] = DMACH_I2S2_TX,
-               [28] = DMACH_I2S2_RX,
-               [29] = DMACH_PWM,
-               [30] = DMACH_UART5_RX,
-               [31] = DMACH_UART5_TX,
+struct dma_pl330_peri s5p6450_pdma_peri[32] = {
+       {
+               .peri_id = (u8)DMACH_UART0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART1_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART2_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART2_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART3_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART3_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART4_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART4_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_PCM0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_PCM0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_I2S0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_I2S0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_SPI0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_SPI0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_PCM1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_PCM1_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_PCM2_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_PCM2_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_SPI1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_SPI1_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_USI_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_USI_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_MAX,
+       }, {
+               .peri_id = (u8)DMACH_I2S1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_I2S1_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_I2S2_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_I2S2_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_PWM,
+       }, {
+               .peri_id = (u8)DMACH_UART5_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART5_TX,
+               .rqtype = MEMTODEV,
        },
 };
 
-static struct platform_device s5p64x0_device_pdma = {
-       .name           = "s3c-pl330",
-       .id             = -1,
-       .num_resources  = ARRAY_SIZE(s5p64x0_pdma_resource),
-       .resource       = s5p64x0_pdma_resource,
-       .dev            = {
+struct dma_pl330_platdata s5p6450_pdma_pdata = {
+       .nr_valid_peri = ARRAY_SIZE(s5p6450_pdma_peri),
+       .peri = s5p6450_pdma_peri,
+};
+
+struct amba_device s5p64x0_device_pdma = {
+       .dev = {
+               .init_name = "dma-pl330",
                .dma_mask = &dma_dmamask,
                .coherent_dma_mask = DMA_BIT_MASK(32),
        },
+       .res = {
+               .start = S5P64X0_PA_PDMA,
+               .end = S5P64X0_PA_PDMA + SZ_4K,
+               .flags = IORESOURCE_MEM,
+       },
+       .irq = {IRQ_DMA0, NO_IRQ},
+       .periphid = 0x00041330,
 };
 
 static int __init s5p64x0_dma_init(void)
@@ -139,7 +232,7 @@ static int __init s5p64x0_dma_init(void)
        else
                s5p64x0_device_pdma.dev.platform_data = &s5p6440_pdma_pdata;
 
-       platform_device_register(&s5p64x0_device_pdma);
+       amba_device_register(&s5p64x0_device_pdma, &iomem_resource);
 
        return 0;
 }
diff --git a/arch/arm/mach-s5p64x0/include/mach/clkdev.h b/arch/arm/mach-s5p64x0/include/mach/clkdev.h
deleted file mode 100644 (file)
index 7dffa83..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __MACH_CLKDEV_H__
-#define __MACH_CLKDEV_H__
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do {} while (0)
-
-#endif
index 81209eb..5a622af 100644 (file)
@@ -20,7 +20,7 @@
 #ifndef __MACH_DMA_H
 #define __MACH_DMA_H
 
-/* This platform uses the common S3C DMA API driver for PL330 */
-#include <plat/s3c-dma-pl330.h>
+/* This platform uses the common common DMA API driver for PL330 */
+#include <plat/dma-pl330.h>
 
 #endif /* __MACH_DMA_H */
index 5837a36..53982db 100644 (file)
 
 #define IRQ_I2S0               IRQ_I2SV40
 
+#define IRQ_LCD_FIFO           IRQ_DISPCON0
+#define IRQ_LCD_VSYNC          IRQ_DISPCON1
+#define IRQ_LCD_SYSTEM         IRQ_DISPCON2
+
 /* S5P6450 EINT feature will be added */
 
 /*
index 95c9125..4d3ac8a 100644 (file)
@@ -47,6 +47,8 @@
 
 #define S5P64X0_PA_HSMMC(x)    (0xED800000 + ((x) * 0x100000))
 
+#define S5P64X0_PA_FB          0xEE000000
+
 #define S5P64X0_PA_I2S         0xF2000000
 #define S5P6450_PA_I2S1                0xF2800000
 #define S5P6450_PA_I2S2                0xF2900000
@@ -64,6 +66,7 @@
 #define S3C_PA_IIC1            S5P6440_PA_IIC1
 #define S3C_PA_RTC             S5P64X0_PA_RTC
 #define S3C_PA_WDT             S5P64X0_PA_WDT
+#define S3C_PA_FB              S5P64X0_PA_FB
 
 #define S5P_PA_CHIPID          S5P64X0_PA_CHIPID
 #define S5P_PA_SROMC           S5P64X0_PA_SROMC
@@ -85,5 +88,6 @@
 #define S5P_PA_UART5           S5P6450_PA_UART(5)
 
 #define S5P_SZ_UART            SZ_256
+#define S3C_VA_UARTx(x)                (S3C_VA_UART + ((x) * S3C_UART_OFFSET))
 
 #endif /* __ASM_ARCH_MAP_H */
diff --git a/arch/arm/mach-s5p64x0/include/mach/pm-core.h b/arch/arm/mach-s5p64x0/include/mach/pm-core.h
new file mode 100644 (file)
index 0000000..e52f754
--- /dev/null
@@ -0,0 +1,117 @@
+/* linux/arch/arm/mach-s5p64x0/include/mach/pm-core.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * S5P64X0 - PM core support for arch/arm/plat-samsung/pm.c
+ *
+ * Based on PM core support for S3C64XX by Ben Dooks
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <mach/regs-gpio.h>
+
+static inline void s3c_pm_debug_init_uart(void)
+{
+       u32 tmp = __raw_readl(S5P64X0_CLK_GATE_PCLK);
+
+       /*
+        * As a note, since the S5P64X0 UARTs generally have multiple
+        * clock sources, we simply enable PCLK at the moment and hope
+        * that the resume settings for the UART are suitable for the
+        * use with PCLK.
+        */
+       tmp |= S5P64X0_CLK_GATE_PCLK_UART0;
+       tmp |= S5P64X0_CLK_GATE_PCLK_UART1;
+       tmp |= S5P64X0_CLK_GATE_PCLK_UART2;
+       tmp |= S5P64X0_CLK_GATE_PCLK_UART3;
+
+       __raw_writel(tmp, S5P64X0_CLK_GATE_PCLK);
+       udelay(10);
+}
+
+static inline void s3c_pm_arch_prepare_irqs(void)
+{
+       /* VIC should have already been taken care of */
+
+       /* clear any pending EINT0 interrupts */
+       __raw_writel(__raw_readl(S5P64X0_EINT0PEND), S5P64X0_EINT0PEND);
+}
+
+static inline void s3c_pm_arch_stop_clocks(void) { }
+static inline void s3c_pm_arch_show_resume_irqs(void) { }
+
+/*
+ * make these defines, we currently do not have any need to change
+ * the IRQ wake controls depending on the CPU we are running on
+ */
+#define s3c_irqwake_eintallow  ((1 << 16) - 1)
+#define s3c_irqwake_intallow   (~0)
+
+static inline void s3c_pm_arch_update_uart(void __iomem *regs,
+                                       struct pm_uart_save *save)
+{
+       u32 ucon = __raw_readl(regs + S3C2410_UCON);
+       u32 ucon_clk = ucon & S3C6400_UCON_CLKMASK;
+       u32 save_clk = save->ucon & S3C6400_UCON_CLKMASK;
+       u32 new_ucon;
+       u32 delta;
+
+       /*
+        * S5P64X0 UART blocks only support level interrupts, so ensure that
+        * when we restore unused UART blocks we force the level interrupt
+        * settings.
+        */
+       save->ucon |= S3C2410_UCON_TXILEVEL | S3C2410_UCON_RXILEVEL;
+
+       /*
+        * We have a constraint on changing the clock type of the UART
+        * between UCLKx and PCLK, so ensure that when we restore UCON
+        * that the CLK field is correctly modified if the bootloader
+        * has changed anything.
+        */
+       if (ucon_clk != save_clk) {
+               new_ucon = save->ucon;
+               delta = ucon_clk ^ save_clk;
+
+               /*
+                * change from UCLKx => wrong PCLK,
+                * either UCLK can be tested for by a bit-test
+                * with UCLK0
+                */
+               if (ucon_clk & S3C6400_UCON_UCLK0 &&
+               !(save_clk & S3C6400_UCON_UCLK0) &&
+               delta & S3C6400_UCON_PCLK2) {
+                       new_ucon &= ~S3C6400_UCON_UCLK0;
+               } else if (delta == S3C6400_UCON_PCLK2) {
+                       /*
+                        * as a precaution, don't change from
+                        * PCLK2 => PCLK or vice-versa
+                        */
+                       new_ucon ^= S3C6400_UCON_PCLK2;
+               }
+
+               S3C_PMDBG("ucon change %04x => %04x (save=%04x)\n",
+                       ucon, new_ucon, save->ucon);
+               save->ucon = new_ucon;
+       }
+}
+
+static inline void s3c_pm_restored_gpios(void)
+{
+       /* ensure sleep mode has been cleared from the system */
+       __raw_writel(0, S5P64X0_SLPEN);
+}
+
+static inline void samsung_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(S5P64X0_SLPEN_USE_xSLP, S5P64X0_SLPEN);
+}
diff --git a/arch/arm/mach-s5p64x0/include/mach/pwm-clock.h b/arch/arm/mach-s5p64x0/include/mach/pwm-clock.h
deleted file mode 100644 (file)
index 19fff8b..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/include/mach/pwm-clock.h
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *      Ben Dooks <ben@simtec.co.uk>
- *      http://armlinux.simtec.co.uk/
- *
- * S5P64X0 - pwm clock and timer 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_PWMCLK_H
-#define __ASM_ARCH_PWMCLK_H __FILE__
-
-/**
- * pwm_cfg_src_is_tclk() - return whether the given mux config is a tclk
- * @tcfg: The timer TCFG1 register bits shifted down to 0.
- *
- * Return true if the given configuration from TCFG1 is a TCLK instead
- * any of the TDIV clocks.
- */
-static inline int pwm_cfg_src_is_tclk(unsigned long tcfg)
-{
-       return 0;
-}
-
-/**
- * tcfg_to_divisor() - convert tcfg1 setting to a divisor
- * @tcfg1: The tcfg1 setting, shifted down.
- *
- * Get the divisor value for the given tcfg1 setting. We assume the
- * caller has already checked to see if this is not a TCLK source.
- */
-static inline unsigned long tcfg_to_divisor(unsigned long tcfg1)
-{
-       return 1 << tcfg1;
-}
-
-/**
- * pwm_tdiv_has_div1() - does the tdiv setting have a /1
- *
- * Return true if we have a /1 in the tdiv setting.
- */
-static inline unsigned int pwm_tdiv_has_div1(void)
-{
-       return 1;
-}
-
-/**
- * pwm_tdiv_div_bits() - calculate TCFG1 divisor value.
- * @div: The divisor to calculate the bit information for.
- *
- * Turn a divisor into the necessary bit field for TCFG1.
- */
-static inline unsigned long pwm_tdiv_div_bits(unsigned int div)
-{
-       return ilog2(div);
-}
-
-#define S3C_TCFG1_MUX_TCLK 0
-
-#endif /* __ASM_ARCH_PWMCLK_H */
index a133f22..bd91112 100644 (file)
 #define S5P6450_DPLL_CON               S5P_CLKREG(0x50)
 #define S5P6450_DPLL_CON_K             S5P_CLKREG(0x54)
 
+#define S5P64X0_AHB_CON0               S5P_CLKREG(0x100)
 #define S5P64X0_CLK_SRC1               S5P_CLKREG(0x10C)
 
 #define S5P64X0_SYS_ID                 S5P_CLKREG(0x118)
 #define S5P64X0_SYS_OTHERS             S5P_CLKREG(0x11C)
 
 #define S5P64X0_PWR_CFG                        S5P_CLKREG(0x804)
+#define S5P64X0_EINT_WAKEUP_MASK       S5P_CLKREG(0x808)
+#define S5P64X0_SLEEP_CFG              S5P_CLKREG(0x818)
+#define S5P64X0_PWR_STABLE             S5P_CLKREG(0x828)
+
 #define S5P64X0_OTHERS                 S5P_CLKREG(0x900)
+#define S5P64X0_WAKEUP_STAT            S5P_CLKREG(0x908)
+
+#define S5P64X0_INFORM0                        S5P_CLKREG(0xA00)
 
 #define S5P64X0_CLKDIV0_HCLK_SHIFT     (8)
 #define S5P64X0_CLKDIV0_HCLK_MASK      (0xF << S5P64X0_CLKDIV0_HCLK_SHIFT)
 
+/* HCLK GATE Registers */
+#define S5P64X0_CLK_GATE_HCLK1_FIMGVG  (1 << 2)
+#define S5P64X0_CLK_GATE_SCLK1_FIMGVG  (1 << 2)
+
+/* PCLK GATE Registers */
+#define S5P64X0_CLK_GATE_PCLK_UART3    (1 << 4)
+#define S5P64X0_CLK_GATE_PCLK_UART2    (1 << 3)
+#define S5P64X0_CLK_GATE_PCLK_UART1    (1 << 2)
+#define S5P64X0_CLK_GATE_PCLK_UART0    (1 << 1)
+
+#define S5P64X0_PWR_CFG_MMC1_DISABLE           (1 << 15)
+#define S5P64X0_PWR_CFG_MMC0_DISABLE           (1 << 14)
+#define S5P64X0_PWR_CFG_RTC_TICK_DISABLE       (1 << 11)
+#define S5P64X0_PWR_CFG_RTC_ALRM_DISABLE       (1 << 10)
+#define S5P64X0_PWR_CFG_WFI_MASK               (3 << 5)
+#define S5P64X0_PWR_CFG_WFI_SLEEP              (3 << 5)
+
+#define S5P64X0_SLEEP_CFG_OSC_EN       (1 << 0)
+
+#define S5P64X0_PWR_STABLE_PWR_CNT_VAL4        (4 << 0)
+
+#define S5P6450_OTHERS_DISABLE_INT     (1 << 31)
+#define S5P64X0_OTHERS_RET_UART                (1 << 26)
+#define S5P64X0_OTHERS_RET_MMC1                (1 << 25)
+#define S5P64X0_OTHERS_RET_MMC0                (1 << 24)
 #define S5P64X0_OTHERS_USB_SIG_MASK    (1 << 16)
 
 /* Compatibility defines */
index 6ce2547..cfdfa4f 100644 (file)
 #define S5P6450_GPQ_BASE               (S5P_VA_GPIO + 0x0180)
 #define S5P6450_GPS_BASE               (S5P_VA_GPIO + 0x0300)
 
+#define S5P64X0_SPCON0                 (S5P_VA_GPIO + 0x1A0)
+#define S5P64X0_SPCON0_LCD_SEL_MASK    (0x3 << 0)
+#define S5P64X0_SPCON0_LCD_SEL_RGB     (0x1 << 0)
+#define S5P64X0_SPCON1                 (S5P_VA_GPIO + 0x2B0)
+
+#define S5P64X0_MEM0CONSLP0            (S5P_VA_GPIO + 0x1C0)
+#define S5P64X0_MEM0CONSLP1            (S5P_VA_GPIO + 0x1C4)
+#define S5P64X0_MEM0DRVCON             (S5P_VA_GPIO + 0x1D0)
+#define S5P64X0_MEM1DRVCON             (S5P_VA_GPIO + 0x1D4)
+
+#define S5P64X0_EINT12CON              (S5P_VA_GPIO + 0x200)
+#define S5P64X0_EINT12FLTCON           (S5P_VA_GPIO + 0x220)
+#define S5P64X0_EINT12MASK             (S5P_VA_GPIO + 0x240)
+
 /* External interrupt control registers for group0 */
 
 #define EINT0CON0_OFFSET               (0x900)
+#define EINT0FLTCON0_OFFSET            (0x910)
+#define EINT0FLTCON1_OFFSET            (0x914)
 #define EINT0MASK_OFFSET               (0x920)
 #define EINT0PEND_OFFSET               (0x924)
 
 #define S5P64X0_EINT0CON0              (S5P_VA_GPIO + EINT0CON0_OFFSET)
+#define S5P64X0_EINT0FLTCON0           (S5P_VA_GPIO + EINT0FLTCON0_OFFSET)
+#define S5P64X0_EINT0FLTCON1           (S5P_VA_GPIO + EINT0FLTCON1_OFFSET)
 #define S5P64X0_EINT0MASK              (S5P_VA_GPIO + EINT0MASK_OFFSET)
 #define S5P64X0_EINT0PEND              (S5P_VA_GPIO + EINT0PEND_OFFSET)
 
+#define S5P64X0_SLPEN                  (S5P_VA_GPIO + 0x930)
+#define S5P64X0_SLPEN_USE_xSLP         (1 << 0)
+
 #endif /* __ASM_ARCH_REGS_GPIO_H */
index 494e1a8..275dc74 100644 (file)
@@ -20,6 +20,7 @@
 #include <plat/cpu.h>
 #include <plat/regs-irqtype.h>
 #include <plat/gpio-cfg.h>
+#include <plat/pm.h>
 
 #include <mach/regs-gpio.h>
 #include <mach/regs-clock.h>
@@ -134,6 +135,7 @@ static int s5p64x0_alloc_gc(void)
        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->chip.irq_set_wake = s3c_irqext_wake;
        ct->regs.ack = EINT0PEND_OFFSET;
        ct->regs.mask = EINT0MASK_OFFSET;
        irq_setup_generic_chip(gc, IRQ_MSK(16), IRQ_GC_INIT_MASK_CACHE,
diff --git a/arch/arm/mach-s5p64x0/irq-pm.c b/arch/arm/mach-s5p64x0/irq-pm.c
new file mode 100644 (file)
index 0000000..3e6f245
--- /dev/null
@@ -0,0 +1,92 @@
+/* linux/arch/arm/mach-s5p64x0/irq-pm.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * S5P64X0 - Interrupt handling Power Management
+ *
+ * Based on arch/arm/mach-s3c64xx/irq-pm.c by Ben Dooks
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/syscore_ops.h>
+#include <linux/serial_core.h>
+#include <linux/io.h>
+
+#include <plat/regs-serial.h>
+#include <plat/pm.h>
+
+#include <mach/regs-gpio.h>
+
+static struct sleep_save irq_save[] = {
+       SAVE_ITEM(S5P64X0_EINT0CON0),
+       SAVE_ITEM(S5P64X0_EINT0FLTCON0),
+       SAVE_ITEM(S5P64X0_EINT0FLTCON1),
+       SAVE_ITEM(S5P64X0_EINT0MASK),
+};
+
+static struct irq_grp_save {
+       u32     con;
+       u32     fltcon;
+       u32     mask;
+} eint_grp_save[4];
+
+static u32 irq_uart_mask[CONFIG_SERIAL_SAMSUNG_UARTS];
+
+static int s5p64x0_irq_pm_suspend(void)
+{
+       struct irq_grp_save *grp = eint_grp_save;
+       int i;
+
+       S3C_PMDBG("%s: suspending IRQs\n", __func__);
+
+       s3c_pm_do_save(irq_save, ARRAY_SIZE(irq_save));
+
+       for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++)
+               irq_uart_mask[i] = __raw_readl(S3C_VA_UARTx(i) + S3C64XX_UINTM);
+
+       for (i = 0; i < ARRAY_SIZE(eint_grp_save); i++, grp++) {
+               grp->con = __raw_readl(S5P64X0_EINT12CON + (i * 4));
+               grp->mask = __raw_readl(S5P64X0_EINT12MASK + (i * 4));
+               grp->fltcon = __raw_readl(S5P64X0_EINT12FLTCON + (i * 4));
+       }
+
+       return 0;
+}
+
+static void s5p64x0_irq_pm_resume(void)
+{
+       struct irq_grp_save *grp = eint_grp_save;
+       int i;
+
+       S3C_PMDBG("%s: resuming IRQs\n", __func__);
+
+       s3c_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
+
+       for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++)
+               __raw_writel(irq_uart_mask[i], S3C_VA_UARTx(i) + S3C64XX_UINTM);
+
+       for (i = 0; i < ARRAY_SIZE(eint_grp_save); i++, grp++) {
+               __raw_writel(grp->con, S5P64X0_EINT12CON + (i * 4));
+               __raw_writel(grp->mask, S5P64X0_EINT12MASK + (i * 4));
+               __raw_writel(grp->fltcon, S5P64X0_EINT12FLTCON + (i * 4));
+       }
+
+       S3C_PMDBG("%s: IRQ configuration restored\n", __func__);
+}
+
+static struct syscore_ops s5p64x0_irq_syscore_ops = {
+       .suspend = s5p64x0_irq_pm_suspend,
+       .resume  = s5p64x0_irq_pm_resume,
+};
+
+static int __init s5p64x0_syscore_init(void)
+{
+       register_syscore_ops(&s5p64x0_irq_syscore_ops);
+
+       return 0;
+}
+core_initcall(s5p64x0_syscore_init);
index 88857f5..4a1250c 100644 (file)
@@ -23,6 +23,9 @@
 #include <linux/clk.h>
 #include <linux/gpio.h>
 #include <linux/pwm_backlight.h>
+#include <linux/fb.h>
+
+#include <video/platform_lcd.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -47,6 +50,8 @@
 #include <plat/ts.h>
 #include <plat/s5p-time.h>
 #include <plat/backlight.h>
+#include <plat/fb.h>
+#include <plat/regs-fb.h>
 
 #define SMDK6440_UCON_DEFAULT  (S3C2410_UCON_TXILEVEL |        \
                                S3C2410_UCON_RXILEVEL |         \
@@ -92,6 +97,59 @@ static struct s3c2410_uartcfg smdk6440_uartcfgs[] __initdata = {
        },
 };
 
+/* Frame Buffer */
+static struct s3c_fb_pd_win smdk6440_fb_win0 = {
+       .win_mode = {
+               .left_margin    = 8,
+               .right_margin   = 13,
+               .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 smdk6440_lcd_pdata __initdata = {
+       .win[0]         = &smdk6440_fb_win0,
+       .vidcon0        = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
+       .vidcon1        = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
+       .setup_gpio     = s5p64x0_fb_gpio_setup_24bpp,
+};
+
+/* LCD power controller */
+static void smdk6440_lte480_reset_power(struct plat_lcd_data *pd,
+                                        unsigned int power)
+{
+       int err;
+
+       if (power) {
+               err = gpio_request(S5P6440_GPN(5), "GPN");
+               if (err) {
+                       printk(KERN_ERR "failed to request GPN for lcd reset\n");
+                       return;
+               }
+
+               gpio_direction_output(S5P6440_GPN(5), 1);
+               gpio_set_value(S5P6440_GPN(5), 0);
+               gpio_set_value(S5P6440_GPN(5), 1);
+               gpio_free(S5P6440_GPN(5));
+       }
+}
+
+static struct plat_lcd_data smdk6440_lcd_power_data = {
+       .set_power      = smdk6440_lte480_reset_power,
+};
+
+static struct platform_device smdk6440_lcd_lte480wv = {
+       .name                   = "platform-lcd",
+       .dev.parent             = &s3c_device_fb.dev,
+       .dev.platform_data      = &smdk6440_lcd_power_data,
+};
+
 static struct platform_device *smdk6440_devices[] __initdata = {
        &s3c_device_adc,
        &s3c_device_rtc,
@@ -101,6 +159,8 @@ static struct platform_device *smdk6440_devices[] __initdata = {
        &s3c_device_wdt,
        &samsung_asoc_dma,
        &s5p6440_device_iis,
+       &s3c_device_fb,
+       &smdk6440_lcd_lte480wv,
 };
 
 static struct s3c2410_platform_i2c s5p6440_i2c0_data __initdata = {
@@ -147,6 +207,17 @@ static void __init smdk6440_map_io(void)
        s5p_set_timer_source(S5P_PWM3, S5P_PWM4);
 }
 
+static void s5p6440_set_lcd_interface(void)
+{
+       unsigned int cfg;
+
+       /* select TFT LCD type (RGB I/F) */
+       cfg = __raw_readl(S5P64X0_SPCON0);
+       cfg &= ~S5P64X0_SPCON0_LCD_SEL_MASK;
+       cfg |= S5P64X0_SPCON0_LCD_SEL_RGB;
+       __raw_writel(cfg, S5P64X0_SPCON0);
+}
+
 static void __init smdk6440_machine_init(void)
 {
        s3c24xx_ts_set_platdata(NULL);
@@ -160,6 +231,9 @@ static void __init smdk6440_machine_init(void)
 
        samsung_bl_set(&smdk6440_bl_gpio_info, &smdk6440_bl_data);
 
+       s5p6440_set_lcd_interface();
+       s3c_fb_set_platdata(&smdk6440_lcd_pdata);
+
        platform_add_devices(smdk6440_devices, ARRAY_SIZE(smdk6440_devices));
 }
 
index e1b277b..0ab129e 100644 (file)
@@ -23,6 +23,9 @@
 #include <linux/clk.h>
 #include <linux/gpio.h>
 #include <linux/pwm_backlight.h>
+#include <linux/fb.h>
+
+#include <video/platform_lcd.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -47,6 +50,8 @@
 #include <plat/ts.h>
 #include <plat/s5p-time.h>
 #include <plat/backlight.h>
+#include <plat/fb.h>
+#include <plat/regs-fb.h>
 
 #define SMDK6450_UCON_DEFAULT  (S3C2410_UCON_TXILEVEL |        \
                                S3C2410_UCON_RXILEVEL |         \
@@ -110,6 +115,59 @@ static struct s3c2410_uartcfg smdk6450_uartcfgs[] __initdata = {
 #endif
 };
 
+/* Frame Buffer */
+static struct s3c_fb_pd_win smdk6450_fb_win0 = {
+       .win_mode       = {
+               .left_margin    = 8,
+               .right_margin   = 13,
+               .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 smdk6450_lcd_pdata __initdata = {
+       .win[0]         = &smdk6450_fb_win0,
+       .vidcon0        = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
+       .vidcon1        = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
+       .setup_gpio     = s5p64x0_fb_gpio_setup_24bpp,
+};
+
+/* LCD power controller */
+static void smdk6450_lte480_reset_power(struct plat_lcd_data *pd,
+                                        unsigned int power)
+{
+       int err;
+
+       if (power) {
+               err = gpio_request(S5P6450_GPN(5), "GPN");
+               if (err) {
+                       printk(KERN_ERR "failed to request GPN for lcd reset\n");
+                       return;
+               }
+
+               gpio_direction_output(S5P6450_GPN(5), 1);
+               gpio_set_value(S5P6450_GPN(5), 0);
+               gpio_set_value(S5P6450_GPN(5), 1);
+               gpio_free(S5P6450_GPN(5));
+       }
+}
+
+static struct plat_lcd_data smdk6450_lcd_power_data = {
+       .set_power      = smdk6450_lte480_reset_power,
+};
+
+static struct platform_device smdk6450_lcd_lte480wv = {
+       .name                   = "platform-lcd",
+       .dev.parent             = &s3c_device_fb.dev,
+       .dev.platform_data      = &smdk6450_lcd_power_data,
+};
+
 static struct platform_device *smdk6450_devices[] __initdata = {
        &s3c_device_adc,
        &s3c_device_rtc,
@@ -119,6 +177,9 @@ static struct platform_device *smdk6450_devices[] __initdata = {
        &s3c_device_wdt,
        &samsung_asoc_dma,
        &s5p6450_device_iis0,
+       &s3c_device_fb,
+       &smdk6450_lcd_lte480wv,
+
        /* s5p6450_device_spi0 will be added */
 };
 
@@ -166,6 +227,17 @@ static void __init smdk6450_map_io(void)
        s5p_set_timer_source(S5P_PWM3, S5P_PWM4);
 }
 
+static void s5p6450_set_lcd_interface(void)
+{
+       unsigned int cfg;
+
+       /* select TFT LCD type (RGB I/F) */
+       cfg = __raw_readl(S5P64X0_SPCON0);
+       cfg &= ~S5P64X0_SPCON0_LCD_SEL_MASK;
+       cfg |= S5P64X0_SPCON0_LCD_SEL_RGB;
+       __raw_writel(cfg, S5P64X0_SPCON0);
+}
+
 static void __init smdk6450_machine_init(void)
 {
        s3c24xx_ts_set_platdata(NULL);
@@ -179,6 +251,9 @@ static void __init smdk6450_machine_init(void)
 
        samsung_bl_set(&smdk6450_bl_gpio_info, &smdk6450_bl_data);
 
+       s5p6450_set_lcd_interface();
+       s3c_fb_set_platdata(&smdk6450_lcd_pdata);
+
        platform_add_devices(smdk6450_devices, ARRAY_SIZE(smdk6450_devices));
 }
 
diff --git a/arch/arm/mach-s5p64x0/pm.c b/arch/arm/mach-s5p64x0/pm.c
new file mode 100644 (file)
index 0000000..6992724
--- /dev/null
@@ -0,0 +1,204 @@
+/* linux/arch/arm/mach-s5p64x0/pm.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * S5P64X0 Power Management Support
+ *
+ * Based on arch/arm/mach-s3c64xx/pm.c by Ben Dooks
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/suspend.h>
+#include <linux/syscore_ops.h>
+#include <linux/io.h>
+
+#include <plat/cpu.h>
+#include <plat/pm.h>
+#include <plat/regs-timer.h>
+#include <plat/wakeup-mask.h>
+
+#include <mach/regs-clock.h>
+#include <mach/regs-gpio.h>
+
+static struct sleep_save s5p64x0_core_save[] = {
+       SAVE_ITEM(S5P64X0_APLL_CON),
+       SAVE_ITEM(S5P64X0_MPLL_CON),
+       SAVE_ITEM(S5P64X0_EPLL_CON),
+       SAVE_ITEM(S5P64X0_EPLL_CON_K),
+       SAVE_ITEM(S5P64X0_CLK_SRC0),
+       SAVE_ITEM(S5P64X0_CLK_SRC1),
+       SAVE_ITEM(S5P64X0_CLK_DIV0),
+       SAVE_ITEM(S5P64X0_CLK_DIV1),
+       SAVE_ITEM(S5P64X0_CLK_DIV2),
+       SAVE_ITEM(S5P64X0_CLK_DIV3),
+       SAVE_ITEM(S5P64X0_CLK_GATE_MEM0),
+       SAVE_ITEM(S5P64X0_CLK_GATE_HCLK1),
+       SAVE_ITEM(S5P64X0_CLK_GATE_SCLK1),
+};
+
+static struct sleep_save s5p64x0_misc_save[] = {
+       SAVE_ITEM(S5P64X0_AHB_CON0),
+       SAVE_ITEM(S5P64X0_SPCON0),
+       SAVE_ITEM(S5P64X0_SPCON1),
+       SAVE_ITEM(S5P64X0_MEM0CONSLP0),
+       SAVE_ITEM(S5P64X0_MEM0CONSLP1),
+       SAVE_ITEM(S5P64X0_MEM0DRVCON),
+       SAVE_ITEM(S5P64X0_MEM1DRVCON),
+
+       SAVE_ITEM(S3C64XX_TINT_CSTAT),
+};
+
+/* DPLL is present only in S5P6450 */
+static struct sleep_save s5p6450_core_save[] = {
+       SAVE_ITEM(S5P6450_DPLL_CON),
+       SAVE_ITEM(S5P6450_DPLL_CON_K),
+};
+
+void s3c_pm_configure_extint(void)
+{
+       __raw_writel(s3c_irqwake_eintmask, S5P64X0_EINT_WAKEUP_MASK);
+}
+
+void s3c_pm_restore_core(void)
+{
+       __raw_writel(0, S5P64X0_EINT_WAKEUP_MASK);
+
+       s3c_pm_do_restore_core(s5p64x0_core_save,
+                               ARRAY_SIZE(s5p64x0_core_save));
+
+       if (soc_is_s5p6450())
+               s3c_pm_do_restore_core(s5p6450_core_save,
+                               ARRAY_SIZE(s5p6450_core_save));
+
+       s3c_pm_do_restore(s5p64x0_misc_save, ARRAY_SIZE(s5p64x0_misc_save));
+}
+
+void s3c_pm_save_core(void)
+{
+       s3c_pm_do_save(s5p64x0_misc_save, ARRAY_SIZE(s5p64x0_misc_save));
+
+       if (soc_is_s5p6450())
+               s3c_pm_do_save(s5p6450_core_save,
+                               ARRAY_SIZE(s5p6450_core_save));
+
+       s3c_pm_do_save(s5p64x0_core_save, ARRAY_SIZE(s5p64x0_core_save));
+}
+
+static int s5p64x0_cpu_suspend(unsigned long arg)
+{
+       unsigned long tmp = 0;
+
+       /*
+        * Issue the standby signal into the pm unit. Note, we
+        * issue a write-buffer drain just in case.
+        */
+       asm("b 1f\n\t"
+           ".align 5\n\t"
+           "1:\n\t"
+           "mcr p15, 0, %0, c7, c10, 5\n\t"
+           "mcr p15, 0, %0, c7, c10, 4\n\t"
+           "mcr p15, 0, %0, c7, c0, 4" : : "r" (tmp));
+
+       /* we should never get past here */
+       panic("sleep resumed to originator?");
+}
+
+/* mapping of interrupts to parts of the wakeup mask */
+static struct samsung_wakeup_mask s5p64x0_wake_irqs[] = {
+       { .irq = IRQ_RTC_ALARM, .bit = S5P64X0_PWR_CFG_RTC_ALRM_DISABLE, },
+       { .irq = IRQ_RTC_TIC,   .bit = S5P64X0_PWR_CFG_RTC_TICK_DISABLE, },
+       { .irq = IRQ_HSMMC0,    .bit = S5P64X0_PWR_CFG_MMC0_DISABLE, },
+       { .irq = IRQ_HSMMC1,    .bit = S5P64X0_PWR_CFG_MMC1_DISABLE, },
+};
+
+static void s5p64x0_pm_prepare(void)
+{
+       u32 tmp;
+
+       samsung_sync_wakemask(S5P64X0_PWR_CFG,
+                       s5p64x0_wake_irqs, ARRAY_SIZE(s5p64x0_wake_irqs));
+
+       /* store the resume address in INFORM0 register */
+       __raw_writel(virt_to_phys(s3c_cpu_resume), S5P64X0_INFORM0);
+
+       /* setup clock gating for FIMGVG block */
+       __raw_writel((__raw_readl(S5P64X0_CLK_GATE_HCLK1) | \
+               (S5P64X0_CLK_GATE_HCLK1_FIMGVG)), S5P64X0_CLK_GATE_HCLK1);
+       __raw_writel((__raw_readl(S5P64X0_CLK_GATE_SCLK1) | \
+               (S5P64X0_CLK_GATE_SCLK1_FIMGVG)), S5P64X0_CLK_GATE_SCLK1);
+
+       /* Configure the stabilization counter with wait time required */
+       __raw_writel(S5P64X0_PWR_STABLE_PWR_CNT_VAL4, S5P64X0_PWR_STABLE);
+
+       /* set WFI to SLEEP mode configuration */
+       tmp = __raw_readl(S5P64X0_SLEEP_CFG);
+       tmp &= ~(S5P64X0_SLEEP_CFG_OSC_EN);
+       __raw_writel(tmp, S5P64X0_SLEEP_CFG);
+
+       tmp = __raw_readl(S5P64X0_PWR_CFG);
+       tmp &= ~(S5P64X0_PWR_CFG_WFI_MASK);
+       tmp |= S5P64X0_PWR_CFG_WFI_SLEEP;
+       __raw_writel(tmp, S5P64X0_PWR_CFG);
+
+       /*
+        * set OTHERS register to disable interrupt before going to
+        * sleep. This bit is present only in S5P6450, it is reserved
+        * in S5P6440.
+        */
+       if (soc_is_s5p6450()) {
+               tmp = __raw_readl(S5P64X0_OTHERS);
+               tmp |= S5P6450_OTHERS_DISABLE_INT;
+               __raw_writel(tmp, S5P64X0_OTHERS);
+       }
+
+       /* ensure previous wakeup state is cleared before sleeping */
+       __raw_writel(__raw_readl(S5P64X0_WAKEUP_STAT), S5P64X0_WAKEUP_STAT);
+
+}
+
+static int s5p64x0_pm_add(struct sys_device *sysdev)
+{
+       pm_cpu_prep = s5p64x0_pm_prepare;
+       pm_cpu_sleep = s5p64x0_cpu_suspend;
+       pm_uart_udivslot = 1;
+
+       return 0;
+}
+
+static struct sysdev_driver s5p64x0_pm_driver = {
+       .add            = s5p64x0_pm_add,
+};
+
+static __init int s5p64x0_pm_drvinit(void)
+{
+       s3c_pm_init();
+
+       return sysdev_driver_register(&s5p64x0_sysclass, &s5p64x0_pm_driver);
+}
+arch_initcall(s5p64x0_pm_drvinit);
+
+static void s5p64x0_pm_resume(void)
+{
+       u32 tmp;
+
+       tmp = __raw_readl(S5P64X0_OTHERS);
+       tmp |= (S5P64X0_OTHERS_RET_MMC0 | S5P64X0_OTHERS_RET_MMC1 | \
+                       S5P64X0_OTHERS_RET_UART);
+       __raw_writel(tmp , S5P64X0_OTHERS);
+}
+
+static struct syscore_ops s5p64x0_pm_syscore_ops = {
+       .resume         = s5p64x0_pm_resume,
+};
+
+static __init int s5p64x0_pm_syscore_init(void)
+{
+       register_syscore_ops(&s5p64x0_pm_syscore_ops);
+
+       return 0;
+}
+arch_initcall(s5p64x0_pm_syscore_init);
diff --git a/arch/arm/mach-s5p64x0/setup-fb-24bpp.c b/arch/arm/mach-s5p64x0/setup-fb-24bpp.c
new file mode 100644 (file)
index 0000000..f346ee4
--- /dev/null
@@ -0,0 +1,29 @@
+/* linux/arch/arm/mach-s5p64x0/setup-fb-24bpp.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * Base S5P64X0 GPIO setup information for LCD framebuffer
+ *
+ * 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/cpu.h>
+#include <plat/fb.h>
+#include <plat/gpio-cfg.h>
+
+void s5p64x0_fb_gpio_setup_24bpp(void)
+{
+       if (soc_is_s5p6440()) {
+               s3c_gpio_cfgrange_nopull(S5P6440_GPI(0), 16, S3C_GPIO_SFN(2));
+               s3c_gpio_cfgrange_nopull(S5P6440_GPJ(0), 12, S3C_GPIO_SFN(2));
+       } else if (soc_is_s5p6450()) {
+               s3c_gpio_cfgrange_nopull(S5P6450_GPI(0), 16, S3C_GPIO_SFN(2));
+               s3c_gpio_cfgrange_nopull(S5P6450_GPJ(0), 12, S3C_GPIO_SFN(2));
+       }
+}
index e8a33c4..e538a4c 100644 (file)
@@ -10,7 +10,7 @@ if ARCH_S5PC100
 config CPU_S5PC100
        bool
        select S5P_EXT_INT
-       select S3C_PL330_DMA
+       select SAMSUNG_DMADEV
        help
          Enable S5PC100 CPU support
 
index ff5cbb3..8d47709 100644 (file)
@@ -33,6 +33,11 @@ static struct clk s5p_clk_otgphy = {
        .name           = "otg_phy",
 };
 
+static struct clk dummy_apb_pclk = {
+       .name           = "apb_pclk",
+       .id             = -1,
+};
+
 static struct clk *clk_src_mout_href_list[] = {
        [0] = &s5p_clk_27m,
        [1] = &clk_fin_hpll,
@@ -454,14 +459,14 @@ static struct clk init_clocks_off[] = {
                .enable         = s5pc100_d1_0_ctrl,
                .ctrlbit        = (1 << 2),
        }, {
-               .name           = "pdma",
-               .devname        = "s3c-pl330.1",
+               .name           = "dma",
+               .devname        = "dma-pl330.1",
                .parent         = &clk_div_d1_bus.clk,
                .enable         = s5pc100_d1_0_ctrl,
                .ctrlbit        = (1 << 1),
        }, {
-               .name           = "pdma",
-               .devname        = "s3c-pl330.0",
+               .name           = "dma",
+               .devname        = "dma-pl330.0",
                .parent         = &clk_div_d1_bus.clk,
                .enable         = s5pc100_d1_0_ctrl,
                .ctrlbit        = (1 << 0),
@@ -1276,5 +1281,7 @@ void __init s5pc100_register_clocks(void)
        s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
        s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 
+       s3c24xx_register_clock(&dummy_apb_pclk);
+
        s3c_pwmclk_init();
 }
index bf4cd0f..065a087 100644 (file)
@@ -1,4 +1,8 @@
-/*
+/* linux/arch/arm/mach-s5pc100/dma.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
  * Copyright (C) 2010 Samsung Electronics Co. Ltd.
  *     Jaswinder Singh <jassi.brar@samsung.com>
  *
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/pl330.h>
 
+#include <asm/irq.h>
 #include <plat/devs.h>
+#include <plat/irqs.h>
 
 #include <mach/map.h>
 #include <mach/irqs.h>
-
-#include <plat/s3c-pl330-pdata.h>
+#include <mach/dma.h>
 
 static u64 dma_dmamask = DMA_BIT_MASK(32);
 
-static struct resource s5pc100_pdma0_resource[] = {
-       [0] = {
-               .start  = S5PC100_PA_PDMA0,
-               .end    = S5PC100_PA_PDMA0 + SZ_4K,
-               .flags = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = IRQ_PDMA0,
-               .end    = IRQ_PDMA0,
-               .flags  = IORESOURCE_IRQ,
+struct dma_pl330_peri pdma0_peri[30] = {
+       {
+               .peri_id = (u8)DMACH_UART0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART1_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART2_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART2_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART3_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART3_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = DMACH_IRDA,
+       }, {
+               .peri_id = (u8)DMACH_I2S0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_I2S0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_I2S0S_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_I2S1_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_I2S1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_I2S2_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_I2S2_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_SPI0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_SPI0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_SPI1_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_SPI1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_SPI2_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_SPI2_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_AC97_MICIN,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_AC97_PCMIN,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_AC97_PCMOUT,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_EXTERNAL,
+       }, {
+               .peri_id = (u8)DMACH_PWM,
+       }, {
+               .peri_id = (u8)DMACH_SPDIF,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_HSI_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_HSI_TX,
+               .rqtype = MEMTODEV,
        },
 };
 
-static struct s3c_pl330_platdata s5pc100_pdma0_pdata = {
-       .peri = {
-               [0] = DMACH_UART0_RX,
-               [1] = DMACH_UART0_TX,
-               [2] = DMACH_UART1_RX,
-               [3] = DMACH_UART1_TX,
-               [4] = DMACH_UART2_RX,
-               [5] = DMACH_UART2_TX,
-               [6] = DMACH_UART3_RX,
-               [7] = DMACH_UART3_TX,
-               [8] = DMACH_IRDA,
-               [9] = DMACH_I2S0_RX,
-               [10] = DMACH_I2S0_TX,
-               [11] = DMACH_I2S0S_TX,
-               [12] = DMACH_I2S1_RX,
-               [13] = DMACH_I2S1_TX,
-               [14] = DMACH_I2S2_RX,
-               [15] = DMACH_I2S2_TX,
-               [16] = DMACH_SPI0_RX,
-               [17] = DMACH_SPI0_TX,
-               [18] = DMACH_SPI1_RX,
-               [19] = DMACH_SPI1_TX,
-               [20] = DMACH_SPI2_RX,
-               [21] = DMACH_SPI2_TX,
-               [22] = DMACH_AC97_MICIN,
-               [23] = DMACH_AC97_PCMIN,
-               [24] = DMACH_AC97_PCMOUT,
-               [25] = DMACH_EXTERNAL,
-               [26] = DMACH_PWM,
-               [27] = DMACH_SPDIF,
-               [28] = DMACH_HSI_RX,
-               [29] = DMACH_HSI_TX,
-               [30] = DMACH_MAX,
-               [31] = DMACH_MAX,
-       },
+struct dma_pl330_platdata s5pc100_pdma0_pdata = {
+       .nr_valid_peri = ARRAY_SIZE(pdma0_peri),
+       .peri = pdma0_peri,
 };
 
-static struct platform_device s5pc100_device_pdma0 = {
-       .name           = "s3c-pl330",
-       .id             = 0,
-       .num_resources  = ARRAY_SIZE(s5pc100_pdma0_resource),
-       .resource       = s5pc100_pdma0_resource,
-       .dev            = {
+struct amba_device s5pc100_device_pdma0 = {
+       .dev = {
+               .init_name = "dma-pl330.0",
                .dma_mask = &dma_dmamask,
                .coherent_dma_mask = DMA_BIT_MASK(32),
                .platform_data = &s5pc100_pdma0_pdata,
        },
-};
-
-static struct resource s5pc100_pdma1_resource[] = {
-       [0] = {
-               .start  = S5PC100_PA_PDMA1,
-               .end    = S5PC100_PA_PDMA1 + SZ_4K,
+       .res = {
+               .start = S5PC100_PA_PDMA0,
+               .end = S5PC100_PA_PDMA0 + SZ_4K,
                .flags = IORESOURCE_MEM,
        },
-       [1] = {
-               .start  = IRQ_PDMA1,
-               .end    = IRQ_PDMA1,
-               .flags  = IORESOURCE_IRQ,
-       },
+       .irq = {IRQ_PDMA0, NO_IRQ},
+       .periphid = 0x00041330,
 };
 
-static struct s3c_pl330_platdata s5pc100_pdma1_pdata = {
-       .peri = {
-               [0] = DMACH_UART0_RX,
-               [1] = DMACH_UART0_TX,
-               [2] = DMACH_UART1_RX,
-               [3] = DMACH_UART1_TX,
-               [4] = DMACH_UART2_RX,
-               [5] = DMACH_UART2_TX,
-               [6] = DMACH_UART3_RX,
-               [7] = DMACH_UART3_TX,
-               [8] = DMACH_IRDA,
-               [9] = DMACH_I2S0_RX,
-               [10] = DMACH_I2S0_TX,
-               [11] = DMACH_I2S0S_TX,
-               [12] = DMACH_I2S1_RX,
-               [13] = DMACH_I2S1_TX,
-               [14] = DMACH_I2S2_RX,
-               [15] = DMACH_I2S2_TX,
-               [16] = DMACH_SPI0_RX,
-               [17] = DMACH_SPI0_TX,
-               [18] = DMACH_SPI1_RX,
-               [19] = DMACH_SPI1_TX,
-               [20] = DMACH_SPI2_RX,
-               [21] = DMACH_SPI2_TX,
-               [22] = DMACH_PCM0_RX,
-               [23] = DMACH_PCM0_TX,
-               [24] = DMACH_PCM1_RX,
-               [25] = DMACH_PCM1_TX,
-               [26] = DMACH_MSM_REQ0,
-               [27] = DMACH_MSM_REQ1,
-               [28] = DMACH_MSM_REQ2,
-               [29] = DMACH_MSM_REQ3,
-               [30] = DMACH_MAX,
-               [31] = DMACH_MAX,
+struct dma_pl330_peri pdma1_peri[30] = {
+       {
+               .peri_id = (u8)DMACH_UART0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART1_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART2_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART2_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART3_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART3_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = DMACH_IRDA,
+       }, {
+               .peri_id = (u8)DMACH_I2S0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_I2S0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_I2S0S_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_I2S1_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_I2S1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_I2S2_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_I2S2_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_SPI0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_SPI0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_SPI1_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_SPI1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_SPI2_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_SPI2_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_PCM0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_PCM1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_PCM1_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_PCM1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_MSM_REQ0,
+       }, {
+               .peri_id = (u8)DMACH_MSM_REQ1,
+       }, {
+               .peri_id = (u8)DMACH_MSM_REQ2,
+       }, {
+               .peri_id = (u8)DMACH_MSM_REQ3,
        },
 };
 
-static struct platform_device s5pc100_device_pdma1 = {
-       .name           = "s3c-pl330",
-       .id             = 1,
-       .num_resources  = ARRAY_SIZE(s5pc100_pdma1_resource),
-       .resource       = s5pc100_pdma1_resource,
-       .dev            = {
+struct dma_pl330_platdata s5pc100_pdma1_pdata = {
+       .nr_valid_peri = ARRAY_SIZE(pdma1_peri),
+       .peri = pdma1_peri,
+};
+
+struct amba_device s5pc100_device_pdma1 = {
+       .dev = {
+               .init_name = "dma-pl330.1",
                .dma_mask = &dma_dmamask,
                .coherent_dma_mask = DMA_BIT_MASK(32),
                .platform_data = &s5pc100_pdma1_pdata,
        },
-};
-
-static struct platform_device *s5pc100_dmacs[] __initdata = {
-       &s5pc100_device_pdma0,
-       &s5pc100_device_pdma1,
+       .res = {
+               .start = S5PC100_PA_PDMA1,
+               .end = S5PC100_PA_PDMA1 + SZ_4K,
+               .flags = IORESOURCE_MEM,
+       },
+       .irq = {IRQ_PDMA1, NO_IRQ},
+       .periphid = 0x00041330,
 };
 
 static int __init s5pc100_dma_init(void)
 {
-       platform_add_devices(s5pc100_dmacs, ARRAY_SIZE(s5pc100_dmacs));
+       amba_device_register(&s5pc100_device_pdma0, &iomem_resource);
+       amba_device_register(&s5pc100_device_pdma1, &iomem_resource);
 
        return 0;
 }
diff --git a/arch/arm/mach-s5pc100/include/mach/clkdev.h b/arch/arm/mach-s5pc100/include/mach/clkdev.h
deleted file mode 100644 (file)
index 7dffa83..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __MACH_CLKDEV_H__
-#define __MACH_CLKDEV_H__
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do {} while (0)
-
-#endif
index 81209eb..201842a 100644 (file)
@@ -20,7 +20,7 @@
 #ifndef __MACH_DMA_H
 #define __MACH_DMA_H
 
-/* This platform uses the common S3C DMA API driver for PL330 */
-#include <plat/s3c-dma-pl330.h>
+/* This platform uses the common DMA API driver for PL330 */
+#include <plat/dma-pl330.h>
 
 #endif /* __MACH_DMA_H */
diff --git a/arch/arm/mach-s5pc100/include/mach/pwm-clock.h b/arch/arm/mach-s5pc100/include/mach/pwm-clock.h
deleted file mode 100644 (file)
index b34d2f7..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/* linux/arch/arm/mach-s5pc100/include/mach/pwm-clock.h
- *
- * Copyright 2009 Samsung Electronics Co.
- *      Byungho Min <bhmin@samsung.com>
- *
- * S5PC100 - pwm clock and timer support
- *
- * Based on mach-s3c6400/include/mach/pwm-clock.h
- */
-
-/**
- * pwm_cfg_src_is_tclk() - return whether the given mux config is a tclk
- * @tcfg: The timer TCFG1 register bits shifted down to 0.
- *
- * Return true if the given configuration from TCFG1 is a TCLK instead
- * any of the TDIV clocks.
- */
-static inline int pwm_cfg_src_is_tclk(unsigned long tcfg)
-{
-       return tcfg >= S3C64XX_TCFG1_MUX_TCLK;
-}
-
-/**
- * tcfg_to_divisor() - convert tcfg1 setting to a divisor
- * @tcfg1: The tcfg1 setting, shifted down.
- *
- * Get the divisor value for the given tcfg1 setting. We assume the
- * caller has already checked to see if this is not a TCLK source.
- */
-static inline unsigned long tcfg_to_divisor(unsigned long tcfg1)
-{
-       return 1 << tcfg1;
-}
-
-/**
- * pwm_tdiv_has_div1() - does the tdiv setting have a /1
- *
- * Return true if we have a /1 in the tdiv setting.
- */
-static inline unsigned int pwm_tdiv_has_div1(void)
-{
-       return 1;
-}
-
-/**
- * pwm_tdiv_div_bits() - calculate TCFG1 divisor value.
- * @div: The divisor to calculate the bit information for.
- *
- * Turn a divisor into the necessary bit field for TCFG1.
- */
-static inline unsigned long pwm_tdiv_div_bits(unsigned int div)
-{
-       return ilog2(div);
-}
-
-#define S3C_TCFG1_MUX_TCLK S3C64XX_TCFG1_MUX_TCLK
index be25879..6418c6e 100644 (file)
  * published by the Free Software Foundation.
 */
 
-#include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-
-#include <linux/mmc/card.h>
-#include <linux/mmc/host.h>
-
-#include <plat/regs-sdhci.h>
-#include <plat/sdhci.h>
 
 /* clock sources for the mmc bus clock, order as for the ctrl2[5..4] */
 
@@ -31,35 +21,3 @@ char *s5pc100_hsmmc_clksrcs[4] = {
        [2] = "sclk_mmc",       /* mmc_bus */
        /* [3] = "48m",         - note not successfully used yet */
 };
-
-
-void s5pc100_setup_sdhci0_cfg_card(struct platform_device *dev,
-                                   void __iomem *r,
-                                   struct mmc_ios *ios,
-                                   struct mmc_card *card)
-{
-       u32 ctrl2, ctrl3;
-
-       /* don't need to alter anything according to card-type */
-
-       writel(S3C64XX_SDHCI_CONTROL4_DRIVE_9mA, r + S3C64XX_SDHCI_CONTROL4);
-
-       ctrl2 = readl(r + S3C_SDHCI_CONTROL2);
-       ctrl2 &= S3C_SDHCI_CTRL2_SELBASECLK_MASK;
-       ctrl2 |= (S3C64XX_SDHCI_CTRL2_ENSTAASYNCCLR |
-                 S3C64XX_SDHCI_CTRL2_ENCMDCNFMSK |
-                 S3C_SDHCI_CTRL2_ENFBCLKRX |
-                 S3C_SDHCI_CTRL2_DFCNT_NONE |
-                 S3C_SDHCI_CTRL2_ENCLKOUTHOLD);
-
-       if (ios->clock < 25 * 1000000)
-               ctrl3 = (S3C_SDHCI_CTRL3_FCSEL3 |
-                        S3C_SDHCI_CTRL3_FCSEL2 |
-                        S3C_SDHCI_CTRL3_FCSEL1 |
-                        S3C_SDHCI_CTRL3_FCSEL0);
-       else
-               ctrl3 = (S3C_SDHCI_CTRL3_FCSEL1 | S3C_SDHCI_CTRL3_FCSEL0);
-
-       writel(ctrl2, r + S3C_SDHCI_CONTROL2);
-       writel(ctrl3, r + S3C_SDHCI_CONTROL3);
-}
index aaeb44a..646057a 100644 (file)
@@ -11,9 +11,11 @@ if ARCH_S5PV210
 
 config CPU_S5PV210
        bool
-       select S3C_PL330_DMA
+       select SAMSUNG_DMADEV
        select S5P_EXT_INT
        select S5P_HRT
+       select S5P_PM if PM
+       select S5P_SLEEP if PM
        help
          Enable S5PV210 CPU support
 
@@ -93,11 +95,13 @@ config MACH_GONI
        select S3C_DEV_USB_HSOTG
        select S5P_DEV_ONENAND
        select SAMSUNG_DEV_KEYPAD
+       select S5P_DEV_TV
        select S5PV210_SETUP_FB_24BPP
        select S5PV210_SETUP_I2C1
        select S5PV210_SETUP_I2C2
        select S5PV210_SETUP_KEYPAD
        select S5PV210_SETUP_SDHCI
+       select S5PV210_SETUP_FIMC
        help
          Machine support for Samsung GONI board
          S5PC110(MCP) is one of package option of S5PV210
index ef7e466..009fbe5 100644 (file)
@@ -14,7 +14,7 @@ obj-                          :=
 
 obj-$(CONFIG_CPU_S5PV210)      += cpu.o init.o clock.o dma.o
 obj-$(CONFIG_CPU_S5PV210)      += setup-i2c0.o
-obj-$(CONFIG_PM)               += pm.o sleep.o
+obj-$(CONFIG_PM)               += pm.o
 
 # machine support
 
index f5f8fa8..4c5ac7a 100644 (file)
@@ -174,6 +174,16 @@ static int s5pv210_clk_mask1_ctrl(struct clk *clk, int enable)
        return s5p_gatectrl(S5P_CLK_SRC_MASK1, clk, enable);
 }
 
+static int exynos4_clk_hdmiphy_ctrl(struct clk *clk, int enable)
+{
+       return s5p_gatectrl(S5P_HDMI_PHY_CONTROL, clk, enable);
+}
+
+static int exynos4_clk_dac_ctrl(struct clk *clk, int enable)
+{
+       return s5p_gatectrl(S5P_DAC_PHY_CONTROL, clk, enable);
+}
+
 static struct clk clk_sclk_hdmi27m = {
        .name           = "sclk_hdmi27m",
        .rate           = 27000000,
@@ -203,6 +213,11 @@ static struct clk clk_pcmcdclk2 = {
        .name           = "pcmcdclk",
 };
 
+static struct clk dummy_apb_pclk = {
+       .name           = "apb_pclk",
+       .id             = -1,
+};
+
 static struct clk *clkset_vpllsrc_list[] = {
        [0] = &clk_fin_vpll,
        [1] = &clk_sclk_hdmi27m,
@@ -289,14 +304,14 @@ static struct clk_ops clk_fout_apll_ops = {
 
 static struct clk init_clocks_off[] = {
        {
-               .name           = "pdma",
-               .devname        = "s3c-pl330.0",
+               .name           = "dma",
+               .devname        = "dma-pl330.0",
                .parent         = &clk_hclk_psys.clk,
                .enable         = s5pv210_clk_ip0_ctrl,
                .ctrlbit        = (1 << 3),
        }, {
-               .name           = "pdma",
-               .devname        = "s3c-pl330.1",
+               .name           = "dma",
+               .devname        = "dma-pl330.1",
                .parent         = &clk_hclk_psys.clk,
                .enable         = s5pv210_clk_ip0_ctrl,
                .ctrlbit        = (1 << 4),
@@ -330,6 +345,40 @@ static struct clk init_clocks_off[] = {
                .enable         = s5pv210_clk_ip0_ctrl,
                .ctrlbit        = (1 << 16),
        }, {
+               .name           = "dac",
+               .devname        = "s5p-sdo",
+               .parent         = &clk_hclk_dsys.clk,
+               .enable         = s5pv210_clk_ip1_ctrl,
+               .ctrlbit        = (1 << 10),
+       }, {
+               .name           = "mixer",
+               .devname        = "s5p-mixer",
+               .parent         = &clk_hclk_dsys.clk,
+               .enable         = s5pv210_clk_ip1_ctrl,
+               .ctrlbit        = (1 << 9),
+       }, {
+               .name           = "vp",
+               .devname        = "s5p-mixer",
+               .parent         = &clk_hclk_dsys.clk,
+               .enable         = s5pv210_clk_ip1_ctrl,
+               .ctrlbit        = (1 << 8),
+       }, {
+               .name           = "hdmi",
+               .devname        = "s5pv210-hdmi",
+               .parent         = &clk_hclk_dsys.clk,
+               .enable         = s5pv210_clk_ip1_ctrl,
+               .ctrlbit        = (1 << 11),
+       }, {
+               .name           = "hdmiphy",
+               .devname        = "s5pv210-hdmi",
+               .enable         = exynos4_clk_hdmiphy_ctrl,
+               .ctrlbit        = (1 << 0),
+       }, {
+               .name           = "dacphy",
+               .devname        = "s5p-sdo",
+               .enable         = exynos4_clk_dac_ctrl,
+               .ctrlbit        = (1 << 0),
+       }, {
                .name           = "otg",
                .parent         = &clk_hclk_psys.clk,
                .enable         = s5pv210_clk_ip1_ctrl,
@@ -407,6 +456,12 @@ static struct clk init_clocks_off[] = {
                .enable         = s5pv210_clk_ip3_ctrl,
                .ctrlbit        = (1<<9),
        }, {
+               .name           = "i2c",
+               .devname        = "s3c2440-hdmiphy-i2c",
+               .parent         = &clk_pclk_psys.clk,
+               .enable         = s5pv210_clk_ip3_ctrl,
+               .ctrlbit        = (1 << 11),
+       }, {
                .name           = "spi",
                .devname        = "s3c64xx-spi.0",
                .parent         = &clk_pclk_psys.clk,
@@ -594,6 +649,23 @@ static struct clksrc_sources clkset_sclk_mixer = {
        .nr_sources     = ARRAY_SIZE(clkset_sclk_mixer_list),
 };
 
+static struct clksrc_clk clk_sclk_mixer = {
+       .clk            = {
+               .name           = "sclk_mixer",
+               .enable         = s5pv210_clk_mask0_ctrl,
+               .ctrlbit        = (1 << 1),
+       },
+       .sources = &clkset_sclk_mixer,
+       .reg_src = { .reg = S5P_CLK_SRC1, .shift = 4, .size = 1 },
+};
+
+static struct clksrc_clk *sclk_tv[] = {
+       &clk_sclk_dac,
+       &clk_sclk_pixel,
+       &clk_sclk_hdmi,
+       &clk_sclk_mixer,
+};
+
 static struct clk *clkset_sclk_audio0_list[] = {
        [0] = &clk_ext_xtal_mux,
        [1] = &clk_pcmcdclk0,
@@ -777,14 +849,6 @@ static struct clksrc_clk clksrcs[] = {
                .reg_div = { .reg = S5P_CLK_DIV4, .shift = 28, .size = 4 },
        }, {
                .clk    = {
-                       .name           = "sclk_mixer",
-                       .enable         = s5pv210_clk_mask0_ctrl,
-                       .ctrlbit        = (1 << 1),
-               },
-               .sources = &clkset_sclk_mixer,
-               .reg_src = { .reg = S5P_CLK_SRC1, .shift = 4, .size = 1 },
-       }, {
-               .clk    = {
                        .name           = "sclk_fimc",
                        .devname        = "s5pv210-fimc.0",
                        .enable         = s5pv210_clk_mask1_ctrl,
@@ -973,9 +1037,6 @@ static struct clksrc_clk *sysclks[] = {
        &clk_pclk_psys,
        &clk_vpllsrc,
        &clk_sclk_vpll,
-       &clk_sclk_dac,
-       &clk_sclk_pixel,
-       &clk_sclk_hdmi,
        &clk_mout_dmc0,
        &clk_sclk_dmc0,
        &clk_sclk_audio0,
@@ -1060,6 +1121,61 @@ static struct clk_ops s5pv210_epll_ops = {
        .get_rate = s5p_epll_get_rate,
 };
 
+static u32 vpll_div[][5] = {
+       {  54000000, 3, 53, 3, 0 },
+       { 108000000, 3, 53, 2, 0 },
+};
+
+static unsigned long s5pv210_vpll_get_rate(struct clk *clk)
+{
+       return clk->rate;
+}
+
+static int s5pv210_vpll_set_rate(struct clk *clk, unsigned long rate)
+{
+       unsigned int vpll_con;
+       unsigned int i;
+
+       /* Return if nothing changed */
+       if (clk->rate == rate)
+               return 0;
+
+       vpll_con = __raw_readl(S5P_VPLL_CON);
+       vpll_con &= ~(0x1 << 27 |                                       \
+                       PLL90XX_MDIV_MASK << PLL90XX_MDIV_SHIFT |       \
+                       PLL90XX_PDIV_MASK << PLL90XX_PDIV_SHIFT |       \
+                       PLL90XX_SDIV_MASK << PLL90XX_SDIV_SHIFT);
+
+       for (i = 0; i < ARRAY_SIZE(vpll_div); i++) {
+               if (vpll_div[i][0] == rate) {
+                       vpll_con |= vpll_div[i][1] << PLL90XX_PDIV_SHIFT;
+                       vpll_con |= vpll_div[i][2] << PLL90XX_MDIV_SHIFT;
+                       vpll_con |= vpll_div[i][3] << PLL90XX_SDIV_SHIFT;
+                       vpll_con |= vpll_div[i][4] << 27;
+                       break;
+               }
+       }
+
+       if (i == ARRAY_SIZE(vpll_div)) {
+               printk(KERN_ERR "%s: Invalid Clock VPLL Frequency\n",
+                               __func__);
+               return -EINVAL;
+       }
+
+       __raw_writel(vpll_con, S5P_VPLL_CON);
+
+       /* Wait for VPLL lock */
+       while (!(__raw_readl(S5P_VPLL_CON) & (1 << PLL90XX_LOCKED_SHIFT)))
+               continue;
+
+       clk->rate = rate;
+       return 0;
+}
+static struct clk_ops s5pv210_vpll_ops = {
+       .get_rate = s5pv210_vpll_get_rate,
+       .set_rate = s5pv210_vpll_set_rate,
+};
+
 void __init_or_cpufreq s5pv210_setup_clocks(void)
 {
        struct clk *xtal_clk;
@@ -1108,6 +1224,7 @@ void __init_or_cpufreq s5pv210_setup_clocks(void)
        clk_fout_apll.ops = &clk_fout_apll_ops;
        clk_fout_mpll.rate = mpll;
        clk_fout_epll.rate = epll;
+       clk_fout_vpll.ops = &s5pv210_vpll_ops;
        clk_fout_vpll.rate = vpll;
 
        printk(KERN_INFO "S5PV210: PLL settings, A=%ld, M=%ld, E=%ld V=%ld",
@@ -1153,11 +1270,15 @@ void __init s5pv210_register_clocks(void)
        for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
                s3c_register_clksrc(sysclks[ptr], 1);
 
+       for (ptr = 0; ptr < ARRAY_SIZE(sclk_tv); ptr++)
+               s3c_register_clksrc(sclk_tv[ptr], 1);
+
        s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
        s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
 
        s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
        s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 
+       s3c24xx_register_clock(&dummy_apb_pclk);
        s3c_pwmclk_init();
 }
index 9114572..84ec746 100644 (file)
@@ -42,6 +42,7 @@
 #include <plat/keypad-core.h>
 #include <plat/sdhci.h>
 #include <plat/reset.h>
+#include <plat/tv-core.h>
 
 /* Initial IO mappings */
 
@@ -145,6 +146,9 @@ void __init s5pv210_map_io(void)
 
        /* Use s5pv210-keypad instead of samsung-keypad */
        samsung_keypad_setname("s5pv210-keypad");
+
+       /* setup TV devices */
+       s5p_hdmi_setname("s5pv210-hdmi");
 }
 
 void __init s5pv210_init_clocks(int xtal)
index 497d343..86b749c 100644 (file)
@@ -1,4 +1,8 @@
-/*
+/* linux/arch/arm/mach-s5pv210/dma.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
  * Copyright (C) 2010 Samsung Electronics Co. Ltd.
  *     Jaswinder Singh <jassi.brar@samsung.com>
  *
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/pl330.h>
 
+#include <asm/irq.h>
 #include <plat/devs.h>
 #include <plat/irqs.h>
 
 #include <mach/map.h>
 #include <mach/irqs.h>
-
-#include <plat/s3c-pl330-pdata.h>
+#include <mach/dma.h>
 
 static u64 dma_dmamask = DMA_BIT_MASK(32);
 
-static struct resource s5pv210_pdma0_resource[] = {
-       [0] = {
-               .start  = S5PV210_PA_PDMA0,
-               .end    = S5PV210_PA_PDMA0 + SZ_4K,
-               .flags = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = IRQ_PDMA0,
-               .end    = IRQ_PDMA0,
-               .flags  = IORESOURCE_IRQ,
+struct dma_pl330_peri pdma0_peri[28] = {
+       {
+               .peri_id = (u8)DMACH_UART0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART1_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART2_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART2_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART3_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART3_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = DMACH_MAX,
+       }, {
+               .peri_id = (u8)DMACH_I2S0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_I2S0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_I2S0S_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_I2S1_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_I2S1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_MAX,
+       }, {
+               .peri_id = (u8)DMACH_MAX,
+       }, {
+               .peri_id = (u8)DMACH_SPI0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_SPI0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_SPI1_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_SPI1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_MAX,
+       }, {
+               .peri_id = (u8)DMACH_MAX,
+       }, {
+               .peri_id = (u8)DMACH_AC97_MICIN,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_AC97_PCMIN,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_AC97_PCMOUT,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_MAX,
+       }, {
+               .peri_id = (u8)DMACH_PWM,
+       }, {
+               .peri_id = (u8)DMACH_SPDIF,
+               .rqtype = MEMTODEV,
        },
 };
 
-static struct s3c_pl330_platdata s5pv210_pdma0_pdata = {
-       .peri = {
-               [0] = DMACH_UART0_RX,
-               [1] = DMACH_UART0_TX,
-               [2] = DMACH_UART1_RX,
-               [3] = DMACH_UART1_TX,
-               [4] = DMACH_UART2_RX,
-               [5] = DMACH_UART2_TX,
-               [6] = DMACH_UART3_RX,
-               [7] = DMACH_UART3_TX,
-               [8] = DMACH_MAX,
-               [9] = DMACH_I2S0_RX,
-               [10] = DMACH_I2S0_TX,
-               [11] = DMACH_I2S0S_TX,
-               [12] = DMACH_I2S1_RX,
-               [13] = DMACH_I2S1_TX,
-               [14] = DMACH_MAX,
-               [15] = DMACH_MAX,
-               [16] = DMACH_SPI0_RX,
-               [17] = DMACH_SPI0_TX,
-               [18] = DMACH_SPI1_RX,
-               [19] = DMACH_SPI1_TX,
-               [20] = DMACH_MAX,
-               [21] = DMACH_MAX,
-               [22] = DMACH_AC97_MICIN,
-               [23] = DMACH_AC97_PCMIN,
-               [24] = DMACH_AC97_PCMOUT,
-               [25] = DMACH_MAX,
-               [26] = DMACH_PWM,
-               [27] = DMACH_SPDIF,
-               [28] = DMACH_MAX,
-               [29] = DMACH_MAX,
-               [30] = DMACH_MAX,
-               [31] = DMACH_MAX,
-       },
+struct dma_pl330_platdata s5pv210_pdma0_pdata = {
+       .nr_valid_peri = ARRAY_SIZE(pdma0_peri),
+       .peri = pdma0_peri,
 };
 
-static struct platform_device s5pv210_device_pdma0 = {
-       .name           = "s3c-pl330",
-       .id             = 0,
-       .num_resources  = ARRAY_SIZE(s5pv210_pdma0_resource),
-       .resource       = s5pv210_pdma0_resource,
-       .dev            = {
+struct amba_device s5pv210_device_pdma0 = {
+       .dev = {
+               .init_name = "dma-pl330.0",
                .dma_mask = &dma_dmamask,
                .coherent_dma_mask = DMA_BIT_MASK(32),
                .platform_data = &s5pv210_pdma0_pdata,
        },
-};
-
-static struct resource s5pv210_pdma1_resource[] = {
-       [0] = {
-               .start  = S5PV210_PA_PDMA1,
-               .end    = S5PV210_PA_PDMA1 + SZ_4K,
+       .res = {
+               .start = S5PV210_PA_PDMA0,
+               .end = S5PV210_PA_PDMA0 + SZ_4K,
                .flags = IORESOURCE_MEM,
        },
-       [1] = {
-               .start  = IRQ_PDMA1,
-               .end    = IRQ_PDMA1,
-               .flags  = IORESOURCE_IRQ,
-       },
+       .irq = {IRQ_PDMA0, NO_IRQ},
+       .periphid = 0x00041330,
 };
 
-static struct s3c_pl330_platdata s5pv210_pdma1_pdata = {
-       .peri = {
-               [0] = DMACH_UART0_RX,
-               [1] = DMACH_UART0_TX,
-               [2] = DMACH_UART1_RX,
-               [3] = DMACH_UART1_TX,
-               [4] = DMACH_UART2_RX,
-               [5] = DMACH_UART2_TX,
-               [6] = DMACH_UART3_RX,
-               [7] = DMACH_UART3_TX,
-               [8] = DMACH_MAX,
-               [9] = DMACH_I2S0_RX,
-               [10] = DMACH_I2S0_TX,
-               [11] = DMACH_I2S0S_TX,
-               [12] = DMACH_I2S1_RX,
-               [13] = DMACH_I2S1_TX,
-               [14] = DMACH_I2S2_RX,
-               [15] = DMACH_I2S2_TX,
-               [16] = DMACH_SPI0_RX,
-               [17] = DMACH_SPI0_TX,
-               [18] = DMACH_SPI1_RX,
-               [19] = DMACH_SPI1_TX,
-               [20] = DMACH_MAX,
-               [21] = DMACH_MAX,
-               [22] = DMACH_PCM0_RX,
-               [23] = DMACH_PCM0_TX,
-               [24] = DMACH_PCM1_RX,
-               [25] = DMACH_PCM1_TX,
-               [26] = DMACH_MSM_REQ0,
-               [27] = DMACH_MSM_REQ1,
-               [28] = DMACH_MSM_REQ2,
-               [29] = DMACH_MSM_REQ3,
-               [30] = DMACH_PCM2_RX,
-               [31] = DMACH_PCM2_TX,
+struct dma_pl330_peri pdma1_peri[32] = {
+       {
+               .peri_id = (u8)DMACH_UART0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART1_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART2_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART2_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_UART3_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_UART3_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = DMACH_MAX,
+       }, {
+               .peri_id = (u8)DMACH_I2S0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_I2S0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_I2S0S_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_I2S1_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_I2S1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_I2S2_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_I2S2_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_SPI0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_SPI0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_SPI1_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_SPI1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_MAX,
+       }, {
+               .peri_id = (u8)DMACH_MAX,
+       }, {
+               .peri_id = (u8)DMACH_PCM0_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_PCM0_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_PCM1_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_PCM1_TX,
+               .rqtype = MEMTODEV,
+       }, {
+               .peri_id = (u8)DMACH_MSM_REQ0,
+       }, {
+               .peri_id = (u8)DMACH_MSM_REQ1,
+       }, {
+               .peri_id = (u8)DMACH_MSM_REQ2,
+       }, {
+               .peri_id = (u8)DMACH_MSM_REQ3,
+       }, {
+               .peri_id = (u8)DMACH_PCM2_RX,
+               .rqtype = DEVTOMEM,
+       }, {
+               .peri_id = (u8)DMACH_PCM2_TX,
+               .rqtype = MEMTODEV,
        },
 };
 
-static struct platform_device s5pv210_device_pdma1 = {
-       .name           = "s3c-pl330",
-       .id             = 1,
-       .num_resources  = ARRAY_SIZE(s5pv210_pdma1_resource),
-       .resource       = s5pv210_pdma1_resource,
-       .dev            = {
+struct dma_pl330_platdata s5pv210_pdma1_pdata = {
+       .nr_valid_peri = ARRAY_SIZE(pdma1_peri),
+       .peri = pdma1_peri,
+};
+
+struct amba_device s5pv210_device_pdma1 = {
+       .dev = {
+               .init_name = "dma-pl330.1",
                .dma_mask = &dma_dmamask,
                .coherent_dma_mask = DMA_BIT_MASK(32),
                .platform_data = &s5pv210_pdma1_pdata,
        },
-};
-
-static struct platform_device *s5pv210_dmacs[] __initdata = {
-       &s5pv210_device_pdma0,
-       &s5pv210_device_pdma1,
+       .res = {
+               .start = S5PV210_PA_PDMA1,
+               .end = S5PV210_PA_PDMA1 + SZ_4K,
+               .flags = IORESOURCE_MEM,
+       },
+       .irq = {IRQ_PDMA1, NO_IRQ},
+       .periphid = 0x00041330,
 };
 
 static int __init s5pv210_dma_init(void)
 {
-       platform_add_devices(s5pv210_dmacs, ARRAY_SIZE(s5pv210_dmacs));
+       amba_device_register(&s5pv210_device_pdma0, &iomem_resource);
+       amba_device_register(&s5pv210_device_pdma1, &iomem_resource);
 
        return 0;
 }
diff --git a/arch/arm/mach-s5pv210/include/mach/clkdev.h b/arch/arm/mach-s5pv210/include/mach/clkdev.h
deleted file mode 100644 (file)
index 7dffa83..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __MACH_CLKDEV_H__
-#define __MACH_CLKDEV_H__
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do {} while (0)
-
-#endif
index 81209eb..201842a 100644 (file)
@@ -20,7 +20,7 @@
 #ifndef __MACH_DMA_H
 #define __MACH_DMA_H
 
-/* This platform uses the common S3C DMA API driver for PL330 */
-#include <plat/s3c-dma-pl330.h>
+/* This platform uses the common DMA API driver for PL330 */
+#include <plat/dma-pl330.h>
 
 #endif /* __MACH_DMA_H */
index b9f9ec3..5e0de3a 100644 (file)
@@ -56,7 +56,7 @@
 #define IRQ_SPI2               S5P_IRQ_VIC1(17)
 #define IRQ_IRDA               S5P_IRQ_VIC1(18)
 #define IRQ_IIC2               S5P_IRQ_VIC1(19)
-#define IRQ_IIC3               S5P_IRQ_VIC1(20)
+#define IRQ_IIC_HDMIPHY                S5P_IRQ_VIC1(20)
 #define IRQ_HSIRX              S5P_IRQ_VIC1(21)
 #define IRQ_HSITX              S5P_IRQ_VIC1(22)
 #define IRQ_UHOST              S5P_IRQ_VIC1(23)
@@ -86,7 +86,7 @@
 #define IRQ_HDMI               S5P_IRQ_VIC2(12)
 #define IRQ_IIC1               S5P_IRQ_VIC2(13)
 #define IRQ_MFC                        S5P_IRQ_VIC2(14)
-#define IRQ_TVENC              S5P_IRQ_VIC2(15)
+#define IRQ_SDO                        S5P_IRQ_VIC2(15)
 #define IRQ_I2S0               S5P_IRQ_VIC2(16)
 #define IRQ_I2S1               S5P_IRQ_VIC2(17)
 #define IRQ_I2S2               S5P_IRQ_VIC2(18)
index aac343c..7ff609f 100644 (file)
 #define S5PV210_PA_FIMC1               0xFB300000
 #define S5PV210_PA_FIMC2               0xFB400000
 
+#define S5PV210_PA_SDO                 0xF9000000
+#define S5PV210_PA_VP                  0xF9100000
+#define S5PV210_PA_MIXER               0xF9200000
+#define S5PV210_PA_HDMI                        0xFA100000
+#define S5PV210_PA_IIC_HDMIPHY         0xFA900000
+
 /* Compatibiltiy Defines */
 
 #define S3C_PA_FB                      S5PV210_PA_FB
 #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_IIC_HDMIPHY             S5PV210_PA_IIC_HDMIPHY
+
+#define S5P_PA_SDO                     S5PV210_PA_SDO
+#define S5P_PA_VP                      S5PV210_PA_VP
+#define S5P_PA_MIXER                   S5PV210_PA_MIXER
+#define S5P_PA_HDMI                    S5PV210_PA_HDMI
+
 #define S5P_PA_ONENAND                 S5PC110_PA_ONENAND
 #define S5P_PA_ONENAND_DMA             S5PC110_PA_ONENAND_DMA
 #define S5P_PA_SDRAM                   S5PV210_PA_SDRAM
index 3e22109..eba8aea 100644 (file)
@@ -43,4 +43,4 @@ static inline void s3c_pm_arch_update_uart(void __iomem *regs,
 }
 
 static inline void s3c_pm_restored_gpios(void) { }
-static inline void s3c_pm_saved_gpios(void) { }
+static inline void samsung_pm_saved_gpios(void) { }
diff --git a/arch/arm/mach-s5pv210/include/mach/pwm-clock.h b/arch/arm/mach-s5pv210/include/mach/pwm-clock.h
deleted file mode 100644 (file)
index f8a9f1b..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/include/mach/pwm-clock.h
- *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *      Ben Dooks <ben@simtec.co.uk>
- *      http://armlinux.simtec.co.uk/
- *
- * Based on arch/arm/mach-s3c64xx/include/mach/pwm-clock.h
- *
- * S5PV210 - pwm clock and timer 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_PWMCLK_H
-#define __ASM_ARCH_PWMCLK_H __FILE__
-
-/**
- * pwm_cfg_src_is_tclk() - return whether the given mux config is a tclk
- * @tcfg: The timer TCFG1 register bits shifted down to 0.
- *
- * Return true if the given configuration from TCFG1 is a TCLK instead
- * any of the TDIV clocks.
- */
-static inline int pwm_cfg_src_is_tclk(unsigned long tcfg)
-{
-       return tcfg == S3C64XX_TCFG1_MUX_TCLK;
-}
-
-/**
- * tcfg_to_divisor() - convert tcfg1 setting to a divisor
- * @tcfg1: The tcfg1 setting, shifted down.
- *
- * Get the divisor value for the given tcfg1 setting. We assume the
- * caller has already checked to see if this is not a TCLK source.
- */
-static inline unsigned long tcfg_to_divisor(unsigned long tcfg1)
-{
-       return 1 << tcfg1;
-}
-
-/**
- * pwm_tdiv_has_div1() - does the tdiv setting have a /1
- *
- * Return true if we have a /1 in the tdiv setting.
- */
-static inline unsigned int pwm_tdiv_has_div1(void)
-{
-       return 1;
-}
-
-/**
- * pwm_tdiv_div_bits() - calculate TCFG1 divisor value.
- * @div: The divisor to calculate the bit information for.
- *
- * Turn a divisor into the necessary bit field for TCFG1.
- */
-static inline unsigned long pwm_tdiv_div_bits(unsigned int div)
-{
-       return ilog2(div);
-}
-
-#define S3C_TCFG1_MUX_TCLK S3C64XX_TCFG1_MUX_TCLK
-
-#endif /* __ASM_ARCH_PWMCLK_H */
index 78925c5..032de66 100644 (file)
 
 #define S5P_OTHERS             S5P_CLKREG(0xE000)
 #define S5P_OM_STAT            S5P_CLKREG(0xE100)
+#define S5P_HDMI_PHY_CONTROL   S5P_CLKREG(0xE804)
 #define S5P_USB_PHY_CONTROL    S5P_CLKREG(0xE80C)
-#define S5P_DAC_CONTROL                S5P_CLKREG(0xE810)
+#define S5P_DAC_PHY_CONTROL    S5P_CLKREG(0xE810)
 #define S5P_MIPI_DPHY_CONTROL(x) S5P_CLKREG(0xE814)
 #define S5P_MIPI_DPHY_ENABLE   (1 << 0)
 #define S5P_MIPI_DPHY_SRESETN  (1 << 1)
index 061cc7e..15edcae 100644 (file)
 #include <plat/s5p-time.h>
 #include <plat/mfc.h>
 #include <plat/regs-fb-v4.h>
+#include <plat/camport.h>
+
+#include <media/v4l2-mediabus.h>
+#include <media/s5p_fimc.h>
+#include <media/noon010pc30.h>
 
 /* Following are default values for UCON, ULCON and UFCON UART registers */
 #define GONI_UCON_DEFAULT      (S3C2410_UCON_TXILEVEL |        \
@@ -272,6 +277,14 @@ static void __init goni_tsp_init(void)
        i2c2_devs[0].irq = gpio_to_irq(gpio);
 }
 
+static void goni_camera_init(void)
+{
+       s5pv210_fimc_setup_gpio(S5P_CAMPORT_A);
+
+       /* Set max driver strength on CAM_A_CLKOUT pin. */
+       s5p_gpio_set_drvstr(S5PV210_GPE1(3), S5P_GPIO_DRVSTR_LV4);
+}
+
 /* MAX8998 regulators */
 #if defined(CONFIG_REGULATOR_MAX8998) || defined(CONFIG_REGULATOR_MAX8998_MODULE)
 
@@ -285,6 +298,7 @@ static struct regulator_consumer_supply goni_ldo5_consumers[] = {
 
 static struct regulator_consumer_supply goni_ldo8_consumers[] = {
        REGULATOR_SUPPLY("vusb_d", "s3c-hsotg"),
+       REGULATOR_SUPPLY("vdd33a_dac", "s5p-sdo"),
 };
 
 static struct regulator_consumer_supply goni_ldo11_consumers[] = {
@@ -475,6 +489,10 @@ static struct regulator_consumer_supply buck1_consumer =
 static struct regulator_consumer_supply buck2_consumer =
        REGULATOR_SUPPLY("vddint", NULL);
 
+static struct regulator_consumer_supply buck3_consumer =
+       REGULATOR_SUPPLY("vdet", "s5p-sdo");
+
+
 static struct regulator_init_data goni_buck1_data = {
        .constraints    = {
                .name           = "VARM_1.2V",
@@ -511,6 +529,8 @@ static struct regulator_init_data goni_buck3_data = {
                        .enabled = 1,
                },
        },
+       .num_consumer_supplies  = 1,
+       .consumer_supplies      = &buck3_consumer,
 };
 
 static struct regulator_init_data goni_buck4_data = {
@@ -801,6 +821,34 @@ static void goni_setup_sdhci(void)
        s3c_sdhci2_set_platdata(&goni_hsmmc2_data);
 };
 
+static struct noon010pc30_platform_data noon010pc30_pldata = {
+       .clk_rate       = 16000000UL,
+       .gpio_nreset    = S5PV210_GPB(2), /* CAM_CIF_NRST */
+       .gpio_nstby     = S5PV210_GPB(0), /* CAM_CIF_NSTBY */
+};
+
+static struct i2c_board_info noon010pc30_board_info = {
+       I2C_BOARD_INFO("NOON010PC30", 0x60 >> 1),
+       .platform_data = &noon010pc30_pldata,
+};
+
+static struct s5p_fimc_isp_info goni_camera_sensors[] = {
+       {
+               .mux_id         = 0,
+               .flags          = V4L2_MBUS_PCLK_SAMPLE_FALLING |
+                                 V4L2_MBUS_VSYNC_ACTIVE_LOW,
+               .bus_type       = FIMC_ITU_601,
+               .board_info     = &noon010pc30_board_info,
+               .i2c_bus_num    = 0,
+               .clk_frequency  = 16000000UL,
+       },
+};
+
+struct s5p_platform_fimc goni_fimc_md_platdata __initdata = {
+       .isp_info       = goni_camera_sensors,
+       .num_clients    = ARRAY_SIZE(goni_camera_sensors),
+};
+
 static struct platform_device *goni_devices[] __initdata = {
        &s3c_device_fb,
        &s5p_device_onenand,
@@ -812,10 +860,13 @@ static struct platform_device *goni_devices[] __initdata = {
        &s5p_device_mfc,
        &s5p_device_mfc_l,
        &s5p_device_mfc_r,
+       &s5p_device_mixer,
+       &s5p_device_sdo,
        &s3c_device_i2c0,
        &s5p_device_fimc0,
        &s5p_device_fimc1,
        &s5p_device_fimc2,
+       &s5p_device_fimc_md,
        &s3c_device_hsmmc0,
        &s3c_device_hsmmc1,
        &s3c_device_hsmmc2,
@@ -884,6 +935,12 @@ static void __init goni_machine_init(void)
        /* FB */
        s3c_fb_set_platdata(&goni_lcd_pdata);
 
+       /* FIMC */
+       s3c_set_platdata(&goni_fimc_md_platdata, sizeof(goni_fimc_md_platdata),
+                        &s5p_device_fimc_md);
+
+       goni_camera_init();
+
        /* SPI */
        spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
 
index a83b6c9..6b8ccc4 100644 (file)
  * published by the Free Software Foundation.
 */
 
-#include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-
-#include <linux/mmc/card.h>
-#include <linux/mmc/host.h>
-
-#include <plat/regs-sdhci.h>
-#include <plat/sdhci.h>
 
 /* clock sources for the mmc bus clock, order as for the ctrl2[5..4] */
 
@@ -30,34 +20,3 @@ char *s5pv210_hsmmc_clksrcs[4] = {
        [2] = "sclk_mmc",       /* mmc_bus */
        /* [3] = NULL,          - reserved */
 };
-
-void s5pv210_setup_sdhci_cfg_card(struct platform_device *dev,
-                                   void __iomem *r,
-                                   struct mmc_ios *ios,
-                                   struct mmc_card *card)
-{
-       u32 ctrl2, ctrl3;
-
-       /* don't need to alter anything according to card-type */
-
-       writel(S3C64XX_SDHCI_CONTROL4_DRIVE_9mA, r + S3C64XX_SDHCI_CONTROL4);
-
-       ctrl2 = readl(r + S3C_SDHCI_CONTROL2);
-       ctrl2 &= S3C_SDHCI_CTRL2_SELBASECLK_MASK;
-       ctrl2 |= (S3C64XX_SDHCI_CTRL2_ENSTAASYNCCLR |
-                 S3C64XX_SDHCI_CTRL2_ENCMDCNFMSK |
-                 S3C_SDHCI_CTRL2_ENFBCLKRX |
-                 S3C_SDHCI_CTRL2_DFCNT_NONE |
-                 S3C_SDHCI_CTRL2_ENCLKOUTHOLD);
-
-       if (ios->clock < 25 * 1000000)
-               ctrl3 = (S3C_SDHCI_CTRL3_FCSEL3 |
-                        S3C_SDHCI_CTRL3_FCSEL2 |
-                        S3C_SDHCI_CTRL3_FCSEL1 |
-                        S3C_SDHCI_CTRL3_FCSEL0);
-       else
-               ctrl3 = (S3C_SDHCI_CTRL3_FCSEL1 | S3C_SDHCI_CTRL3_FCSEL0);
-
-       writel(ctrl2, r + S3C_SDHCI_CONTROL2);
-       writel(ctrl3, r + S3C_SDHCI_CONTROL3);
-}
diff --git a/arch/arm/mach-s5pv210/sleep.S b/arch/arm/mach-s5pv210/sleep.S
deleted file mode 100644 (file)
index e3452cc..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/* linux/arch/arm/plat-s5p/sleep.S
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com
- *
- * S5PV210 power Manager (Suspend-To-RAM) support
- * Based on S3C2410 sleep code by:
- *     Ben Dooks, (c) 2004 Simtec Electronics
- *
- * Based on PXA/SA1100 sleep code by:
- *     Nicolas Pitre, (c) 2002 Monta Vista Software Inc
- *     Cliff Brake, (c) 2001
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include <linux/linkage.h>
-#include <asm/assembler.h>
-#include <asm/memory.h>
-
-       .text
-
-       /* sleep magic, to allow the bootloader to check for an valid
-        * image to resume to. Must be the first word before the
-        * s3c_cpu_resume entry.
-       */
-
-       .word   0x2bedf00d
-
-       /* s3c_cpu_resume
-        *
-        * resume code entry for bootloader to call
-        *
-        * we must put this code here in the data segment as we have no
-        * other way of restoring the stack pointer after sleep, and we
-        * must not write to the code segment (code is read-only)
-       */
-
-ENTRY(s3c_cpu_resume)
-       b       cpu_resume
index 7283d69..a3aa0f6 100644 (file)
@@ -933,7 +933,7 @@ static struct platform_device ap4evb_camera = {
 static struct sh_csi2_client_config csi2_clients[] = {
        {
                .phy            = SH_CSI2_PHY_MAIN,
-               .lanes          = 3,
+               .lanes          = 0,            /* default: 2 lanes */
                .channel        = 0,
                .pdev           = &ap4evb_camera,
        },
index 6c621c2..9c5e598 100644 (file)
@@ -1223,9 +1223,10 @@ static struct soc_camera_platform_info camera_info = {
                .width = 640,
                .height = 480,
        },
-       .bus_param = SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH |
-       SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_MASTER | SOCAM_DATAWIDTH_8 |
-       SOCAM_DATA_ACTIVE_HIGH,
+       .mbus_param = V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_MASTER |
+       V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_HIGH |
+       V4L2_MBUS_DATA_ACTIVE_HIGH,
+       .mbus_type = V4L2_MBUS_PARALLEL,
        .set_capture = camera_set_capture,
 };
 
index 8c5b302..d8973ac 100644 (file)
@@ -9,7 +9,6 @@ config PLAT_S3C24XX
        select NO_IOPORT
        select ARCH_REQUIRE_GPIOLIB
        select S3C_DEV_NAND
-       select S3C_GPIO_CFG_S3C24XX
        help
          Base platform code for any Samsung S3C24XX device
 
index 0291bd6..b2b0112 100644 (file)
@@ -14,9 +14,7 @@ obj-                          :=
 
 obj-y                          += cpu.o
 obj-y                          += irq.o
-obj-y                          += devs.o
-obj-y                          += gpio.o
-obj-y                          += gpiolib.o
+obj-y                          += dev-uart.o
 obj-y                          += clock.o
 obj-$(CONFIG_S3C24XX_DCLK)     += clock-dclk.o
 
diff --git a/arch/arm/plat-s3c24xx/dev-uart.c b/arch/arm/plat-s3c24xx/dev-uart.c
new file mode 100644 (file)
index 0000000..9ab22e6
--- /dev/null
@@ -0,0 +1,100 @@
+/* linux/arch/arm/plat-s3c24xx/dev-uart.c
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * Base S3C24XX UART resource and platform 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/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+#include <mach/hardware.h>
+#include <mach/map.h>
+
+#include <plat/devs.h>
+#include <plat/regs-serial.h>
+
+/* Serial port registrations */
+
+static struct resource s3c2410_uart0_resource[] = {
+       [0] = {
+               .start = S3C2410_PA_UART0,
+               .end   = S3C2410_PA_UART0 + 0x3fff,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = IRQ_S3CUART_RX0,
+               .end   = IRQ_S3CUART_ERR0,
+               .flags = IORESOURCE_IRQ,
+       }
+};
+
+static struct resource s3c2410_uart1_resource[] = {
+       [0] = {
+               .start = S3C2410_PA_UART1,
+               .end   = S3C2410_PA_UART1 + 0x3fff,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = IRQ_S3CUART_RX1,
+               .end   = IRQ_S3CUART_ERR1,
+               .flags = IORESOURCE_IRQ,
+       }
+};
+
+static struct resource s3c2410_uart2_resource[] = {
+       [0] = {
+               .start = S3C2410_PA_UART2,
+               .end   = S3C2410_PA_UART2 + 0x3fff,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = IRQ_S3CUART_RX2,
+               .end   = IRQ_S3CUART_ERR2,
+               .flags = IORESOURCE_IRQ,
+       }
+};
+
+static struct resource s3c2410_uart3_resource[] = {
+       [0] = {
+               .start = S3C2443_PA_UART3,
+               .end   = S3C2443_PA_UART3 + 0x3fff,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = IRQ_S3CUART_RX3,
+               .end   = IRQ_S3CUART_ERR3,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+struct s3c24xx_uart_resources s3c2410_uart_resources[] __initdata = {
+       [0] = {
+               .resources      = s3c2410_uart0_resource,
+               .nr_resources   = ARRAY_SIZE(s3c2410_uart0_resource),
+       },
+       [1] = {
+               .resources      = s3c2410_uart1_resource,
+               .nr_resources   = ARRAY_SIZE(s3c2410_uart1_resource),
+       },
+       [2] = {
+               .resources      = s3c2410_uart2_resource,
+               .nr_resources   = ARRAY_SIZE(s3c2410_uart2_resource),
+       },
+       [3] = {
+               .resources      = s3c2410_uart3_resource,
+               .nr_resources   = ARRAY_SIZE(s3c2410_uart3_resource),
+       },
+};
diff --git a/arch/arm/plat-s3c24xx/devs.c b/arch/arm/plat-s3c24xx/devs.c
deleted file mode 100644 (file)
index a76bf2d..0000000
+++ /dev/null
@@ -1,528 +0,0 @@
-/* linux/arch/arm/plat-s3c24xx/devs.c
- *
- * Copyright (c) 2004 Simtec Electronics
- *     Ben Dooks <ben@simtec.co.uk>
- *
- * Base S3C24XX platform 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/types.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/timer.h>
-#include <linux/init.h>
-#include <linux/serial_core.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/dma-mapping.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-#include <mach/fb.h>
-#include <mach/hardware.h>
-#include <mach/dma.h>
-#include <mach/irqs.h>
-#include <asm/irq.h>
-
-#include <plat/regs-serial.h>
-#include <plat/udc.h>
-#include <plat/mci.h>
-
-#include <plat/devs.h>
-#include <plat/cpu.h>
-#include <plat/regs-spi.h>
-#include <plat/ts.h>
-
-/* Serial port registrations */
-
-static struct resource s3c2410_uart0_resource[] = {
-       [0] = {
-               .start = S3C2410_PA_UART0,
-               .end   = S3C2410_PA_UART0 + 0x3fff,
-               .flags = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start = IRQ_S3CUART_RX0,
-               .end   = IRQ_S3CUART_ERR0,
-               .flags = IORESOURCE_IRQ,
-       }
-};
-
-static struct resource s3c2410_uart1_resource[] = {
-       [0] = {
-               .start = S3C2410_PA_UART1,
-               .end   = S3C2410_PA_UART1 + 0x3fff,
-               .flags = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start = IRQ_S3CUART_RX1,
-               .end   = IRQ_S3CUART_ERR1,
-               .flags = IORESOURCE_IRQ,
-       }
-};
-
-static struct resource s3c2410_uart2_resource[] = {
-       [0] = {
-               .start = S3C2410_PA_UART2,
-               .end   = S3C2410_PA_UART2 + 0x3fff,
-               .flags = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start = IRQ_S3CUART_RX2,
-               .end   = IRQ_S3CUART_ERR2,
-               .flags = IORESOURCE_IRQ,
-       }
-};
-
-static struct resource s3c2410_uart3_resource[] = {
-       [0] = {
-               .start = S3C2443_PA_UART3,
-               .end   = S3C2443_PA_UART3 + 0x3fff,
-               .flags = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start = IRQ_S3CUART_RX3,
-               .end   = IRQ_S3CUART_ERR3,
-               .flags = IORESOURCE_IRQ,
-       },
-};
-
-struct s3c24xx_uart_resources s3c2410_uart_resources[] __initdata = {
-       [0] = {
-               .resources      = s3c2410_uart0_resource,
-               .nr_resources   = ARRAY_SIZE(s3c2410_uart0_resource),
-       },
-       [1] = {
-               .resources      = s3c2410_uart1_resource,
-               .nr_resources   = ARRAY_SIZE(s3c2410_uart1_resource),
-       },
-       [2] = {
-               .resources      = s3c2410_uart2_resource,
-               .nr_resources   = ARRAY_SIZE(s3c2410_uart2_resource),
-       },
-       [3] = {
-               .resources      = s3c2410_uart3_resource,
-               .nr_resources   = ARRAY_SIZE(s3c2410_uart3_resource),
-       },
-};
-
-/* LCD Controller */
-
-static struct resource s3c_lcd_resource[] = {
-       [0] = {
-               .start = S3C24XX_PA_LCD,
-               .end   = S3C24XX_PA_LCD + S3C24XX_SZ_LCD - 1,
-               .flags = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start = IRQ_LCD,
-               .end   = IRQ_LCD,
-               .flags = IORESOURCE_IRQ,
-       }
-
-};
-
-static u64 s3c_device_lcd_dmamask = 0xffffffffUL;
-
-struct platform_device s3c_device_lcd = {
-       .name             = "s3c2410-lcd",
-       .id               = -1,
-       .num_resources    = ARRAY_SIZE(s3c_lcd_resource),
-       .resource         = s3c_lcd_resource,
-       .dev              = {
-               .dma_mask               = &s3c_device_lcd_dmamask,
-               .coherent_dma_mask      = 0xffffffffUL
-       }
-};
-
-EXPORT_SYMBOL(s3c_device_lcd);
-
-void __init s3c24xx_fb_set_platdata(struct s3c2410fb_mach_info *pd)
-{
-       struct s3c2410fb_mach_info *npd;
-
-       npd = s3c_set_platdata(pd, sizeof(*npd), &s3c_device_lcd);
-       if (npd) {
-               npd->displays = kmemdup(pd->displays,
-                       sizeof(struct s3c2410fb_display) * npd->num_displays,
-                       GFP_KERNEL);
-               if (!npd->displays)
-                       printk(KERN_ERR "no memory for LCD display data\n");
-       } else {
-               printk(KERN_ERR "no memory for LCD platform data\n");
-       }
-}
-
-/* Touchscreen */
-
-static struct resource s3c_ts_resource[] = {
-       [0] = {
-               .start = S3C24XX_PA_ADC,
-               .end   = S3C24XX_PA_ADC + S3C24XX_SZ_ADC - 1,
-               .flags = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start = IRQ_TC,
-               .end   = IRQ_TC,
-               .flags = IORESOURCE_IRQ,
-       },
-
-};
-
-struct platform_device s3c_device_ts = {
-       .name             = "s3c2410-ts",
-       .id               = -1,
-       .dev.parent     = &s3c_device_adc.dev,
-       .num_resources    = ARRAY_SIZE(s3c_ts_resource),
-       .resource         = s3c_ts_resource,
-};
-EXPORT_SYMBOL(s3c_device_ts);
-
-void __init s3c24xx_ts_set_platdata(struct s3c2410_ts_mach_info *hard_s3c2410ts_info)
-{
-       s3c_set_platdata(hard_s3c2410ts_info,
-                        sizeof(struct s3c2410_ts_mach_info), &s3c_device_ts);
-}
-
-/* USB Device (Gadget)*/
-
-static struct resource s3c_usbgadget_resource[] = {
-       [0] = {
-               .start = S3C24XX_PA_USBDEV,
-               .end   = S3C24XX_PA_USBDEV + S3C24XX_SZ_USBDEV - 1,
-               .flags = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start = IRQ_USBD,
-               .end   = IRQ_USBD,
-               .flags = IORESOURCE_IRQ,
-       }
-
-};
-
-struct platform_device s3c_device_usbgadget = {
-       .name             = "s3c2410-usbgadget",
-       .id               = -1,
-       .num_resources    = ARRAY_SIZE(s3c_usbgadget_resource),
-       .resource         = s3c_usbgadget_resource,
-};
-
-EXPORT_SYMBOL(s3c_device_usbgadget);
-
-void __init s3c24xx_udc_set_platdata(struct s3c2410_udc_mach_info *pd)
-{
-       s3c_set_platdata(pd, sizeof(*pd), &s3c_device_usbgadget);
-}
-
-/* USB High Speed 2.0 Device (Gadget) */
-static struct resource s3c_hsudc_resource[] = {
-       [0] = {
-               .start  = S3C2416_PA_HSUDC,
-               .end    = S3C2416_PA_HSUDC + S3C2416_SZ_HSUDC - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = IRQ_USBD,
-               .end    = IRQ_USBD,
-               .flags  = IORESOURCE_IRQ,
-       }
-};
-
-static u64 s3c_hsudc_dmamask = DMA_BIT_MASK(32);
-
-struct platform_device s3c_device_usb_hsudc = {
-       .name           = "s3c-hsudc",
-       .id             = -1,
-       .num_resources  = ARRAY_SIZE(s3c_hsudc_resource),
-       .resource       = s3c_hsudc_resource,
-       .dev            = {
-               .dma_mask               = &s3c_hsudc_dmamask,
-               .coherent_dma_mask      = DMA_BIT_MASK(32),
-       },
-};
-
-void __init s3c24xx_hsudc_set_platdata(struct s3c24xx_hsudc_platdata *pd)
-{
-       s3c_set_platdata(pd, sizeof(*pd), &s3c_device_usb_hsudc);
-}
-
-/* IIS */
-
-static struct resource s3c_iis_resource[] = {
-       [0] = {
-               .start = S3C24XX_PA_IIS,
-               .end   = S3C24XX_PA_IIS + S3C24XX_SZ_IIS -1,
-               .flags = IORESOURCE_MEM,
-       }
-};
-
-static u64 s3c_device_iis_dmamask = 0xffffffffUL;
-
-struct platform_device s3c_device_iis = {
-       .name             = "s3c24xx-iis",
-       .id               = -1,
-       .num_resources    = ARRAY_SIZE(s3c_iis_resource),
-       .resource         = s3c_iis_resource,
-       .dev              = {
-               .dma_mask = &s3c_device_iis_dmamask,
-               .coherent_dma_mask = 0xffffffffUL
-       }
-};
-
-EXPORT_SYMBOL(s3c_device_iis);
-
-/* RTC */
-
-static struct resource s3c_rtc_resource[] = {
-       [0] = {
-               .start = S3C24XX_PA_RTC,
-               .end   = S3C24XX_PA_RTC + 0xff,
-               .flags = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start = IRQ_RTC,
-               .end   = IRQ_RTC,
-               .flags = IORESOURCE_IRQ,
-       },
-       [2] = {
-               .start = IRQ_TICK,
-               .end   = IRQ_TICK,
-               .flags = IORESOURCE_IRQ
-       }
-};
-
-struct platform_device s3c_device_rtc = {
-       .name             = "s3c2410-rtc",
-       .id               = -1,
-       .num_resources    = ARRAY_SIZE(s3c_rtc_resource),
-       .resource         = s3c_rtc_resource,
-};
-
-EXPORT_SYMBOL(s3c_device_rtc);
-
-/* ADC */
-
-static struct resource s3c_adc_resource[] = {
-       [0] = {
-               .start = S3C24XX_PA_ADC,
-               .end   = S3C24XX_PA_ADC + S3C24XX_SZ_ADC - 1,
-               .flags = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start = IRQ_TC,
-               .end   = IRQ_TC,
-               .flags = IORESOURCE_IRQ,
-       },
-       [2] = {
-               .start = IRQ_ADC,
-               .end   = IRQ_ADC,
-               .flags = IORESOURCE_IRQ,
-       }
-
-};
-
-struct platform_device s3c_device_adc = {
-       .name             = "s3c24xx-adc",
-       .id               = -1,
-       .num_resources    = ARRAY_SIZE(s3c_adc_resource),
-       .resource         = s3c_adc_resource,
-};
-
-/* SDI */
-
-static struct resource s3c_sdi_resource[] = {
-       [0] = {
-               .start = S3C24XX_PA_SDI,
-               .end   = S3C24XX_PA_SDI + S3C24XX_SZ_SDI - 1,
-               .flags = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start = IRQ_SDI,
-               .end   = IRQ_SDI,
-               .flags = IORESOURCE_IRQ,
-       }
-
-};
-
-struct platform_device s3c_device_sdi = {
-       .name             = "s3c2410-sdi",
-       .id               = -1,
-       .num_resources    = ARRAY_SIZE(s3c_sdi_resource),
-       .resource         = s3c_sdi_resource,
-};
-
-EXPORT_SYMBOL(s3c_device_sdi);
-
-void __init s3c24xx_mci_set_platdata(struct s3c24xx_mci_pdata *pdata)
-{
-       s3c_set_platdata(pdata, sizeof(struct s3c24xx_mci_pdata),
-                        &s3c_device_sdi);
-}
-
-
-/* SPI (0) */
-
-static struct resource s3c_spi0_resource[] = {
-       [0] = {
-               .start = S3C24XX_PA_SPI,
-               .end   = S3C24XX_PA_SPI + 0x1f,
-               .flags = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start = IRQ_SPI0,
-               .end   = IRQ_SPI0,
-               .flags = IORESOURCE_IRQ,
-       }
-
-};
-
-static u64 s3c_device_spi0_dmamask = 0xffffffffUL;
-
-struct platform_device s3c_device_spi0 = {
-       .name             = "s3c2410-spi",
-       .id               = 0,
-       .num_resources    = ARRAY_SIZE(s3c_spi0_resource),
-       .resource         = s3c_spi0_resource,
-        .dev              = {
-                .dma_mask = &s3c_device_spi0_dmamask,
-                .coherent_dma_mask = 0xffffffffUL
-        }
-};
-
-EXPORT_SYMBOL(s3c_device_spi0);
-
-/* SPI (1) */
-
-static struct resource s3c_spi1_resource[] = {
-       [0] = {
-               .start = S3C24XX_PA_SPI + S3C2410_SPI1,
-               .end   = S3C24XX_PA_SPI + S3C2410_SPI1 + 0x1f,
-               .flags = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start = IRQ_SPI1,
-               .end   = IRQ_SPI1,
-               .flags = IORESOURCE_IRQ,
-       }
-
-};
-
-static u64 s3c_device_spi1_dmamask = 0xffffffffUL;
-
-struct platform_device s3c_device_spi1 = {
-       .name             = "s3c2410-spi",
-       .id               = 1,
-       .num_resources    = ARRAY_SIZE(s3c_spi1_resource),
-       .resource         = s3c_spi1_resource,
-        .dev              = {
-                .dma_mask = &s3c_device_spi1_dmamask,
-                .coherent_dma_mask = 0xffffffffUL
-        }
-};
-
-EXPORT_SYMBOL(s3c_device_spi1);
-
-#ifdef CONFIG_CPU_S3C2440
-
-/* Camif Controller */
-
-static struct resource s3c_camif_resource[] = {
-       [0] = {
-               .start = S3C2440_PA_CAMIF,
-               .end   = S3C2440_PA_CAMIF + S3C2440_SZ_CAMIF - 1,
-               .flags = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start = IRQ_CAM,
-               .end   = IRQ_CAM,
-               .flags = IORESOURCE_IRQ,
-       }
-
-};
-
-static u64 s3c_device_camif_dmamask = 0xffffffffUL;
-
-struct platform_device s3c_device_camif = {
-       .name             = "s3c2440-camif",
-       .id               = -1,
-       .num_resources    = ARRAY_SIZE(s3c_camif_resource),
-       .resource         = s3c_camif_resource,
-       .dev              = {
-               .dma_mask = &s3c_device_camif_dmamask,
-               .coherent_dma_mask = 0xffffffffUL
-       }
-};
-
-EXPORT_SYMBOL(s3c_device_camif);
-
-/* AC97 */
-
-static struct resource s3c_ac97_resource[] = {
-       [0] = {
-               .start = S3C2440_PA_AC97,
-               .end   = S3C2440_PA_AC97 + S3C2440_SZ_AC97 -1,
-               .flags = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start = IRQ_S3C244x_AC97,
-               .end   = IRQ_S3C244x_AC97,
-               .flags = IORESOURCE_IRQ,
-       },
-       [2] = {
-               .name  = "PCM out",
-               .start = DMACH_PCM_OUT,
-               .end   = DMACH_PCM_OUT,
-               .flags = IORESOURCE_DMA,
-       },
-       [3] = {
-               .name  = "PCM in",
-               .start = DMACH_PCM_IN,
-               .end   = DMACH_PCM_IN,
-               .flags = IORESOURCE_DMA,
-       },
-       [4] = {
-               .name  = "Mic in",
-               .start = DMACH_MIC_IN,
-               .end   = DMACH_MIC_IN,
-               .flags = IORESOURCE_DMA,
-       },
-};
-
-static u64 s3c_device_audio_dmamask = 0xffffffffUL;
-
-struct platform_device s3c_device_ac97 = {
-       .name             = "samsung-ac97",
-       .id               = -1,
-       .num_resources    = ARRAY_SIZE(s3c_ac97_resource),
-       .resource         = s3c_ac97_resource,
-       .dev              = {
-               .dma_mask = &s3c_device_audio_dmamask,
-               .coherent_dma_mask = 0xffffffffUL
-       }
-};
-
-EXPORT_SYMBOL(s3c_device_ac97);
-
-/* ASoC I2S */
-
-struct platform_device s3c2412_device_iis = {
-       .name             = "s3c2412-iis",
-       .id               = -1,
-       .dev              = {
-               .dma_mask = &s3c_device_audio_dmamask,
-               .coherent_dma_mask = 0xffffffffUL
-       }
-};
-
-EXPORT_SYMBOL(s3c2412_device_iis);
-
-#endif // CONFIG_CPU_S32440
index 539bd0e..53754bc 100644 (file)
@@ -1094,14 +1094,14 @@ EXPORT_SYMBOL(s3c2410_dma_config);
  *
  * configure the dma source/destination hardware type and address
  *
- * source:    S3C2410_DMASRC_HW: source is hardware
- *            S3C2410_DMASRC_MEM: source is memory
+ * source:    DMA_FROM_DEVICE: source is hardware
+ *            DMA_TO_DEVICE: source is memory
  *
  * devaddr:   physical address of the source
 */
 
 int s3c2410_dma_devconfig(enum dma_ch channel,
-                         enum s3c2410_dmasrc source,
+                         enum dma_data_direction source,
                          unsigned long devaddr)
 {
        struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
@@ -1131,7 +1131,7 @@ int s3c2410_dma_devconfig(enum dma_ch channel,
         hwcfg |= S3C2410_DISRCC_INC;
 
        switch (source) {
-       case S3C2410_DMASRC_HW:
+       case DMA_FROM_DEVICE:
                /* source is hardware */
                pr_debug("%s: hw source, devaddr=%08lx, hwcfg=%d\n",
                         __func__, devaddr, hwcfg);
@@ -1142,7 +1142,7 @@ int s3c2410_dma_devconfig(enum dma_ch channel,
                chan->addr_reg = dma_regaddr(chan, S3C2410_DMA_DIDST);
                break;
 
-       case S3C2410_DMASRC_MEM:
+       case DMA_TO_DEVICE:
                /* source is memory */
                pr_debug("%s: mem source, devaddr=%08lx, hwcfg=%d\n",
                         __func__, devaddr, hwcfg);
diff --git a/arch/arm/plat-s3c24xx/gpio.c b/arch/arm/plat-s3c24xx/gpio.c
deleted file mode 100644 (file)
index 2f3d7c0..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-/* linux/arch/arm/plat-s3c24xx/gpio.c
- *
- * Copyright (c) 2004-2010 Simtec Electronics
- *     Ben Dooks <ben@simtec.co.uk>
- *
- * S3C24XX GPIO support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/gpio.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <mach/gpio-fns.h>
-#include <asm/irq.h>
-
-#include <mach/regs-gpio.h>
-
-#include <plat/gpio-core.h>
-
-/* gpiolib wrappers until these are totally eliminated */
-
-void s3c2410_gpio_pullup(unsigned int pin, unsigned int to)
-{
-       int ret;
-
-       WARN_ON(to);    /* should be none of these left */
-
-       if (!to) {
-               /* if pull is enabled, try first with up, and if that
-                * fails, try using down */
-
-               ret = s3c_gpio_setpull(pin, S3C_GPIO_PULL_UP);
-               if (ret)
-                       s3c_gpio_setpull(pin, S3C_GPIO_PULL_DOWN);
-       } else {
-               s3c_gpio_setpull(pin, S3C_GPIO_PULL_NONE);
-       }
-}
-EXPORT_SYMBOL(s3c2410_gpio_pullup);
-
-void s3c2410_gpio_setpin(unsigned int pin, unsigned int to)
-{
-       /* do this via gpiolib until all users removed */
-
-       gpio_request(pin, "temporary");
-       gpio_set_value(pin, to);
-       gpio_free(pin);
-}
-
-EXPORT_SYMBOL(s3c2410_gpio_setpin);
-
-unsigned int s3c2410_gpio_getpin(unsigned int pin)
-{
-       struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
-       unsigned long offs = pin - chip->chip.base;
-
-       return __raw_readl(chip->base + 0x04) & (1<< offs);
-}
-
-EXPORT_SYMBOL(s3c2410_gpio_getpin);
-
-unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change)
-{
-       unsigned long flags;
-       unsigned long misccr;
-
-       local_irq_save(flags);
-       misccr = __raw_readl(S3C24XX_MISCCR);
-       misccr &= ~clear;
-       misccr ^= change;
-       __raw_writel(misccr, S3C24XX_MISCCR);
-       local_irq_restore(flags);
-
-       return misccr;
-}
-
-EXPORT_SYMBOL(s3c2410_modify_misccr);
diff --git a/arch/arm/plat-s3c24xx/gpiolib.c b/arch/arm/plat-s3c24xx/gpiolib.c
deleted file mode 100644 (file)
index 243b641..0000000
+++ /dev/null
@@ -1,229 +0,0 @@
-/* linux/arch/arm/plat-s3c24xx/gpiolib.c
- *
- * Copyright (c) 2008-2010 Simtec Electronics
- *     http://armlinux.simtec.co.uk/
- *     Ben Dooks <ben@simtec.co.uk>
- *
- * S3C24XX GPIOlib support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License.
-*/
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/sysdev.h>
-#include <linux/ioport.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-
-#include <plat/gpio-core.h>
-#include <plat/gpio-cfg.h>
-#include <plat/gpio-cfg-helpers.h>
-#include <mach/hardware.h>
-#include <asm/irq.h>
-#include <plat/pm.h>
-
-#include <mach/regs-gpio.h>
-
-static int s3c24xx_gpiolib_banka_input(struct gpio_chip *chip, unsigned offset)
-{
-       return -EINVAL;
-}
-
-static int s3c24xx_gpiolib_banka_output(struct gpio_chip *chip,
-                                       unsigned offset, int value)
-{
-       struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-       void __iomem *base = ourchip->base;
-       unsigned long flags;
-       unsigned long dat;
-       unsigned long con;
-
-       local_irq_save(flags);
-
-       con = __raw_readl(base + 0x00);
-       dat = __raw_readl(base + 0x04);
-
-       dat &= ~(1 << offset);
-       if (value)
-               dat |= 1 << offset;
-
-       __raw_writel(dat, base + 0x04);
-
-       con &= ~(1 << offset);
-
-       __raw_writel(con, base + 0x00);
-       __raw_writel(dat, base + 0x04);
-
-       local_irq_restore(flags);
-       return 0;
-}
-
-static int s3c24xx_gpiolib_bankf_toirq(struct gpio_chip *chip, unsigned offset)
-{
-       if (offset < 4)
-               return IRQ_EINT0 + offset;
-       
-       if (offset < 8)
-               return IRQ_EINT4 + offset - 4;
-       
-       return -EINVAL;
-}
-
-static struct s3c_gpio_cfg s3c24xx_gpiocfg_banka = {
-       .set_config     = s3c_gpio_setcfg_s3c24xx_a,
-       .get_config     = s3c_gpio_getcfg_s3c24xx_a,
-};
-
-struct s3c_gpio_cfg s3c24xx_gpiocfg_default = {
-       .set_config     = s3c_gpio_setcfg_s3c24xx,
-       .get_config     = s3c_gpio_getcfg_s3c24xx,
-};
-
-struct s3c_gpio_chip s3c24xx_gpios[] = {
-       [0] = {
-               .base   = S3C2410_GPACON,
-               .pm     = __gpio_pm(&s3c_gpio_pm_1bit),
-               .config = &s3c24xx_gpiocfg_banka,
-               .chip   = {
-                       .base                   = S3C2410_GPA(0),
-                       .owner                  = THIS_MODULE,
-                       .label                  = "GPIOA",
-                       .ngpio                  = 24,
-                       .direction_input        = s3c24xx_gpiolib_banka_input,
-                       .direction_output       = s3c24xx_gpiolib_banka_output,
-               },
-       },
-       [1] = {
-               .base   = S3C2410_GPBCON,
-               .pm     = __gpio_pm(&s3c_gpio_pm_2bit),
-               .chip   = {
-                       .base                   = S3C2410_GPB(0),
-                       .owner                  = THIS_MODULE,
-                       .label                  = "GPIOB",
-                       .ngpio                  = 16,
-               },
-       },
-       [2] = {
-               .base   = S3C2410_GPCCON,
-               .pm     = __gpio_pm(&s3c_gpio_pm_2bit),
-               .chip   = {
-                       .base                   = S3C2410_GPC(0),
-                       .owner                  = THIS_MODULE,
-                       .label                  = "GPIOC",
-                       .ngpio                  = 16,
-               },
-       },
-       [3] = {
-               .base   = S3C2410_GPDCON,
-               .pm     = __gpio_pm(&s3c_gpio_pm_2bit),
-               .chip   = {
-                       .base                   = S3C2410_GPD(0),
-                       .owner                  = THIS_MODULE,
-                       .label                  = "GPIOD",
-                       .ngpio                  = 16,
-               },
-       },
-       [4] = {
-               .base   = S3C2410_GPECON,
-               .pm     = __gpio_pm(&s3c_gpio_pm_2bit),
-               .chip   = {
-                       .base                   = S3C2410_GPE(0),
-                       .label                  = "GPIOE",
-                       .owner                  = THIS_MODULE,
-                       .ngpio                  = 16,
-               },
-       },
-       [5] = {
-               .base   = S3C2410_GPFCON,
-               .pm     = __gpio_pm(&s3c_gpio_pm_2bit),
-               .chip   = {
-                       .base                   = S3C2410_GPF(0),
-                       .owner                  = THIS_MODULE,
-                       .label                  = "GPIOF",
-                       .ngpio                  = 8,
-                       .to_irq                 = s3c24xx_gpiolib_bankf_toirq,
-               },
-       },
-       [6] = {
-               .base   = S3C2410_GPGCON,
-               .pm     = __gpio_pm(&s3c_gpio_pm_2bit),
-               .irq_base = IRQ_EINT8,
-               .chip   = {
-                       .base                   = S3C2410_GPG(0),
-                       .owner                  = THIS_MODULE,
-                       .label                  = "GPIOG",
-                       .ngpio                  = 16,
-                       .to_irq                 = samsung_gpiolib_to_irq,
-               },
-       }, {
-               .base   = S3C2410_GPHCON,
-               .pm     = __gpio_pm(&s3c_gpio_pm_2bit),
-               .chip   = {
-                       .base                   = S3C2410_GPH(0),
-                       .owner                  = THIS_MODULE,
-                       .label                  = "GPIOH",
-                       .ngpio                  = 11,
-               },
-       },
-               /* GPIOS for the S3C2443 and later devices. */
-       {
-               .base   = S3C2440_GPJCON,
-               .pm     = __gpio_pm(&s3c_gpio_pm_2bit),
-               .chip   = {
-                       .base                   = S3C2410_GPJ(0),
-                       .owner                  = THIS_MODULE,
-                       .label                  = "GPIOJ",
-                       .ngpio                  = 16,
-               },
-       }, {
-               .base   = S3C2443_GPKCON,
-               .pm     = __gpio_pm(&s3c_gpio_pm_2bit),
-               .chip   = {
-                       .base                   = S3C2410_GPK(0),
-                       .owner                  = THIS_MODULE,
-                       .label                  = "GPIOK",
-                       .ngpio                  = 16,
-               },
-       }, {
-               .base   = S3C2443_GPLCON,
-               .pm     = __gpio_pm(&s3c_gpio_pm_2bit),
-               .chip   = {
-                       .base                   = S3C2410_GPL(0),
-                       .owner                  = THIS_MODULE,
-                       .label                  = "GPIOL",
-                       .ngpio                  = 15,
-               },
-       }, {
-               .base   = S3C2443_GPMCON,
-               .pm     = __gpio_pm(&s3c_gpio_pm_2bit),
-               .chip   = {
-                       .base                   = S3C2410_GPM(0),
-                       .owner                  = THIS_MODULE,
-                       .label                  = "GPIOM",
-                       .ngpio                  = 2,
-               },
-       },
-};
-
-
-static __init int s3c24xx_gpiolib_init(void)
-{
-       struct s3c_gpio_chip *chip = s3c24xx_gpios;
-       int gpn;
-
-       for (gpn = 0; gpn < ARRAY_SIZE(s3c24xx_gpios); gpn++, chip++) {
-               if (!chip->config)
-                       chip->config = &s3c24xx_gpiocfg_default;
-
-               s3c_gpiolib_add(chip);
-       }
-
-       return 0;
-}
-
-core_initcall(s3c24xx_gpiolib_init);
diff --git a/arch/arm/plat-s3c24xx/include/mach/clkdev.h b/arch/arm/plat-s3c24xx/include/mach/clkdev.h
deleted file mode 100644 (file)
index 7dffa83..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#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/plat-s3c24xx/include/mach/pwm-clock.h b/arch/arm/plat-s3c24xx/include/mach/pwm-clock.h
deleted file mode 100644 (file)
index a087de2..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/* linux/arch/arm/plat-s3c24xx/include/mach/pwm-clock.h
- *
- * Copyright 2008 Simtec Electronics
- *      Ben Dooks <ben@simtec.co.uk>
- *      http://armlinux.simtec.co.uk/
- *
- * S3C24xx - pwm clock and timer support
- */
-
-/**
- * pwm_cfg_src_is_tclk() - return whether the given mux config is a tclk
- * @cfg: The timer TCFG1 register bits shifted down to 0.
- *
- * Return true if the given configuration from TCFG1 is a TCLK instead
- * any of the TDIV clocks.
- */
-static inline int pwm_cfg_src_is_tclk(unsigned long tcfg)
-{
-       return tcfg == S3C2410_TCFG1_MUX_TCLK;
-}
-
-/**
- * tcfg_to_divisor() - convert tcfg1 setting to a divisor
- * @tcfg1: The tcfg1 setting, shifted down.
- *
- * Get the divisor value for the given tcfg1 setting. We assume the
- * caller has already checked to see if this is not a TCLK source.
- */
-static inline unsigned long tcfg_to_divisor(unsigned long tcfg1)
-{
-       return 1 << (1 + tcfg1);
-}
-
-/**
- * pwm_tdiv_has_div1() - does the tdiv setting have a /1
- *
- * Return true if we have a /1 in the tdiv setting.
- */
-static inline unsigned int pwm_tdiv_has_div1(void)
-{
-       return 0;
-}
-
-/**
- * pwm_tdiv_div_bits() - calculate TCFG1 divisor value.
- * @div: The divisor to calculate the bit information for.
- *
- * Turn a divisor into the necessary bit field for TCFG1.
- */
-static inline unsigned long pwm_tdiv_div_bits(unsigned int div)
-{
-       return ilog2(div) - 1;
-}
-
-#define S3C_TCFG1_MUX_TCLK S3C2410_TCFG1_MUX_TCLK
diff --git a/arch/arm/plat-s3c24xx/include/plat/pll.h b/arch/arm/plat-s3c24xx/include/plat/pll.h
deleted file mode 100644 (file)
index 005729a..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/* linux/arch/arm/plat-s3c24xx/include/plat/pll.h
- *
- * Copyright 2008 Simtec Electronics
- *      Ben Dooks <ben@simtec.co.uk>
- *      http://armlinux.simtec.co.uk/
- *
- * S3C24xx - common pll registers and code
- */
-
-#define S3C24XX_PLLCON_MDIVSHIFT       12
-#define S3C24XX_PLLCON_PDIVSHIFT       4
-#define S3C24XX_PLLCON_SDIVSHIFT       0
-#define S3C24XX_PLLCON_MDIVMASK                ((1<<(1+(19-12)))-1)
-#define S3C24XX_PLLCON_PDIVMASK                ((1<<5)-1)
-#define S3C24XX_PLLCON_SDIVMASK                3
-
-#include <asm/div64.h>
-
-static inline unsigned int
-s3c24xx_get_pll(unsigned int pllval, unsigned int baseclk)
-{
-       unsigned int mdiv, pdiv, sdiv;
-       uint64_t fvco;
-
-       mdiv = pllval >> S3C24XX_PLLCON_MDIVSHIFT;
-       pdiv = pllval >> S3C24XX_PLLCON_PDIVSHIFT;
-       sdiv = pllval >> S3C24XX_PLLCON_SDIVSHIFT;
-
-       mdiv &= S3C24XX_PLLCON_MDIVMASK;
-       pdiv &= S3C24XX_PLLCON_PDIVMASK;
-       sdiv &= S3C24XX_PLLCON_SDIVMASK;
-
-       fvco = (uint64_t)baseclk * (mdiv + 8);
-       do_div(fvco, (pdiv + 2) << sdiv);
-
-       return (unsigned int)fvco;
-}
-
-#define S3C2416_PLL_M_SHIFT    (14)
-#define S3C2416_PLL_P_SHIFT    (5)
-#define S3C2416_PLL_S_MASK     (7)
-#define S3C2416_PLL_M_MASK     ((1 << 10) - 1)
-#define S3C2416_PLL_P_MASK     (63)
-
-static inline unsigned int
-s3c2416_get_pll(unsigned int pllval, unsigned int baseclk)
-{
-       unsigned int m, p, s;
-       uint64_t fvco;
-
-       m = pllval >> S3C2416_PLL_M_SHIFT;
-       p = pllval >> S3C2416_PLL_P_SHIFT;
-
-       s = pllval & S3C2416_PLL_S_MASK;
-       m &= S3C2416_PLL_M_MASK;
-       p &= S3C2416_PLL_P_MASK;
-
-       fvco = (uint64_t)baseclk * m;
-       do_div(fvco, (p << s));
-
-       return (unsigned int)fvco;
-}
diff --git a/arch/arm/plat-s3c24xx/include/plat/regs-iis.h b/arch/arm/plat-s3c24xx/include/plat/regs-iis.h
deleted file mode 100644 (file)
index cc44e0e..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/* arch/arm/mach-s3c2410/include/mach/regs-iis.h
- *
- * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
- *                   http://www.simtec.co.uk/products/SWLINUX/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * S3C2410 IIS register definition
-*/
-
-#ifndef __ASM_ARCH_REGS_IIS_H
-#define __ASM_ARCH_REGS_IIS_H
-
-#define S3C2410_IISCON  (0x00)
-
-#define S3C2410_IISCON_LRINDEX   (1<<8)
-#define S3C2410_IISCON_TXFIFORDY  (1<<7)
-#define S3C2410_IISCON_RXFIFORDY  (1<<6)
-#define S3C2410_IISCON_TXDMAEN   (1<<5)
-#define S3C2410_IISCON_RXDMAEN   (1<<4)
-#define S3C2410_IISCON_TXIDLE    (1<<3)
-#define S3C2410_IISCON_RXIDLE    (1<<2)
-#define S3C2410_IISCON_PSCEN     (1<<1)
-#define S3C2410_IISCON_IISEN     (1<<0)
-
-#define S3C2410_IISMOD  (0x04)
-
-#define S3C2440_IISMOD_MPLL      (1<<9)
-#define S3C2410_IISMOD_SLAVE     (1<<8)
-#define S3C2410_IISMOD_NOXFER    (0<<6)
-#define S3C2410_IISMOD_RXMODE    (1<<6)
-#define S3C2410_IISMOD_TXMODE    (2<<6)
-#define S3C2410_IISMOD_TXRXMODE          (3<<6)
-#define S3C2410_IISMOD_LR_LLOW   (0<<5)
-#define S3C2410_IISMOD_LR_RLOW   (1<<5)
-#define S3C2410_IISMOD_IIS       (0<<4)
-#define S3C2410_IISMOD_MSB       (1<<4)
-#define S3C2410_IISMOD_8BIT      (0<<3)
-#define S3C2410_IISMOD_16BIT     (1<<3)
-#define S3C2410_IISMOD_BITMASK   (1<<3)
-#define S3C2410_IISMOD_256FS     (0<<2)
-#define S3C2410_IISMOD_384FS     (1<<2)
-#define S3C2410_IISMOD_16FS      (0<<0)
-#define S3C2410_IISMOD_32FS      (1<<0)
-#define S3C2410_IISMOD_48FS      (2<<0)
-#define S3C2410_IISMOD_FS_MASK   (3<<0)
-
-#define S3C2410_IISPSR         (0x08)
-#define S3C2410_IISPSR_INTMASK (31<<5)
-#define S3C2410_IISPSR_INTSHIFT        (5)
-#define S3C2410_IISPSR_EXTMASK (31<<0)
-#define S3C2410_IISPSR_EXTSHFIT        (0)
-
-#define S3C2410_IISFCON  (0x0c)
-
-#define S3C2410_IISFCON_TXDMA    (1<<15)
-#define S3C2410_IISFCON_RXDMA    (1<<14)
-#define S3C2410_IISFCON_TXENABLE  (1<<13)
-#define S3C2410_IISFCON_RXENABLE  (1<<12)
-#define S3C2410_IISFCON_TXMASK   (0x3f << 6)
-#define S3C2410_IISFCON_TXSHIFT          (6)
-#define S3C2410_IISFCON_RXMASK   (0x3f)
-#define S3C2410_IISFCON_RXSHIFT          (0)
-
-#define S3C2410_IISFIFO  (0x10)
-#endif /* __ASM_ARCH_REGS_IIS_H */
diff --git a/arch/arm/plat-s3c24xx/include/plat/regs-spi.h b/arch/arm/plat-s3c24xx/include/plat/regs-spi.h
deleted file mode 100644 (file)
index 892e2f6..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-/* arch/arm/mach-s3c2410/include/mach/regs-spi.h
- *
- * Copyright (c) 2004 Fetron GmbH
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * S3C2410 SPI register definition
-*/
-
-#ifndef __ASM_ARCH_REGS_SPI_H
-#define __ASM_ARCH_REGS_SPI_H
-
-#define S3C2410_SPI1   (0x20)
-#define S3C2412_SPI1   (0x100)
-
-#define S3C2410_SPCON  (0x00)
-
-#define S3C2412_SPCON_RXFIFO_RB2       (0<<14)
-#define S3C2412_SPCON_RXFIFO_RB4       (1<<14)
-#define S3C2412_SPCON_RXFIFO_RB12      (2<<14)
-#define S3C2412_SPCON_RXFIFO_RB14      (3<<14)
-#define S3C2412_SPCON_TXFIFO_RB2       (0<<12)
-#define S3C2412_SPCON_TXFIFO_RB4       (1<<12)
-#define S3C2412_SPCON_TXFIFO_RB12      (2<<12)
-#define S3C2412_SPCON_TXFIFO_RB14      (3<<12)
-#define S3C2412_SPCON_RXFIFO_RESET     (1<<11) /* RxFIFO reset */
-#define S3C2412_SPCON_TXFIFO_RESET     (1<<10) /* TxFIFO reset */
-#define S3C2412_SPCON_RXFIFO_EN                (1<<9)  /* RxFIFO Enable */
-#define S3C2412_SPCON_TXFIFO_EN                (1<<8)  /* TxFIFO Enable */
-
-#define S3C2412_SPCON_DIRC_RX    (1<<7)
-
-#define S3C2410_SPCON_SMOD_DMA   (2<<5)        /* DMA mode */
-#define S3C2410_SPCON_SMOD_INT   (1<<5)        /* interrupt mode */
-#define S3C2410_SPCON_SMOD_POLL   (0<<5)       /* polling mode */
-#define S3C2410_SPCON_ENSCK      (1<<4)        /* Enable SCK */
-#define S3C2410_SPCON_MSTR       (1<<3)        /* Master/Slave select
-                                                  0: slave, 1: master */
-#define S3C2410_SPCON_CPOL_HIGH          (1<<2)        /* Clock polarity select */
-#define S3C2410_SPCON_CPOL_LOW   (0<<2)        /* Clock polarity select */
-
-#define S3C2410_SPCON_CPHA_FMTB          (1<<1)        /* Clock Phase Select */
-#define S3C2410_SPCON_CPHA_FMTA          (0<<1)        /* Clock Phase Select */
-
-#define S3C2410_SPCON_TAGD       (1<<0)        /* Tx auto garbage data mode */
-
-
-#define S3C2410_SPSTA   (0x04)
-
-#define S3C2412_SPSTA_RXFIFO_AE                (1<<11)
-#define S3C2412_SPSTA_TXFIFO_AE                (1<<10)
-#define S3C2412_SPSTA_RXFIFO_ERROR     (1<<9)
-#define S3C2412_SPSTA_TXFIFO_ERROR     (1<<8)
-#define S3C2412_SPSTA_RXFIFO_FIFO      (1<<7)
-#define S3C2412_SPSTA_RXFIFO_EMPTY     (1<<6)
-#define S3C2412_SPSTA_TXFIFO_NFULL     (1<<5)
-#define S3C2412_SPSTA_TXFIFO_EMPTY     (1<<4)
-
-#define S3C2410_SPSTA_DCOL       (1<<2)        /* Data Collision Error */
-#define S3C2410_SPSTA_MULD       (1<<1)        /* Multi Master Error */
-#define S3C2410_SPSTA_READY      (1<<0)        /* Data Tx/Rx ready */
-#define S3C2412_SPSTA_READY_ORG          (1<<3)
-
-#define S3C2410_SPPIN   (0x08)
-
-#define S3C2410_SPPIN_ENMUL      (1<<2)        /* Multi Master Error detect */
-#define S3C2410_SPPIN_RESERVED   (1<<1)
-#define S3C2410_SPPIN_KEEP       (1<<0)        /* Master Out keep */
-
-#define S3C2410_SPPRE   (0x0C)
-#define S3C2410_SPTDAT  (0x10)
-#define S3C2410_SPRDAT  (0x14)
-
-#define S3C2412_TXFIFO  (0x18)
-#define S3C2412_RXFIFO  (0x18)
-#define S3C2412_SPFIC   (0x24)
-
-
-#endif /* __ASM_ARCH_REGS_SPI_H */
index 59552c0..5a21b15 100644 (file)
@@ -160,6 +160,124 @@ static struct clk clk_prediv = {
        },
 };
 
+/* armdiv
+ *
+ * this clock is sourced from msysclk and can have a number of
+ * divider values applied to it to then be fed into armclk.
+*/
+
+static unsigned int *armdiv;
+static int nr_armdiv;
+static int armdivmask;
+
+static unsigned long s3c2443_armclk_roundrate(struct clk *clk,
+                                             unsigned long rate)
+{
+       unsigned long parent = clk_get_rate(clk->parent);
+       unsigned long calc;
+       unsigned best = 256; /* bigger than any value */
+       unsigned div;
+       int ptr;
+
+       if (!nr_armdiv)
+               return -EINVAL;
+
+       for (ptr = 0; ptr < nr_armdiv; ptr++) {
+               div = armdiv[ptr];
+               if (div) {
+                       /* cpufreq provides 266mhz as 266666000 not 266666666 */
+                       calc = (parent / div / 1000) * 1000;
+                       if (calc <= rate && div < best)
+                               best = div;
+               }
+       }
+
+       return parent / best;
+}
+
+static unsigned long s3c2443_armclk_getrate(struct clk *clk)
+{
+       unsigned long rate = clk_get_rate(clk->parent);
+       unsigned long clkcon0;
+       int val;
+
+       if (!nr_armdiv || !armdivmask)
+               return -EINVAL;
+
+       clkcon0 = __raw_readl(S3C2443_CLKDIV0);
+       clkcon0 &= armdivmask;
+       val = clkcon0 >> S3C2443_CLKDIV0_ARMDIV_SHIFT;
+
+       return rate / armdiv[val];
+}
+
+static int s3c2443_armclk_setrate(struct clk *clk, unsigned long rate)
+{
+       unsigned long parent = clk_get_rate(clk->parent);
+       unsigned long calc;
+       unsigned div;
+       unsigned best = 256; /* bigger than any value */
+       int ptr;
+       int val = -1;
+
+       if (!nr_armdiv || !armdivmask)
+               return -EINVAL;
+
+       for (ptr = 0; ptr < nr_armdiv; ptr++) {
+               div = armdiv[ptr];
+               if (div) {
+                       /* cpufreq provides 266mhz as 266666000 not 266666666 */
+                       calc = (parent / div / 1000) * 1000;
+                       if (calc <= rate && div < best) {
+                               best = div;
+                               val = ptr;
+                       }
+               }
+       }
+
+       if (val >= 0) {
+               unsigned long clkcon0;
+
+               clkcon0 = __raw_readl(S3C2443_CLKDIV0);
+               clkcon0 &= ~armdivmask;
+               clkcon0 |= val << S3C2443_CLKDIV0_ARMDIV_SHIFT;
+               __raw_writel(clkcon0, S3C2443_CLKDIV0);
+       }
+
+       return (val == -1) ? -EINVAL : 0;
+}
+
+static struct clk clk_armdiv = {
+       .name           = "armdiv",
+       .parent         = &clk_msysclk.clk,
+       .ops            = &(struct clk_ops) {
+               .round_rate = s3c2443_armclk_roundrate,
+               .get_rate = s3c2443_armclk_getrate,
+               .set_rate = s3c2443_armclk_setrate,
+       },
+};
+
+/* armclk
+ *
+ * this is the clock fed into the ARM core itself, from armdiv or from hclk.
+ */
+
+static struct clk *clk_arm_sources[] = {
+       [0] = &clk_armdiv,
+       [1] = &clk_h,
+};
+
+static struct clksrc_clk clk_arm = {
+       .clk    = {
+               .name           = "armclk",
+       },
+       .sources = &(struct clksrc_sources) {
+               .sources = clk_arm_sources,
+               .nr_sources = ARRAY_SIZE(clk_arm_sources),
+       },
+       .reg_src = { .reg = S3C2443_CLKDIV0, .size = 1, .shift = 13 },
+};
+
 /* usbhost
  *
  * usb host bus-clock, usually 48MHz to provide USB bus clock timing
@@ -205,9 +323,64 @@ static struct clksrc_clk clksrc_clks[] = {
        },
 };
 
+static struct clk clk_i2s_ext = {
+       .name           = "i2s-ext",
+};
+
+/* i2s_eplldiv
+ *
+ * This clock is the output from the I2S divisor of ESYSCLK, and is separate
+ * from the mux that comes after it (cannot merge into one single clock)
+*/
+
+static struct clksrc_clk clk_i2s_eplldiv = {
+       .clk    = {
+               .name           = "i2s-eplldiv",
+               .parent         = &clk_esysclk.clk,
+       },
+       .reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 12, },
+};
+
+/* i2s-ref
+ *
+ * i2s bus reference clock, selectable from external, esysclk or epllref
+ *
+ * Note, this used to be two clocks, but was compressed into one.
+*/
+
+static struct clk *clk_i2s_srclist[] = {
+       [0] = &clk_i2s_eplldiv.clk,
+       [1] = &clk_i2s_ext,
+       [2] = &clk_epllref.clk,
+       [3] = &clk_epllref.clk,
+};
+
+static struct clksrc_clk clk_i2s = {
+       .clk    = {
+               .name           = "i2s-if",
+               .ctrlbit        = S3C2443_SCLKCON_I2SCLK,
+               .enable         = s3c2443_clkcon_enable_s,
+
+       },
+       .sources = &(struct clksrc_sources) {
+               .sources = clk_i2s_srclist,
+               .nr_sources = ARRAY_SIZE(clk_i2s_srclist),
+       },
+       .reg_src = { .reg = S3C2443_CLKSRC, .size = 2, .shift = 14 },
+};
 
 static struct clk init_clocks_off[] = {
        {
+               .name           = "iis",
+               .parent         = &clk_p,
+               .enable         = s3c2443_clkcon_enable_p,
+               .ctrlbit        = S3C2443_PCLKCON_IIS,
+       }, {
+               .name           = "hsspi",
+               .parent         = &clk_p,
+               .enable         = s3c2443_clkcon_enable_p,
+               .ctrlbit        = S3C2443_PCLKCON_HSSPI,
+       }, {
                .name           = "adc",
                .parent         = &clk_p,
                .enable         = s3c2443_clkcon_enable_p,
@@ -253,6 +426,7 @@ static struct clk init_clocks[] = {
                .ctrlbit        = S3C2443_HCLKCON_DMA5,
        }, {
                .name           = "hsmmc",
+               .devname        = "s3c-sdhci.1",
                .parent         = &clk_h,
                .enable         = s3c2443_clkcon_enable_h,
                .ctrlbit        = S3C2443_HCLKCON_HSMMC,
@@ -347,8 +521,7 @@ static inline unsigned long s3c2443_get_hdiv(unsigned long clkcon0)
 
 /* EPLLCON compatible enough to get on/off information */
 
-void __init_or_cpufreq s3c2443_common_setup_clocks(pll_fn get_mpll,
-                                                  fdiv_fn get_fdiv)
+void __init_or_cpufreq s3c2443_common_setup_clocks(pll_fn get_mpll)
 {
        unsigned long epllcon = __raw_readl(S3C2443_EPLLCON);
        unsigned long mpllcon = __raw_readl(S3C2443_MPLLCON);
@@ -368,7 +541,7 @@ void __init_or_cpufreq s3c2443_common_setup_clocks(pll_fn get_mpll,
        pll = get_mpll(mpllcon, xtal);
        clk_msysclk.clk.rate = pll;
 
-       fclk = pll / get_fdiv(clkdiv0);
+       fclk = clk_get_rate(&clk_armdiv);
        hclk = s3c2443_prediv_getrate(&clk_prediv);
        hclk /= s3c2443_get_hdiv(clkdiv0);
        pclk = hclk / ((clkdiv0 & S3C2443_CLKDIV0_HALF_PCLK) ? 2 : 1);
@@ -403,20 +576,29 @@ static struct clk *clks[] __initdata = {
        &clk_ext,
        &clk_epll,
        &clk_usb_bus,
+       &clk_armdiv,
 };
 
 static struct clksrc_clk *clksrcs[] __initdata = {
+       &clk_i2s_eplldiv,
+       &clk_i2s,
        &clk_usb_bus_host,
        &clk_epllref,
        &clk_esysclk,
        &clk_msysclk,
+       &clk_arm,
 };
 
 void __init s3c2443_common_init_clocks(int xtal, pll_fn get_mpll,
-                                      fdiv_fn get_fdiv)
+                                      unsigned int *divs, int nr_divs,
+                                      int divmask)
 {
        int ptr;
 
+       armdiv = divs;
+       nr_armdiv = nr_divs;
+       armdivmask = divmask;
+
        /* s3c2443 parents h and p clocks from prediv */
        clk_h.parent = &clk_prediv;
        clk_p.parent = &clk_prediv;
@@ -437,5 +619,5 @@ void __init s3c2443_common_init_clocks(int xtal, pll_fn get_mpll,
        s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
        s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 
-       s3c2443_common_setup_clocks(get_mpll, get_fdiv);
+       s3c2443_common_setup_clocks(get_mpll);
 }
index 9a197e5..9b9968f 100644 (file)
@@ -7,7 +7,7 @@
 
 config PLAT_S5P
        bool
-       depends on (ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS4)
+       depends on (ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS)
        default y
        select ARM_VIC if !ARCH_EXYNOS4
        select ARM_GIC if ARCH_EXYNOS4
@@ -16,9 +16,6 @@ config PLAT_S5P
        select S3C_GPIO_TRACK
        select S5P_GPIO_DRVSTR
        select SAMSUNG_GPIOLIB_4BIT
-       select S3C_GPIO_CFG_S3C64XX
-       select S3C_GPIO_PULL_UPDOWN
-       select S3C_GPIO_CFG_S3C24XX
        select PLAT_SAMSUNG
        select SAMSUNG_CLKSRC
        select SAMSUNG_IRQ_VIC_TIMER
@@ -42,6 +39,12 @@ config S5P_HRT
        help
          Use the High Resolution timer support
 
+config S5P_PM
+       bool
+       help
+         Common code for power management support on S5P and newer SoCs
+         Note: Do not select this for S5P6440 and S5P6450.
+
 comment "System MMU"
 
 config S5P_SYSTEM_MMU
@@ -50,6 +53,12 @@ config S5P_SYSTEM_MMU
        help
          Say Y here if you want to enable System MMU
 
+config S5P_SLEEP
+       bool
+       help
+         Internal config node to apply common S5P sleep management code.
+         Can be selected by S5P and newer SoCs with similar sleep procedure.
+
 config S5P_DEV_FIMC0
        bool
        help
@@ -75,6 +84,11 @@ config S5P_DEV_FIMD0
        help
          Compile in platform device definitions for FIMD controller 0
 
+config S5P_DEV_I2C_HDMIPHY
+       bool
+       help
+         Compile in platform device definitions for I2C HDMIPHY controller
+
 config S5P_DEV_MFC
        bool
        help
@@ -95,6 +109,11 @@ config S5P_DEV_CSIS1
        help
          Compile in platform device definitions for MIPI-CSIS channel 1
 
+config S5P_DEV_TV
+       bool
+       help
+         Compile in platform device definition for TV interface
+
 config S5P_DEV_USB_EHCI
        bool
        help
index 4b53e04..8763440 100644 (file)
@@ -12,7 +12,6 @@ obj-                          :=
 
 # Core files
 
-obj-y                          += dev-pmu.o
 obj-y                          += dev-uart.o
 obj-y                          += cpu.o
 obj-y                          += clock.o
@@ -20,19 +19,10 @@ obj-y                               += irq.o
 obj-$(CONFIG_S5P_EXT_INT)      += irq-eint.o
 obj-$(CONFIG_S5P_GPIO_INT)     += irq-gpioint.o
 obj-$(CONFIG_S5P_SYSTEM_MMU)   += sysmmu.o
-obj-$(CONFIG_PM)               += pm.o
-obj-$(CONFIG_PM)               += irq-pm.o
+obj-$(CONFIG_S5P_PM)           += pm.o irq-pm.o
+obj-$(CONFIG_S5P_SLEEP)                += sleep.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
-obj-$(CONFIG_S5P_DEV_USB_EHCI) += dev-ehci.o
 obj-$(CONFIG_S5P_SETUP_MIPIPHY)        += setup-mipiphy.o
index 7b0a28f..a56959e 100644 (file)
@@ -75,7 +75,7 @@ static struct cpu_table cpu_ids[] __initdata = {
                .map_io         = exynos4_map_io,
                .init_clocks    = exynos4_init_clocks,
                .init_uarts     = exynos4_init_uarts,
-               .init           = exynos4_init,
+               .init           = exynos_init,
                .name           = name_exynos4210,
        }, {
                .idcode         = EXYNOS4212_CPU_ID,
@@ -83,7 +83,7 @@ static struct cpu_table cpu_ids[] __initdata = {
                .map_io         = exynos4_map_io,
                .init_clocks    = exynos4_init_clocks,
                .init_uarts     = exynos4_init_uarts,
-               .init           = exynos4_init,
+               .init           = exynos_init,
                .name           = name_exynos4212,
        }, {
                .idcode         = EXYNOS4412_CPU_ID,
@@ -91,7 +91,7 @@ static struct cpu_table cpu_ids[] __initdata = {
                .map_io         = exynos4_map_io,
                .init_clocks    = exynos4_init_clocks,
                .init_uarts     = exynos4_init_uarts,
-               .init           = exynos4_init,
+               .init           = exynos_init,
                .name           = name_exynos4412,
        },
 };
diff --git a/arch/arm/plat-s5p/dev-csis0.c b/arch/arm/plat-s5p/dev-csis0.c
deleted file mode 100644 (file)
index e3aabef..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2010-2011 Samsung Electronics Co., Ltd.
- *
- * S5P series device definition for MIPI-CSIS channel 0
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <mach/map.h>
-
-static struct resource s5p_mipi_csis0_resource[] = {
-       [0] = {
-               .start = S5P_PA_MIPI_CSIS0,
-               .end   = S5P_PA_MIPI_CSIS0 + SZ_4K - 1,
-               .flags = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start = IRQ_MIPI_CSIS0,
-               .end   = IRQ_MIPI_CSIS0,
-               .flags = IORESOURCE_IRQ,
-       }
-};
-
-struct platform_device s5p_device_mipi_csis0 = {
-       .name             = "s5p-mipi-csis",
-       .id               = 0,
-       .num_resources    = ARRAY_SIZE(s5p_mipi_csis0_resource),
-       .resource         = s5p_mipi_csis0_resource,
-};
diff --git a/arch/arm/plat-s5p/dev-csis1.c b/arch/arm/plat-s5p/dev-csis1.c
deleted file mode 100644 (file)
index 08b91b5..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2010-2011 Samsung Electronics Co., Ltd.
- *
- * S5P series device definition for MIPI-CSIS channel 1
- *
- * 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 <mach/map.h>
-
-static struct resource s5p_mipi_csis1_resource[] = {
-       [0] = {
-               .start = S5P_PA_MIPI_CSIS1,
-               .end   = S5P_PA_MIPI_CSIS1 + SZ_4K - 1,
-               .flags = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start = IRQ_MIPI_CSIS1,
-               .end   = IRQ_MIPI_CSIS1,
-               .flags = IORESOURCE_IRQ,
-       },
-};
-
-struct platform_device s5p_device_mipi_csis1 = {
-       .name             = "s5p-mipi-csis",
-       .id               = 1,
-       .num_resources    = ARRAY_SIZE(s5p_mipi_csis1_resource),
-       .resource         = s5p_mipi_csis1_resource,
-};
diff --git a/arch/arm/plat-s5p/dev-ehci.c b/arch/arm/plat-s5p/dev-ehci.c
deleted file mode 100644 (file)
index 94080ff..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2011 Samsung Electronics Co.Ltd
- * Author: Joonyoung Shim <jy0922.shim@samsung.com>
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- */
-
-#include <linux/platform_device.h>
-#include <mach/irqs.h>
-#include <mach/map.h>
-#include <plat/devs.h>
-#include <plat/ehci.h>
-#include <plat/usb-phy.h>
-
-/* USB EHCI Host Controller registration */
-static struct resource s5p_ehci_resource[] = {
-       [0] = {
-               .start  = S5P_PA_EHCI,
-               .end    = S5P_PA_EHCI + SZ_256 - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = IRQ_USB_HOST,
-               .end    = IRQ_USB_HOST,
-               .flags  = IORESOURCE_IRQ,
-       }
-};
-
-static u64 s5p_device_ehci_dmamask = 0xffffffffUL;
-
-struct platform_device s5p_device_ehci = {
-       .name           = "s5p-ehci",
-       .id             = -1,
-       .num_resources  = ARRAY_SIZE(s5p_ehci_resource),
-       .resource       = s5p_ehci_resource,
-       .dev            = {
-               .dma_mask = &s5p_device_ehci_dmamask,
-               .coherent_dma_mask = 0xffffffffUL
-       }
-};
-
-void __init s5p_ehci_set_platdata(struct s5p_ehci_platdata *pd)
-{
-       struct s5p_ehci_platdata *npd;
-
-       npd = s3c_set_platdata(pd, sizeof(struct s5p_ehci_platdata),
-                       &s5p_device_ehci);
-
-       if (!npd->phy_init)
-               npd->phy_init = s5p_usb_phy_init;
-       if (!npd->phy_exit)
-               npd->phy_exit = s5p_usb_phy_exit;
-}
diff --git a/arch/arm/plat-s5p/dev-fimc0.c b/arch/arm/plat-s5p/dev-fimc0.c
deleted file mode 100644 (file)
index 608770f..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/* linux/arch/arm/plat-s5p/dev-fimc0.c
- *
- * Copyright (c) 2010 Samsung Electronics
- *
- * Base S5P FIMC0 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/dma-mapping.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <mach/map.h>
-
-static struct resource s5p_fimc0_resource[] = {
-       [0] = {
-               .start  = S5P_PA_FIMC0,
-               .end    = S5P_PA_FIMC0 + SZ_4K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = IRQ_FIMC0,
-               .end    = IRQ_FIMC0,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static u64 s5p_fimc0_dma_mask = DMA_BIT_MASK(32);
-
-struct platform_device s5p_device_fimc0 = {
-       .name           = "s5p-fimc",
-       .id             = 0,
-       .num_resources  = ARRAY_SIZE(s5p_fimc0_resource),
-       .resource       = s5p_fimc0_resource,
-       .dev            = {
-               .dma_mask               = &s5p_fimc0_dma_mask,
-               .coherent_dma_mask      = DMA_BIT_MASK(32),
-       },
-};
diff --git a/arch/arm/plat-s5p/dev-fimc1.c b/arch/arm/plat-s5p/dev-fimc1.c
deleted file mode 100644 (file)
index 76e3a97..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/* linux/arch/arm/plat-s5p/dev-fimc1.c
- *
- * Copyright (c) 2010 Samsung Electronics
- *
- * Base S5P FIMC1 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/dma-mapping.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <mach/map.h>
-
-static struct resource s5p_fimc1_resource[] = {
-       [0] = {
-               .start  = S5P_PA_FIMC1,
-               .end    = S5P_PA_FIMC1 + SZ_4K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = IRQ_FIMC1,
-               .end    = IRQ_FIMC1,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static u64 s5p_fimc1_dma_mask = DMA_BIT_MASK(32);
-
-struct platform_device s5p_device_fimc1 = {
-       .name           = "s5p-fimc",
-       .id             = 1,
-       .num_resources  = ARRAY_SIZE(s5p_fimc1_resource),
-       .resource       = s5p_fimc1_resource,
-       .dev            = {
-               .dma_mask               = &s5p_fimc1_dma_mask,
-               .coherent_dma_mask      = DMA_BIT_MASK(32),
-       },
-};
diff --git a/arch/arm/plat-s5p/dev-fimc2.c b/arch/arm/plat-s5p/dev-fimc2.c
deleted file mode 100644 (file)
index 24d2981..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/* linux/arch/arm/plat-s5p/dev-fimc2.c
- *
- * Copyright (c) 2010 Samsung Electronics
- *
- * Base S5P FIMC2 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/dma-mapping.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <mach/map.h>
-
-static struct resource s5p_fimc2_resource[] = {
-       [0] = {
-               .start  = S5P_PA_FIMC2,
-               .end    = S5P_PA_FIMC2 + SZ_4K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = IRQ_FIMC2,
-               .end    = IRQ_FIMC2,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static u64 s5p_fimc2_dma_mask = DMA_BIT_MASK(32);
-
-struct platform_device s5p_device_fimc2 = {
-       .name           = "s5p-fimc",
-       .id             = 2,
-       .num_resources  = ARRAY_SIZE(s5p_fimc2_resource),
-       .resource       = s5p_fimc2_resource,
-       .dev            = {
-               .dma_mask               = &s5p_fimc2_dma_mask,
-               .coherent_dma_mask      = DMA_BIT_MASK(32),
-       },
-};
diff --git a/arch/arm/plat-s5p/dev-fimc3.c b/arch/arm/plat-s5p/dev-fimc3.c
deleted file mode 100644 (file)
index ef31bec..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/* linux/arch/arm/plat-s5p/dev-fimc3.c
- *
- * Copyright (c) 2010 Samsung Electronics
- *
- * Base S5P FIMC3 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/dma-mapping.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <mach/map.h>
-
-static struct resource s5p_fimc3_resource[] = {
-       [0] = {
-               .start  = S5P_PA_FIMC3,
-               .end    = S5P_PA_FIMC3 + SZ_4K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = IRQ_FIMC3,
-               .end    = IRQ_FIMC3,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static u64 s5p_fimc3_dma_mask = DMA_BIT_MASK(32);
-
-struct platform_device s5p_device_fimc3 = {
-       .name           = "s5p-fimc",
-       .id             = 3,
-       .num_resources  = ARRAY_SIZE(s5p_fimc3_resource),
-       .resource       = s5p_fimc3_resource,
-       .dev            = {
-               .dma_mask               = &s5p_fimc3_dma_mask,
-               .coherent_dma_mask      = DMA_BIT_MASK(32),
-       },
-};
diff --git a/arch/arm/plat-s5p/dev-fimd0.c b/arch/arm/plat-s5p/dev-fimd0.c
deleted file mode 100644 (file)
index f728bb5..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/* 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);
-}
index 94226a0..a30d36b 100644 (file)
 #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;
diff --git a/arch/arm/plat-s5p/dev-onenand.c b/arch/arm/plat-s5p/dev-onenand.c
deleted file mode 100644 (file)
index 20336c8..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/* linux/arch/arm/plat-s5p/dev-onenand.c
- *
- * Copyright 2010 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com
- *
- *  Copyright (c) 2008-2010 Samsung Electronics
- *  Kyungmin Park <kyungmin.park@samsung.com>
- *
- * S5P series device definition for OneNAND devices
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-static struct resource s5p_onenand_resources[] = {
-       [0] = {
-               .start  = S5P_PA_ONENAND,
-               .end    = S5P_PA_ONENAND + SZ_128K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = S5P_PA_ONENAND_DMA,
-               .end    = S5P_PA_ONENAND_DMA + SZ_8K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [2] = {
-               .start  = IRQ_ONENAND_AUDI,
-               .end    = IRQ_ONENAND_AUDI,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-struct platform_device s5p_device_onenand = {
-       .name           = "s5pc110-onenand",
-       .id             = -1,
-       .num_resources  = ARRAY_SIZE(s5p_onenand_resources),
-       .resource       = s5p_onenand_resources,
-};
diff --git a/arch/arm/plat-s5p/dev-pmu.c b/arch/arm/plat-s5p/dev-pmu.c
deleted file mode 100644 (file)
index a08576d..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * linux/arch/arm/plat-s5p/dev-pmu.c
- *
- * Copyright (C) 2010 Samsung Electronics Co.Ltd
- * Author: Joonyoung Shim <jy0922.shim@samsung.com>
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- */
-
-#include <linux/platform_device.h>
-#include <asm/pmu.h>
-#include <mach/irqs.h>
-
-static struct resource s5p_pmu_resource = {
-       .start  = IRQ_PMU,
-       .end    = IRQ_PMU,
-       .flags  = IORESOURCE_IRQ,
-};
-
-struct platform_device s5p_device_pmu = {
-       .name           = "arm-pmu",
-       .id             = ARM_PMU_DEVICE_CPU,
-       .num_resources  = 1,
-       .resource       = &s5p_pmu_resource,
-};
-
-static int __init s5p_pmu_init(void)
-{
-       platform_device_register(&s5p_device_pmu);
-       return 0;
-}
-arch_initcall(s5p_pmu_init);
index c65eb79..1fdfaa4 100644 (file)
@@ -37,7 +37,7 @@ struct s5p_gpioint_bank {
        int                     start;
        int                     nr_groups;
        int                     irq;
-       struct s3c_gpio_chip    **chips;
+       struct samsung_gpio_chip        **chips;
        void                    (*handler)(unsigned int, struct irq_desc *);
 };
 
@@ -87,7 +87,7 @@ static void s5p_gpioint_handler(unsigned int irq, struct irq_desc *desc)
        chained_irq_enter(chip, desc);
 
        for (group = 0; group < bank->nr_groups; group++) {
-               struct s3c_gpio_chip *chip = bank->chips[group];
+               struct samsung_gpio_chip *chip = bank->chips[group];
                if (!chip)
                        continue;
 
@@ -110,7 +110,7 @@ static void s5p_gpioint_handler(unsigned int irq, struct irq_desc *desc)
        chained_irq_exit(chip, desc);
 }
 
-static __init int s5p_gpioint_add(struct s3c_gpio_chip *chip)
+static __init int s5p_gpioint_add(struct samsung_gpio_chip *chip)
 {
        static int used_gpioint_groups = 0;
        int group = chip->group;
@@ -131,7 +131,7 @@ static __init int s5p_gpioint_add(struct s3c_gpio_chip *chip)
                return -EINVAL;
 
        if (!bank->handler) {
-               bank->chips = kzalloc(sizeof(struct s3c_gpio_chip *) *
+               bank->chips = kzalloc(sizeof(struct samsung_gpio_chip *) *
                                      bank->nr_groups, GFP_KERNEL);
                if (!bank->chips)
                        return -ENOMEM;
@@ -174,7 +174,7 @@ static __init int s5p_gpioint_add(struct s3c_gpio_chip *chip)
 
 int __init s5p_register_gpio_interrupt(int pin)
 {
-       struct s3c_gpio_chip *my_chip = s3c_gpiolib_getchip(pin);
+       struct samsung_gpio_chip *my_chip = samsung_gpiolib_getchip(pin);
        int offset, group;
        int ret;
 
similarity index 81%
rename from arch/arm/mach-exynos4/sleep.S
rename to arch/arm/plat-s5p/sleep.S
index 0984078..0fd591b 100644 (file)
@@ -1,15 +1,11 @@
-/* linux/arch/arm/mach-exynos4/sleep.S
+/* linux/arch/arm/plat-s5p/sleep.S
  *
  * Copyright (c) 2011 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com
  *
- * EXYNOS4210 power Manager (Suspend-To-RAM) support
- * Based on S3C2410 sleep code by:
- *     Ben Dooks, (c) 2004 Simtec Electronics
- *
- * Based on PXA/SA1100 sleep code by:
- *     Nicolas Pitre, (c) 2002 Monta Vista Software Inc
- *     Cliff Brake, (c) 2001
+ * Common S5P Sleep Code
+ * Based on S3C64XX sleep code by:
+ *     Ben Dooks, (c) 2008 Simtec Electronics
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -28,7 +24,6 @@
 
 #include <linux/linkage.h>
 #include <asm/assembler.h>
-#include <asm/memory.h>
 
        .text
 
index 3895f9a..313eb26 100644 (file)
@@ -74,39 +74,12 @@ config SAMSUNG_GPIOLIB_4BIT
          configuration. GPIOlib shall be compiled only for S3C64XX and S5P
          series of processors.
 
-config S3C_GPIO_CFG_S3C24XX
-       bool
-       help
-         Internal configuration to enable S3C24XX style GPIO configuration
-         functions.
-
 config S3C_GPIO_CFG_S3C64XX
        bool
        help
          Internal configuration to enable S3C64XX style GPIO configuration
          functions.
 
-config S3C_GPIO_PULL_UPDOWN
-       bool
-       help
-         Internal configuration to enable the correct GPIO pull helper
-
-config S3C_GPIO_PULL_S3C2443
-       bool
-       select S3C_GPIO_PULL_UPDOWN
-       help
-         Internal configuration to enable the correct GPIO pull helper for S3C2443-style GPIO
-
-config S3C_GPIO_PULL_DOWN
-       bool
-       help
-         Internal configuration to enable the correct GPIO pull helper
-
-config S3C_GPIO_PULL_UP
-       bool
-       help
-         Internal configuration to enable the correct GPIO pull helper
-
 config S5P_GPIO_DRVSTR
        bool
        help
@@ -295,11 +268,14 @@ config S3C_DMA
        help
          Internal configuration for S3C DMA core
 
-config S3C_PL330_DMA
+config SAMSUNG_DMADEV
        bool
-       select PL330
+       select DMADEVICES
+       select PL330_DMA if (CPU_EXYNOS4210 || CPU_S5PV210 || CPU_S5PC100 || \
+                                       CPU_S5P6450 || CPU_S5P6440)
+       select ARM_AMBA
        help
-         S3C DMA API Driver for PL330 DMAC.
+         Use DMA device engine for PL330 DMAC.
 
 comment "Power management"
 
index 09adb84..6012366 100644 (file)
@@ -1,4 +1,4 @@
-# arch/arm/plat-s3c64xx/Makefile
+# arch/arm/plat-samsung/Makefile
 #
 # Copyright 2009 Simtec Electronics
 #
@@ -15,9 +15,6 @@ obj-y                         += init.o cpu.o
 obj-$(CONFIG_ARCH_USES_GETTIMEOFFSET)   += time.o
 obj-y                          += clock.o
 obj-y                          += pwm-clock.o
-obj-y                          += gpio.o
-obj-y                          += gpio-config.o
-obj-y                          += dev-asocdma.o
 
 obj-$(CONFIG_SAMSUNG_CLKSRC)   += clock-clksrc.o
 
@@ -31,40 +28,16 @@ obj-$(CONFIG_S3C_ADC)       += adc.o
 
 obj-y                          += platformdata.o
 
-obj-$(CONFIG_S3C_DEV_HSMMC)    += dev-hsmmc.o
-obj-$(CONFIG_S3C_DEV_HSMMC1)   += dev-hsmmc1.o
-obj-$(CONFIG_S3C_DEV_HSMMC2)   += dev-hsmmc2.o
-obj-$(CONFIG_S3C_DEV_HSMMC3)   += dev-hsmmc3.o
-obj-$(CONFIG_S3C_DEV_HWMON)    += dev-hwmon.o
-obj-y                          += dev-i2c0.o
-obj-$(CONFIG_S3C_DEV_I2C1)     += dev-i2c1.o
-obj-$(CONFIG_S3C_DEV_I2C2)     += dev-i2c2.o
-obj-$(CONFIG_S3C_DEV_I2C3)     += dev-i2c3.o
-obj-$(CONFIG_S3C_DEV_I2C4)     += dev-i2c4.o
-obj-$(CONFIG_S3C_DEV_I2C5)     += dev-i2c5.o
-obj-$(CONFIG_S3C_DEV_I2C6)     += dev-i2c6.o
-obj-$(CONFIG_S3C_DEV_I2C7)     += dev-i2c7.o
-obj-$(CONFIG_S3C_DEV_FB)       += dev-fb.o
+obj-y                          += devs.o
 obj-y                          += dev-uart.o
-obj-$(CONFIG_S3C_DEV_USB_HOST) += dev-usb.o
-obj-$(CONFIG_S3C_DEV_USB_HSOTG)        += dev-usb-hsotg.o
-obj-$(CONFIG_S3C_DEV_WDT)      += dev-wdt.o
-obj-$(CONFIG_S3C_DEV_NAND)     += dev-nand.o
-obj-$(CONFIG_S3C_DEV_ONENAND)  += dev-onenand.o
-obj-$(CONFIG_S3C_DEV_RTC)      += dev-rtc.o
-
-obj-$(CONFIG_SAMSUNG_DEV_ADC)  += dev-adc.o
-obj-$(CONFIG_SAMSUNG_DEV_IDE)  += dev-ide.o
-obj-$(CONFIG_SAMSUNG_DEV_TS)   += dev-ts.o
-obj-$(CONFIG_SAMSUNG_DEV_KEYPAD)       += dev-keypad.o
-obj-$(CONFIG_SAMSUNG_DEV_PWM)  += dev-pwm.o
+
 obj-$(CONFIG_SAMSUNG_DEV_BACKLIGHT)    += dev-backlight.o
 
 # DMA support
 
-obj-$(CONFIG_S3C_DMA)          += dma.o
+obj-$(CONFIG_S3C_DMA)          += dma.o s3c-dma-ops.o
 
-obj-$(CONFIG_S3C_PL330_DMA)    += s3c-pl330.o
+obj-$(CONFIG_SAMSUNG_DMADEV)   += dma-ops.o
 
 # PM support
 
index ee8deef..33ecd0c 100644 (file)
@@ -41,6 +41,8 @@
 
 enum s3c_cpu_type {
        TYPE_ADCV1, /* S3C24XX */
+       TYPE_ADCV11, /* S3C2443 */
+       TYPE_ADCV12, /* S3C2416, S3C2450 */
        TYPE_ADCV2, /* S3C64XX, S5P64X0, S5PC100 */
        TYPE_ADCV3, /* S5PV210, S5PC110, EXYNOS4210 */
 };
@@ -98,13 +100,17 @@ static inline void s3c_adc_select(struct adc_device *adc,
 
        client->select_cb(client, 1);
 
-       con &= ~S3C2410_ADCCON_MUXMASK;
+       if (cpu == TYPE_ADCV1 || cpu == TYPE_ADCV2)
+               con &= ~S3C2410_ADCCON_MUXMASK;
        con &= ~S3C2410_ADCCON_STDBM;
        con &= ~S3C2410_ADCCON_STARTMASK;
 
        if (!client->is_ts) {
                if (cpu == TYPE_ADCV3)
                        writel(client->channel & 0xf, adc->regs + S5P_ADCMUX);
+               else if (cpu == TYPE_ADCV11 || cpu == TYPE_ADCV12)
+                       writel(client->channel & 0xf,
+                                               adc->regs + S3C2443_ADCMUX);
                else
                        con |= S3C2410_ADCCON_SELMUX(client->channel);
        }
@@ -293,13 +299,13 @@ static irqreturn_t s3c_adc_irq(int irq, void *pw)
 
        client->nr_samples--;
 
-       if (cpu != TYPE_ADCV1) {
-               /* S3C64XX/S5P ADC resolution is 12-bit */
-               data0 &= 0xfff;
-               data1 &= 0xfff;
-       } else {
+       if (cpu == TYPE_ADCV1 || cpu == TYPE_ADCV11) {
                data0 &= 0x3ff;
                data1 &= 0x3ff;
+       } else {
+               /* S3C2416/S3C64XX/S5P ADC resolution is 12-bit */
+               data0 &= 0xfff;
+               data1 &= 0xfff;
        }
 
        if (client->convert_cb)
@@ -320,7 +326,7 @@ static irqreturn_t s3c_adc_irq(int irq, void *pw)
        }
 
 exit:
-       if (cpu != TYPE_ADCV1) {
+       if (cpu == TYPE_ADCV2 || cpu == TYPE_ADCV3) {
                /* Clear ADC interrupt */
                writel(0, adc->regs + S3C64XX_ADCCLRINT);
        }
@@ -332,6 +338,7 @@ static int s3c_adc_probe(struct platform_device *pdev)
        struct device *dev = &pdev->dev;
        struct adc_device *adc;
        struct resource *regs;
+       enum s3c_cpu_type cpu = platform_get_device_id(pdev)->driver_data;
        int ret;
        unsigned tmp;
 
@@ -394,10 +401,13 @@ static int s3c_adc_probe(struct platform_device *pdev)
        clk_enable(adc->clk);
 
        tmp = adc->prescale | S3C2410_ADCCON_PRSCEN;
-       if (platform_get_device_id(pdev)->driver_data != TYPE_ADCV1) {
-               /* Enable 12-bit ADC resolution */
+
+       /* Enable 12-bit ADC resolution */
+       if (cpu == TYPE_ADCV12)
+               tmp |= S3C2416_ADCCON_RESSEL;
+       if (cpu == TYPE_ADCV2 || cpu == TYPE_ADCV3)
                tmp |= S3C64XX_ADCCON_RESSEL;
-       }
+
        writel(tmp, adc->regs + S3C2410_ADCCON);
 
        dev_info(dev, "attached adc driver\n");
@@ -464,6 +474,7 @@ 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);
+       enum s3c_cpu_type cpu = platform_get_device_id(pdev)->driver_data;
        int ret;
        unsigned long tmp;
 
@@ -474,9 +485,13 @@ static int s3c_adc_resume(struct device *dev)
        enable_irq(adc->irq);
 
        tmp = adc->prescale | S3C2410_ADCCON_PRSCEN;
+
        /* Enable 12-bit ADC resolution */
-       if (platform_get_device_id(pdev)->driver_data != TYPE_ADCV1)
+       if (cpu == TYPE_ADCV12)
+               tmp |= S3C2416_ADCCON_RESSEL;
+       if (cpu == TYPE_ADCV2 || cpu == TYPE_ADCV3)
                tmp |= S3C64XX_ADCCON_RESSEL;
+
        writel(tmp, adc->regs + S3C2410_ADCCON);
 
        return 0;
@@ -492,6 +507,12 @@ static struct platform_device_id s3c_adc_driver_ids[] = {
                .name           = "s3c24xx-adc",
                .driver_data    = TYPE_ADCV1,
        }, {
+               .name           = "s3c2443-adc",
+               .driver_data    = TYPE_ADCV11,
+       }, {
+               .name           = "s3c2416-adc",
+               .driver_data    = TYPE_ADCV12,
+       }, {
                .name           = "s3c64xx-adc",
                .driver_data    = TYPE_ADCV2,
        }, {
diff --git a/arch/arm/plat-samsung/dev-adc.c b/arch/arm/plat-samsung/dev-adc.c
deleted file mode 100644 (file)
index 9d903d4..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/* linux/arch/arm/plat-samsung/dev-adc.c
- *
- * Copyright 2010 Maurus Cuelenaere
- *
- * S3C64xx series device definition for ADC device
- *
- * 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 <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/adc.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-
-static struct resource s3c_adc_resource[] = {
-       [0] = {
-               .start = SAMSUNG_PA_ADC,
-               .end   = SAMSUNG_PA_ADC + SZ_256 - 1,
-               .flags = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start = IRQ_TC,
-               .end   = IRQ_TC,
-               .flags = IORESOURCE_IRQ,
-       },
-       [2] = {
-               .start = IRQ_ADC,
-               .end   = IRQ_ADC,
-               .flags = IORESOURCE_IRQ,
-       },
-};
-
-struct platform_device s3c_device_adc = {
-       .name           = "samsung-adc",
-       .id             = -1,
-       .num_resources  = ARRAY_SIZE(s3c_adc_resource),
-       .resource       = s3c_adc_resource,
-};
diff --git a/arch/arm/plat-samsung/dev-asocdma.c b/arch/arm/plat-samsung/dev-asocdma.c
deleted file mode 100644 (file)
index 97e35d3..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/* linux/arch/arm/plat-samsung/dev-asocdma.c
- *
- * Copyright (c) 2010 Samsung Electronics Co. Ltd
- *     Jaswinder Singh <jassi.brar@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-#include <plat/devs.h>
-
-static u64 audio_dmamask = DMA_BIT_MASK(32);
-
-struct platform_device samsung_asoc_dma = {
-       .name             = "samsung-audio",
-       .id               = -1,
-       .dev              = {
-               .dma_mask = &audio_dmamask,
-               .coherent_dma_mask = DMA_BIT_MASK(32),
-       }
-};
-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 3cedd4c..2adbeae 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/pwm_backlight.h>
+#include <linux/slab.h>
 
 #include <plat/devs.h>
 #include <plat/gpio-cfg.h>
diff --git a/arch/arm/plat-samsung/dev-fb.c b/arch/arm/plat-samsung/dev-fb.c
deleted file mode 100644 (file)
index 49a1362..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/* linux/arch/arm/plat-s3c/dev-fb.c
- *
- * Copyright 2008 Simtec Electronics
- *     Ben Dooks <ben@simtec.co.uk>
- *     http://armlinux.simtec.co.uk/
- *
- * S3C series device definition for framebuffer device
- *
- * 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 <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/fb.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-
-static struct resource s3c_fb_resource[] = {
-       [0] = {
-               .start = S3C_PA_FB,
-               .end   = S3C_PA_FB + SZ_16K - 1,
-               .flags = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start = IRQ_LCD_VSYNC,
-               .end   = IRQ_LCD_VSYNC,
-               .flags = IORESOURCE_IRQ,
-       },
-       [2] = {
-               .start = IRQ_LCD_FIFO,
-               .end   = IRQ_LCD_FIFO,
-               .flags = IORESOURCE_IRQ,
-       },
-       [3] = {
-               .start = IRQ_LCD_SYSTEM,
-               .end   = IRQ_LCD_SYSTEM,
-               .flags = IORESOURCE_IRQ,
-       },
-};
-
-struct platform_device s3c_device_fb = {
-       .name             = "s3c-fb",
-       .id               = -1,
-       .num_resources    = ARRAY_SIZE(s3c_fb_resource),
-       .resource         = s3c_fb_resource,
-       .dev.dma_mask     = &s3c_device_fb.dev.coherent_dma_mask,
-       .dev.coherent_dma_mask = 0xffffffffUL,
-};
-
-void __init s3c_fb_set_platdata(struct s3c_fb_platdata *pd)
-{
-       s3c_set_platdata(pd, sizeof(struct s3c_fb_platdata),
-                        &s3c_device_fb);
-}
diff --git a/arch/arm/plat-samsung/dev-hsmmc.c b/arch/arm/plat-samsung/dev-hsmmc.c
deleted file mode 100644 (file)
index 06825c4..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/* linux/arch/arm/plat-s3c/dev-hsmmc.c
- *
- * Copyright (c) 2008 Simtec Electronics
- *     Ben Dooks <ben@simtec.co.uk>
- *     http://armlinux.simtec.co.uk/
- *
- * S3C series device definition for hsmmc devices
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/mmc/host.h>
-
-#include <mach/map.h>
-#include <plat/sdhci.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-
-#define S3C_SZ_HSMMC   (0x1000)
-
-static struct resource s3c_hsmmc_resource[] = {
-       [0] = {
-               .start = S3C_PA_HSMMC0,
-               .end   = S3C_PA_HSMMC0 + S3C_SZ_HSMMC - 1,
-               .flags = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start = IRQ_HSMMC0,
-               .end   = IRQ_HSMMC0,
-               .flags = IORESOURCE_IRQ,
-       }
-};
-
-static u64 s3c_device_hsmmc_dmamask = 0xffffffffUL;
-
-struct s3c_sdhci_platdata s3c_hsmmc0_def_platdata = {
-       .max_width      = 4,
-       .host_caps      = (MMC_CAP_4_BIT_DATA |
-                          MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED),
-       .clk_type       = S3C_SDHCI_CLK_DIV_INTERNAL,
-};
-
-struct platform_device s3c_device_hsmmc0 = {
-       .name           = "s3c-sdhci",
-       .id             = 0,
-       .num_resources  = ARRAY_SIZE(s3c_hsmmc_resource),
-       .resource       = s3c_hsmmc_resource,
-       .dev            = {
-               .dma_mask               = &s3c_device_hsmmc_dmamask,
-               .coherent_dma_mask      = 0xffffffffUL,
-               .platform_data          = &s3c_hsmmc0_def_platdata,
-       },
-};
-
-void s3c_sdhci0_set_platdata(struct s3c_sdhci_platdata *pd)
-{
-       s3c_sdhci_set_platdata(pd, &s3c_hsmmc0_def_platdata);
-}
diff --git a/arch/arm/plat-samsung/dev-hsmmc1.c b/arch/arm/plat-samsung/dev-hsmmc1.c
deleted file mode 100644 (file)
index 4524ef4..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/* linux/arch/arm/plat-s3c/dev-hsmmc1.c
- *
- * Copyright (c) 2008 Simtec Electronics
- *     Ben Dooks <ben@simtec.co.uk>
- *     http://armlinux.simtec.co.uk/
- *
- * S3C series device definition for hsmmc device 1
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/mmc/host.h>
-
-#include <mach/map.h>
-#include <plat/sdhci.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-
-#define S3C_SZ_HSMMC   (0x1000)
-
-static struct resource s3c_hsmmc1_resource[] = {
-       [0] = {
-               .start = S3C_PA_HSMMC1,
-               .end   = S3C_PA_HSMMC1 + S3C_SZ_HSMMC - 1,
-               .flags = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start = IRQ_HSMMC1,
-               .end   = IRQ_HSMMC1,
-               .flags = IORESOURCE_IRQ,
-       }
-};
-
-static u64 s3c_device_hsmmc1_dmamask = 0xffffffffUL;
-
-struct s3c_sdhci_platdata s3c_hsmmc1_def_platdata = {
-       .max_width      = 4,
-       .host_caps      = (MMC_CAP_4_BIT_DATA |
-                          MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED),
-       .clk_type       = S3C_SDHCI_CLK_DIV_INTERNAL,
-};
-
-struct platform_device s3c_device_hsmmc1 = {
-       .name           = "s3c-sdhci",
-       .id             = 1,
-       .num_resources  = ARRAY_SIZE(s3c_hsmmc1_resource),
-       .resource       = s3c_hsmmc1_resource,
-       .dev            = {
-               .dma_mask               = &s3c_device_hsmmc1_dmamask,
-               .coherent_dma_mask      = 0xffffffffUL,
-               .platform_data          = &s3c_hsmmc1_def_platdata,
-       },
-};
-
-void s3c_sdhci1_set_platdata(struct s3c_sdhci_platdata *pd)
-{
-       s3c_sdhci_set_platdata(pd, &s3c_hsmmc1_def_platdata);
-}
diff --git a/arch/arm/plat-samsung/dev-hsmmc2.c b/arch/arm/plat-samsung/dev-hsmmc2.c
deleted file mode 100644 (file)
index 9cede96..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/* linux/arch/arm/plat-s3c/dev-hsmmc2.c
- *
- * Copyright (c) 2009 Samsung Electronics
- * Copyright (c) 2009 Maurus Cuelenaere
- *
- * Based on arch/arm/plat-s3c/dev-hsmmc1.c
- * original file Copyright (c) 2008 Simtec Electronics
- *
- * S3C series device definition for hsmmc device 2
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/mmc/host.h>
-
-#include <mach/map.h>
-#include <plat/sdhci.h>
-#include <plat/devs.h>
-
-#define S3C_SZ_HSMMC   (0x1000)
-
-static struct resource s3c_hsmmc2_resource[] = {
-       [0] = {
-               .start = S3C_PA_HSMMC2,
-               .end   = S3C_PA_HSMMC2 + S3C_SZ_HSMMC - 1,
-               .flags = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start = IRQ_HSMMC2,
-               .end   = IRQ_HSMMC2,
-               .flags = IORESOURCE_IRQ,
-       }
-};
-
-static u64 s3c_device_hsmmc2_dmamask = 0xffffffffUL;
-
-struct s3c_sdhci_platdata s3c_hsmmc2_def_platdata = {
-       .max_width      = 4,
-       .host_caps      = (MMC_CAP_4_BIT_DATA |
-                          MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED),
-       .clk_type       = S3C_SDHCI_CLK_DIV_INTERNAL,
-};
-
-struct platform_device s3c_device_hsmmc2 = {
-       .name           = "s3c-sdhci",
-       .id             = 2,
-       .num_resources  = ARRAY_SIZE(s3c_hsmmc2_resource),
-       .resource       = s3c_hsmmc2_resource,
-       .dev            = {
-               .dma_mask               = &s3c_device_hsmmc2_dmamask,
-               .coherent_dma_mask      = 0xffffffffUL,
-               .platform_data          = &s3c_hsmmc2_def_platdata,
-       },
-};
-
-void s3c_sdhci2_set_platdata(struct s3c_sdhci_platdata *pd)
-{
-       s3c_sdhci_set_platdata(pd, &s3c_hsmmc2_def_platdata);
-}
diff --git a/arch/arm/plat-samsung/dev-hsmmc3.c b/arch/arm/plat-samsung/dev-hsmmc3.c
deleted file mode 100644 (file)
index 0358ef4..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/* linux/arch/arm/plat-samsung/dev-hsmmc3.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com
- *
- * Copyright (c) 2008 Simtec Electronics
- *     Ben Dooks <ben@simtec.co.uk>
- *     http://armlinux.simtec.co.uk/
- *
- * Based on arch/arm/plat-samsung/dev-hsmmc1.c
- *
- * Samsung device definition for hsmmc device 3
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/mmc/host.h>
-
-#include <mach/map.h>
-#include <plat/sdhci.h>
-#include <plat/devs.h>
-
-#define S3C_SZ_HSMMC   (0x1000)
-
-static struct resource s3c_hsmmc3_resource[] = {
-       [0] = {
-               .start  = S3C_PA_HSMMC3,
-               .end    = S3C_PA_HSMMC3 + S3C_SZ_HSMMC - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = IRQ_HSMMC3,
-               .end    = IRQ_HSMMC3,
-               .flags  = IORESOURCE_IRQ,
-       }
-};
-
-static u64 s3c_device_hsmmc3_dmamask = 0xffffffffUL;
-
-struct s3c_sdhci_platdata s3c_hsmmc3_def_platdata = {
-       .max_width      = 4,
-       .host_caps      = (MMC_CAP_4_BIT_DATA |
-                          MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED),
-       .clk_type       = S3C_SDHCI_CLK_DIV_INTERNAL,
-};
-
-struct platform_device s3c_device_hsmmc3 = {
-       .name           = "s3c-sdhci",
-       .id             = 3,
-       .num_resources  = ARRAY_SIZE(s3c_hsmmc3_resource),
-       .resource       = s3c_hsmmc3_resource,
-       .dev            = {
-               .dma_mask               = &s3c_device_hsmmc3_dmamask,
-               .coherent_dma_mask      = 0xffffffffUL,
-               .platform_data          = &s3c_hsmmc3_def_platdata,
-       },
-};
-
-void s3c_sdhci3_set_platdata(struct s3c_sdhci_platdata *pd)
-{
-       s3c_sdhci_set_platdata(pd, &s3c_hsmmc3_def_platdata);
-}
diff --git a/arch/arm/plat-samsung/dev-hwmon.c b/arch/arm/plat-samsung/dev-hwmon.c
deleted file mode 100644 (file)
index c91a79c..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/* linux/arch/arm/plat-samsung/dev-hwmon.c
- *
- * Copyright 2008 Simtec Electronics
- *     Ben Dooks <ben@simtec.co.uk>
- *     http://armlinux.simtec.co.uk/
- *
- * Adapted for HWMON by Maurus Cuelenaere
- *
- * Samsung series device definition for HWMON
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-
-#include <plat/devs.h>
-#include <plat/hwmon.h>
-
-struct platform_device s3c_device_hwmon = {
-       .name           = "s3c-hwmon",
-       .id             = -1,
-       .dev.parent     = &s3c_device_adc.dev,
-};
-
-void __init s3c_hwmon_set_platdata(struct s3c_hwmon_pdata *pd)
-{
-       s3c_set_platdata(pd, sizeof(struct s3c_hwmon_pdata),
-                        &s3c_device_hwmon);
-}
diff --git a/arch/arm/plat-samsung/dev-i2c0.c b/arch/arm/plat-samsung/dev-i2c0.c
deleted file mode 100644 (file)
index f8251f5..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/* linux/arch/arm/plat-s3c/dev-i2c0.c
- *
- * Copyright 2008-2009 Simtec Electronics
- *     Ben Dooks <ben@simtec.co.uk>
- *     http://armlinux.simtec.co.uk/
- *
- * S3C series device definition for i2c device 0
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/gfp.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/platform_device.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/regs-iic.h>
-#include <plat/iic.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-
-static struct resource s3c_i2c_resource[] = {
-       [0] = {
-               .start = S3C_PA_IIC,
-               .end   = S3C_PA_IIC + SZ_4K - 1,
-               .flags = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start = IRQ_IIC,
-               .end   = IRQ_IIC,
-               .flags = IORESOURCE_IRQ,
-       },
-};
-
-struct platform_device s3c_device_i2c0 = {
-       .name             = "s3c2410-i2c",
-#ifdef CONFIG_S3C_DEV_I2C1
-       .id               = 0,
-#else
-       .id               = -1,
-#endif
-       .num_resources    = ARRAY_SIZE(s3c_i2c_resource),
-       .resource         = s3c_i2c_resource,
-};
-
-struct s3c2410_platform_i2c default_i2c_data __initdata = {
-       .flags          = 0,
-       .slave_addr     = 0x10,
-       .frequency      = 100*1000,
-       .sda_delay      = 100,
-};
-
-void __init s3c_i2c0_set_platdata(struct s3c2410_platform_i2c *pd)
-{
-       struct s3c2410_platform_i2c *npd;
-
-       if (!pd)
-               pd = &default_i2c_data;
-
-       npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
-                              &s3c_device_i2c0);
-
-       if (!npd->cfg_gpio)
-               npd->cfg_gpio = s3c_i2c0_cfg_gpio;
-}
diff --git a/arch/arm/plat-samsung/dev-i2c1.c b/arch/arm/plat-samsung/dev-i2c1.c
deleted file mode 100644 (file)
index 3b7c7be..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/* linux/arch/arm/plat-s3c/dev-i2c1.c
- *
- * Copyright 2008-2009 Simtec Electronics
- *     Ben Dooks <ben@simtec.co.uk>
- *     http://armlinux.simtec.co.uk/
- *
- * S3C series device definition for i2c device 1
- *
- * 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/gfp.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/platform_device.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/regs-iic.h>
-#include <plat/iic.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-
-static struct resource s3c_i2c_resource[] = {
-       [0] = {
-               .start = S3C_PA_IIC1,
-               .end   = S3C_PA_IIC1 + SZ_4K - 1,
-               .flags = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start = IRQ_IIC1,
-               .end   = IRQ_IIC1,
-               .flags = IORESOURCE_IRQ,
-       },
-};
-
-struct platform_device s3c_device_i2c1 = {
-       .name             = "s3c2410-i2c",
-       .id               = 1,
-       .num_resources    = ARRAY_SIZE(s3c_i2c_resource),
-       .resource         = s3c_i2c_resource,
-};
-
-void __init s3c_i2c1_set_platdata(struct s3c2410_platform_i2c *pd)
-{
-       struct s3c2410_platform_i2c *npd;
-
-       if (!pd) {
-               pd = &default_i2c_data;
-               pd->bus_num = 1;
-       }
-
-       npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
-                              &s3c_device_i2c1);
-
-       if (!npd->cfg_gpio)
-               npd->cfg_gpio = s3c_i2c1_cfg_gpio;
-}
diff --git a/arch/arm/plat-samsung/dev-i2c2.c b/arch/arm/plat-samsung/dev-i2c2.c
deleted file mode 100644 (file)
index 07e9fd0..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/* linux/arch/arm/plat-s3c/dev-i2c2.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * S3C series device definition for i2c device 2
- *
- * Based on plat-samsung/dev-i2c0.c
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/gfp.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/platform_device.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/regs-iic.h>
-#include <plat/iic.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-
-static struct resource s3c_i2c_resource[] = {
-       [0] = {
-               .start = S3C_PA_IIC2,
-               .end   = S3C_PA_IIC2 + SZ_4K - 1,
-               .flags = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start = IRQ_IIC2,
-               .end   = IRQ_IIC2,
-               .flags = IORESOURCE_IRQ,
-       },
-};
-
-struct platform_device s3c_device_i2c2 = {
-       .name             = "s3c2410-i2c",
-       .id               = 2,
-       .num_resources    = ARRAY_SIZE(s3c_i2c_resource),
-       .resource         = s3c_i2c_resource,
-};
-
-void __init s3c_i2c2_set_platdata(struct s3c2410_platform_i2c *pd)
-{
-       struct s3c2410_platform_i2c *npd;
-
-       if (!pd) {
-               pd = &default_i2c_data;
-               pd->bus_num = 2;
-       }
-
-       npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
-                              &s3c_device_i2c2);
-
-       if (!npd->cfg_gpio)
-               npd->cfg_gpio = s3c_i2c2_cfg_gpio;
-}
diff --git a/arch/arm/plat-samsung/dev-i2c3.c b/arch/arm/plat-samsung/dev-i2c3.c
deleted file mode 100644 (file)
index d48efa9..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/* linux/arch/arm/plat-samsung/dev-i2c3.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * S5P series device definition for i2c device 3
- *
- * 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/gfp.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/platform_device.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/regs-iic.h>
-#include <plat/iic.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-
-static struct resource s3c_i2c_resource[] = {
-       [0] = {
-               .start  = S3C_PA_IIC3,
-               .end    = S3C_PA_IIC3 + SZ_4K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = IRQ_IIC3,
-               .end    = IRQ_IIC3,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-struct platform_device s3c_device_i2c3 = {
-       .name           = "s3c2440-i2c",
-       .id             = 3,
-       .num_resources  = ARRAY_SIZE(s3c_i2c_resource),
-       .resource       = s3c_i2c_resource,
-};
-
-void __init s3c_i2c3_set_platdata(struct s3c2410_platform_i2c *pd)
-{
-       struct s3c2410_platform_i2c *npd;
-
-       if (!pd) {
-               pd = &default_i2c_data;
-               pd->bus_num = 3;
-       }
-
-       npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
-                              &s3c_device_i2c3);
-
-       if (!npd->cfg_gpio)
-               npd->cfg_gpio = s3c_i2c3_cfg_gpio;
-}
diff --git a/arch/arm/plat-samsung/dev-i2c4.c b/arch/arm/plat-samsung/dev-i2c4.c
deleted file mode 100644 (file)
index 07e2644..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/* linux/arch/arm/plat-samsung/dev-i2c4.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * S5P series device definition for i2c device 3
- *
- * 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/gfp.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/platform_device.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/regs-iic.h>
-#include <plat/iic.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-
-static struct resource s3c_i2c_resource[] = {
-       [0] = {
-               .start  = S3C_PA_IIC4,
-               .end    = S3C_PA_IIC4 + SZ_4K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = IRQ_IIC4,
-               .end    = IRQ_IIC4,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-struct platform_device s3c_device_i2c4 = {
-       .name           = "s3c2440-i2c",
-       .id             = 4,
-       .num_resources  = ARRAY_SIZE(s3c_i2c_resource),
-       .resource       = s3c_i2c_resource,
-};
-
-void __init s3c_i2c4_set_platdata(struct s3c2410_platform_i2c *pd)
-{
-       struct s3c2410_platform_i2c *npd;
-
-       if (!pd) {
-               pd = &default_i2c_data;
-               pd->bus_num = 4;
-       }
-
-       npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
-                              &s3c_device_i2c4);
-
-       if (!npd->cfg_gpio)
-               npd->cfg_gpio = s3c_i2c4_cfg_gpio;
-}
diff --git a/arch/arm/plat-samsung/dev-i2c5.c b/arch/arm/plat-samsung/dev-i2c5.c
deleted file mode 100644 (file)
index f496557..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/* linux/arch/arm/plat-samsung/dev-i2c3.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * S5P series device definition for i2c device 3
- *
- * 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/gfp.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/platform_device.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/regs-iic.h>
-#include <plat/iic.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-
-static struct resource s3c_i2c_resource[] = {
-       [0] = {
-               .start  = S3C_PA_IIC5,
-               .end    = S3C_PA_IIC5 + SZ_4K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = IRQ_IIC5,
-               .end    = IRQ_IIC5,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-struct platform_device s3c_device_i2c5 = {
-       .name           = "s3c2440-i2c",
-       .id             = 5,
-       .num_resources  = ARRAY_SIZE(s3c_i2c_resource),
-       .resource       = s3c_i2c_resource,
-};
-
-void __init s3c_i2c5_set_platdata(struct s3c2410_platform_i2c *pd)
-{
-       struct s3c2410_platform_i2c *npd;
-
-       if (!pd) {
-               pd = &default_i2c_data;
-               pd->bus_num = 5;
-       }
-
-       npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
-                              &s3c_device_i2c5);
-
-       if (!npd->cfg_gpio)
-               npd->cfg_gpio = s3c_i2c5_cfg_gpio;
-}
diff --git a/arch/arm/plat-samsung/dev-i2c6.c b/arch/arm/plat-samsung/dev-i2c6.c
deleted file mode 100644 (file)
index 141d799..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/* linux/arch/arm/plat-samsung/dev-i2c6.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * S5P series device definition for i2c device 6
- *
- * 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/gfp.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/platform_device.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/regs-iic.h>
-#include <plat/iic.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-
-static struct resource s3c_i2c_resource[] = {
-       [0] = {
-               .start  = S3C_PA_IIC6,
-               .end    = S3C_PA_IIC6 + SZ_4K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = IRQ_IIC6,
-               .end    = IRQ_IIC6,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-struct platform_device s3c_device_i2c6 = {
-       .name           = "s3c2440-i2c",
-       .id             = 6,
-       .num_resources  = ARRAY_SIZE(s3c_i2c_resource),
-       .resource       = s3c_i2c_resource,
-};
-
-void __init s3c_i2c6_set_platdata(struct s3c2410_platform_i2c *pd)
-{
-       struct s3c2410_platform_i2c *npd;
-
-       if (!pd) {
-               pd = &default_i2c_data;
-               pd->bus_num = 6;
-       }
-
-       npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
-                              &s3c_device_i2c6);
-
-       if (!npd->cfg_gpio)
-               npd->cfg_gpio = s3c_i2c6_cfg_gpio;
-}
diff --git a/arch/arm/plat-samsung/dev-i2c7.c b/arch/arm/plat-samsung/dev-i2c7.c
deleted file mode 100644 (file)
index 9dddcd1..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/* linux/arch/arm/plat-samsung/dev-i2c7.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * S5P series device definition for i2c device 7
- *
- * 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/gfp.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/platform_device.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/regs-iic.h>
-#include <plat/iic.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-
-static struct resource s3c_i2c_resource[] = {
-       [0] = {
-               .start  = S3C_PA_IIC7,
-               .end    = S3C_PA_IIC7 + SZ_4K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = IRQ_IIC7,
-               .end    = IRQ_IIC7,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-struct platform_device s3c_device_i2c7 = {
-       .name           = "s3c2440-i2c",
-       .id             = 7,
-       .num_resources  = ARRAY_SIZE(s3c_i2c_resource),
-       .resource       = s3c_i2c_resource,
-};
-
-void __init s3c_i2c7_set_platdata(struct s3c2410_platform_i2c *pd)
-{
-       struct s3c2410_platform_i2c *npd;
-
-       if (!pd) {
-               pd = &default_i2c_data;
-               pd->bus_num = 7;
-       }
-
-       npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
-                              &s3c_device_i2c7);
-
-       if (!npd->cfg_gpio)
-               npd->cfg_gpio = s3c_i2c7_cfg_gpio;
-}
diff --git a/arch/arm/plat-samsung/dev-ide.c b/arch/arm/plat-samsung/dev-ide.c
deleted file mode 100644 (file)
index b497982..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/* linux/arch/arm/plat-samsung/dev-ide.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com
- *
- * Samsung CF-ATA device definition.
- *
- * 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 <mach/map.h>
-#include <plat/ata.h>
-#include <plat/devs.h>
-
-static struct resource s3c_cfcon_resource[] = {
-       [0] = {
-               .start  = SAMSUNG_PA_CFCON,
-               .end    = SAMSUNG_PA_CFCON + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = IRQ_CFCON,
-               .end    = IRQ_CFCON,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-struct platform_device s3c_device_cfcon = {
-       .id             = 0,
-       .num_resources  = ARRAY_SIZE(s3c_cfcon_resource),
-       .resource       = s3c_cfcon_resource,
-};
-
-void s3c_ide_set_platdata(struct s3c_ide_platdata *pdata)
-{
-       s3c_set_platdata(pdata, sizeof(struct s3c_ide_platdata),
-                        &s3c_device_cfcon);
-}
diff --git a/arch/arm/plat-samsung/dev-keypad.c b/arch/arm/plat-samsung/dev-keypad.c
deleted file mode 100644 (file)
index 677c2d7..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * linux/arch/arm/plat-samsung/dev-keypad.c
- *
- * Copyright (C) 2010 Samsung Electronics Co.Ltd
- * Author: Joonyoung Shim <jy0922.shim@samsung.com>
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- */
-
-#include <linux/platform_device.h>
-#include <mach/irqs.h>
-#include <mach/map.h>
-#include <plat/cpu.h>
-#include <plat/devs.h>
-#include <plat/keypad.h>
-
-static struct resource samsung_keypad_resources[] = {
-       [0] = {
-               .start  = SAMSUNG_PA_KEYPAD,
-               .end    = SAMSUNG_PA_KEYPAD + 0x20 - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = IRQ_KEYPAD,
-               .end    = IRQ_KEYPAD,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-struct platform_device samsung_device_keypad = {
-       .name           = "samsung-keypad",
-       .id             = -1,
-       .num_resources  = ARRAY_SIZE(samsung_keypad_resources),
-       .resource       = samsung_keypad_resources,
-};
-
-void __init samsung_keypad_set_platdata(struct samsung_keypad_platdata *pd)
-{
-       struct samsung_keypad_platdata *npd;
-
-       npd = s3c_set_platdata(pd, sizeof(struct samsung_keypad_platdata),
-                       &samsung_device_keypad);
-
-       if (!npd->cfg_gpio)
-               npd->cfg_gpio = samsung_keypad_cfg_gpio;
-}
diff --git a/arch/arm/plat-samsung/dev-nand.c b/arch/arm/plat-samsung/dev-nand.c
deleted file mode 100644 (file)
index b8e30ec..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * S3C series device definition for nand device
- *
- * 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/gfp.h>
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/partitions.h>
-
-#include <mach/map.h>
-#include <plat/devs.h>
-#include <plat/nand.h>
-
-static struct resource s3c_nand_resource[] = {
-       [0] = {
-               .start = S3C_PA_NAND,
-               .end   = S3C_PA_NAND + SZ_1M,
-               .flags = IORESOURCE_MEM,
-       }
-};
-
-struct platform_device s3c_device_nand = {
-       .name             = "s3c2410-nand",
-       .id               = -1,
-       .num_resources    = ARRAY_SIZE(s3c_nand_resource),
-       .resource         = s3c_nand_resource,
-};
-
-EXPORT_SYMBOL(s3c_device_nand);
-
-/**
- * s3c_nand_copy_set() - copy nand set data
- * @set: The new structure, directly copied from the old.
- *
- * Copy all the fields from the NAND set field from what is probably __initdata
- * to new kernel memory. The code returns 0 if the copy happened correctly or
- * an error code for the calling function to display.
- *
- * Note, we currently do not try and look to see if we've already copied the
- * data in a previous set.
- */
-static int __init s3c_nand_copy_set(struct s3c2410_nand_set *set)
-{
-       void *ptr;
-       int size;
-
-       size = sizeof(struct mtd_partition) * set->nr_partitions;
-       if (size) {
-               ptr = kmemdup(set->partitions, size, GFP_KERNEL);
-               set->partitions = ptr;
-
-               if (!ptr)
-                       return -ENOMEM;
-       }
-       
-       if (set->nr_map && set->nr_chips) {
-               size = sizeof(int) * set->nr_chips;
-               ptr = kmemdup(set->nr_map, size, GFP_KERNEL);
-               set->nr_map = ptr;
-
-               if (!ptr)
-                       return -ENOMEM;
-       }
-
-       if (set->ecc_layout) {
-               ptr = kmemdup(set->ecc_layout,
-                             sizeof(struct nand_ecclayout), GFP_KERNEL);
-               set->ecc_layout = ptr;
-
-               if (!ptr)
-                       return -ENOMEM;
-       }
-       
-       return 0;
-}
-
-void __init s3c_nand_set_platdata(struct s3c2410_platform_nand *nand)
-{
-       struct s3c2410_platform_nand *npd;
-       int size;
-       int ret;
-
-       /* note, if we get a failure in allocation, we simply drop out of the
-        * function. If there is so little memory available at initialisation
-        * time then there is little chance the system is going to run.
-        */ 
-
-       npd = s3c_set_platdata(nand, sizeof(struct s3c2410_platform_nand),
-                               &s3c_device_nand);
-       if (!npd)
-               return;
-
-       /* now see if we need to copy any of the nand set data */
-
-       size = sizeof(struct s3c2410_nand_set) * npd->nr_sets;
-       if (size) {
-               struct s3c2410_nand_set *from = npd->sets;
-               struct s3c2410_nand_set *to;
-               int i;
-
-               to = kmemdup(from, size, GFP_KERNEL);
-               npd->sets = to; /* set, even if we failed */
-
-               if (!to) {
-                       printk(KERN_ERR "%s: no memory for sets\n", __func__);
-                       return;
-               }
-               
-               for (i = 0; i < npd->nr_sets; i++) {
-                       ret = s3c_nand_copy_set(to);
-                       if (ret) {
-                               printk(KERN_ERR "%s: failed to copy set %d\n",
-                               __func__, i);
-                               return;
-                       }
-                       to++;
-               }
-       }
-}
diff --git a/arch/arm/plat-samsung/dev-onenand.c b/arch/arm/plat-samsung/dev-onenand.c
deleted file mode 100644 (file)
index f54ae71..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * linux/arch/arm/plat-samsung/dev-onenand.c
- *
- *  Copyright (c) 2008-2010 Samsung Electronics
- *  Kyungmin Park <kyungmin.park@samsung.com>
- *
- * S3C64XX/S5PC100 series device definition for OneNAND devices
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-static struct resource s3c_onenand_resources[] = {
-       [0] = {
-               .start  = S3C_PA_ONENAND,
-               .end    = S3C_PA_ONENAND + 0x400 - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = S3C_PA_ONENAND_BUF,
-               .end    = S3C_PA_ONENAND_BUF + S3C_SZ_ONENAND_BUF - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [2] = {
-               .start  = IRQ_ONENAND,
-               .end    = IRQ_ONENAND,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-struct platform_device s3c_device_onenand = {
-       .name           = "samsung-onenand",
-       .id             = 0,
-       .num_resources  = ARRAY_SIZE(s3c_onenand_resources),
-       .resource       = s3c_onenand_resources,
-};
diff --git a/arch/arm/plat-samsung/dev-pwm.c b/arch/arm/plat-samsung/dev-pwm.c
deleted file mode 100644 (file)
index dab47b0..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/* linux/arch/arm/plat-samsung/dev-pwm.c
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com
- *
- * Copyright (c) 2007 Ben Dooks
- * Copyright (c) 2008 Simtec Electronics
- *     Ben Dooks <ben@simtec.co.uk>, <ben-linux@fluff.org>
- *
- * S3C series device definition for the PWM timer
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-
-#include <mach/irqs.h>
-
-#include <plat/devs.h>
-
-#define TIMER_RESOURCE_SIZE (1)
-
-#define TIMER_RESOURCE(_tmr, _irq)                     \
-       (struct resource [TIMER_RESOURCE_SIZE]) {       \
-               [0] = {                                 \
-                       .start  = _irq,                 \
-                       .end    = _irq,                 \
-                       .flags  = IORESOURCE_IRQ        \
-               }                                       \
-       }
-
-#define DEFINE_S3C_TIMER(_tmr_no, _irq)                        \
-       .name           = "s3c24xx-pwm",                \
-       .id             = _tmr_no,                      \
-       .num_resources  = TIMER_RESOURCE_SIZE,          \
-       .resource       = TIMER_RESOURCE(_tmr_no, _irq),        \
-
-/*
- * since we already have an static mapping for the timer,
- * we do not bother setting any IO resource for the base.
- */
-
-struct platform_device s3c_device_timer[] = {
-       [0] = { DEFINE_S3C_TIMER(0, IRQ_TIMER0) },
-       [1] = { DEFINE_S3C_TIMER(1, IRQ_TIMER1) },
-       [2] = { DEFINE_S3C_TIMER(2, IRQ_TIMER2) },
-       [3] = { DEFINE_S3C_TIMER(3, IRQ_TIMER3) },
-       [4] = { DEFINE_S3C_TIMER(4, IRQ_TIMER4) },
-};
-EXPORT_SYMBOL(s3c_device_timer);
diff --git a/arch/arm/plat-samsung/dev-rtc.c b/arch/arm/plat-samsung/dev-rtc.c
deleted file mode 100644 (file)
index bf4e226..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/* linux/arch/arm/plat-samsung/dev-rtc.c
- *
- * Copyright 2009 by Maurus Cuelenaere <mcuelenaere@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/platform_device.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/devs.h>
-
-static struct resource s3c_rtc_resource[] = {
-       [0] = {
-               .start  = S3C_PA_RTC,
-               .end    = S3C_PA_RTC + 0xff,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = IRQ_RTC_ALARM,
-               .end    = IRQ_RTC_ALARM,
-               .flags  = IORESOURCE_IRQ,
-       },
-       [2] = {
-               .start  = IRQ_RTC_TIC,
-               .end    = IRQ_RTC_TIC,
-               .flags  = IORESOURCE_IRQ
-       }
-};
-
-struct platform_device s3c_device_rtc = {
-       .name           = "s3c64xx-rtc",
-       .id             = -1,
-       .num_resources  = ARRAY_SIZE(s3c_rtc_resource),
-       .resource       = s3c_rtc_resource,
-};
-EXPORT_SYMBOL(s3c_device_rtc);
diff --git a/arch/arm/plat-samsung/dev-ts.c b/arch/arm/plat-samsung/dev-ts.c
deleted file mode 100644 (file)
index 5f3d46a..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/* linux/arch/arm/mach-s3c64xx/dev-ts.c
- *
- * Copyright (c) 2008 Simtec Electronics
- *     http://armlinux.simtec.co.uk/
- *     Ben Dooks <ben@simtec.co.uk>, <ben-linux@fluff.org>
- *
- * Adapted by Maurus Cuelenaere for s3c64xx
- *
- * S3C64XX series device definition for touchscreen device
- *
- * 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 <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/devs.h>
-#include <plat/ts.h>
-
-static struct resource s3c_ts_resource[] = {
-       [0] = {
-               .start = SAMSUNG_PA_ADC,
-               .end   = SAMSUNG_PA_ADC + SZ_256 - 1,
-               .flags = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start = IRQ_TC,
-               .end   = IRQ_TC,
-               .flags = IORESOURCE_IRQ,
-       },
-};
-
-struct platform_device s3c_device_ts = {
-       .name           = "s3c64xx-ts",
-       .id             = -1,
-       .num_resources  = ARRAY_SIZE(s3c_ts_resource),
-       .resource       = s3c_ts_resource,
-};
-
-static struct s3c2410_ts_mach_info default_ts_data __initdata = {
-       .delay                  = 10000,
-       .presc                  = 49,
-       .oversampling_shift     = 2,
-};
-
-void __init s3c24xx_ts_set_platdata(struct s3c2410_ts_mach_info *pd)
-{
-       if (!pd)
-               pd = &default_ts_data;
-
-       s3c_set_platdata(pd, sizeof(struct s3c2410_ts_mach_info),
-                        &s3c_device_ts);
-}
diff --git a/arch/arm/plat-samsung/dev-usb-hsotg.c b/arch/arm/plat-samsung/dev-usb-hsotg.c
deleted file mode 100644 (file)
index 33a844a..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/* linux/arch/arm/plat-s3c/dev-usb-hsotg.c
- *
- * Copyright 2008 Simtec Electronics
- *     Ben Dooks <ben@simtec.co.uk>
- *     http://armlinux.simtec.co.uk/
- *
- * S3C series device definition for USB high-speed UDC/OtG block
- *
- * 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/dma-mapping.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/devs.h>
-
-static struct resource s3c_usb_hsotg_resources[] = {
-       [0] = {
-               .start  = S3C_PA_USB_HSOTG,
-               .end    = S3C_PA_USB_HSOTG + 0x10000 - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = IRQ_OTG,
-               .end    = IRQ_OTG,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static u64 s3c_hsotg_dmamask = DMA_BIT_MASK(32);
-
-struct platform_device s3c_device_usb_hsotg = {
-       .name           = "s3c-hsotg",
-       .id             = -1,
-       .num_resources  = ARRAY_SIZE(s3c_usb_hsotg_resources),
-       .resource       = s3c_usb_hsotg_resources,
-       .dev            = {
-               .dma_mask               = &s3c_hsotg_dmamask,
-               .coherent_dma_mask      = DMA_BIT_MASK(32),
-       },
-};
diff --git a/arch/arm/plat-samsung/dev-usb.c b/arch/arm/plat-samsung/dev-usb.c
deleted file mode 100644 (file)
index 33fbaa9..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/* linux/arch/arm/plat-s3c/dev-usb.c
- *
- * Copyright 2008 Simtec Electronics
- *     Ben Dooks <ben@simtec.co.uk>
- *     http://armlinux.simtec.co.uk/
- *
- * S3C series device definition for USB host
- *
- * 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/gfp.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/platform_device.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/devs.h>
-#include <plat/usb-control.h>
-
-static struct resource s3c_usb_resource[] = {
-       [0] = {
-               .start = S3C_PA_USBHOST,
-               .end   = S3C_PA_USBHOST + 0x100 - 1,
-               .flags = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start = IRQ_USBH,
-               .end   = IRQ_USBH,
-               .flags = IORESOURCE_IRQ,
-       }
-};
-
-static u64 s3c_device_usb_dmamask = 0xffffffffUL;
-
-struct platform_device s3c_device_ohci = {
-       .name             = "s3c2410-ohci",
-       .id               = -1,
-       .num_resources    = ARRAY_SIZE(s3c_usb_resource),
-       .resource         = s3c_usb_resource,
-       .dev              = {
-               .dma_mask = &s3c_device_usb_dmamask,
-               .coherent_dma_mask = 0xffffffffUL
-       }
-};
-
-EXPORT_SYMBOL(s3c_device_ohci);
-
-/**
- * s3c_ohci_set_platdata - initialise OHCI device platform data
- * @info: The platform data.
- *
- * This call copies the @info passed in and sets the device .platform_data
- * field to that copy. The @info is copied so that the original can be marked
- * __initdata.
- */
-void __init s3c_ohci_set_platdata(struct s3c2410_hcd_info *info)
-{
-       s3c_set_platdata(info, sizeof(struct s3c2410_hcd_info),
-                        &s3c_device_ohci);
-}
diff --git a/arch/arm/plat-samsung/dev-wdt.c b/arch/arm/plat-samsung/dev-wdt.c
deleted file mode 100644 (file)
index 019b5b8..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/* linux/arch/arm/plat-samsung/dev-wdt.c
- *
- * Copyright (c) 2004 Simtec Electronics
- *     Ben Dooks <ben@simtec.co.uk>
- *
- * S3C series device definition for the watchdog timer
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/devs.h>
-
-static struct resource s3c_wdt_resource[] = {
-       [0] = {
-               .start  = S3C_PA_WDT,
-               .end    = S3C_PA_WDT + SZ_1K,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = IRQ_WDT,
-               .end    = IRQ_WDT,
-               .flags  = IORESOURCE_IRQ,
-       }
-};
-
-struct platform_device s3c_device_wdt = {
-       .name           = "s3c2410-wdt",
-       .id             = -1,
-       .num_resources  = ARRAY_SIZE(s3c_wdt_resource),
-       .resource       = s3c_wdt_resource,
-};
-EXPORT_SYMBOL(s3c_device_wdt);
diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c
new file mode 100644 (file)
index 0000000..4ca8b57
--- /dev/null
@@ -0,0 +1,1463 @@
+/* linux/arch/arm/plat-samsung/devs.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Base SAMSUNG platform 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/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/dma-mapping.h>
+#include <linux/fb.h>
+#include <linux/gfp.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/onenand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mmc/host.h>
+#include <linux/ioport.h>
+
+#include <asm/irq.h>
+#include <asm/pmu.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <mach/hardware.h>
+#include <mach/dma.h>
+#include <mach/irqs.h>
+#include <mach/map.h>
+
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/adc.h>
+#include <plat/ata.h>
+#include <plat/ehci.h>
+#include <plat/fb.h>
+#include <plat/fb-s3c2410.h>
+#include <plat/hwmon.h>
+#include <plat/iic.h>
+#include <plat/keypad.h>
+#include <plat/mci.h>
+#include <plat/nand.h>
+#include <plat/sdhci.h>
+#include <plat/ts.h>
+#include <plat/udc.h>
+#include <plat/usb-control.h>
+#include <plat/usb-phy.h>
+#include <plat/regs-iic.h>
+#include <plat/regs-serial.h>
+#include <plat/regs-spi.h>
+
+static u64 samsung_device_dma_mask = DMA_BIT_MASK(32);
+
+/* AC97 */
+#ifdef CONFIG_CPU_S3C2440
+static struct resource s3c_ac97_resource[] = {
+       [0] = DEFINE_RES_MEM(S3C2440_PA_AC97, S3C2440_SZ_AC97),
+       [1] = DEFINE_RES_IRQ(IRQ_S3C244X_AC97),
+       [2] = DEFINE_RES_DMA_NAMED(DMACH_PCM_OUT, "PCM out"),
+       [3] = DEFINE_RES_DMA_NAMED(DMACH_PCM_IN, "PCM in"),
+       [4] = DEFINE_RES_DMA_NAMED(DMACH_MIC_IN, "Mic in"),
+};
+
+struct platform_device s3c_device_ac97 = {
+       .name           = "samsung-ac97",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(s3c_ac97_resource),
+       .resource       = s3c_ac97_resource,
+       .dev            = {
+               .dma_mask               = &samsung_device_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       }
+};
+#endif /* CONFIG_CPU_S3C2440 */
+
+/* ADC */
+
+#ifdef CONFIG_PLAT_S3C24XX
+static struct resource s3c_adc_resource[] = {
+       [0] = DEFINE_RES_MEM(S3C24XX_PA_ADC, S3C24XX_SZ_ADC),
+       [1] = DEFINE_RES_IRQ(IRQ_TC),
+       [2] = DEFINE_RES_IRQ(IRQ_ADC),
+};
+
+struct platform_device s3c_device_adc = {
+       .name           = "s3c24xx-adc",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(s3c_adc_resource),
+       .resource       = s3c_adc_resource,
+};
+#endif /* CONFIG_PLAT_S3C24XX */
+
+#if defined(CONFIG_SAMSUNG_DEV_ADC)
+static struct resource s3c_adc_resource[] = {
+       [0] = DEFINE_RES_MEM(SAMSUNG_PA_ADC, SZ_256),
+       [1] = DEFINE_RES_IRQ(IRQ_TC),
+       [2] = DEFINE_RES_IRQ(IRQ_ADC),
+};
+
+struct platform_device s3c_device_adc = {
+       .name           = "samsung-adc",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(s3c_adc_resource),
+       .resource       = s3c_adc_resource,
+};
+#endif /* CONFIG_SAMSUNG_DEV_ADC */
+
+/* Camif Controller */
+
+#ifdef CONFIG_CPU_S3C2440
+static struct resource s3c_camif_resource[] = {
+       [0] = DEFINE_RES_MEM(S3C2440_PA_CAMIF, S3C2440_SZ_CAMIF),
+       [1] = DEFINE_RES_IRQ(IRQ_CAM),
+};
+
+struct platform_device s3c_device_camif = {
+       .name           = "s3c2440-camif",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(s3c_camif_resource),
+       .resource       = s3c_camif_resource,
+       .dev            = {
+               .dma_mask               = &samsung_device_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       }
+};
+#endif /* CONFIG_CPU_S3C2440 */
+
+/* ASOC DMA */
+
+struct platform_device samsung_asoc_dma = {
+       .name           = "samsung-audio",
+       .id             = -1,
+       .dev            = {
+               .dma_mask               = &samsung_device_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       }
+};
+
+struct platform_device samsung_asoc_idma = {
+       .name           = "samsung-idma",
+       .id             = -1,
+       .dev            = {
+               .dma_mask               = &samsung_device_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       }
+};
+
+/* FB */
+
+#ifdef CONFIG_S3C_DEV_FB
+static struct resource s3c_fb_resource[] = {
+       [0] = DEFINE_RES_MEM(S3C_PA_FB, SZ_16K),
+       [1] = DEFINE_RES_IRQ(IRQ_LCD_VSYNC),
+       [2] = DEFINE_RES_IRQ(IRQ_LCD_FIFO),
+       [3] = DEFINE_RES_IRQ(IRQ_LCD_SYSTEM),
+};
+
+struct platform_device s3c_device_fb = {
+       .name           = "s3c-fb",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(s3c_fb_resource),
+       .resource       = s3c_fb_resource,
+       .dev            = {
+               .dma_mask               = &samsung_device_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       },
+};
+
+void __init s3c_fb_set_platdata(struct s3c_fb_platdata *pd)
+{
+       s3c_set_platdata(pd, sizeof(struct s3c_fb_platdata),
+                        &s3c_device_fb);
+}
+#endif /* CONFIG_S3C_DEV_FB */
+
+/* FIMC */
+
+#ifdef CONFIG_S5P_DEV_FIMC0
+static struct resource s5p_fimc0_resource[] = {
+       [0] = DEFINE_RES_MEM(S5P_PA_FIMC0, SZ_4K),
+       [1] = DEFINE_RES_IRQ(IRQ_FIMC0),
+};
+
+struct platform_device s5p_device_fimc0 = {
+       .name           = "s5p-fimc",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(s5p_fimc0_resource),
+       .resource       = s5p_fimc0_resource,
+       .dev            = {
+               .dma_mask               = &samsung_device_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       },
+};
+
+struct platform_device s5p_device_fimc_md = {
+       .name   = "s5p-fimc-md",
+       .id     = -1,
+};
+#endif /* CONFIG_S5P_DEV_FIMC0 */
+
+#ifdef CONFIG_S5P_DEV_FIMC1
+static struct resource s5p_fimc1_resource[] = {
+       [0] = DEFINE_RES_MEM(S5P_PA_FIMC1, SZ_4K),
+       [1] = DEFINE_RES_IRQ(IRQ_FIMC1),
+};
+
+struct platform_device s5p_device_fimc1 = {
+       .name           = "s5p-fimc",
+       .id             = 1,
+       .num_resources  = ARRAY_SIZE(s5p_fimc1_resource),
+       .resource       = s5p_fimc1_resource,
+       .dev            = {
+               .dma_mask               = &samsung_device_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       },
+};
+#endif /* CONFIG_S5P_DEV_FIMC1 */
+
+#ifdef CONFIG_S5P_DEV_FIMC2
+static struct resource s5p_fimc2_resource[] = {
+       [0] = DEFINE_RES_MEM(S5P_PA_FIMC2, SZ_4K),
+       [1] = DEFINE_RES_IRQ(IRQ_FIMC2),
+};
+
+struct platform_device s5p_device_fimc2 = {
+       .name           = "s5p-fimc",
+       .id             = 2,
+       .num_resources  = ARRAY_SIZE(s5p_fimc2_resource),
+       .resource       = s5p_fimc2_resource,
+       .dev            = {
+               .dma_mask               = &samsung_device_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       },
+};
+#endif /* CONFIG_S5P_DEV_FIMC2 */
+
+#ifdef CONFIG_S5P_DEV_FIMC3
+static struct resource s5p_fimc3_resource[] = {
+       [0] = DEFINE_RES_MEM(S5P_PA_FIMC3, SZ_4K),
+       [1] = DEFINE_RES_IRQ(IRQ_FIMC3),
+};
+
+struct platform_device s5p_device_fimc3 = {
+       .name           = "s5p-fimc",
+       .id             = 3,
+       .num_resources  = ARRAY_SIZE(s5p_fimc3_resource),
+       .resource       = s5p_fimc3_resource,
+       .dev            = {
+               .dma_mask               = &samsung_device_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       },
+};
+#endif /* CONFIG_S5P_DEV_FIMC3 */
+
+/* FIMD0 */
+
+#ifdef CONFIG_S5P_DEV_FIMD0
+static struct resource s5p_fimd0_resource[] = {
+       [0] = DEFINE_RES_MEM(S5P_PA_FIMD0, SZ_32K),
+       [1] = DEFINE_RES_IRQ(IRQ_FIMD0_VSYNC),
+       [2] = DEFINE_RES_IRQ(IRQ_FIMD0_FIFO),
+       [3] = DEFINE_RES_IRQ(IRQ_FIMD0_SYSTEM),
+};
+
+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               = &samsung_device_dma_mask,
+               .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);
+}
+#endif /* CONFIG_S5P_DEV_FIMD0 */
+
+/* HWMON */
+
+#ifdef CONFIG_S3C_DEV_HWMON
+struct platform_device s3c_device_hwmon = {
+       .name           = "s3c-hwmon",
+       .id             = -1,
+       .dev.parent     = &s3c_device_adc.dev,
+};
+
+void __init s3c_hwmon_set_platdata(struct s3c_hwmon_pdata *pd)
+{
+       s3c_set_platdata(pd, sizeof(struct s3c_hwmon_pdata),
+                        &s3c_device_hwmon);
+}
+#endif /* CONFIG_S3C_DEV_HWMON */
+
+/* HSMMC */
+
+#ifdef CONFIG_S3C_DEV_HSMMC
+static struct resource s3c_hsmmc_resource[] = {
+       [0] = DEFINE_RES_MEM(S3C_PA_HSMMC0, SZ_4K),
+       [1] = DEFINE_RES_IRQ(IRQ_HSMMC0),
+};
+
+struct s3c_sdhci_platdata s3c_hsmmc0_def_platdata = {
+       .max_width      = 4,
+       .host_caps      = (MMC_CAP_4_BIT_DATA |
+                          MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED),
+       .clk_type       = S3C_SDHCI_CLK_DIV_INTERNAL,
+};
+
+struct platform_device s3c_device_hsmmc0 = {
+       .name           = "s3c-sdhci",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(s3c_hsmmc_resource),
+       .resource       = s3c_hsmmc_resource,
+       .dev            = {
+               .dma_mask               = &samsung_device_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+               .platform_data          = &s3c_hsmmc0_def_platdata,
+       },
+};
+
+void s3c_sdhci0_set_platdata(struct s3c_sdhci_platdata *pd)
+{
+       s3c_sdhci_set_platdata(pd, &s3c_hsmmc0_def_platdata);
+}
+#endif /* CONFIG_S3C_DEV_HSMMC */
+
+#ifdef CONFIG_S3C_DEV_HSMMC1
+static struct resource s3c_hsmmc1_resource[] = {
+       [0] = DEFINE_RES_MEM(S3C_PA_HSMMC1, SZ_4K),
+       [1] = DEFINE_RES_IRQ(IRQ_HSMMC1),
+};
+
+struct s3c_sdhci_platdata s3c_hsmmc1_def_platdata = {
+       .max_width      = 4,
+       .host_caps      = (MMC_CAP_4_BIT_DATA |
+                          MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED),
+       .clk_type       = S3C_SDHCI_CLK_DIV_INTERNAL,
+};
+
+struct platform_device s3c_device_hsmmc1 = {
+       .name           = "s3c-sdhci",
+       .id             = 1,
+       .num_resources  = ARRAY_SIZE(s3c_hsmmc1_resource),
+       .resource       = s3c_hsmmc1_resource,
+       .dev            = {
+               .dma_mask               = &samsung_device_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+               .platform_data          = &s3c_hsmmc1_def_platdata,
+       },
+};
+
+void s3c_sdhci1_set_platdata(struct s3c_sdhci_platdata *pd)
+{
+       s3c_sdhci_set_platdata(pd, &s3c_hsmmc1_def_platdata);
+}
+#endif /* CONFIG_S3C_DEV_HSMMC1 */
+
+/* HSMMC2 */
+
+#ifdef CONFIG_S3C_DEV_HSMMC2
+static struct resource s3c_hsmmc2_resource[] = {
+       [0] = DEFINE_RES_MEM(S3C_PA_HSMMC2, SZ_4K),
+       [1] = DEFINE_RES_IRQ(IRQ_HSMMC2),
+};
+
+struct s3c_sdhci_platdata s3c_hsmmc2_def_platdata = {
+       .max_width      = 4,
+       .host_caps      = (MMC_CAP_4_BIT_DATA |
+                          MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED),
+       .clk_type       = S3C_SDHCI_CLK_DIV_INTERNAL,
+};
+
+struct platform_device s3c_device_hsmmc2 = {
+       .name           = "s3c-sdhci",
+       .id             = 2,
+       .num_resources  = ARRAY_SIZE(s3c_hsmmc2_resource),
+       .resource       = s3c_hsmmc2_resource,
+       .dev            = {
+               .dma_mask               = &samsung_device_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+               .platform_data          = &s3c_hsmmc2_def_platdata,
+       },
+};
+
+void s3c_sdhci2_set_platdata(struct s3c_sdhci_platdata *pd)
+{
+       s3c_sdhci_set_platdata(pd, &s3c_hsmmc2_def_platdata);
+}
+#endif /* CONFIG_S3C_DEV_HSMMC2 */
+
+#ifdef CONFIG_S3C_DEV_HSMMC3
+static struct resource s3c_hsmmc3_resource[] = {
+       [0] = DEFINE_RES_MEM(S3C_PA_HSMMC3, SZ_4K),
+       [1] = DEFINE_RES_IRQ(IRQ_HSMMC3),
+};
+
+struct s3c_sdhci_platdata s3c_hsmmc3_def_platdata = {
+       .max_width      = 4,
+       .host_caps      = (MMC_CAP_4_BIT_DATA |
+                          MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED),
+       .clk_type       = S3C_SDHCI_CLK_DIV_INTERNAL,
+};
+
+struct platform_device s3c_device_hsmmc3 = {
+       .name           = "s3c-sdhci",
+       .id             = 3,
+       .num_resources  = ARRAY_SIZE(s3c_hsmmc3_resource),
+       .resource       = s3c_hsmmc3_resource,
+       .dev            = {
+               .dma_mask               = &samsung_device_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+               .platform_data          = &s3c_hsmmc3_def_platdata,
+       },
+};
+
+void s3c_sdhci3_set_platdata(struct s3c_sdhci_platdata *pd)
+{
+       s3c_sdhci_set_platdata(pd, &s3c_hsmmc3_def_platdata);
+}
+#endif /* CONFIG_S3C_DEV_HSMMC3 */
+
+/* I2C */
+
+static struct resource s3c_i2c0_resource[] = {
+       [0] = DEFINE_RES_MEM(S3C_PA_IIC, SZ_4K),
+       [1] = DEFINE_RES_IRQ(IRQ_IIC),
+};
+
+struct platform_device s3c_device_i2c0 = {
+       .name           = "s3c2410-i2c",
+#ifdef CONFIG_S3C_DEV_I2C1
+       .id             = 0,
+#else
+       .id             = -1,
+#endif
+       .num_resources  = ARRAY_SIZE(s3c_i2c0_resource),
+       .resource       = s3c_i2c0_resource,
+};
+
+struct s3c2410_platform_i2c default_i2c_data __initdata = {
+       .flags          = 0,
+       .slave_addr     = 0x10,
+       .frequency      = 100*1000,
+       .sda_delay      = 100,
+};
+
+void __init s3c_i2c0_set_platdata(struct s3c2410_platform_i2c *pd)
+{
+       struct s3c2410_platform_i2c *npd;
+
+       if (!pd)
+               pd = &default_i2c_data;
+
+       npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+                              &s3c_device_i2c0);
+
+       if (!npd->cfg_gpio)
+               npd->cfg_gpio = s3c_i2c0_cfg_gpio;
+}
+
+#ifdef CONFIG_S3C_DEV_I2C1
+static struct resource s3c_i2c1_resource[] = {
+       [0] = DEFINE_RES_MEM(S3C_PA_IIC1, SZ_4K),
+       [1] = DEFINE_RES_IRQ(IRQ_IIC1),
+};
+
+struct platform_device s3c_device_i2c1 = {
+       .name           = "s3c2410-i2c",
+       .id             = 1,
+       .num_resources  = ARRAY_SIZE(s3c_i2c1_resource),
+       .resource       = s3c_i2c1_resource,
+};
+
+void __init s3c_i2c1_set_platdata(struct s3c2410_platform_i2c *pd)
+{
+       struct s3c2410_platform_i2c *npd;
+
+       if (!pd) {
+               pd = &default_i2c_data;
+               pd->bus_num = 1;
+       }
+
+       npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+                              &s3c_device_i2c1);
+
+       if (!npd->cfg_gpio)
+               npd->cfg_gpio = s3c_i2c1_cfg_gpio;
+}
+#endif /* CONFIG_S3C_DEV_I2C1 */
+
+#ifdef CONFIG_S3C_DEV_I2C2
+static struct resource s3c_i2c2_resource[] = {
+       [0] = DEFINE_RES_MEM(S3C_PA_IIC2, SZ_4K),
+       [1] = DEFINE_RES_IRQ(IRQ_IIC2),
+};
+
+struct platform_device s3c_device_i2c2 = {
+       .name           = "s3c2410-i2c",
+       .id             = 2,
+       .num_resources  = ARRAY_SIZE(s3c_i2c2_resource),
+       .resource       = s3c_i2c2_resource,
+};
+
+void __init s3c_i2c2_set_platdata(struct s3c2410_platform_i2c *pd)
+{
+       struct s3c2410_platform_i2c *npd;
+
+       if (!pd) {
+               pd = &default_i2c_data;
+               pd->bus_num = 2;
+       }
+
+       npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+                              &s3c_device_i2c2);
+
+       if (!npd->cfg_gpio)
+               npd->cfg_gpio = s3c_i2c2_cfg_gpio;
+}
+#endif /* CONFIG_S3C_DEV_I2C2 */
+
+#ifdef CONFIG_S3C_DEV_I2C3
+static struct resource s3c_i2c3_resource[] = {
+       [0] = DEFINE_RES_MEM(S3C_PA_IIC3, SZ_4K),
+       [1] = DEFINE_RES_IRQ(IRQ_IIC3),
+};
+
+struct platform_device s3c_device_i2c3 = {
+       .name           = "s3c2440-i2c",
+       .id             = 3,
+       .num_resources  = ARRAY_SIZE(s3c_i2c3_resource),
+       .resource       = s3c_i2c3_resource,
+};
+
+void __init s3c_i2c3_set_platdata(struct s3c2410_platform_i2c *pd)
+{
+       struct s3c2410_platform_i2c *npd;
+
+       if (!pd) {
+               pd = &default_i2c_data;
+               pd->bus_num = 3;
+       }
+
+       npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+                              &s3c_device_i2c3);
+
+       if (!npd->cfg_gpio)
+               npd->cfg_gpio = s3c_i2c3_cfg_gpio;
+}
+#endif /*CONFIG_S3C_DEV_I2C3 */
+
+#ifdef CONFIG_S3C_DEV_I2C4
+static struct resource s3c_i2c4_resource[] = {
+       [0] = DEFINE_RES_MEM(S3C_PA_IIC4, SZ_4K),
+       [1] = DEFINE_RES_IRQ(IRQ_IIC4),
+};
+
+struct platform_device s3c_device_i2c4 = {
+       .name           = "s3c2440-i2c",
+       .id             = 4,
+       .num_resources  = ARRAY_SIZE(s3c_i2c4_resource),
+       .resource       = s3c_i2c4_resource,
+};
+
+void __init s3c_i2c4_set_platdata(struct s3c2410_platform_i2c *pd)
+{
+       struct s3c2410_platform_i2c *npd;
+
+       if (!pd) {
+               pd = &default_i2c_data;
+               pd->bus_num = 4;
+       }
+
+       npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+                              &s3c_device_i2c4);
+
+       if (!npd->cfg_gpio)
+               npd->cfg_gpio = s3c_i2c4_cfg_gpio;
+}
+#endif /*CONFIG_S3C_DEV_I2C4 */
+
+#ifdef CONFIG_S3C_DEV_I2C5
+static struct resource s3c_i2c5_resource[] = {
+       [0] = DEFINE_RES_MEM(S3C_PA_IIC5, SZ_4K),
+       [1] = DEFINE_RES_IRQ(IRQ_IIC5),
+};
+
+struct platform_device s3c_device_i2c5 = {
+       .name           = "s3c2440-i2c",
+       .id             = 5,
+       .num_resources  = ARRAY_SIZE(s3c_i2c5_resource),
+       .resource       = s3c_i2c5_resource,
+};
+
+void __init s3c_i2c5_set_platdata(struct s3c2410_platform_i2c *pd)
+{
+       struct s3c2410_platform_i2c *npd;
+
+       if (!pd) {
+               pd = &default_i2c_data;
+               pd->bus_num = 5;
+       }
+
+       npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+                              &s3c_device_i2c5);
+
+       if (!npd->cfg_gpio)
+               npd->cfg_gpio = s3c_i2c5_cfg_gpio;
+}
+#endif /*CONFIG_S3C_DEV_I2C5 */
+
+#ifdef CONFIG_S3C_DEV_I2C6
+static struct resource s3c_i2c6_resource[] = {
+       [0] = DEFINE_RES_MEM(S3C_PA_IIC6, SZ_4K),
+       [1] = DEFINE_RES_IRQ(IRQ_IIC6),
+};
+
+struct platform_device s3c_device_i2c6 = {
+       .name           = "s3c2440-i2c",
+       .id             = 6,
+       .num_resources  = ARRAY_SIZE(s3c_i2c6_resource),
+       .resource       = s3c_i2c6_resource,
+};
+
+void __init s3c_i2c6_set_platdata(struct s3c2410_platform_i2c *pd)
+{
+       struct s3c2410_platform_i2c *npd;
+
+       if (!pd) {
+               pd = &default_i2c_data;
+               pd->bus_num = 6;
+       }
+
+       npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+                              &s3c_device_i2c6);
+
+       if (!npd->cfg_gpio)
+               npd->cfg_gpio = s3c_i2c6_cfg_gpio;
+}
+#endif /* CONFIG_S3C_DEV_I2C6 */
+
+#ifdef CONFIG_S3C_DEV_I2C7
+static struct resource s3c_i2c7_resource[] = {
+       [0] = DEFINE_RES_MEM(S3C_PA_IIC7, SZ_4K),
+       [1] = DEFINE_RES_IRQ(IRQ_IIC7),
+};
+
+struct platform_device s3c_device_i2c7 = {
+       .name           = "s3c2440-i2c",
+       .id             = 7,
+       .num_resources  = ARRAY_SIZE(s3c_i2c7_resource),
+       .resource       = s3c_i2c7_resource,
+};
+
+void __init s3c_i2c7_set_platdata(struct s3c2410_platform_i2c *pd)
+{
+       struct s3c2410_platform_i2c *npd;
+
+       if (!pd) {
+               pd = &default_i2c_data;
+               pd->bus_num = 7;
+       }
+
+       npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+                              &s3c_device_i2c7);
+
+       if (!npd->cfg_gpio)
+               npd->cfg_gpio = s3c_i2c7_cfg_gpio;
+}
+#endif /* CONFIG_S3C_DEV_I2C7 */
+
+/* I2C HDMIPHY */
+
+#ifdef CONFIG_S5P_DEV_I2C_HDMIPHY
+static struct resource s5p_i2c_resource[] = {
+       [0] = DEFINE_RES_MEM(S5P_PA_IIC_HDMIPHY, SZ_4K),
+       [1] = DEFINE_RES_IRQ(IRQ_IIC_HDMIPHY),
+};
+
+struct platform_device s5p_device_i2c_hdmiphy = {
+       .name           = "s3c2440-hdmiphy-i2c",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(s5p_i2c_resource),
+       .resource       = s5p_i2c_resource,
+};
+
+void __init s5p_i2c_hdmiphy_set_platdata(struct s3c2410_platform_i2c *pd)
+{
+       struct s3c2410_platform_i2c *npd;
+
+       if (!pd) {
+               pd = &default_i2c_data;
+
+               if (soc_is_exynos4210())
+                       pd->bus_num = 8;
+               else if (soc_is_s5pv210())
+                       pd->bus_num = 3;
+               else
+                       pd->bus_num = 0;
+       }
+
+       npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
+                              &s5p_device_i2c_hdmiphy);
+}
+#endif /* CONFIG_S5P_DEV_I2C_HDMIPHY */
+
+/* I2S */
+
+#ifdef CONFIG_PLAT_S3C24XX
+static struct resource s3c_iis_resource[] = {
+       [0] = DEFINE_RES_MEM(S3C24XX_PA_IIS, S3C24XX_SZ_IIS),
+};
+
+struct platform_device s3c_device_iis = {
+       .name           = "s3c24xx-iis",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(s3c_iis_resource),
+       .resource       = s3c_iis_resource,
+       .dev            = {
+               .dma_mask               = &samsung_device_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       }
+};
+#endif /* CONFIG_PLAT_S3C24XX */
+
+#ifdef CONFIG_CPU_S3C2440
+struct platform_device s3c2412_device_iis = {
+       .name           = "s3c2412-iis",
+       .id             = -1,
+       .dev            = {
+               .dma_mask               = &samsung_device_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       }
+};
+#endif /* CONFIG_CPU_S3C2440 */
+
+/* IDE CFCON */
+
+#ifdef CONFIG_SAMSUNG_DEV_IDE
+static struct resource s3c_cfcon_resource[] = {
+       [0] = DEFINE_RES_MEM(SAMSUNG_PA_CFCON, SZ_16K),
+       [1] = DEFINE_RES_IRQ(IRQ_CFCON),
+};
+
+struct platform_device s3c_device_cfcon = {
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(s3c_cfcon_resource),
+       .resource       = s3c_cfcon_resource,
+};
+
+void s3c_ide_set_platdata(struct s3c_ide_platdata *pdata)
+{
+       s3c_set_platdata(pdata, sizeof(struct s3c_ide_platdata),
+                        &s3c_device_cfcon);
+}
+#endif /* CONFIG_SAMSUNG_DEV_IDE */
+
+/* KEYPAD */
+
+#ifdef CONFIG_SAMSUNG_DEV_KEYPAD
+static struct resource samsung_keypad_resources[] = {
+       [0] = DEFINE_RES_MEM(SAMSUNG_PA_KEYPAD, SZ_32),
+       [1] = DEFINE_RES_IRQ(IRQ_KEYPAD),
+};
+
+struct platform_device samsung_device_keypad = {
+       .name           = "samsung-keypad",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(samsung_keypad_resources),
+       .resource       = samsung_keypad_resources,
+};
+
+void __init samsung_keypad_set_platdata(struct samsung_keypad_platdata *pd)
+{
+       struct samsung_keypad_platdata *npd;
+
+       npd = s3c_set_platdata(pd, sizeof(struct samsung_keypad_platdata),
+                       &samsung_device_keypad);
+
+       if (!npd->cfg_gpio)
+               npd->cfg_gpio = samsung_keypad_cfg_gpio;
+}
+#endif /* CONFIG_SAMSUNG_DEV_KEYPAD */
+
+/* LCD Controller */
+
+#ifdef CONFIG_PLAT_S3C24XX
+static struct resource s3c_lcd_resource[] = {
+       [0] = DEFINE_RES_MEM(S3C24XX_PA_LCD, S3C24XX_SZ_LCD),
+       [1] = DEFINE_RES_IRQ(IRQ_LCD),
+};
+
+struct platform_device s3c_device_lcd = {
+       .name           = "s3c2410-lcd",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(s3c_lcd_resource),
+       .resource       = s3c_lcd_resource,
+       .dev            = {
+               .dma_mask               = &samsung_device_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       }
+};
+
+void __init s3c24xx_fb_set_platdata(struct s3c2410fb_mach_info *pd)
+{
+       struct s3c2410fb_mach_info *npd;
+
+       npd = s3c_set_platdata(pd, sizeof(*npd), &s3c_device_lcd);
+       if (npd) {
+               npd->displays = kmemdup(pd->displays,
+                       sizeof(struct s3c2410fb_display) * npd->num_displays,
+                       GFP_KERNEL);
+               if (!npd->displays)
+                       printk(KERN_ERR "no memory for LCD display data\n");
+       } else {
+               printk(KERN_ERR "no memory for LCD platform data\n");
+       }
+}
+#endif /* CONFIG_PLAT_S3C24XX */
+
+/* MFC */
+
+#ifdef CONFIG_S5P_DEV_MFC
+static struct resource s5p_mfc_resource[] = {
+       [0] = DEFINE_RES_MEM(S5P_PA_MFC, SZ_64K),
+       [1] = DEFINE_RES_IRQ(IRQ_MFC),
+};
+
+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).
+ */
+
+struct platform_device s5p_device_mfc_l = {
+       .name           = "s5p-mfc-l",
+       .id             = -1,
+       .dev            = {
+               .parent                 = &s5p_device_mfc.dev,
+               .dma_mask               = &samsung_device_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               = &samsung_device_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       },
+};
+#endif /* CONFIG_S5P_DEV_MFC */
+
+/* MIPI CSIS */
+
+#ifdef CONFIG_S5P_DEV_CSIS0
+static struct resource s5p_mipi_csis0_resource[] = {
+       [0] = DEFINE_RES_MEM(S5P_PA_MIPI_CSIS0, SZ_4K),
+       [1] = DEFINE_RES_IRQ(IRQ_MIPI_CSIS0),
+};
+
+struct platform_device s5p_device_mipi_csis0 = {
+       .name           = "s5p-mipi-csis",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(s5p_mipi_csis0_resource),
+       .resource       = s5p_mipi_csis0_resource,
+};
+#endif /* CONFIG_S5P_DEV_CSIS0 */
+
+#ifdef CONFIG_S5P_DEV_CSIS1
+static struct resource s5p_mipi_csis1_resource[] = {
+       [0] = DEFINE_RES_MEM(S5P_PA_MIPI_CSIS1, SZ_4K),
+       [1] = DEFINE_RES_IRQ(IRQ_MIPI_CSIS1),
+};
+
+struct platform_device s5p_device_mipi_csis1 = {
+       .name           = "s5p-mipi-csis",
+       .id             = 1,
+       .num_resources  = ARRAY_SIZE(s5p_mipi_csis1_resource),
+       .resource       = s5p_mipi_csis1_resource,
+};
+#endif
+
+/* NAND */
+
+#ifdef CONFIG_S3C_DEV_NAND
+static struct resource s3c_nand_resource[] = {
+       [0] = DEFINE_RES_MEM(S3C_PA_NAND, SZ_1M),
+};
+
+struct platform_device s3c_device_nand = {
+       .name           = "s3c2410-nand",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(s3c_nand_resource),
+       .resource       = s3c_nand_resource,
+};
+
+/*
+ * s3c_nand_copy_set() - copy nand set data
+ * @set: The new structure, directly copied from the old.
+ *
+ * Copy all the fields from the NAND set field from what is probably __initdata
+ * to new kernel memory. The code returns 0 if the copy happened correctly or
+ * an error code for the calling function to display.
+ *
+ * Note, we currently do not try and look to see if we've already copied the
+ * data in a previous set.
+ */
+static int __init s3c_nand_copy_set(struct s3c2410_nand_set *set)
+{
+       void *ptr;
+       int size;
+
+       size = sizeof(struct mtd_partition) * set->nr_partitions;
+       if (size) {
+               ptr = kmemdup(set->partitions, size, GFP_KERNEL);
+               set->partitions = ptr;
+
+               if (!ptr)
+                       return -ENOMEM;
+       }
+
+       if (set->nr_map && set->nr_chips) {
+               size = sizeof(int) * set->nr_chips;
+               ptr = kmemdup(set->nr_map, size, GFP_KERNEL);
+               set->nr_map = ptr;
+
+               if (!ptr)
+                       return -ENOMEM;
+       }
+
+       if (set->ecc_layout) {
+               ptr = kmemdup(set->ecc_layout,
+                             sizeof(struct nand_ecclayout), GFP_KERNEL);
+               set->ecc_layout = ptr;
+
+               if (!ptr)
+                       return -ENOMEM;
+       }
+
+       return 0;
+}
+
+void __init s3c_nand_set_platdata(struct s3c2410_platform_nand *nand)
+{
+       struct s3c2410_platform_nand *npd;
+       int size;
+       int ret;
+
+       /* note, if we get a failure in allocation, we simply drop out of the
+        * function. If there is so little memory available at initialisation
+        * time then there is little chance the system is going to run.
+        */
+
+       npd = s3c_set_platdata(nand, sizeof(struct s3c2410_platform_nand),
+                               &s3c_device_nand);
+       if (!npd)
+               return;
+
+       /* now see if we need to copy any of the nand set data */
+
+       size = sizeof(struct s3c2410_nand_set) * npd->nr_sets;
+       if (size) {
+               struct s3c2410_nand_set *from = npd->sets;
+               struct s3c2410_nand_set *to;
+               int i;
+
+               to = kmemdup(from, size, GFP_KERNEL);
+               npd->sets = to; /* set, even if we failed */
+
+               if (!to) {
+                       printk(KERN_ERR "%s: no memory for sets\n", __func__);
+                       return;
+               }
+
+               for (i = 0; i < npd->nr_sets; i++) {
+                       ret = s3c_nand_copy_set(to);
+                       if (ret) {
+                               printk(KERN_ERR "%s: failed to copy set %d\n",
+                               __func__, i);
+                               return;
+                       }
+                       to++;
+               }
+       }
+}
+#endif /* CONFIG_S3C_DEV_NAND */
+
+/* ONENAND */
+
+#ifdef CONFIG_S3C_DEV_ONENAND
+static struct resource s3c_onenand_resources[] = {
+       [0] = DEFINE_RES_MEM(S3C_PA_ONENAND, SZ_1K),
+       [1] = DEFINE_RES_MEM(S3C_PA_ONENAND_BUF, S3C_SZ_ONENAND_BUF),
+       [2] = DEFINE_RES_IRQ(IRQ_ONENAND),
+};
+
+struct platform_device s3c_device_onenand = {
+       .name           = "samsung-onenand",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(s3c_onenand_resources),
+       .resource       = s3c_onenand_resources,
+};
+#endif /* CONFIG_S3C_DEV_ONENAND */
+
+#ifdef CONFIG_S3C64XX_DEV_ONENAND1
+static struct resource s3c64xx_onenand1_resources[] = {
+       [0] = DEFINE_RES_MEM(S3C64XX_PA_ONENAND1, SZ_1K),
+       [1] = DEFINE_RES_MEM(S3C64XX_PA_ONENAND1_BUF, S3C64XX_SZ_ONENAND1_BUF),
+       [2] = DEFINE_RES_IRQ(IRQ_ONENAND1),
+};
+
+struct platform_device s3c64xx_device_onenand1 = {
+       .name           = "samsung-onenand",
+       .id             = 1,
+       .num_resources  = ARRAY_SIZE(s3c64xx_onenand1_resources),
+       .resource       = s3c64xx_onenand1_resources,
+};
+
+void s3c64xx_onenand1_set_platdata(struct onenand_platform_data *pdata)
+{
+       s3c_set_platdata(pdata, sizeof(struct onenand_platform_data),
+                        &s3c64xx_device_onenand1);
+}
+#endif /* CONFIG_S3C64XX_DEV_ONENAND1 */
+
+#ifdef CONFIG_S5P_DEV_ONENAND
+static struct resource s5p_onenand_resources[] = {
+       [0] = DEFINE_RES_MEM(S5P_PA_ONENAND, SZ_128K),
+       [1] = DEFINE_RES_MEM(S5P_PA_ONENAND_DMA, SZ_8K),
+       [2] = DEFINE_RES_IRQ(IRQ_ONENAND_AUDI),
+};
+
+struct platform_device s5p_device_onenand = {
+       .name           = "s5pc110-onenand",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(s5p_onenand_resources),
+       .resource       = s5p_onenand_resources,
+};
+#endif /* CONFIG_S5P_DEV_ONENAND */
+
+/* PMU */
+
+#ifdef CONFIG_PLAT_S5P
+static struct resource s5p_pmu_resource[] = {
+       DEFINE_RES_IRQ(IRQ_PMU)
+};
+
+struct platform_device s5p_device_pmu = {
+       .name           = "arm-pmu",
+       .id             = ARM_PMU_DEVICE_CPU,
+       .num_resources  = ARRAY_SIZE(s5p_pmu_resource),
+       .resource       = s5p_pmu_resource,
+};
+
+static int __init s5p_pmu_init(void)
+{
+       platform_device_register(&s5p_device_pmu);
+       return 0;
+}
+arch_initcall(s5p_pmu_init);
+#endif /* CONFIG_PLAT_S5P */
+
+/* PWM Timer */
+
+#ifdef CONFIG_SAMSUNG_DEV_PWM
+
+#define TIMER_RESOURCE_SIZE (1)
+
+#define TIMER_RESOURCE(_tmr, _irq)                     \
+       (struct resource [TIMER_RESOURCE_SIZE]) {       \
+               [0] = {                                 \
+                       .start  = _irq,                 \
+                       .end    = _irq,                 \
+                       .flags  = IORESOURCE_IRQ        \
+               }                                       \
+       }
+
+#define DEFINE_S3C_TIMER(_tmr_no, _irq)                        \
+       .name           = "s3c24xx-pwm",                \
+       .id             = _tmr_no,                      \
+       .num_resources  = TIMER_RESOURCE_SIZE,          \
+       .resource       = TIMER_RESOURCE(_tmr_no, _irq),        \
+
+/*
+ * since we already have an static mapping for the timer,
+ * we do not bother setting any IO resource for the base.
+ */
+
+struct platform_device s3c_device_timer[] = {
+       [0] = { DEFINE_S3C_TIMER(0, IRQ_TIMER0) },
+       [1] = { DEFINE_S3C_TIMER(1, IRQ_TIMER1) },
+       [2] = { DEFINE_S3C_TIMER(2, IRQ_TIMER2) },
+       [3] = { DEFINE_S3C_TIMER(3, IRQ_TIMER3) },
+       [4] = { DEFINE_S3C_TIMER(4, IRQ_TIMER4) },
+};
+#endif /* CONFIG_SAMSUNG_DEV_PWM */
+
+/* RTC */
+
+#ifdef CONFIG_PLAT_S3C24XX
+static struct resource s3c_rtc_resource[] = {
+       [0] = DEFINE_RES_MEM(S3C24XX_PA_RTC, SZ_256),
+       [1] = DEFINE_RES_IRQ(IRQ_RTC),
+       [2] = DEFINE_RES_IRQ(IRQ_TICK),
+};
+
+struct platform_device s3c_device_rtc = {
+       .name           = "s3c2410-rtc",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(s3c_rtc_resource),
+       .resource       = s3c_rtc_resource,
+};
+#endif /* CONFIG_PLAT_S3C24XX */
+
+#ifdef CONFIG_S3C_DEV_RTC
+static struct resource s3c_rtc_resource[] = {
+       [0] = DEFINE_RES_MEM(S3C_PA_RTC, SZ_256),
+       [1] = DEFINE_RES_IRQ(IRQ_RTC_ALARM),
+       [2] = DEFINE_RES_IRQ(IRQ_RTC_TIC),
+};
+
+struct platform_device s3c_device_rtc = {
+       .name           = "s3c64xx-rtc",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(s3c_rtc_resource),
+       .resource       = s3c_rtc_resource,
+};
+#endif /* CONFIG_S3C_DEV_RTC */
+
+/* SDI */
+
+#ifdef CONFIG_PLAT_S3C24XX
+static struct resource s3c_sdi_resource[] = {
+       [0] = DEFINE_RES_MEM(S3C24XX_PA_SDI, S3C24XX_SZ_SDI),
+       [1] = DEFINE_RES_IRQ(IRQ_SDI),
+};
+
+struct platform_device s3c_device_sdi = {
+       .name           = "s3c2410-sdi",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(s3c_sdi_resource),
+       .resource       = s3c_sdi_resource,
+};
+
+void __init s3c24xx_mci_set_platdata(struct s3c24xx_mci_pdata *pdata)
+{
+       s3c_set_platdata(pdata, sizeof(struct s3c24xx_mci_pdata),
+                        &s3c_device_sdi);
+}
+#endif /* CONFIG_PLAT_S3C24XX */
+
+/* SPI */
+
+#ifdef CONFIG_PLAT_S3C24XX
+static struct resource s3c_spi0_resource[] = {
+       [0] = DEFINE_RES_MEM(S3C24XX_PA_SPI, SZ_32),
+       [1] = DEFINE_RES_IRQ(IRQ_SPI0),
+};
+
+struct platform_device s3c_device_spi0 = {
+       .name           = "s3c2410-spi",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(s3c_spi0_resource),
+       .resource       = s3c_spi0_resource,
+       .dev            = {
+               .dma_mask               = &samsung_device_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       }
+};
+
+static struct resource s3c_spi1_resource[] = {
+       [0] = DEFINE_RES_MEM(S3C24XX_PA_SPI1, SZ_32),
+       [1] = DEFINE_RES_IRQ(IRQ_SPI1),
+};
+
+struct platform_device s3c_device_spi1 = {
+       .name           = "s3c2410-spi",
+       .id             = 1,
+       .num_resources  = ARRAY_SIZE(s3c_spi1_resource),
+       .resource       = s3c_spi1_resource,
+       .dev            = {
+               .dma_mask               = &samsung_device_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       }
+};
+#endif /* CONFIG_PLAT_S3C24XX */
+
+/* Touchscreen */
+
+#ifdef CONFIG_PLAT_S3C24XX
+static struct resource s3c_ts_resource[] = {
+       [0] = DEFINE_RES_MEM(S3C24XX_PA_ADC, S3C24XX_SZ_ADC),
+       [1] = DEFINE_RES_IRQ(IRQ_TC),
+};
+
+struct platform_device s3c_device_ts = {
+       .name           = "s3c2410-ts",
+       .id             = -1,
+       .dev.parent     = &s3c_device_adc.dev,
+       .num_resources  = ARRAY_SIZE(s3c_ts_resource),
+       .resource       = s3c_ts_resource,
+};
+
+void __init s3c24xx_ts_set_platdata(struct s3c2410_ts_mach_info *hard_s3c2410ts_info)
+{
+       s3c_set_platdata(hard_s3c2410ts_info,
+                        sizeof(struct s3c2410_ts_mach_info), &s3c_device_ts);
+}
+#endif /* CONFIG_PLAT_S3C24XX */
+
+#ifdef CONFIG_SAMSUNG_DEV_TS
+static struct resource s3c_ts_resource[] = {
+       [0] = DEFINE_RES_MEM(SAMSUNG_PA_ADC, SZ_256),
+       [1] = DEFINE_RES_IRQ(IRQ_TC),
+};
+
+static struct s3c2410_ts_mach_info default_ts_data __initdata = {
+       .delay                  = 10000,
+       .presc                  = 49,
+       .oversampling_shift     = 2,
+};
+
+struct platform_device s3c_device_ts = {
+       .name           = "s3c64xx-ts",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(s3c_ts_resource),
+       .resource       = s3c_ts_resource,
+};
+
+void __init s3c24xx_ts_set_platdata(struct s3c2410_ts_mach_info *pd)
+{
+       if (!pd)
+               pd = &default_ts_data;
+
+       s3c_set_platdata(pd, sizeof(struct s3c2410_ts_mach_info),
+                        &s3c_device_ts);
+}
+#endif /* CONFIG_SAMSUNG_DEV_TS */
+
+/* TV */
+
+#ifdef CONFIG_S5P_DEV_TV
+
+static struct resource s5p_hdmi_resources[] = {
+       [0] = DEFINE_RES_MEM(S5P_PA_HDMI, SZ_1M),
+       [1] = DEFINE_RES_IRQ(IRQ_HDMI),
+};
+
+struct platform_device s5p_device_hdmi = {
+       .name           = "s5p-hdmi",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(s5p_hdmi_resources),
+       .resource       = s5p_hdmi_resources,
+};
+
+static struct resource s5p_sdo_resources[] = {
+       [0] = DEFINE_RES_MEM(S5P_PA_SDO, SZ_64K),
+       [1] = DEFINE_RES_IRQ(IRQ_SDO),
+};
+
+struct platform_device s5p_device_sdo = {
+       .name           = "s5p-sdo",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(s5p_sdo_resources),
+       .resource       = s5p_sdo_resources,
+};
+
+static struct resource s5p_mixer_resources[] = {
+       [0] = DEFINE_RES_MEM_NAMED(S5P_PA_MIXER, SZ_64K, "mxr"),
+       [1] = DEFINE_RES_MEM_NAMED(S5P_PA_VP, SZ_64K, "vp"),
+       [2] = DEFINE_RES_IRQ_NAMED(IRQ_MIXER, "irq"),
+};
+
+struct platform_device s5p_device_mixer = {
+       .name           = "s5p-mixer",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(s5p_mixer_resources),
+       .resource       = s5p_mixer_resources,
+       .dev            = {
+               .dma_mask               = &samsung_device_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       }
+};
+#endif /* CONFIG_S5P_DEV_TV */
+
+/* USB */
+
+#ifdef CONFIG_S3C_DEV_USB_HOST
+static struct resource s3c_usb_resource[] = {
+       [0] = DEFINE_RES_MEM(S3C_PA_USBHOST, SZ_256),
+       [1] = DEFINE_RES_IRQ(IRQ_USBH),
+};
+
+struct platform_device s3c_device_ohci = {
+       .name           = "s3c2410-ohci",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(s3c_usb_resource),
+       .resource       = s3c_usb_resource,
+       .dev            = {
+               .dma_mask               = &samsung_device_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       }
+};
+
+/*
+ * s3c_ohci_set_platdata - initialise OHCI device platform data
+ * @info: The platform data.
+ *
+ * This call copies the @info passed in and sets the device .platform_data
+ * field to that copy. The @info is copied so that the original can be marked
+ * __initdata.
+ */
+
+void __init s3c_ohci_set_platdata(struct s3c2410_hcd_info *info)
+{
+       s3c_set_platdata(info, sizeof(struct s3c2410_hcd_info),
+                        &s3c_device_ohci);
+}
+#endif /* CONFIG_S3C_DEV_USB_HOST */
+
+/* USB Device (Gadget) */
+
+#ifdef CONFIG_PLAT_S3C24XX
+static struct resource s3c_usbgadget_resource[] = {
+       [0] = DEFINE_RES_MEM(S3C24XX_PA_USBDEV, S3C24XX_SZ_USBDEV),
+       [1] = DEFINE_RES_IRQ(IRQ_USBD),
+};
+
+struct platform_device s3c_device_usbgadget = {
+       .name           = "s3c2410-usbgadget",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(s3c_usbgadget_resource),
+       .resource       = s3c_usbgadget_resource,
+};
+
+void __init s3c24xx_udc_set_platdata(struct s3c2410_udc_mach_info *pd)
+{
+       s3c_set_platdata(pd, sizeof(*pd), &s3c_device_usbgadget);
+}
+#endif /* CONFIG_PLAT_S3C24XX */
+
+/* USB EHCI Host Controller */
+
+#ifdef CONFIG_S5P_DEV_USB_EHCI
+static struct resource s5p_ehci_resource[] = {
+       [0] = DEFINE_RES_MEM(S5P_PA_EHCI, SZ_256),
+       [1] = DEFINE_RES_IRQ(IRQ_USB_HOST),
+};
+
+struct platform_device s5p_device_ehci = {
+       .name           = "s5p-ehci",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(s5p_ehci_resource),
+       .resource       = s5p_ehci_resource,
+       .dev            = {
+               .dma_mask               = &samsung_device_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       }
+};
+
+void __init s5p_ehci_set_platdata(struct s5p_ehci_platdata *pd)
+{
+       struct s5p_ehci_platdata *npd;
+
+       npd = s3c_set_platdata(pd, sizeof(struct s5p_ehci_platdata),
+                       &s5p_device_ehci);
+
+       if (!npd->phy_init)
+               npd->phy_init = s5p_usb_phy_init;
+       if (!npd->phy_exit)
+               npd->phy_exit = s5p_usb_phy_exit;
+}
+#endif /* CONFIG_S5P_DEV_USB_EHCI */
+
+/* USB HSOTG */
+
+#ifdef CONFIG_S3C_DEV_USB_HSOTG
+static struct resource s3c_usb_hsotg_resources[] = {
+       [0] = DEFINE_RES_MEM(S3C_PA_USB_HSOTG, SZ_16K),
+       [1] = DEFINE_RES_IRQ(IRQ_OTG),
+};
+
+struct platform_device s3c_device_usb_hsotg = {
+       .name           = "s3c-hsotg",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(s3c_usb_hsotg_resources),
+       .resource       = s3c_usb_hsotg_resources,
+       .dev            = {
+               .dma_mask               = &samsung_device_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       },
+};
+#endif /* CONFIG_S3C_DEV_USB_HSOTG */
+
+/* USB High Spped 2.0 Device (Gadget) */
+
+#ifdef CONFIG_PLAT_S3C24XX
+static struct resource s3c_hsudc_resource[] = {
+       [0] = DEFINE_RES_MEM(S3C2416_PA_HSUDC, S3C2416_SZ_HSUDC),
+       [1] = DEFINE_RES_IRQ(IRQ_USBD),
+};
+
+struct platform_device s3c_device_usb_hsudc = {
+       .name           = "s3c-hsudc",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(s3c_hsudc_resource),
+       .resource       = s3c_hsudc_resource,
+       .dev            = {
+               .dma_mask               = &samsung_device_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       },
+};
+
+void __init s3c24xx_hsudc_set_platdata(struct s3c24xx_hsudc_platdata *pd)
+{
+       s3c_set_platdata(pd, sizeof(*pd), &s3c_device_usb_hsudc);
+}
+#endif /* CONFIG_PLAT_S3C24XX */
+
+/* WDT */
+
+#ifdef CONFIG_S3C_DEV_WDT
+static struct resource s3c_wdt_resource[] = {
+       [0] = DEFINE_RES_MEM(S3C_PA_WDT, SZ_1K),
+       [1] = DEFINE_RES_IRQ(IRQ_WDT),
+};
+
+struct platform_device s3c_device_wdt = {
+       .name           = "s3c2410-wdt",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(s3c_wdt_resource),
+       .resource       = s3c_wdt_resource,
+};
+#endif /* CONFIG_S3C_DEV_WDT */
diff --git a/arch/arm/plat-samsung/dma-ops.c b/arch/arm/plat-samsung/dma-ops.c
new file mode 100644 (file)
index 0000000..6e3d9ab
--- /dev/null
@@ -0,0 +1,131 @@
+/* linux/arch/arm/plat-samsung/dma-ops.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Samsung DMA Operations
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/amba/pl330.h>
+#include <linux/scatterlist.h>
+
+#include <mach/dma.h>
+
+static inline bool pl330_filter(struct dma_chan *chan, void *param)
+{
+       struct dma_pl330_peri *peri = chan->private;
+       return peri->peri_id == (unsigned)param;
+}
+
+static unsigned samsung_dmadev_request(enum dma_ch dma_ch,
+                               struct samsung_dma_info *info)
+{
+       struct dma_chan *chan;
+       dma_cap_mask_t mask;
+       struct dma_slave_config slave_config;
+
+       dma_cap_zero(mask);
+       dma_cap_set(info->cap, mask);
+
+       chan = dma_request_channel(mask, pl330_filter, (void *)dma_ch);
+
+       if (info->direction == DMA_FROM_DEVICE) {
+               memset(&slave_config, 0, sizeof(struct dma_slave_config));
+               slave_config.direction = info->direction;
+               slave_config.src_addr = info->fifo;
+               slave_config.src_addr_width = info->width;
+               slave_config.src_maxburst = 1;
+               dmaengine_slave_config(chan, &slave_config);
+       } else if (info->direction == DMA_TO_DEVICE) {
+               memset(&slave_config, 0, sizeof(struct dma_slave_config));
+               slave_config.direction = info->direction;
+               slave_config.dst_addr = info->fifo;
+               slave_config.dst_addr_width = info->width;
+               slave_config.dst_maxburst = 1;
+               dmaengine_slave_config(chan, &slave_config);
+       }
+
+       return (unsigned)chan;
+}
+
+static int samsung_dmadev_release(unsigned ch,
+                       struct s3c2410_dma_client *client)
+{
+       dma_release_channel((struct dma_chan *)ch);
+
+       return 0;
+}
+
+static int samsung_dmadev_prepare(unsigned ch,
+                       struct samsung_dma_prep_info *info)
+{
+       struct scatterlist sg;
+       struct dma_chan *chan = (struct dma_chan *)ch;
+       struct dma_async_tx_descriptor *desc;
+
+       switch (info->cap) {
+       case DMA_SLAVE:
+               sg_init_table(&sg, 1);
+               sg_dma_len(&sg) = info->len;
+               sg_set_page(&sg, pfn_to_page(PFN_DOWN(info->buf)),
+                           info->len, offset_in_page(info->buf));
+               sg_dma_address(&sg) = info->buf;
+
+               desc = chan->device->device_prep_slave_sg(chan,
+                       &sg, 1, info->direction, DMA_PREP_INTERRUPT);
+               break;
+       case DMA_CYCLIC:
+               desc = chan->device->device_prep_dma_cyclic(chan,
+                       info->buf, info->len, info->period, info->direction);
+               break;
+       default:
+               dev_err(&chan->dev->device, "unsupported format\n");
+               return -EFAULT;
+       }
+
+       if (!desc) {
+               dev_err(&chan->dev->device, "cannot prepare cyclic dma\n");
+               return -EFAULT;
+       }
+
+       desc->callback = info->fp;
+       desc->callback_param = info->fp_param;
+
+       dmaengine_submit((struct dma_async_tx_descriptor *)desc);
+
+       return 0;
+}
+
+static inline int samsung_dmadev_trigger(unsigned ch)
+{
+       dma_async_issue_pending((struct dma_chan *)ch);
+
+       return 0;
+}
+
+static inline int samsung_dmadev_flush(unsigned ch)
+{
+       return dmaengine_terminate_all((struct dma_chan *)ch);
+}
+
+struct samsung_dma_ops dmadev_ops = {
+       .request        = samsung_dmadev_request,
+       .release        = samsung_dmadev_release,
+       .prepare        = samsung_dmadev_prepare,
+       .trigger        = samsung_dmadev_trigger,
+       .started        = NULL,
+       .flush          = samsung_dmadev_flush,
+       .stop           = samsung_dmadev_flush,
+};
+
+void *samsung_dmadev_get_ops(void)
+{
+       return &dmadev_ops;
+}
+EXPORT_SYMBOL(samsung_dmadev_get_ops);
diff --git a/arch/arm/plat-samsung/gpio-config.c b/arch/arm/plat-samsung/gpio-config.c
deleted file mode 100644 (file)
index 1c0b040..0000000
+++ /dev/null
@@ -1,431 +0,0 @@
-/* linux/arch/arm/plat-s3c/gpio-config.c
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008-2010 Simtec Electronics
- *     Ben Dooks <ben@simtec.co.uk>
- *     http://armlinux.simtec.co.uk/
- *
- * S3C series GPIO configuration core
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/gpio.h>
-#include <linux/io.h>
-
-#include <plat/gpio-core.h>
-#include <plat/gpio-cfg.h>
-#include <plat/gpio-cfg-helpers.h>
-
-int s3c_gpio_cfgpin(unsigned int pin, unsigned int config)
-{
-       struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
-       unsigned long flags;
-       int offset;
-       int ret;
-
-       if (!chip)
-               return -EINVAL;
-
-       offset = pin - chip->chip.base;
-
-       s3c_gpio_lock(chip, flags);
-       ret = s3c_gpio_do_setcfg(chip, offset, config);
-       s3c_gpio_unlock(chip, flags);
-
-       return ret;
-}
-EXPORT_SYMBOL(s3c_gpio_cfgpin);
-
-int s3c_gpio_cfgpin_range(unsigned int start, unsigned int nr,
-                         unsigned int cfg)
-{
-       int ret;
-
-       for (; nr > 0; nr--, start++) {
-               ret = s3c_gpio_cfgpin(start, cfg);
-               if (ret != 0)
-                       return ret;
-       }
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(s3c_gpio_cfgpin_range);
-
-int s3c_gpio_cfgall_range(unsigned int start, unsigned int nr,
-                         unsigned int cfg, s3c_gpio_pull_t pull)
-{
-       int ret;
-
-       for (; nr > 0; nr--, start++) {
-               s3c_gpio_setpull(start, pull);
-               ret = s3c_gpio_cfgpin(start, cfg);
-               if (ret != 0)
-                       return ret;
-       }
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(s3c_gpio_cfgall_range);
-
-unsigned s3c_gpio_getcfg(unsigned int pin)
-{
-       struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
-       unsigned long flags;
-       unsigned ret = 0;
-       int offset;
-
-       if (chip) {
-               offset = pin - chip->chip.base;
-
-               s3c_gpio_lock(chip, flags);
-               ret = s3c_gpio_do_getcfg(chip, offset);
-               s3c_gpio_unlock(chip, flags);
-       }
-
-       return ret;
-}
-EXPORT_SYMBOL(s3c_gpio_getcfg);
-
-
-int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull)
-{
-       struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
-       unsigned long flags;
-       int offset, ret;
-
-       if (!chip)
-               return -EINVAL;
-
-       offset = pin - chip->chip.base;
-
-       s3c_gpio_lock(chip, flags);
-       ret = s3c_gpio_do_setpull(chip, offset, pull);
-       s3c_gpio_unlock(chip, flags);
-
-       return ret;
-}
-EXPORT_SYMBOL(s3c_gpio_setpull);
-
-s3c_gpio_pull_t s3c_gpio_getpull(unsigned int pin)
-{
-       struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
-       unsigned long flags;
-       int offset;
-       u32 pup = 0;
-
-       if (chip) {
-               offset = pin - chip->chip.base;
-
-               s3c_gpio_lock(chip, flags);
-               pup = s3c_gpio_do_getpull(chip, offset);
-               s3c_gpio_unlock(chip, flags);
-       }
-
-       return (__force s3c_gpio_pull_t)pup;
-}
-EXPORT_SYMBOL(s3c_gpio_getpull);
-
-#ifdef CONFIG_S3C_GPIO_CFG_S3C24XX
-int s3c_gpio_setcfg_s3c24xx_a(struct s3c_gpio_chip *chip,
-                             unsigned int off, unsigned int cfg)
-{
-       void __iomem *reg = chip->base;
-       unsigned int shift = off;
-       u32 con;
-
-       if (s3c_gpio_is_cfg_special(cfg)) {
-               cfg &= 0xf;
-
-               /* Map output to 0, and SFN2 to 1 */
-               cfg -= 1;
-               if (cfg > 1)
-                       return -EINVAL;
-
-               cfg <<= shift;
-       }
-
-       con = __raw_readl(reg);
-       con &= ~(0x1 << shift);
-       con |= cfg;
-       __raw_writel(con, reg);
-
-       return 0;
-}
-
-unsigned s3c_gpio_getcfg_s3c24xx_a(struct s3c_gpio_chip *chip,
-                                  unsigned int off)
-{
-       u32 con;
-
-       con = __raw_readl(chip->base);
-       con >>= off;
-       con &= 1;
-       con++;
-
-       return S3C_GPIO_SFN(con);
-}
-
-int s3c_gpio_setcfg_s3c24xx(struct s3c_gpio_chip *chip,
-                           unsigned int off, unsigned int cfg)
-{
-       void __iomem *reg = chip->base;
-       unsigned int shift = off * 2;
-       u32 con;
-
-       if (s3c_gpio_is_cfg_special(cfg)) {
-               cfg &= 0xf;
-               if (cfg > 3)
-                       return -EINVAL;
-
-               cfg <<= shift;
-       }
-
-       con = __raw_readl(reg);
-       con &= ~(0x3 << shift);
-       con |= cfg;
-       __raw_writel(con, reg);
-
-       return 0;
-}
-
-unsigned int s3c_gpio_getcfg_s3c24xx(struct s3c_gpio_chip *chip,
-                                    unsigned int off)
-{
-       u32 con;
-
-       con = __raw_readl(chip->base);
-       con >>= off * 2;
-       con &= 3;
-
-       /* this conversion works for IN and OUT as well as special mode */
-       return S3C_GPIO_SPECIAL(con);
-}
-#endif
-
-#ifdef CONFIG_S3C_GPIO_CFG_S3C64XX
-int s3c_gpio_setcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
-                                unsigned int off, unsigned int cfg)
-{
-       void __iomem *reg = chip->base;
-       unsigned int shift = (off & 7) * 4;
-       u32 con;
-
-       if (off < 8 && chip->chip.ngpio > 8)
-               reg -= 4;
-
-       if (s3c_gpio_is_cfg_special(cfg)) {
-               cfg &= 0xf;
-               cfg <<= shift;
-       }
-
-       con = __raw_readl(reg);
-       con &= ~(0xf << shift);
-       con |= cfg;
-       __raw_writel(con, reg);
-
-       return 0;
-}
-
-unsigned s3c_gpio_getcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
-                                     unsigned int off)
-{
-       void __iomem *reg = chip->base;
-       unsigned int shift = (off & 7) * 4;
-       u32 con;
-
-       if (off < 8 && chip->chip.ngpio > 8)
-               reg -= 4;
-
-       con = __raw_readl(reg);
-       con >>= shift;
-       con &= 0xf;
-
-       /* this conversion works for IN and OUT as well as special mode */
-       return S3C_GPIO_SPECIAL(con);
-}
-
-#endif /* CONFIG_S3C_GPIO_CFG_S3C64XX */
-
-#ifdef CONFIG_S3C_GPIO_PULL_UPDOWN
-int s3c_gpio_setpull_updown(struct s3c_gpio_chip *chip,
-                           unsigned int off, s3c_gpio_pull_t pull)
-{
-       void __iomem *reg = chip->base + 0x08;
-       int shift = off * 2;
-       u32 pup;
-
-       pup = __raw_readl(reg);
-       pup &= ~(3 << shift);
-       pup |= pull << shift;
-       __raw_writel(pup, reg);
-
-       return 0;
-}
-
-s3c_gpio_pull_t s3c_gpio_getpull_updown(struct s3c_gpio_chip *chip,
-                                       unsigned int off)
-{
-       void __iomem *reg = chip->base + 0x08;
-       int shift = off * 2;
-       u32 pup = __raw_readl(reg);
-
-       pup >>= shift;
-       pup &= 0x3;
-       return (__force s3c_gpio_pull_t)pup;
-}
-
-#ifdef CONFIG_S3C_GPIO_PULL_S3C2443
-int s3c_gpio_setpull_s3c2443(struct s3c_gpio_chip *chip,
-                               unsigned int off, s3c_gpio_pull_t pull)
-{
-       switch (pull) {
-       case S3C_GPIO_PULL_NONE:
-               pull = 0x01;
-               break;
-       case S3C_GPIO_PULL_UP:
-               pull = 0x00;
-               break;
-       case S3C_GPIO_PULL_DOWN:
-               pull = 0x02;
-               break;
-       }
-       return s3c_gpio_setpull_updown(chip, off, pull);
-}
-
-s3c_gpio_pull_t s3c_gpio_getpull_s3c2443(struct s3c_gpio_chip *chip,
-                                       unsigned int off)
-{
-       s3c_gpio_pull_t pull;
-
-       pull = s3c_gpio_getpull_updown(chip, off);
-
-       switch (pull) {
-       case 0x00:
-               pull = S3C_GPIO_PULL_UP;
-               break;
-       case 0x01:
-       case 0x03:
-               pull = S3C_GPIO_PULL_NONE;
-               break;
-       case 0x02:
-               pull = S3C_GPIO_PULL_DOWN;
-               break;
-       }
-
-       return pull;
-}
-#endif
-#endif
-
-#if defined(CONFIG_S3C_GPIO_PULL_UP) || defined(CONFIG_S3C_GPIO_PULL_DOWN)
-static int s3c_gpio_setpull_1(struct s3c_gpio_chip *chip,
-                        unsigned int off, s3c_gpio_pull_t pull,
-                        s3c_gpio_pull_t updown)
-{
-       void __iomem *reg = chip->base + 0x08;
-       u32 pup = __raw_readl(reg);
-
-       if (pull == updown)
-               pup &= ~(1 << off);
-       else if (pull == S3C_GPIO_PULL_NONE)
-               pup |= (1 << off);
-       else
-               return -EINVAL;
-
-       __raw_writel(pup, reg);
-       return 0;
-}
-
-static s3c_gpio_pull_t s3c_gpio_getpull_1(struct s3c_gpio_chip *chip,
-                                    unsigned int off, s3c_gpio_pull_t updown)
-{
-       void __iomem *reg = chip->base + 0x08;
-       u32 pup = __raw_readl(reg);
-
-       pup &= (1 << off);
-       return pup ? S3C_GPIO_PULL_NONE : updown;
-}
-#endif /* CONFIG_S3C_GPIO_PULL_UP || CONFIG_S3C_GPIO_PULL_DOWN */
-
-#ifdef CONFIG_S3C_GPIO_PULL_UP
-s3c_gpio_pull_t s3c_gpio_getpull_1up(struct s3c_gpio_chip *chip,
-                                    unsigned int off)
-{
-       return s3c_gpio_getpull_1(chip, off, S3C_GPIO_PULL_UP);
-}
-
-int s3c_gpio_setpull_1up(struct s3c_gpio_chip *chip,
-                        unsigned int off, s3c_gpio_pull_t pull)
-{
-       return s3c_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_UP);
-}
-#endif /* CONFIG_S3C_GPIO_PULL_UP */
-
-#ifdef CONFIG_S3C_GPIO_PULL_DOWN
-s3c_gpio_pull_t s3c_gpio_getpull_1down(struct s3c_gpio_chip *chip,
-                                    unsigned int off)
-{
-       return s3c_gpio_getpull_1(chip, off, S3C_GPIO_PULL_DOWN);
-}
-
-int s3c_gpio_setpull_1down(struct s3c_gpio_chip *chip,
-                        unsigned int off, s3c_gpio_pull_t pull)
-{
-       return s3c_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_DOWN);
-}
-#endif /* CONFIG_S3C_GPIO_PULL_DOWN */
-
-#ifdef CONFIG_S5P_GPIO_DRVSTR
-s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin)
-{
-       struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
-       unsigned int off;
-       void __iomem *reg;
-       int shift;
-       u32 drvstr;
-
-       if (!chip)
-               return -EINVAL;
-
-       off = pin - chip->chip.base;
-       shift = off * 2;
-       reg = chip->base + 0x0C;
-
-       drvstr = __raw_readl(reg);
-       drvstr = drvstr >> shift;
-       drvstr &= 0x3;
-
-       return (__force s5p_gpio_drvstr_t)drvstr;
-}
-EXPORT_SYMBOL(s5p_gpio_get_drvstr);
-
-int s5p_gpio_set_drvstr(unsigned int pin, s5p_gpio_drvstr_t drvstr)
-{
-       struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
-       unsigned int off;
-       void __iomem *reg;
-       int shift;
-       u32 tmp;
-
-       if (!chip)
-               return -EINVAL;
-
-       off = pin - chip->chip.base;
-       shift = off * 2;
-       reg = chip->base + 0x0C;
-
-       tmp = __raw_readl(reg);
-       tmp &= ~(0x3 << shift);
-       tmp |= drvstr << shift;
-
-       __raw_writel(tmp, reg);
-
-       return 0;
-}
-EXPORT_SYMBOL(s5p_gpio_set_drvstr);
-#endif /* CONFIG_S5P_GPIO_DRVSTR */
diff --git a/arch/arm/plat-samsung/gpio.c b/arch/arm/plat-samsung/gpio.c
deleted file mode 100644 (file)
index 7743c4b..0000000
+++ /dev/null
@@ -1,167 +0,0 @@
-/* linux/arch/arm/plat-s3c/gpio.c
- *
- * Copyright 2008 Simtec Electronics
- *     Ben Dooks <ben@simtec.co.uk>
- *     http://armlinux.simtec.co.uk/
- *
- * S3C series GPIO core
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <linux/spinlock.h>
-
-#include <plat/gpio-core.h>
-
-#ifdef CONFIG_S3C_GPIO_TRACK
-struct s3c_gpio_chip *s3c_gpios[S3C_GPIO_END];
-
-static __init void s3c_gpiolib_track(struct s3c_gpio_chip *chip)
-{
-       unsigned int gpn;
-       int i;
-
-       gpn = chip->chip.base;
-       for (i = 0; i < chip->chip.ngpio; i++, gpn++) {
-               BUG_ON(gpn >= ARRAY_SIZE(s3c_gpios));
-               s3c_gpios[gpn] = chip;
-       }
-}
-#endif /* CONFIG_S3C_GPIO_TRACK */
-
-/* Default routines for controlling GPIO, based on the original S3C24XX
- * GPIO functions which deal with the case where each gpio bank of the
- * chip is as following:
- *
- * base + 0x00: Control register, 2 bits per gpio
- *             gpio n: 2 bits starting at (2*n)
- *             00 = input, 01 = output, others mean special-function
- * base + 0x04: Data register, 1 bit per gpio
- *             bit n: data bit n
-*/
-
-static int s3c_gpiolib_input(struct gpio_chip *chip, unsigned offset)
-{
-       struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-       void __iomem *base = ourchip->base;
-       unsigned long flags;
-       unsigned long con;
-
-       s3c_gpio_lock(ourchip, flags);
-
-       con = __raw_readl(base + 0x00);
-       con &= ~(3 << (offset * 2));
-
-       __raw_writel(con, base + 0x00);
-
-       s3c_gpio_unlock(ourchip, flags);
-       return 0;
-}
-
-static int s3c_gpiolib_output(struct gpio_chip *chip,
-                             unsigned offset, int value)
-{
-       struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-       void __iomem *base = ourchip->base;
-       unsigned long flags;
-       unsigned long dat;
-       unsigned long con;
-
-       s3c_gpio_lock(ourchip, flags);
-
-       dat = __raw_readl(base + 0x04);
-       dat &= ~(1 << offset);
-       if (value)
-               dat |= 1 << offset;
-       __raw_writel(dat, base + 0x04);
-
-       con = __raw_readl(base + 0x00);
-       con &= ~(3 << (offset * 2));
-       con |= 1 << (offset * 2);
-
-       __raw_writel(con, base + 0x00);
-       __raw_writel(dat, base + 0x04);
-
-       s3c_gpio_unlock(ourchip, flags);
-       return 0;
-}
-
-static void s3c_gpiolib_set(struct gpio_chip *chip,
-                           unsigned offset, int value)
-{
-       struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-       void __iomem *base = ourchip->base;
-       unsigned long flags;
-       unsigned long dat;
-
-       s3c_gpio_lock(ourchip, flags);
-
-       dat = __raw_readl(base + 0x04);
-       dat &= ~(1 << offset);
-       if (value)
-               dat |= 1 << offset;
-       __raw_writel(dat, base + 0x04);
-
-       s3c_gpio_unlock(ourchip, flags);
-}
-
-static int s3c_gpiolib_get(struct gpio_chip *chip, unsigned offset)
-{
-       struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-       unsigned long val;
-
-       val = __raw_readl(ourchip->base + 0x04);
-       val >>= offset;
-       val &= 1;
-
-       return val;
-}
-
-__init void s3c_gpiolib_add(struct s3c_gpio_chip *chip)
-{
-       struct gpio_chip *gc = &chip->chip;
-       int ret;
-
-       BUG_ON(!chip->base);
-       BUG_ON(!gc->label);
-       BUG_ON(!gc->ngpio);
-
-       spin_lock_init(&chip->lock);
-
-       if (!gc->direction_input)
-               gc->direction_input = s3c_gpiolib_input;
-       if (!gc->direction_output)
-               gc->direction_output = s3c_gpiolib_output;
-       if (!gc->set)
-               gc->set = s3c_gpiolib_set;
-       if (!gc->get)
-               gc->get = s3c_gpiolib_get;
-
-#ifdef CONFIG_PM
-       if (chip->pm != NULL) {
-               if (!chip->pm->save || !chip->pm->resume)
-                       printk(KERN_ERR "gpio: %s has missing PM functions\n",
-                              gc->label);
-       } else
-               printk(KERN_ERR "gpio: %s has no PM function\n", gc->label);
-#endif
-
-       /* gpiochip_add() prints own failure message on error. */
-       ret = gpiochip_add(gc);
-       if (ret >= 0)
-               s3c_gpiolib_track(chip);
-}
-
-int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset)
-{
-       struct s3c_gpio_chip *s3c_chip = container_of(chip,
-                       struct s3c_gpio_chip, chip);
-
-       return s3c_chip->irq_base + offset;
-}
index a281568..a927bee 100644 (file)
@@ -20,7 +20,7 @@
 /* re-define device name depending on support. */
 static inline void s3c_adc_setname(char *name)
 {
-#ifdef CONFIG_SAMSUNG_DEV_ADC
+#if defined(CONFIG_SAMSUNG_DEV_ADC) || defined(CONFIG_PLAT_S3C24XX)
        s3c_device_adc.name = name;
 #endif
 }
@@ -1,4 +1,4 @@
-/* arch/arm/plat-s3c24xx/include/plat/audio-simtec.h
+/* arch/arm/plat-samsung/include/plat/audio-simtec.h
  *
  * Copyright 2008 Simtec Electronics
  *     http://armlinux.simtec.co.uk/
similarity index 86%
rename from arch/arm/plat-s5p/include/plat/camport.h
rename to arch/arm/plat-samsung/include/plat/camport.h
index 71688c8..a5708bf 100644 (file)
@@ -8,8 +8,8 @@
  * published by the Free Software Foundation.
  */
 
-#ifndef PLAT_S5P_CAMPORT_H_
-#define PLAT_S5P_CAMPORT_H_ __FILE__
+#ifndef __PLAT_SAMSUNG_CAMPORT_H_
+#define __PLAT_SAMSUNG_CAMPORT_H_ __FILE__
 
 enum s5p_camport_id {
        S5P_CAMPORT_A,
@@ -25,4 +25,4 @@ enum s5p_camport_id {
 int s5pv210_fimc_setup_gpio(enum s5p_camport_id id);
 int exynos4_fimc_setup_gpio(enum s5p_camport_id id);
 
-#endif
+#endif /* __PLAT_SAMSUNG_CAMPORT_H */
@@ -1,4 +1,4 @@
-/* linux/include/asm-arm/plat-s3c24xx/common-smdk.h
+/* linux/arch/arm/plat-samsung/include/plat/common-smdk.h
  *
  * Copyright (c) 2006 Simtec Electronics
  *     Ben Dooks <ben@simtec.co.uk>
@@ -1,4 +1,4 @@
-/* arch/arm/plat-s3c/include/plat/cpu-freq.h
+/* arch/arm/plat-samsung/include/plat/cpu-freq-core.h
  *
  * Copyright (c) 2006-2009 Simtec Electronics
  *     http://armlinux.simtec.co.uk/
@@ -195,7 +195,8 @@ struct s3c_cpufreq_info {
 
 extern int s3c_cpufreq_register(struct s3c_cpufreq_info *info);
 
-extern int s3c_plltab_register(struct cpufreq_frequency_table *plls, unsigned int plls_no);
+extern int s3c_plltab_register(struct cpufreq_frequency_table *plls,
+                              unsigned int plls_no);
 
 /* exports and utilities for debugfs */
 extern struct s3c_cpufreq_config *s3c_cpufreq_getconfig(void);
index 54f370f..40fd7b6 100644 (file)
@@ -25,7 +25,6 @@ extern unsigned long samsung_cpu_id;
 
 #define S3C6400_CPU_ID         0x36400000
 #define S3C6410_CPU_ID         0x36410000
-#define S3C64XX_CPU_ID         (S3C6400_CPU_ID & S3C6410_CPU_ID)
 #define S3C64XX_CPU_MASK       0xFFFFF000
 
 #define S5P6440_CPU_ID         0x56440000
@@ -50,7 +49,8 @@ static inline int is_samsung_##name(void)     \
 }
 
 IS_SAMSUNG_CPU(s3c24xx, S3C24XX_CPU_ID, S3C24XX_CPU_MASK)
-IS_SAMSUNG_CPU(s3c64xx, S3C64XX_CPU_ID, S3C64XX_CPU_MASK)
+IS_SAMSUNG_CPU(s3c6400, S3C6400_CPU_ID, S3C64XX_CPU_MASK)
+IS_SAMSUNG_CPU(s3c6410, S3C6410_CPU_ID, S3C64XX_CPU_MASK)
 IS_SAMSUNG_CPU(s5p6440, S5P6440_CPU_ID, S5P64XX_CPU_MASK)
 IS_SAMSUNG_CPU(s5p6450, S5P6450_CPU_ID, S5P64XX_CPU_MASK)
 IS_SAMSUNG_CPU(s5pc100, S5PC100_CPU_ID, S5PC100_CPU_MASK)
@@ -69,7 +69,7 @@ IS_SAMSUNG_CPU(exynos4412, EXYNOS4412_CPU_ID, EXYNOS4_CPU_MASK)
 #endif
 
 #if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
-# define soc_is_s3c64xx()      is_samsung_s3c64xx()
+# define soc_is_s3c64xx()      (is_samsung_s3c6400() || is_samsung_s3c6410())
 #else
 # define soc_is_s3c64xx()      0
 #endif
index 24ebb1e..ab633c9 100644 (file)
@@ -30,30 +30,24 @@ extern struct s3c24xx_uart_resources s5p_uart_resources[];
 extern struct platform_device *s3c24xx_uart_devs[];
 extern struct platform_device *s3c24xx_uart_src[];
 
-extern struct platform_device s3c_device_timer[];
-
+extern struct platform_device s3c64xx_device_ac97;
 extern struct platform_device s3c64xx_device_iis0;
 extern struct platform_device s3c64xx_device_iis1;
 extern struct platform_device s3c64xx_device_iisv4;
-
-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_onenand1;
 extern struct platform_device s3c64xx_device_pcm0;
 extern struct platform_device s3c64xx_device_pcm1;
+extern struct platform_device s3c64xx_device_spi0;
+extern struct platform_device s3c64xx_device_spi1;
 
-extern struct platform_device s3c64xx_device_ac97;
-
-extern struct platform_device s3c_device_ts;
-
+extern struct platform_device s3c_device_adc;
+extern struct platform_device s3c_device_cfcon;
 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;
+extern struct platform_device s3c_device_hwmon;
+extern struct platform_device s3c_device_hsmmc0;
+extern struct platform_device s3c_device_hsmmc1;
+extern struct platform_device s3c_device_hsmmc2;
+extern struct platform_device s3c_device_hsmmc3;
 extern struct platform_device s3c_device_i2c0;
 extern struct platform_device s3c_device_i2c1;
 extern struct platform_device s3c_device_i2c2;
@@ -62,93 +56,90 @@ extern struct platform_device s3c_device_i2c4;
 extern struct platform_device s3c_device_i2c5;
 extern struct platform_device s3c_device_i2c6;
 extern struct platform_device s3c_device_i2c7;
+extern struct platform_device s3c_device_iis;
+extern struct platform_device s3c_device_lcd;
+extern struct platform_device s3c_device_nand;
+extern struct platform_device s3c_device_ohci;
+extern struct platform_device s3c_device_onenand;
 extern struct platform_device s3c_device_rtc;
-extern struct platform_device s3c_device_adc;
 extern struct platform_device s3c_device_sdi;
-extern struct platform_device s3c_device_iis;
-extern struct platform_device s3c_device_hwmon;
-extern struct platform_device s3c_device_hsmmc0;
-extern struct platform_device s3c_device_hsmmc1;
-extern struct platform_device s3c_device_hsmmc2;
-extern struct platform_device s3c_device_hsmmc3;
-extern struct platform_device s3c_device_cfcon;
-
 extern struct platform_device s3c_device_spi0;
 extern struct platform_device s3c_device_spi1;
-
-extern struct platform_device s5pc100_device_spi0;
-extern struct platform_device s5pc100_device_spi1;
-extern struct platform_device s5pc100_device_spi2;
-extern struct platform_device s5pv210_device_spi0;
-extern struct platform_device s5pv210_device_spi1;
-extern struct platform_device s5p64x0_device_spi0;
-extern struct platform_device s5p64x0_device_spi1;
-
-extern struct platform_device s3c_device_hwmon;
-
-extern struct platform_device s3c_device_nand;
-extern struct platform_device s3c_device_onenand;
-extern struct platform_device s3c64xx_device_onenand1;
-extern struct platform_device s5p_device_onenand;
-
+extern struct platform_device s3c_device_ts;
+extern struct platform_device s3c_device_timer[];
 extern struct platform_device s3c_device_usbgadget;
-extern struct platform_device s3c_device_usb_hsudc;
 extern struct platform_device s3c_device_usb_hsotg;
+extern struct platform_device s3c_device_usb_hsudc;
+extern struct platform_device s3c_device_wdt;
 
-extern struct platform_device s5pv210_device_ac97;
-extern struct platform_device s5pv210_device_pcm0;
-extern struct platform_device s5pv210_device_pcm1;
-extern struct platform_device s5pv210_device_pcm2;
-extern struct platform_device s5pv210_device_iis0;
-extern struct platform_device s5pv210_device_iis1;
-extern struct platform_device s5pv210_device_iis2;
-extern struct platform_device s5pv210_device_spdif;
-
-extern struct platform_device exynos4_device_ac97;
-extern struct platform_device exynos4_device_pcm0;
-extern struct platform_device exynos4_device_pcm1;
-extern struct platform_device exynos4_device_pcm2;
-extern struct platform_device exynos4_device_i2s0;
-extern struct platform_device exynos4_device_i2s1;
-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 s5p_device_ehci;
+extern struct platform_device s5p_device_fimc0;
+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_fimc_md;
+extern struct platform_device s5p_device_fimd0;
+extern struct platform_device s5p_device_hdmi;
+extern struct platform_device s5p_device_i2c_hdmiphy;
+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;
+extern struct platform_device s5p_device_mixer;
+extern struct platform_device s5p_device_onenand;
+extern struct platform_device s5p_device_sdo;
 
-extern struct platform_device s5p6440_device_pcm;
 extern struct platform_device s5p6440_device_iis;
+extern struct platform_device s5p6440_device_pcm;
 
 extern struct platform_device s5p6450_device_iis0;
 extern struct platform_device s5p6450_device_iis1;
 extern struct platform_device s5p6450_device_iis2;
 extern struct platform_device s5p6450_device_pcm0;
 
+extern struct platform_device s5p64x0_device_spi0;
+extern struct platform_device s5p64x0_device_spi1;
+
 extern struct platform_device s5pc100_device_ac97;
-extern struct platform_device s5pc100_device_pcm0;
-extern struct platform_device s5pc100_device_pcm1;
 extern struct platform_device s5pc100_device_iis0;
 extern struct platform_device s5pc100_device_iis1;
 extern struct platform_device s5pc100_device_iis2;
+extern struct platform_device s5pc100_device_pcm0;
+extern struct platform_device s5pc100_device_pcm1;
 extern struct platform_device s5pc100_device_spdif;
+extern struct platform_device s5pc100_device_spi0;
+extern struct platform_device s5pc100_device_spi1;
+extern struct platform_device s5pc100_device_spi2;
 
-extern struct platform_device samsung_device_keypad;
-
-extern struct platform_device s5p_device_fimc0;
-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;
-
-extern struct platform_device s5p_device_ehci;
+extern struct platform_device s5pv210_device_ac97;
+extern struct platform_device s5pv210_device_iis0;
+extern struct platform_device s5pv210_device_iis1;
+extern struct platform_device s5pv210_device_iis2;
+extern struct platform_device s5pv210_device_pcm0;
+extern struct platform_device s5pv210_device_pcm1;
+extern struct platform_device s5pv210_device_pcm2;
+extern struct platform_device s5pv210_device_spdif;
+extern struct platform_device s5pv210_device_spi0;
+extern struct platform_device s5pv210_device_spi1;
 
+extern struct platform_device exynos4_device_ac97;
+extern struct platform_device exynos4_device_ahci;
+extern struct platform_device exynos4_device_dwmci;
+extern struct platform_device exynos4_device_i2s0;
+extern struct platform_device exynos4_device_i2s1;
+extern struct platform_device exynos4_device_i2s2;
+extern struct platform_device exynos4_device_pcm0;
+extern struct platform_device exynos4_device_pcm1;
+extern struct platform_device exynos4_device_pcm2;
+extern struct platform_device exynos4_device_pd[];
+extern struct platform_device exynos4_device_spdif;
 extern struct platform_device exynos4_device_sysmmu;
 
+extern struct platform_device samsung_asoc_dma;
+extern struct platform_device samsung_asoc_idma;
+extern struct platform_device samsung_device_keypad;
+
 /* s3c2440 specific devices */
 
 #ifdef CONFIG_CPU_S3C2440
diff --git a/arch/arm/plat-samsung/include/plat/dma-ops.h b/arch/arm/plat-samsung/include/plat/dma-ops.h
new file mode 100644 (file)
index 0000000..4c1a363
--- /dev/null
@@ -0,0 +1,63 @@
+/* arch/arm/plat-samsung/include/plat/dma-ops.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Samsung DMA 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 __SAMSUNG_DMA_OPS_H_
+#define __SAMSUNG_DMA_OPS_H_ __FILE__
+
+#include <linux/dmaengine.h>
+
+struct samsung_dma_prep_info {
+       enum dma_transaction_type cap;
+       enum dma_data_direction direction;
+       dma_addr_t buf;
+       unsigned long period;
+       unsigned long len;
+       void (*fp)(void *data);
+       void *fp_param;
+};
+
+struct samsung_dma_info {
+       enum dma_transaction_type cap;
+       enum dma_data_direction direction;
+       enum dma_slave_buswidth width;
+       dma_addr_t fifo;
+       struct s3c2410_dma_client *client;
+};
+
+struct samsung_dma_ops {
+       unsigned (*request)(enum dma_ch ch, struct samsung_dma_info *info);
+       int (*release)(unsigned ch, struct s3c2410_dma_client *client);
+       int (*prepare)(unsigned ch, struct samsung_dma_prep_info *info);
+       int (*trigger)(unsigned ch);
+       int (*started)(unsigned ch);
+       int (*flush)(unsigned ch);
+       int (*stop)(unsigned ch);
+};
+
+extern void *samsung_dmadev_get_ops(void);
+extern void *s3c_dma_get_ops(void);
+
+static inline void *__samsung_dma_get_ops(void)
+{
+       if (samsung_dma_is_dmadev())
+               return samsung_dmadev_get_ops();
+       else
+               return s3c_dma_get_ops();
+}
+
+/*
+ * samsung_dma_get_ops
+ * get the set of samsung dma operations
+ */
+#define samsung_dma_get_ops() __samsung_dma_get_ops()
+
+#endif /* __SAMSUNG_DMA_OPS_H_ */
@@ -8,11 +8,8 @@
  * (at your option) any later version.
  */
 
-#ifndef        __S3C_DMA_PL330_H_
-#define        __S3C_DMA_PL330_H_
-
-#define S3C2410_DMAF_AUTOSTART         (1 << 0)
-#define S3C2410_DMAF_CIRCULAR          (1 << 1)
+#ifndef __DMA_PL330_H_
+#define __DMA_PL330_H_ __FILE__
 
 /*
  * PL330 can assign any channel to communicate with
@@ -20,7 +17,7 @@
  * For the sake of consistency across client drivers,
  * We keep the channel names unchanged and only add
  * missing peripherals are added.
- * Order is not important since S3C PL330 API driver
+ * Order is not important since DMA PL330 API driver
  * use these just as IDs.
  */
 enum dma_ch {
@@ -88,11 +85,20 @@ enum dma_ch {
        DMACH_MAX,
 };
 
-static inline bool s3c_dma_has_circular(void)
+struct s3c2410_dma_client {
+       char    *name;
+};
+
+static inline bool samsung_dma_has_circular(void)
+{
+       return true;
+}
+
+static inline bool samsung_dma_is_dmadev(void)
 {
        return true;
 }
 
-#include <plat/dma.h>
+#include <plat/dma-ops.h>
 
-#endif /* __S3C_DMA_PL330_H_ */
+#endif /* __DMA_PL330_H_ */
index ab9bce6..1c1ed54 100644 (file)
@@ -41,7 +41,7 @@ struct s3c24xx_dma_selection {
 
        void    (*direction)(struct s3c2410_dma_chan *chan,
                             struct s3c24xx_dma_map *map,
-                            enum s3c2410_dmasrc dir);
+                            enum dma_data_direction dir);
 };
 
 extern int s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel);
index 8c273b7..b906112 100644 (file)
  * published by the Free Software Foundation.
 */
 
+#include <linux/dma-mapping.h>
+
 enum s3c2410_dma_buffresult {
        S3C2410_RES_OK,
        S3C2410_RES_ERR,
        S3C2410_RES_ABORT
 };
 
-enum s3c2410_dmasrc {
-       S3C2410_DMASRC_HW,              /* source is memory */
-       S3C2410_DMASRC_MEM              /* source is hardware */
-};
-
 /* enum s3c2410_chan_op
  *
  * operation codes passed to the DMA code by the user, and also used
@@ -112,7 +109,7 @@ extern int s3c2410_dma_config(enum dma_ch channel, int xferunit);
 */
 
 extern int s3c2410_dma_devconfig(enum dma_ch channel,
-               enum s3c2410_dmasrc source, unsigned long devaddr);
+               enum dma_data_direction source, unsigned long devaddr);
 
 /* s3c2410_dma_getposition
  *
@@ -126,3 +123,4 @@ extern int s3c2410_dma_set_opfn(enum dma_ch, s3c2410_dma_opfn_t rtn);
 extern int s3c2410_dma_set_buffdone_fn(enum dma_ch, s3c2410_dma_cbfn_t rtn);
 
 
+#include <plat/dma-ops.h>
similarity index 84%
rename from arch/arm/plat-s5p/include/plat/ehci.h
rename to arch/arm/plat-samsung/include/plat/ehci.h
index 6ae6810..5f28cae 100644 (file)
@@ -8,8 +8,8 @@
  * option) any later version.
  */
 
-#ifndef __PLAT_S5P_EHCI_H
-#define __PLAT_S5P_EHCI_H
+#ifndef __PLAT_SAMSUNG_EHCI_H
+#define __PLAT_SAMSUNG_EHCI_H __FILE__
 
 struct s5p_ehci_platdata {
        int (*phy_init)(struct platform_device *pdev, int type);
@@ -18,4 +18,4 @@ struct s5p_ehci_platdata {
 
 extern void s5p_ehci_set_platdata(struct s5p_ehci_platdata *pd);
 
-#endif /* __PLAT_S5P_EHCI_H */
+#endif /* __PLAT_SAMSUNG_EHCI_H */
similarity index 87%
rename from arch/arm/plat-s5p/include/plat/exynos4.h
rename to arch/arm/plat-samsung/include/plat/exynos4.h
index f680a14..f546e88 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/arch/arm/plat-s5p/include/plat/exynos4.h
+/* linux/arch/arm/plat-samsung/include/plat/exynos4.h
  *
  * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com
@@ -18,8 +18,8 @@ extern void exynos4210_register_clocks(void);
 extern void exynos4212_register_clocks(void);
 extern void exynos4_setup_clocks(void);
 
-#ifdef CONFIG_ARCH_EXYNOS4
-extern  int exynos4_init(void);
+#ifdef CONFIG_ARCH_EXYNOS
+extern  int exynos_init(void);
 extern void exynos4_init_irq(void);
 extern void exynos4_map_io(void);
 extern void exynos4_init_clocks(int xtal);
@@ -31,5 +31,5 @@ extern struct sys_timer exynos4_timer;
 #define exynos4_init_clocks NULL
 #define exynos4_init_uarts NULL
 #define exynos4_map_io NULL
-#define exynos4_init NULL
+#define exynos_init NULL
 #endif
diff --git a/arch/arm/plat-samsung/include/plat/fb-s3c2410.h b/arch/arm/plat-samsung/include/plat/fb-s3c2410.h
new file mode 100644 (file)
index 0000000..4e5d958
--- /dev/null
@@ -0,0 +1,72 @@
+/* arch/arm/plat-samsung/include/plat/fb-s3c2410.h
+ *
+ * Copyright (c) 2004 Arnaud Patard <arnaud.patard@rtp-net.org>
+ *
+ * Inspired by pxafb.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_PLAT_FB_S3C2410_H
+#define __ASM_PLAT_FB_S3C2410_H __FILE__
+
+struct s3c2410fb_hw {
+       unsigned long   lcdcon1;
+       unsigned long   lcdcon2;
+       unsigned long   lcdcon3;
+       unsigned long   lcdcon4;
+       unsigned long   lcdcon5;
+};
+
+/* LCD description */
+struct s3c2410fb_display {
+       /* LCD type */
+       unsigned type;
+
+       /* Screen size */
+       unsigned short width;
+       unsigned short height;
+
+       /* Screen info */
+       unsigned short xres;
+       unsigned short yres;
+       unsigned short bpp;
+
+       unsigned pixclock;              /* pixclock in picoseconds */
+       unsigned short left_margin;  /* value in pixels (TFT) or HCLKs (STN) */
+       unsigned short right_margin; /* value in pixels (TFT) or HCLKs (STN) */
+       unsigned short hsync_len;    /* value in pixels (TFT) or HCLKs (STN) */
+       unsigned short upper_margin;    /* value in lines (TFT) or 0 (STN) */
+       unsigned short lower_margin;    /* value in lines (TFT) or 0 (STN) */
+       unsigned short vsync_len;       /* value in lines (TFT) or 0 (STN) */
+
+       /* lcd configuration registers */
+       unsigned long   lcdcon5;
+};
+
+struct s3c2410fb_mach_info {
+
+       struct s3c2410fb_display *displays;     /* attached diplays info */
+       unsigned num_displays;                  /* number of defined displays */
+       unsigned default_display;
+
+       /* GPIOs */
+
+       unsigned long   gpcup;
+       unsigned long   gpcup_mask;
+       unsigned long   gpccon;
+       unsigned long   gpccon_mask;
+       unsigned long   gpdup;
+       unsigned long   gpdup_mask;
+       unsigned long   gpdcon;
+       unsigned long   gpdcon_mask;
+
+       /* lpc3600 control register */
+       unsigned long   lpcsel;
+};
+
+extern void __init s3c24xx_fb_set_platdata(struct s3c2410fb_mach_info *);
+
+#endif /* __ASM_PLAT_FB_S3C2410_H */
index 01f10e4..0fedf47 100644 (file)
@@ -109,4 +109,11 @@ extern void s5pv210_fb_gpio_setup_24bpp(void);
  */
 extern void exynos4_fimd0_gpio_setup_24bpp(void);
 
+/**
+ * s5p64x0_fb_gpio_setup_24bpp() - S5P6440/S5P6450 setup function for 24bpp LCD
+ *
+ * Initialise the GPIO for an 24bpp LCD display on the RGB interface.
+ */
+extern void s5p64x0_fb_gpio_setup_24bpp(void);
+
 #endif /* __PLAT_S3C_FB_H */
similarity index 88%
rename from arch/arm/plat-s3c24xx/include/plat/fiq.h
rename to arch/arm/plat-samsung/include/plat/fiq.h
index 8521b83..535d06a 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/include/asm-arm/plat-s3c24xx/fiq.h
+/* linux/arch/arm/plat-samsung/include/plat/fiq.h
  *
  * Copyright (c) 2009 Simtec Electronics
  *     Ben Dooks <ben@simtec.co.uk>
index 9a4e53d..a181d7c 100644 (file)
@@ -1,11 +1,11 @@
-/* linux/arch/arm/plat-s3c/include/plat/gpio-cfg-helper.h
+/* linux/arch/arm/plat-samsung/include/plat/gpio-cfg-helper.h
  *
  * Copyright 2008 Openmoko, Inc.
  * Copyright 2008 Simtec Electronics
  *     http://armlinux.simtec.co.uk/
  *     Ben Dooks <ben@simtec.co.uk>
  *
- * S3C Platform - GPIO pin configuration helper definitions
+ * Samsung Platform - GPIO pin configuration helper 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
  * by disabling interrupts.
 */
 
-static inline int s3c_gpio_do_setcfg(struct s3c_gpio_chip *chip,
-                                    unsigned int off, unsigned int config)
+static inline int samsung_gpio_do_setcfg(struct samsung_gpio_chip *chip,
+                                        unsigned int off, unsigned int config)
 {
        return (chip->config->set_config)(chip, off, config);
 }
 
-static inline unsigned s3c_gpio_do_getcfg(struct s3c_gpio_chip *chip,
-                                         unsigned int off)
+static inline unsigned samsung_gpio_do_getcfg(struct samsung_gpio_chip *chip,
+                                             unsigned int off)
 {
        return (chip->config->get_config)(chip, off);
 }
 
-static inline int s3c_gpio_do_setpull(struct s3c_gpio_chip *chip,
-                                     unsigned int off, s3c_gpio_pull_t pull)
+static inline int samsung_gpio_do_setpull(struct samsung_gpio_chip *chip,
+                                         unsigned int off, samsung_gpio_pull_t pull)
 {
        return (chip->config->set_pull)(chip, off, pull);
 }
 
-static inline s3c_gpio_pull_t s3c_gpio_do_getpull(struct s3c_gpio_chip *chip,
-                                                 unsigned int off)
+static inline samsung_gpio_pull_t samsung_gpio_do_getpull(struct samsung_gpio_chip *chip,
+                                                         unsigned int off)
 {
        return chip->config->get_pull(chip, off);
 }
 
-/**
- * s3c_gpio_setcfg_s3c24xx - S3C24XX style GPIO configuration.
- * @chip: The gpio chip that is being configured.
- * @off: The offset for the GPIO being configured.
- * @cfg: The configuration value to set.
- *
- * This helper deal with the GPIO cases where the control register
- * has two bits of configuration per gpio, which have the following
- * functions:
- *     00 = input
- *     01 = output
- *     1x = special function
-*/
-extern int s3c_gpio_setcfg_s3c24xx(struct s3c_gpio_chip *chip,
-                                  unsigned int off, unsigned int cfg);
-
-/**
- * s3c_gpio_getcfg_s3c24xx - S3C24XX style GPIO configuration read.
- * @chip: The gpio chip that is being configured.
- * @off: The offset for the GPIO being configured.
- *
- * The reverse of s3c_gpio_setcfg_s3c24xx(). Will return a value whicg
- * could be directly passed back to s3c_gpio_setcfg_s3c24xx(), from the
- * S3C_GPIO_SPECIAL() macro.
- */
-unsigned int s3c_gpio_getcfg_s3c24xx(struct s3c_gpio_chip *chip,
-                                    unsigned int off);
-
-/**
- * s3c_gpio_setcfg_s3c24xx_a - S3C24XX style GPIO configuration (Bank A)
- * @chip: The gpio chip that is being configured.
- * @off: The offset for the GPIO being configured.
- * @cfg: The configuration value to set.
- *
- * This helper deal with the GPIO cases where the control register
- * has one bit of configuration for the gpio, where setting the bit
- * means the pin is in special function mode and unset means output.
-*/
-extern int s3c_gpio_setcfg_s3c24xx_a(struct s3c_gpio_chip *chip,
-                                    unsigned int off, unsigned int cfg);
-
-
-/**
- * s3c_gpio_getcfg_s3c24xx_a - S3C24XX style GPIO configuration read (Bank A)
- * @chip: The gpio chip that is being configured.
- * @off: The offset for the GPIO being configured.
- *
- * The reverse of s3c_gpio_setcfg_s3c24xx_a() turning an GPIO into a usable
- * GPIO configuration value.
- *
- * @sa s3c_gpio_getcfg_s3c24xx
- * @sa s3c_gpio_getcfg_s3c64xx_4bit
- */
-extern unsigned s3c_gpio_getcfg_s3c24xx_a(struct s3c_gpio_chip *chip,
-                                         unsigned int off);
-
-/**
- * s3c_gpio_setcfg_s3c64xx_4bit - S3C64XX 4bit single register GPIO config.
- * @chip: The gpio chip that is being configured.
- * @off: The offset for the GPIO being configured.
- * @cfg: The configuration value to set.
- *
- * This helper deal with the GPIO cases where the control register has 4 bits
- * of control per GPIO, generally in the form of:
- *     0000 = Input
- *     0001 = Output
- *     others = Special functions (dependent on bank)
- *
- * Note, since the code to deal with the case where there are two control
- * registers instead of one, we do not have a separate set of functions for
- * each case.
-*/
-extern int s3c_gpio_setcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
-                                       unsigned int off, unsigned int cfg);
-
-
-/**
- * s3c_gpio_getcfg_s3c64xx_4bit - S3C64XX 4bit single register GPIO config read.
- * @chip: The gpio chip that is being configured.
- * @off: The offset for the GPIO being configured.
- *
- * The reverse of s3c_gpio_setcfg_s3c64xx_4bit(), turning a gpio configuration
- * register setting into a value the software can use, such as could be passed
- * to s3c_gpio_setcfg_s3c64xx_4bit().
- *
- * @sa s3c_gpio_getcfg_s3c24xx
- */
-extern unsigned s3c_gpio_getcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
-                                            unsigned int off);
-
 /* Pull-{up,down} resistor controls.
  *
  * S3C2410,S3C2440 = Pull-UP,
@@ -147,7 +57,7 @@ extern unsigned s3c_gpio_getcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
  */
 
 /**
- * s3c_gpio_setpull_1up() - Pull configuration for choice of up or none.
+ * s3c24xx_gpio_setpull_1up() - Pull configuration for choice of up or none.
  * @chip: The gpio chip that is being configured.
  * @off: The offset for the GPIO being configured.
  * @param: pull: The pull mode being requested.
@@ -155,11 +65,11 @@ extern unsigned s3c_gpio_getcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
  * This is a helper function for the case where we have GPIOs with one
  * bit configuring the presence of a pull-up resistor.
  */
-extern int s3c_gpio_setpull_1up(struct s3c_gpio_chip *chip,
-                               unsigned int off, s3c_gpio_pull_t pull);
+extern int s3c24xx_gpio_setpull_1up(struct samsung_gpio_chip *chip,
+                                   unsigned int off, samsung_gpio_pull_t pull);
 
 /**
- * s3c_gpio_setpull_1down() - Pull configuration for choice of down or none
+ * s3c24xx_gpio_setpull_1down() - Pull configuration for choice of down or none
  * @chip: The gpio chip that is being configured
  * @off: The offset for the GPIO being configured
  * @param: pull: The pull mode being requested
@@ -167,11 +77,13 @@ extern int s3c_gpio_setpull_1up(struct s3c_gpio_chip *chip,
  * This is a helper function for the case where we have GPIOs with one
  * bit configuring the presence of a pull-down resistor.
  */
-extern int s3c_gpio_setpull_1down(struct s3c_gpio_chip *chip,
-                                 unsigned int off, s3c_gpio_pull_t pull);
+extern int s3c24xx_gpio_setpull_1down(struct samsung_gpio_chip *chip,
+                                     unsigned int off, samsung_gpio_pull_t pull);
 
 /**
- * s3c_gpio_setpull_upown() - Pull configuration for choice of up, down or none
+ * samsung_gpio_setpull_upown() - Pull configuration for choice of up,
+ * down or none
+ *
  * @chip: The gpio chip that is being configured.
  * @off: The offset for the GPIO being configured.
  * @param: pull: The pull mode being requested.
@@ -183,45 +95,46 @@ extern int s3c_gpio_setpull_1down(struct s3c_gpio_chip *chip,
  *     01 = Pull-up resistor connected
  *     10 = Pull-down resistor connected
  */
-extern int s3c_gpio_setpull_updown(struct s3c_gpio_chip *chip,
-                                  unsigned int off, s3c_gpio_pull_t pull);
-
+extern int samsung_gpio_setpull_updown(struct samsung_gpio_chip *chip,
+                                      unsigned int off, samsung_gpio_pull_t pull);
 
 /**
- * s3c_gpio_getpull_updown() - Get configuration for choice of up, down or none
+ * samsung_gpio_getpull_updown() - Get configuration for choice of up,
+ * down or none
+ *
  * @chip: The gpio chip that the GPIO pin belongs to
  * @off: The offset to the pin to get the configuration of.
  *
- * This helper function reads the state of the pull-{up,down} resistor for the
- * given GPIO in the same case as s3c_gpio_setpull_upown.
+ * This helper function reads the state of the pull-{up,down} resistor
+ * for the given GPIO in the same case as samsung_gpio_setpull_upown.
 */
-extern s3c_gpio_pull_t s3c_gpio_getpull_updown(struct s3c_gpio_chip *chip,
-                                              unsigned int off);
+extern samsung_gpio_pull_t samsung_gpio_getpull_updown(struct samsung_gpio_chip *chip,
+                                                      unsigned int off);
 
 /**
- * s3c_gpio_getpull_1up() - Get configuration for choice of up or none
+ * s3c24xx_gpio_getpull_1up() - Get configuration for choice of up or none
  * @chip: The gpio chip that the GPIO pin belongs to
  * @off: The offset to the pin to get the configuration of.
  *
  * This helper function reads the state of the pull-up resistor for the
- * given GPIO in the same case as s3c_gpio_setpull_1up.
+ * given GPIO in the same case as s3c24xx_gpio_setpull_1up.
 */
-extern s3c_gpio_pull_t s3c_gpio_getpull_1up(struct s3c_gpio_chip *chip,
-                                           unsigned int off);
+extern samsung_gpio_pull_t s3c24xx_gpio_getpull_1up(struct samsung_gpio_chip *chip,
+                                                   unsigned int off);
 
 /**
- * s3c_gpio_getpull_1down() - Get configuration for choice of down or none
+ * s3c24xx_gpio_getpull_1down() - Get configuration for choice of down or none
  * @chip: The gpio chip that the GPIO pin belongs to
  * @off: The offset to the pin to get the configuration of.
  *
  * This helper function reads the state of the pull-down resistor for the
- * given GPIO in the same case as s3c_gpio_setpull_1down.
+ * given GPIO in the same case as s3c24xx_gpio_setpull_1down.
 */
-extern s3c_gpio_pull_t s3c_gpio_getpull_1down(struct s3c_gpio_chip *chip,
-                                           unsigned int off);
+extern samsung_gpio_pull_t s3c24xx_gpio_getpull_1down(struct samsung_gpio_chip *chip,
+                                                     unsigned int off);
 
 /**
- * s3c_gpio_setpull_s3c2443() - Pull configuration for s3c2443.
+ * s3c2443_gpio_setpull() - Pull configuration for s3c2443.
  * @chip: The gpio chip that is being configured.
  * @off: The offset for the GPIO being configured.
  * @param: pull: The pull mode being requested.
@@ -233,19 +146,18 @@ extern s3c_gpio_pull_t s3c_gpio_getpull_1down(struct s3c_gpio_chip *chip,
  *     10 = Pull-down resistor connected
  *     x1 = No pull up resistor
  */
-extern int s3c_gpio_setpull_s3c2443(struct s3c_gpio_chip *chip,
-                                   unsigned int off, s3c_gpio_pull_t pull);
+extern int s3c2443_gpio_setpull(struct samsung_gpio_chip *chip,
+                               unsigned int off, samsung_gpio_pull_t pull);
 
 /**
- * s3c_gpio_getpull_s3c2443() - Get configuration for s3c2443 pull resistors
+ * s3c2443_gpio_getpull() - Get configuration for s3c2443 pull resistors
  * @chip: The gpio chip that the GPIO pin belongs to.
  * @off: The offset to the pin to get the configuration of.
  *
  * This helper function reads the state of the pull-{up,down} resistor for the
- * given GPIO in the same case as s3c_gpio_setpull_upown.
+ * given GPIO in the same case as samsung_gpio_setpull_upown.
 */
-extern s3c_gpio_pull_t s3c_gpio_getpull_s3c2443(struct s3c_gpio_chip *chip,
+extern samsung_gpio_pull_t s3c2443_gpio_getpull(struct samsung_gpio_chip *chip,
                                                unsigned int off);
 
 #endif /* __PLAT_GPIO_CFG_HELPERS_H */
-
index 1762dcb..d48245b 100644 (file)
 #ifndef __PLAT_GPIO_CFG_H
 #define __PLAT_GPIO_CFG_H __FILE__
 
-typedef unsigned int __bitwise__ s3c_gpio_pull_t;
+typedef unsigned int __bitwise__ samsung_gpio_pull_t;
 typedef unsigned int __bitwise__ s5p_gpio_drvstr_t;
 
 /* forward declaration if gpio-core.h hasn't been included */
-struct s3c_gpio_chip;
+struct samsung_gpio_chip;
 
 /**
- * struct s3c_gpio_cfg GPIO configuration
+ * struct samsung_gpio_cfg GPIO configuration
  * @cfg_eint: Configuration setting when used for external interrupt source
  * @get_pull: Read the current pull configuration for the GPIO
  * @set_pull: Set the current pull configuraiton for the GPIO
@@ -44,20 +44,20 @@ struct s3c_gpio_chip;
  * per-bank configuration information that other systems such as the
  * external interrupt code will need.
  *
- * @sa s3c_gpio_cfgpin
+ * @sa samsung_gpio_cfgpin
  * @sa s3c_gpio_getcfg
  * @sa s3c_gpio_setpull
  * @sa s3c_gpio_getpull
  */
-struct s3c_gpio_cfg {
+struct samsung_gpio_cfg {
        unsigned int    cfg_eint;
 
-       s3c_gpio_pull_t (*get_pull)(struct s3c_gpio_chip *chip, unsigned offs);
-       int             (*set_pull)(struct s3c_gpio_chip *chip, unsigned offs,
-                                   s3c_gpio_pull_t pull);
+       samsung_gpio_pull_t     (*get_pull)(struct samsung_gpio_chip *chip, unsigned offs);
+       int             (*set_pull)(struct samsung_gpio_chip *chip, unsigned offs,
+                                   samsung_gpio_pull_t pull);
 
-       unsigned (*get_config)(struct s3c_gpio_chip *chip, unsigned offs);
-       int      (*set_config)(struct s3c_gpio_chip *chip, unsigned offs,
+       unsigned (*get_config)(struct samsung_gpio_chip *chip, unsigned offs);
+       int      (*set_config)(struct samsung_gpio_chip *chip, unsigned offs,
                               unsigned config);
 };
 
@@ -69,7 +69,7 @@ struct s3c_gpio_cfg {
 #define S3C_GPIO_OUTPUT        (S3C_GPIO_SPECIAL(1))
 #define S3C_GPIO_SFN(x)        (S3C_GPIO_SPECIAL(x))
 
-#define s3c_gpio_is_cfg_special(_cfg) \
+#define samsung_gpio_is_cfg_special(_cfg) \
        (((_cfg) & S3C_GPIO_SPECIAL_MARK) == S3C_GPIO_SPECIAL_MARK)
 
 /**
@@ -128,9 +128,9 @@ extern int s3c_gpio_cfgpin_range(unsigned int start, unsigned int nr,
  * up or down settings, and it may be dependent on the chip that is being
  * used to whether the particular mode is available.
  */
-#define S3C_GPIO_PULL_NONE     ((__force s3c_gpio_pull_t)0x00)
-#define S3C_GPIO_PULL_DOWN     ((__force s3c_gpio_pull_t)0x01)
-#define S3C_GPIO_PULL_UP       ((__force s3c_gpio_pull_t)0x02)
+#define S3C_GPIO_PULL_NONE     ((__force samsung_gpio_pull_t)0x00)
+#define S3C_GPIO_PULL_DOWN     ((__force samsung_gpio_pull_t)0x01)
+#define S3C_GPIO_PULL_UP       ((__force samsung_gpio_pull_t)0x02)
 
 /**
  * s3c_gpio_setpull() - set the state of a gpio pin pull resistor
@@ -143,7 +143,7 @@ extern int s3c_gpio_cfgpin_range(unsigned int start, unsigned int nr,
  *
  * @pull is one of S3C_GPIO_PULL_NONE, S3C_GPIO_PULL_DOWN or S3C_GPIO_PULL_UP.
 */
-extern int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull);
+extern int s3c_gpio_setpull(unsigned int pin, samsung_gpio_pull_t pull);
 
 /**
  * s3c_gpio_getpull() - get the pull resistor state of a gpio pin
@@ -151,7 +151,7 @@ extern int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull);
  *
  * Read the pull resistor value for the specified pin.
 */
-extern s3c_gpio_pull_t s3c_gpio_getpull(unsigned int pin);
+extern samsung_gpio_pull_t s3c_gpio_getpull(unsigned int pin);
 
 /* configure `all` aspects of an gpio */
 
@@ -170,7 +170,7 @@ extern s3c_gpio_pull_t s3c_gpio_getpull(unsigned int pin);
  * @sa s3c_gpio_cfgpin_range
  */
 extern int s3c_gpio_cfgall_range(unsigned int start, unsigned int nr,
-                                unsigned int cfg, s3c_gpio_pull_t pull);
+                                unsigned int cfg, samsung_gpio_pull_t pull);
 
 static inline int s3c_gpio_cfgrange_nopull(unsigned int pin, unsigned int size,
                                           unsigned int cfg)
index 8cad4cf..1fe6917 100644 (file)
  * specific code.
 */
 
-struct s3c_gpio_chip;
+struct samsung_gpio_chip;
 
 /**
- * struct s3c_gpio_pm - power management (suspend/resume) information
+ * struct samsung_gpio_pm - power management (suspend/resume) information
  * @save: Routine to save the state of the GPIO block
  * @resume: Routine to resume the GPIO block.
  */
-struct s3c_gpio_pm {
-       void (*save)(struct s3c_gpio_chip *chip);
-       void (*resume)(struct s3c_gpio_chip *chip);
+struct samsung_gpio_pm {
+       void (*save)(struct samsung_gpio_chip *chip);
+       void (*resume)(struct samsung_gpio_chip *chip);
 };
 
-struct s3c_gpio_cfg;
+struct samsung_gpio_cfg;
 
 /**
- * struct s3c_gpio_chip - wrapper for specific implementation of gpio
+ * struct samsung_gpio_chip - wrapper for specific implementation of gpio
  * @chip: The chip structure to be exported via gpiolib.
  * @base: The base pointer to the gpio configuration registers.
  * @group: The group register number for gpio interrupt support.
@@ -60,10 +60,10 @@ struct s3c_gpio_cfg;
  * CPU cores trying to get one lock for different GPIO banks, where each
  * bank of GPIO has its own register space and configuration registers.
  */
-struct s3c_gpio_chip {
+struct samsung_gpio_chip {
        struct gpio_chip        chip;
-       struct s3c_gpio_cfg     *config;
-       struct s3c_gpio_pm      *pm;
+       struct samsung_gpio_cfg *config;
+       struct samsung_gpio_pm  *pm;
        void __iomem            *base;
        int                     irq_base;
        int                     group;
@@ -73,58 +73,11 @@ struct s3c_gpio_chip {
 #endif
 };
 
-static inline struct s3c_gpio_chip *to_s3c_gpio(struct gpio_chip *gpc)
+static inline struct samsung_gpio_chip *to_samsung_gpio(struct gpio_chip *gpc)
 {
-       return container_of(gpc, struct s3c_gpio_chip, chip);
+       return container_of(gpc, struct samsung_gpio_chip, chip);
 }
 
-/** s3c_gpiolib_add() - add the s3c specific version of a gpio_chip.
- * @chip: The chip to register
- *
- * This is a wrapper to gpiochip_add() that takes our specific gpio chip
- * information and makes the necessary alterations for the platform and
- * notes the information for use with the configuration systems and any
- * other parts of the system.
- */
-extern void s3c_gpiolib_add(struct s3c_gpio_chip *chip);
-
-/* CONFIG_S3C_GPIO_TRACK enables the tracking of the s3c specific gpios
- * for use with the configuration calls, and other parts of the s3c gpiolib
- * support code.
- *
- * Not all s3c support code will need this, as some configurations of cpu
- * may only support one or two different configuration options and have an
- * easy gpio to s3c_gpio_chip mapping function. If this is the case, then
- * the machine support file should provide its own s3c_gpiolib_getchip()
- * and any other necessary functions.
- */
-
-/**
- * samsung_gpiolib_add_4bit_chips - 4bit single register GPIO config.
- * @chip: The gpio chip that is being configured.
- * @nr_chips: The no of chips (gpio ports) for the GPIO being configured.
- *
- * This helper deal with the GPIO cases where the control register has 4 bits
- * of control per GPIO, generally in the form of:
- * 0000 = Input
- * 0001 = Output
- * others = Special functions (dependent on bank)
- *
- * Note, since the code to deal with the case where there are two control
- * registers instead of one, we do not have a separate set of function
- * (samsung_gpiolib_add_4bit2_chips)for each case.
- */
-extern void samsung_gpiolib_add_4bit_chips(struct s3c_gpio_chip *chip,
-                                          int nr_chips);
-extern void samsung_gpiolib_add_4bit2_chips(struct s3c_gpio_chip *chip,
-                                           int nr_chips);
-extern void samsung_gpiolib_add_2bit_chips(struct s3c_gpio_chip *chip,
-                                          int nr_chips);
-
-extern void samsung_gpiolib_add_4bit(struct s3c_gpio_chip *chip);
-extern void samsung_gpiolib_add_4bit2(struct s3c_gpio_chip *chip);
-
-
 /**
  * samsung_gpiolib_to_irq - convert gpio pin to irq number
  * @chip: The gpio chip that the pin belongs to.
@@ -136,36 +89,36 @@ extern void samsung_gpiolib_add_4bit2(struct s3c_gpio_chip *chip);
 extern int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset);
 
 /* exported for core SoC support to change */
-extern struct s3c_gpio_cfg s3c24xx_gpiocfg_default;
+extern struct samsung_gpio_cfg s3c24xx_gpiocfg_default;
 
 #ifdef CONFIG_S3C_GPIO_TRACK
-extern struct s3c_gpio_chip *s3c_gpios[S3C_GPIO_END];
+extern struct samsung_gpio_chip *s3c_gpios[S3C_GPIO_END];
 
-static inline struct s3c_gpio_chip *s3c_gpiolib_getchip(unsigned int chip)
+static inline struct samsung_gpio_chip *samsung_gpiolib_getchip(unsigned int chip)
 {
        return (chip < S3C_GPIO_END) ? s3c_gpios[chip] : NULL;
 }
 #else
-/* machine specific code should provide s3c_gpiolib_getchip */
+/* machine specific code should provide samsung_gpiolib_getchip */
 
 #include <mach/gpio-track.h>
 
-static inline void s3c_gpiolib_track(struct s3c_gpio_chip *chip) { }
+static inline void s3c_gpiolib_track(struct samsung_gpio_chip *chip) { }
 #endif
 
 #ifdef CONFIG_PM
-extern struct s3c_gpio_pm s3c_gpio_pm_1bit;
-extern struct s3c_gpio_pm s3c_gpio_pm_2bit;
-extern struct s3c_gpio_pm s3c_gpio_pm_4bit;
+extern struct samsung_gpio_pm samsung_gpio_pm_1bit;
+extern struct samsung_gpio_pm samsung_gpio_pm_2bit;
+extern struct samsung_gpio_pm samsung_gpio_pm_4bit;
 #define __gpio_pm(x) x
 #else
-#define s3c_gpio_pm_1bit NULL
-#define s3c_gpio_pm_2bit NULL
-#define s3c_gpio_pm_4bit NULL
+#define samsung_gpio_pm_1bit NULL
+#define samsung_gpio_pm_2bit NULL
+#define samsung_gpio_pm_4bit NULL
 #define __gpio_pm(x) NULL
 
 #endif /* CONFIG_PM */
 
 /* locking wrappers to deal with multiple access to the same gpio bank */
-#define s3c_gpio_lock(_oc, _fl) spin_lock_irqsave(&(_oc)->lock, _fl)
-#define s3c_gpio_unlock(_oc, _fl) spin_unlock_irqrestore(&(_oc)->lock, _fl)
+#define samsung_gpio_lock(_oc, _fl) spin_lock_irqsave(&(_oc)->lock, _fl)
+#define samsung_gpio_unlock(_oc, _fl) spin_unlock_irqrestore(&(_oc)->lock, _fl)
diff --git a/arch/arm/plat-samsung/include/plat/gpio-fns.h b/arch/arm/plat-samsung/include/plat/gpio-fns.h
new file mode 100644 (file)
index 0000000..bab1392
--- /dev/null
@@ -0,0 +1,98 @@
+/* arch/arm/mach-s3c2410/include/mach/gpio-fns.h
+ *
+ * Copyright (c) 2003-2009 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2410 - hardware
+ *
+ * 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_GPIO_FNS_H
+#define __MACH_GPIO_FNS_H __FILE__
+
+/* These functions are in the to-be-removed category and it is strongly
+ * encouraged not to use these in new code. They will be marked deprecated
+ * very soon.
+ *
+ * Most of the functionality can be either replaced by the gpiocfg calls
+ * for the s3c platform or by the generic GPIOlib API.
+ *
+ * As of 2.6.35-rc, these will be removed, with the few drivers using them
+ * either replaced or given a wrapper until the calls can be removed.
+*/
+
+#include <plat/gpio-cfg.h>
+
+static inline void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int cfg)
+{
+       /* 1:1 mapping between cfgpin and setcfg calls at the moment */
+       s3c_gpio_cfgpin(pin, cfg);
+}
+
+/* external functions for GPIO support
+ *
+ * These allow various different clients to access the same GPIO
+ * registers without conflicting. If your driver only owns the entire
+ * GPIO register, then it is safe to ioremap/__raw_{read|write} to it.
+*/
+
+extern unsigned int s3c2410_gpio_getcfg(unsigned int pin);
+
+/* s3c2410_gpio_getirq
+ *
+ * turn the given pin number into the corresponding IRQ number
+ *
+ * returns:
+ *     < 0 = no interrupt for this pin
+ *     >=0 = interrupt number for the pin
+*/
+
+extern int s3c2410_gpio_getirq(unsigned int pin);
+
+/* s3c2410_gpio_irqfilter
+ *
+ * set the irq filtering on the given pin
+ *
+ * on = 0 => disable filtering
+ *      1 => enable filtering
+ *
+ * config = S3C2410_EINTFLT_PCLK or S3C2410_EINTFLT_EXTCLK orred with
+ *          width of filter (0 through 63)
+ *
+ *
+*/
+
+extern int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
+                                 unsigned int config);
+
+/* s3c2410_gpio_pullup
+ *
+ * This call should be replaced with s3c_gpio_setpull().
+ *
+ * As a note, there is currently no distinction between pull-up and pull-down
+ * in the s3c24xx series devices with only an on/off configuration.
+ */
+
+/* s3c2410_gpio_pullup
+ *
+ * configure the pull-up control on the given pin
+ *
+ * to = 1 => disable the pull-up
+ *      0 => enable the pull-up
+ *
+ * eg;
+ *
+ *   s3c2410_gpio_pullup(S3C2410_GPB(0), 0);
+ *   s3c2410_gpio_pullup(S3C2410_GPE(8), 0);
+*/
+
+extern void s3c2410_gpio_pullup(unsigned int pin, unsigned int to);
+
+extern void s3c2410_gpio_setpin(unsigned int pin, unsigned int to);
+
+extern unsigned int s3c2410_gpio_getpin(unsigned int pin);
+
+#endif /* __MACH_GPIO_FNS_H */
index 56b0059..51d52e7 100644 (file)
@@ -60,6 +60,7 @@ extern void s3c_i2c4_set_platdata(struct s3c2410_platform_i2c *i2c);
 extern void s3c_i2c5_set_platdata(struct s3c2410_platform_i2c *i2c);
 extern void s3c_i2c6_set_platdata(struct s3c2410_platform_i2c *i2c);
 extern void s3c_i2c7_set_platdata(struct s3c2410_platform_i2c *i2c);
+extern void s5p_i2c_hdmiphy_set_platdata(struct s3c2410_platform_i2c *i2c);
 
 /* defined by architecture to configure gpio */
 extern void s3c_i2c0_cfg_gpio(struct platform_device *dev);
similarity index 81%
rename from arch/arm/plat-s3c24xx/include/plat/irq.h
rename to arch/arm/plat-samsung/include/plat/irq.h
index ec087d6..e21a89b 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/include/asm-arm/plat-s3c24xx/irq.h
+/* linux/arch/arm/plat-samsung/include/plat/irq.h
  *
  * Copyright (c) 2004-2005 Simtec Electronics
  *     Ben Dooks <ben@simtec.co.uk>
@@ -25,9 +25,9 @@
 extern struct irq_chip s3c_irq_level_chip;
 extern struct irq_chip s3c_irq_chip;
 
-static inline void
-s3c_irqsub_mask(unsigned int irqno, unsigned int parentbit,
-               int subcheck)
+static inline void s3c_irqsub_mask(unsigned int irqno,
+                                  unsigned int parentbit,
+                                  int subcheck)
 {
        unsigned long mask;
        unsigned long submask;
@@ -39,17 +39,16 @@ s3c_irqsub_mask(unsigned int irqno, unsigned int parentbit,
 
        /* check to see if we need to mask the parent IRQ */
 
-       if ((submask  & subcheck) == subcheck) {
+       if ((submask  & subcheck) == subcheck)
                __raw_writel(mask | parentbit, S3C2410_INTMSK);
-       }
 
        /* write back masks */
        __raw_writel(submask, S3C2410_INTSUBMSK);
 
 }
 
-static inline void
-s3c_irqsub_unmask(unsigned int irqno, unsigned int parentbit)
+static inline void s3c_irqsub_unmask(unsigned int irqno,
+                                    unsigned int parentbit)
 {
        unsigned long mask;
        unsigned long submask;
@@ -66,8 +65,9 @@ s3c_irqsub_unmask(unsigned int irqno, unsigned int parentbit)
 }
 
 
-static inline void
-s3c_irqsub_maskack(unsigned int irqno, unsigned int parentmask, unsigned int group)
+static inline void s3c_irqsub_maskack(unsigned int irqno,
+                                     unsigned int parentmask,
+                                     unsigned int group)
 {
        unsigned int bit = 1UL << (irqno - IRQ_S3CUART_RX0);
 
@@ -86,8 +86,9 @@ s3c_irqsub_maskack(unsigned int irqno, unsigned int parentmask, unsigned int gro
        }
 }
 
-static inline void
-s3c_irqsub_ack(unsigned int irqno, unsigned int parentmask, unsigned int group)
+static inline void s3c_irqsub_ack(unsigned int irqno,
+                                 unsigned int parentmask,
+                                 unsigned int group)
 {
        unsigned int bit = 1UL << (irqno - IRQ_S3CUART_RX0);
 
similarity index 93%
rename from arch/arm/plat-s5p/include/plat/irqs.h
rename to arch/arm/plat-samsung/include/plat/irqs.h
index 144dbfc..08d1a7e 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/arch/arm/plat-s5p/include/plat/irqs.h
+/* linux/arch/arm/plat-samsung/include/plat/irqs.h
  *
  * Copyright (c) 2009 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com/
@@ -10,8 +10,8 @@
  * published by the Free Software Foundation.
 */
 
-#ifndef __ASM_PLAT_S5P_IRQS_H
-#define __ASM_PLAT_S5P_IRQS_H __FILE__
+#ifndef __PLAT_SAMSUNG_IRQS_H
+#define __PLAT_SAMSUNG_IRQS_H __FILE__
 
 /* we keep the first set of CPU IRQs out of the range of
  * the ISA space, so that the PC104 has them to itself
@@ -77,4 +77,4 @@
 #define S5P_IRQ_TYPE_EDGE_RISING       (0x03)
 #define S5P_IRQ_TYPE_EDGE_BOTH         (0x04)
 
-#endif /* __ASM_PLAT_S5P_IRQS_H */
+#endif /* __PLAT_SAMSUNG_IRQS_H */
similarity index 90%
rename from arch/arm/plat-s3c24xx/include/plat/mci.h
rename to arch/arm/plat-samsung/include/plat/mci.h
index 2ac2b21..c42d317 100644 (file)
  * to a non-zero value, otherwise the default of 3.2-3.4V is used.
  */
 struct s3c24xx_mci_pdata {
-       unsigned int    no_wprotect : 1;
-       unsigned int    no_detect : 1;
-       unsigned int    wprotect_invert : 1;
-       unsigned int    detect_invert : 1;   /* set => detect active high. */
-       unsigned int    use_dma : 1;
+       unsigned int    no_wprotect:1;
+       unsigned int    no_detect:1;
+       unsigned int    wprotect_invert:1;
+       unsigned int    detect_invert:1;        /* set => detect active high */
+       unsigned int    use_dma:1;
 
        unsigned int    gpio_detect;
        unsigned int    gpio_wprotect;
similarity index 90%
rename from arch/arm/plat-s5p/include/plat/mfc.h
rename to arch/arm/plat-samsung/include/plat/mfc.h
index 6697f8c..ac13227 100644 (file)
@@ -7,8 +7,8 @@
  * option) any later version.
  */
 
-#ifndef __PLAT_S5P_MFC_H
-#define __PLAT_S5P_MFC_H
+#ifndef __PLAT_SAMSUNG_MFC_H
+#define __PLAT_SAMSUNG_MFC_H __FILE__
 
 /**
  * s5p_mfc_reserve_mem - function to early reserve memory for MFC driver
@@ -24,4 +24,4 @@
 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 */
+#endif /* __PLAT_SAMSUNG_MFC_H */
similarity index 90%
rename from arch/arm/plat-s5p/include/plat/mipi_csis.h
rename to arch/arm/plat-samsung/include/plat/mipi_csis.h
index 9bd254c..c45b1e8 100644 (file)
@@ -8,8 +8,8 @@
  * published by the Free Software Foundation.
  */
 
-#ifndef PLAT_S5P_MIPI_CSIS_H_
-#define PLAT_S5P_MIPI_CSIS_H_ __FILE__
+#ifndef __PLAT_SAMSUNG_MIPI_CSIS_H_
+#define __PLAT_SAMSUNG_MIPI_CSIS_H_ __FILE__
 
 struct platform_device;
 
@@ -40,4 +40,4 @@ struct s5p_platform_mipi_csis {
  */
 int s5p_csis_phy_enable(struct platform_device *pdev, bool on);
 
-#endif /* PLAT_S5P_MIPI_CSIS_H_ */
+#endif /* __PLAT_SAMSUNG_MIPI_CSIS_H_ */
similarity index 57%
rename from arch/arm/plat-s5p/include/plat/pll.h
rename to arch/arm/plat-samsung/include/plat/pll.h
index 3e21b94..357af7c 100644 (file)
@@ -1,11 +1,14 @@
-/* arch/arm/plat-s5p/include/plat/pll.h
+/* linux/arch/arm/plat-samsung/include/plat/pll.h
  *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com/
  *
- * S5P PLL code
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *     http://armlinux.simtec.co.uk/
  *
- * Based on arch/arm/plat-s3c64xx/include/plat/pll.h
+ * Samsung PLL codes
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
 
 #include <asm/div64.h>
 
+#define S3C24XX_PLL_MDIV_MASK          (0xFF)
+#define S3C24XX_PLL_PDIV_MASK          (0x1F)
+#define S3C24XX_PLL_SDIV_MASK          (0x3)
+#define S3C24XX_PLL_MDIV_SHIFT         (12)
+#define S3C24XX_PLL_PDIV_SHIFT         (4)
+#define S3C24XX_PLL_SDIV_SHIFT         (0)
+
+static inline unsigned int s3c24xx_get_pll(unsigned int pllval,
+                                          unsigned int baseclk)
+{
+       unsigned int mdiv, pdiv, sdiv;
+       uint64_t fvco;
+
+       mdiv = (pllval >> S3C24XX_PLL_MDIV_SHIFT) & S3C24XX_PLL_MDIV_MASK;
+       pdiv = (pllval >> S3C24XX_PLL_PDIV_SHIFT) & S3C24XX_PLL_PDIV_MASK;
+       sdiv = (pllval >> S3C24XX_PLL_SDIV_SHIFT) & S3C24XX_PLL_SDIV_MASK;
+
+       fvco = (uint64_t)baseclk * (mdiv + 8);
+       do_div(fvco, (pdiv + 2) << sdiv);
+
+       return (unsigned int)fvco;
+}
+
+#define S3C2416_PLL_MDIV_MASK          (0x3FF)
+#define S3C2416_PLL_PDIV_MASK          (0x3F)
+#define S3C2416_PLL_SDIV_MASK          (0x7)
+#define S3C2416_PLL_MDIV_SHIFT         (14)
+#define S3C2416_PLL_PDIV_SHIFT         (5)
+#define S3C2416_PLL_SDIV_SHIFT         (0)
+
+static inline unsigned int s3c2416_get_pll(unsigned int pllval,
+                                          unsigned int baseclk)
+{
+       unsigned int mdiv, pdiv, sdiv;
+       uint64_t fvco;
+
+       mdiv = (pllval >> S3C2416_PLL_MDIV_SHIFT) & S3C2416_PLL_MDIV_MASK;
+       pdiv = (pllval >> S3C2416_PLL_PDIV_SHIFT) & S3C2416_PLL_PDIV_MASK;
+       sdiv = (pllval >> S3C2416_PLL_SDIV_SHIFT) & S3C2416_PLL_SDIV_MASK;
+
+       fvco = (uint64_t)baseclk * mdiv;
+       do_div(fvco, (pdiv << sdiv));
+
+       return (unsigned int)fvco;
+}
+
+#define S3C6400_PLL_MDIV_MASK          (0x3FF)
+#define S3C6400_PLL_PDIV_MASK          (0x3F)
+#define S3C6400_PLL_SDIV_MASK          (0x7)
+#define S3C6400_PLL_MDIV_SHIFT         (16)
+#define S3C6400_PLL_PDIV_SHIFT         (8)
+#define S3C6400_PLL_SDIV_SHIFT         (0)
+
+static inline unsigned long s3c6400_get_pll(unsigned long baseclk,
+                                           u32 pllcon)
+{
+       u32 mdiv, pdiv, sdiv;
+       u64 fvco = baseclk;
+
+       mdiv = (pllcon >> S3C6400_PLL_MDIV_SHIFT) & S3C6400_PLL_MDIV_MASK;
+       pdiv = (pllcon >> S3C6400_PLL_PDIV_SHIFT) & S3C6400_PLL_PDIV_MASK;
+       sdiv = (pllcon >> S3C6400_PLL_SDIV_SHIFT) & S3C6400_PLL_SDIV_MASK;
+
+       fvco *= mdiv;
+       do_div(fvco, (pdiv << sdiv));
+
+       return (unsigned long)fvco;
+}
+
+#define PLL6553X_MDIV_MASK     (0x7F)
+#define PLL6553X_PDIV_MASK     (0x1F)
+#define PLL6553X_SDIV_MASK     (0x3)
+#define PLL6553X_KDIV_MASK     (0xFFFF)
+#define PLL6553X_MDIV_SHIFT    (16)
+#define PLL6553X_PDIV_SHIFT    (8)
+#define PLL6553X_SDIV_SHIFT    (0)
+
+static inline unsigned long s3c_get_pll6553x(unsigned long baseclk,
+                                            u32 pll_con0, u32 pll_con1)
+{
+       unsigned long result;
+       u32 mdiv, pdiv, sdiv, kdiv;
+       u64 tmp;
+
+       mdiv = (pll_con0 >> PLL6553X_MDIV_SHIFT) & PLL6553X_MDIV_MASK;
+       pdiv = (pll_con0 >> PLL6553X_PDIV_SHIFT) & PLL6553X_PDIV_MASK;
+       sdiv = (pll_con0 >> PLL6553X_SDIV_SHIFT) & PLL6553X_SDIV_MASK;
+       kdiv = pll_con1 & PLL6553X_KDIV_MASK;
+
+       /*
+        * We need to multiple baseclk by mdiv (the integer part) and kdiv
+        * which is in 2^16ths, so shift mdiv up (does not overflow) and
+        * add kdiv before multiplying. The use of tmp is to avoid any
+        * overflows before shifting bac down into result when multipling
+        * by the mdiv and kdiv pair.
+        */
+
+       tmp = baseclk;
+       tmp *= (mdiv << 16) + kdiv;
+       do_div(tmp, (pdiv << sdiv));
+       result = tmp >> 16;
+
+       return result;
+}
+
 #define PLL35XX_MDIV_MASK      (0x3FF)
 #define PLL35XX_PDIV_MASK      (0x3F)
 #define PLL35XX_SDIV_MASK      (0x7)
@@ -97,15 +205,24 @@ static inline unsigned long s5p_get_pll45xx(unsigned long baseclk, u32 pll_con,
        return (unsigned long)fvco;
 }
 
-#define PLL46XX_KDIV_MASK      (0xFFFF)
-#define PLL4650C_KDIV_MASK     (0xFFF)
+/* CON0 bit-fields */
 #define PLL46XX_MDIV_MASK      (0x1FF)
 #define PLL46XX_PDIV_MASK      (0x3F)
 #define PLL46XX_SDIV_MASK      (0x7)
+#define PLL46XX_LOCKED_SHIFT   (29)
 #define PLL46XX_MDIV_SHIFT     (16)
 #define PLL46XX_PDIV_SHIFT     (8)
 #define PLL46XX_SDIV_SHIFT     (0)
 
+/* CON1 bit-fields */
+#define PLL46XX_MRR_MASK       (0x1F)
+#define PLL46XX_MFR_MASK       (0x3F)
+#define PLL46XX_KDIV_MASK      (0xFFFF)
+#define PLL4650C_KDIV_MASK     (0xFFF)
+#define PLL46XX_MRR_SHIFT      (24)
+#define PLL46XX_MFR_SHIFT      (16)
+#define PLL46XX_KDIV_SHIFT     (0)
+
 enum pll46xx_type_t {
        pll_4600,
        pll_4650,
@@ -123,6 +240,7 @@ static inline unsigned long s5p_get_pll46xx(unsigned long baseclk,
        mdiv = (pll_con0 >> PLL46XX_MDIV_SHIFT) & PLL46XX_MDIV_MASK;
        pdiv = (pll_con0 >> PLL46XX_PDIV_SHIFT) & PLL46XX_PDIV_MASK;
        sdiv = (pll_con0 >> PLL46XX_SDIV_SHIFT) & PLL46XX_SDIV_MASK;
+       kdiv = pll_con1 & PLL46XX_KDIV_MASK;
 
        if (pll_type == pll_4650c)
                kdiv = pll_con1 & PLL4650C_KDIV_MASK;
@@ -148,6 +266,7 @@ static inline unsigned long s5p_get_pll46xx(unsigned long baseclk,
 #define PLL90XX_PDIV_MASK      (0x3F)
 #define PLL90XX_SDIV_MASK      (0x7)
 #define PLL90XX_KDIV_MASK      (0xffff)
+#define PLL90XX_LOCKED_SHIFT   (29)
 #define PLL90XX_MDIV_SHIFT     (16)
 #define PLL90XX_PDIV_SHIFT     (8)
 #define PLL90XX_SDIV_SHIFT     (0)
@@ -165,7 +284,8 @@ static inline unsigned long s5p_get_pll90xx(unsigned long baseclk,
        sdiv = (pll_con >> PLL90XX_SDIV_SHIFT) & PLL90XX_SDIV_MASK;
        kdiv = pll_conk & PLL90XX_KDIV_MASK;
 
-       /* We need to multiple baseclk by mdiv (the integer part) and kdiv
+       /*
+        * We need to multiple baseclk by mdiv (the integer part) and kdiv
         * which is in 2^16ths, so shift mdiv up (does not overflow) and
         * add kdiv before multiplying. The use of tmp is to avoid any
         * overflows before shifting bac down into result when multipling
diff --git a/arch/arm/plat-samsung/include/plat/pll6553x.h b/arch/arm/plat-samsung/include/plat/pll6553x.h
deleted file mode 100644 (file)
index b8b7e1d..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/* arch/arm/plat-samsung/include/plat/pll6553x.h
- *     partially from arch/arm/mach-s3c64xx/include/mach/pll.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *     Ben Dooks <ben@simtec.co.uk>
- *     http://armlinux.simtec.co.uk/
- *
- * Samsung PLL6553x PLL code
- *
- * 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.
-*/
-
-/* S3C6400 and compatible (S3C2416, etc.) EPLL code */
-
-#define PLL6553X_MDIV_MASK     ((1 << (23-16)) - 1)
-#define PLL6553X_PDIV_MASK     ((1 << (13-8)) - 1)
-#define PLL6553X_SDIV_MASK     ((1 << (2-0)) - 1)
-#define PLL6553X_MDIV_SHIFT    (16)
-#define PLL6553X_PDIV_SHIFT    (8)
-#define PLL6553X_SDIV_SHIFT    (0)
-#define PLL6553X_KDIV_MASK     (0xffff)
-
-static inline unsigned long s3c_get_pll6553x(unsigned long baseclk,
-                                            u32 pll0, u32 pll1)
-{
-       unsigned long result;
-       u32 mdiv, pdiv, sdiv, kdiv;
-       u64 tmp;
-
-       mdiv = (pll0 >> PLL6553X_MDIV_SHIFT) & PLL6553X_MDIV_MASK;
-       pdiv = (pll0 >> PLL6553X_PDIV_SHIFT) & PLL6553X_PDIV_MASK;
-       sdiv = (pll0 >> PLL6553X_SDIV_SHIFT) & PLL6553X_SDIV_MASK;
-       kdiv = pll1 & PLL6553X_KDIV_MASK;
-
-       /* We need to multiple baseclk by mdiv (the integer part) and kdiv
-        * which is in 2^16ths, so shift mdiv up (does not overflow) and
-        * add kdiv before multiplying. The use of tmp is to avoid any
-        * overflows before shifting bac down into result when multipling
-        * by the mdiv and kdiv pair.
-        */
-
-       tmp = baseclk;
-       tmp *= (mdiv << 16) + kdiv;
-       do_div(tmp, (pdiv << sdiv));
-       result = tmp >> 16;
-
-       return result;
-}
index f674991..dcf6870 100644 (file)
@@ -165,20 +165,20 @@ extern void s3c_pm_check_store(void);
 extern void s3c_pm_configure_extint(void);
 
 /**
- * s3c_pm_restore_gpios() - restore the state of the gpios after sleep.
+ * samsung_pm_restore_gpios() - restore the state of the gpios after sleep.
  *
  * Restore the state of the GPIO pins after sleep, which may involve ensuring
  * that we do not glitch the state of the pins from that the bootloader's
  * resume code has done.
 */
-extern void s3c_pm_restore_gpios(void);
+extern void samsung_pm_restore_gpios(void);
 
 /**
- * s3c_pm_save_gpios() - save the state of the GPIOs for restoring after sleep.
+ * samsung_pm_save_gpios() - save the state of the GPIOs for restoring after sleep.
  *
- * Save the GPIO states for resotration on resume. See s3c_pm_restore_gpios().
+ * Save the GPIO states for resotration on resume. See samsung_pm_restore_gpios().
  */
-extern void s3c_pm_save_gpios(void);
+extern void samsung_pm_save_gpios(void);
 
 extern void s3c_pm_save_core(void);
 extern void s3c_pm_restore_core(void);
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-exynos4/include/mach/pwm-clock.h
+/* linux/arch/arm/plat-samsung/include/plat/pwm-clock.h
  *
  * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com
@@ -8,17 +8,15 @@
  *      Ben Dooks <ben@simtec.co.uk>
  *      http://armlinux.simtec.co.uk/
  *
- * Based on arch/arm/mach-s3c64xx/include/mach/pwm-clock.h
- *
- * EXYNOS4 - pwm clock and timer support
+ * SAMSUNG - pwm clock and timer 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_PWMCLK_H
-#define __ASM_ARCH_PWMCLK_H __FILE__
+#ifndef __ASM_PLAT_PWM_CLOCK_H
+#define __ASM_PLAT_PWM_CLOCK_H __FILE__
 
 /**
  * pwm_cfg_src_is_tclk() - return whether the given mux config is a tclk
  */
 static inline int pwm_cfg_src_is_tclk(unsigned long tcfg)
 {
-       return tcfg == S3C64XX_TCFG1_MUX_TCLK;
+       if (soc_is_s3c24xx())
+               return tcfg == S3C2410_TCFG1_MUX_TCLK;
+       else if (soc_is_s3c64xx() || soc_is_s5pc100())
+               return tcfg >= S3C64XX_TCFG1_MUX_TCLK;
+       else if (soc_is_s5p6440() || soc_is_s5p6450())
+               return 0;
+       else
+               return tcfg == S3C64XX_TCFG1_MUX_TCLK;
 }
 
 /**
@@ -41,7 +46,10 @@ static inline int pwm_cfg_src_is_tclk(unsigned long tcfg)
  */
 static inline unsigned long tcfg_to_divisor(unsigned long tcfg1)
 {
-       return 1 << tcfg1;
+       if (soc_is_s3c24xx())
+               return 1 << (tcfg1 + 1);
+       else
+               return 1 << tcfg1;
 }
 
 /**
@@ -51,7 +59,10 @@ static inline unsigned long tcfg_to_divisor(unsigned long tcfg1)
  */
 static inline unsigned int pwm_tdiv_has_div1(void)
 {
-       return 1;
+       if (soc_is_s3c24xx())
+               return 0;
+       else
+               return 1;
 }
 
 /**
@@ -62,9 +73,9 @@ static inline unsigned int pwm_tdiv_has_div1(void)
  */
 static inline unsigned long pwm_tdiv_div_bits(unsigned int div)
 {
-       return ilog2(div);
+       if (soc_is_s3c24xx())
+               return ilog2(div) - 1;
+       else
+               return ilog2(div);
 }
-
-#define S3C_TCFG1_MUX_TCLK S3C64XX_TCFG1_MUX_TCLK
-
-#endif /* __ASM_ARCH_PWMCLK_H */
+#endif /* __ASM_PLAT_PWM_CLOCK_H */
index 035e8c3..7061210 100644 (file)
@@ -20,6 +20,7 @@
 #define S3C2410_ADCDAT0           S3C2410_ADCREG(0x0C)
 #define S3C2410_ADCDAT1           S3C2410_ADCREG(0x10)
 #define S3C64XX_ADCUPDN                S3C2410_ADCREG(0x14)
+#define S3C2443_ADCMUX         S3C2410_ADCREG(0x18)
 #define S3C64XX_ADCCLRINT      S3C2410_ADCREG(0x18)
 #define S5P_ADCMUX             S3C2410_ADCREG(0x1C)
 #define S3C64XX_ADCCLRINTPNDNUP        S3C2410_ADCREG(0x20)
@@ -33,6 +34,7 @@
 #define S3C2410_ADCCON_PRSCVLMASK      (0xFF<<6)
 #define S3C2410_ADCCON_SELMUX(x)       (((x)&0x7)<<3)
 #define S3C2410_ADCCON_MUXMASK         (0x7<<3)
+#define S3C2416_ADCCON_RESSEL          (1 << 3)
 #define S3C2410_ADCCON_STDBM           (1<<2)
 #define S3C2410_ADCCON_READ_START      (1<<1)
 #define S3C2410_ADCCON_ENABLE_START    (1<<0)
@@ -40,6 +42,7 @@
 
 
 /* ADCTSC Register Bits */
+#define S3C2443_ADCTSC_UD_SEN          (1 << 8)
 #define S3C2410_ADCTSC_YM_SEN          (1<<7)
 #define S3C2410_ADCTSC_YP_SEN          (1<<6)
 #define S3C2410_ADCTSC_XM_SEN          (1<<5)
@@ -1,4 +1,4 @@
-/* arch/arm/mach-s3c2410/include/mach/dma.h
+/* arch/arm/plat-samsung/include/plat/regs-dma.h
  *
  * Copyright (C) 2003-2006 Simtec Electronics
  *     Ben Dooks <ben@simtec.co.uk>
@@ -10,7 +10,8 @@
  * published by the Free Software Foundation.
 */
 
-/* DMA Register definitions */
+#ifndef __ASM_PLAT_REGS_DMA_H
+#define __ASM_PLAT_REGS_DMA_H __FILE__
 
 #define S3C2410_DMA_DISRC              (0x00)
 #define S3C2410_DMA_DISRCC             (0x04)
 #define S3C2412_DMA_DMAREQSEL          (0x24)
 #define S3C2443_DMA_DMAREQSEL          (0x24)
 
-#define S3C2410_DISRCC_INC             (1<<0)
-#define S3C2410_DISRCC_APB             (1<<1)
+#define S3C2410_DISRCC_INC             (1 << 0)
+#define S3C2410_DISRCC_APB             (1 << 1)
 
-#define S3C2410_DMASKTRIG_STOP         (1<<2)
-#define S3C2410_DMASKTRIG_ON           (1<<1)
-#define S3C2410_DMASKTRIG_SWTRIG       (1<<0)
+#define S3C2410_DMASKTRIG_STOP         (1 << 2)
+#define S3C2410_DMASKTRIG_ON           (1 << 1)
+#define S3C2410_DMASKTRIG_SWTRIG       (1 << 0)
 
-#define S3C2410_DCON_DEMAND            (0<<31)
-#define S3C2410_DCON_HANDSHAKE         (1<<31)
-#define S3C2410_DCON_SYNC_PCLK         (0<<30)
-#define S3C2410_DCON_SYNC_HCLK         (1<<30)
+#define S3C2410_DCON_DEMAND            (0 << 31)
+#define S3C2410_DCON_HANDSHAKE         (1 << 31)
+#define S3C2410_DCON_SYNC_PCLK         (0 << 30)
+#define S3C2410_DCON_SYNC_HCLK         (1 << 30)
 
-#define S3C2410_DCON_INTREQ            (1<<29)
+#define S3C2410_DCON_INTREQ            (1 << 29)
 
-#define S3C2410_DCON_CH0_XDREQ0                (0<<24)
-#define S3C2410_DCON_CH0_UART0         (1<<24)
-#define S3C2410_DCON_CH0_SDI           (2<<24)
-#define S3C2410_DCON_CH0_TIMER         (3<<24)
-#define S3C2410_DCON_CH0_USBEP1                (4<<24)
+#define S3C2410_DCON_CH0_XDREQ0                (0 << 24)
+#define S3C2410_DCON_CH0_UART0         (1 << 24)
+#define S3C2410_DCON_CH0_SDI           (2 << 24)
+#define S3C2410_DCON_CH0_TIMER         (3 << 24)
+#define S3C2410_DCON_CH0_USBEP1                (4 << 24)
 
-#define S3C2410_DCON_CH1_XDREQ1                (0<<24)
-#define S3C2410_DCON_CH1_UART1         (1<<24)
-#define S3C2410_DCON_CH1_I2SSDI                (2<<24)
-#define S3C2410_DCON_CH1_SPI           (3<<24)
-#define S3C2410_DCON_CH1_USBEP2                (4<<24)
+#define S3C2410_DCON_CH1_XDREQ1                (0 << 24)
+#define S3C2410_DCON_CH1_UART1         (1 << 24)
+#define S3C2410_DCON_CH1_I2SSDI                (2 << 24)
+#define S3C2410_DCON_CH1_SPI           (3 << 24)
+#define S3C2410_DCON_CH1_USBEP2                (4 << 24)
 
-#define S3C2410_DCON_CH2_I2SSDO                (0<<24)
-#define S3C2410_DCON_CH2_I2SSDI                (1<<24)
-#define S3C2410_DCON_CH2_SDI           (2<<24)
-#define S3C2410_DCON_CH2_TIMER         (3<<24)
-#define S3C2410_DCON_CH2_USBEP3                (4<<24)
+#define S3C2410_DCON_CH2_I2SSDO                (0 << 24)
+#define S3C2410_DCON_CH2_I2SSDI                (1 << 24)
+#define S3C2410_DCON_CH2_SDI           (2 << 24)
+#define S3C2410_DCON_CH2_TIMER         (3 << 24)
+#define S3C2410_DCON_CH2_USBEP3                (4 << 24)
 
-#define S3C2410_DCON_CH3_UART2         (0<<24)
-#define S3C2410_DCON_CH3_SDI           (1<<24)
-#define S3C2410_DCON_CH3_SPI           (2<<24)
-#define S3C2410_DCON_CH3_TIMER         (3<<24)
-#define S3C2410_DCON_CH3_USBEP4                (4<<24)
+#define S3C2410_DCON_CH3_UART2         (0 << 24)
+#define S3C2410_DCON_CH3_SDI           (1 << 24)
+#define S3C2410_DCON_CH3_SPI           (2 << 24)
+#define S3C2410_DCON_CH3_TIMER         (3 << 24)
+#define S3C2410_DCON_CH3_USBEP4                (4 << 24)
 
 #define S3C2410_DCON_SRCSHIFT          (24)
-#define S3C2410_DCON_SRCMASK           (7<<24)
+#define S3C2410_DCON_SRCMASK           (7 << 24)
 
-#define S3C2410_DCON_BYTE              (0<<20)
-#define S3C2410_DCON_HALFWORD          (1<<20)
-#define S3C2410_DCON_WORD              (2<<20)
+#define S3C2410_DCON_BYTE              (0 << 20)
+#define S3C2410_DCON_HALFWORD          (1 << 20)
+#define S3C2410_DCON_WORD              (2 << 20)
 
-#define S3C2410_DCON_AUTORELOAD                (0<<22)
-#define S3C2410_DCON_NORELOAD          (1<<22)
-#define S3C2410_DCON_HWTRIG            (1<<23)
+#define S3C2410_DCON_AUTORELOAD                (0 << 22)
+#define S3C2410_DCON_NORELOAD          (1 << 22)
+#define S3C2410_DCON_HWTRIG            (1 << 23)
 
 #ifdef CONFIG_CPU_S3C2440
-#define S3C2440_DIDSTC_CHKINT          (1<<2)
 
-#define S3C2440_DCON_CH0_I2SSDO                (5<<24)
-#define S3C2440_DCON_CH0_PCMIN         (6<<24)
+#define S3C2440_DIDSTC_CHKINT          (1 << 2)
 
-#define S3C2440_DCON_CH1_PCMOUT                (5<<24)
-#define S3C2440_DCON_CH1_SDI           (6<<24)
+#define S3C2440_DCON_CH0_I2SSDO                (5 << 24)
+#define S3C2440_DCON_CH0_PCMIN         (6 << 24)
 
-#define S3C2440_DCON_CH2_PCMIN         (5<<24)
-#define S3C2440_DCON_CH2_MICIN         (6<<24)
+#define S3C2440_DCON_CH1_PCMOUT                (5 << 24)
+#define S3C2440_DCON_CH1_SDI           (6 << 24)
 
-#define S3C2440_DCON_CH3_MICIN         (5<<24)
-#define S3C2440_DCON_CH3_PCMOUT                (6<<24)
-#endif
+#define S3C2440_DCON_CH2_PCMIN         (5 << 24)
+#define S3C2440_DCON_CH2_MICIN         (6 << 24)
+
+#define S3C2440_DCON_CH3_MICIN         (5 << 24)
+#define S3C2440_DCON_CH3_PCMOUT                (6 << 24)
+#endif /* CONFIG_CPU_S3C2440 */
 
 #ifdef CONFIG_CPU_S3C2412
 
-#define S3C2412_DMAREQSEL_SRC(x)       ((x)<<1)
+#define S3C2412_DMAREQSEL_SRC(x)       ((x) << 1)
 
 #define S3C2412_DMAREQSEL_HW           (1)
 
 #define S3C2412_DMAREQSEL_UART1_1      S3C2412_DMAREQSEL_SRC(22)
 #define S3C2412_DMAREQSEL_UART2_0      S3C2412_DMAREQSEL_SRC(23)
 #define S3C2412_DMAREQSEL_UART2_1      S3C2412_DMAREQSEL_SRC(24)
+#endif /* CONFIG_CPU_S3C2412 */
 
-#endif
+#ifdef CONFIG_CPU_S3C2443
 
-#define S3C2443_DMAREQSEL_SRC(x)       ((x)<<1)
+#define S3C2443_DMAREQSEL_SRC(x)       ((x) << 1)
 
 #define S3C2443_DMAREQSEL_HW           (1)
 
 #define S3C2443_DMAREQSEL_UART3_0      S3C2443_DMAREQSEL_SRC(25)
 #define S3C2443_DMAREQSEL_UART3_1      S3C2443_DMAREQSEL_SRC(26)
 #define S3C2443_DMAREQSEL_PCMOUT       S3C2443_DMAREQSEL_SRC(27)
-#define S3C2443_DMAREQSEL_PCMIN        S3C2443_DMAREQSEL_SRC(28)
+#define S3C2443_DMAREQSEL_PCMIN                S3C2443_DMAREQSEL_SRC(28)
 #define S3C2443_DMAREQSEL_MICIN                S3C2443_DMAREQSEL_SRC(29)
+#endif /* CONFIG_CPU_S3C2443 */
+
+#endif /* __ASM_PLAT_REGS_DMA_H */
diff --git a/arch/arm/plat-samsung/include/plat/regs-iis.h b/arch/arm/plat-samsung/include/plat/regs-iis.h
new file mode 100644 (file)
index 0000000..a18d35e
--- /dev/null
@@ -0,0 +1,70 @@
+/* arch/arm/plat-samsung/include/plat/regs-iis.h
+ *
+ * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
+ *                   http://www.simtec.co.uk/products/SWLINUX/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * S3C2410 IIS register definition
+*/
+
+#ifndef __ASM_ARCH_REGS_IIS_H
+#define __ASM_ARCH_REGS_IIS_H
+
+#define S3C2410_IISCON                 (0x00)
+
+#define S3C2410_IISCON_LRINDEX         (1 << 8)
+#define S3C2410_IISCON_TXFIFORDY       (1 << 7)
+#define S3C2410_IISCON_RXFIFORDY       (1 << 6)
+#define S3C2410_IISCON_TXDMAEN         (1 << 5)
+#define S3C2410_IISCON_RXDMAEN         (1 << 4)
+#define S3C2410_IISCON_TXIDLE          (1 << 3)
+#define S3C2410_IISCON_RXIDLE          (1 << 2)
+#define S3C2410_IISCON_PSCEN           (1 << 1)
+#define S3C2410_IISCON_IISEN           (1 << 0)
+
+#define S3C2410_IISMOD                 (0x04)
+
+#define S3C2440_IISMOD_MPLL            (1 << 9)
+#define S3C2410_IISMOD_SLAVE           (1 << 8)
+#define S3C2410_IISMOD_NOXFER          (0 << 6)
+#define S3C2410_IISMOD_RXMODE          (1 << 6)
+#define S3C2410_IISMOD_TXMODE          (2 << 6)
+#define S3C2410_IISMOD_TXRXMODE                (3 << 6)
+#define S3C2410_IISMOD_LR_LLOW         (0 << 5)
+#define S3C2410_IISMOD_LR_RLOW         (1 << 5)
+#define S3C2410_IISMOD_IIS             (0 << 4)
+#define S3C2410_IISMOD_MSB             (1 << 4)
+#define S3C2410_IISMOD_8BIT            (0 << 3)
+#define S3C2410_IISMOD_16BIT           (1 << 3)
+#define S3C2410_IISMOD_BITMASK         (1 << 3)
+#define S3C2410_IISMOD_256FS           (0 << 2)
+#define S3C2410_IISMOD_384FS           (1 << 2)
+#define S3C2410_IISMOD_16FS            (0 << 0)
+#define S3C2410_IISMOD_32FS            (1 << 0)
+#define S3C2410_IISMOD_48FS            (2 << 0)
+#define S3C2410_IISMOD_FS_MASK         (3 << 0)
+
+#define S3C2410_IISPSR                 (0x08)
+
+#define S3C2410_IISPSR_INTMASK         (31 << 5)
+#define S3C2410_IISPSR_INTSHIFT                (5)
+#define S3C2410_IISPSR_EXTMASK         (31 << 0)
+#define S3C2410_IISPSR_EXTSHFIT                (0)
+
+#define S3C2410_IISFCON                        (0x0c)
+
+#define S3C2410_IISFCON_TXDMA          (1 << 15)
+#define S3C2410_IISFCON_RXDMA          (1 << 14)
+#define S3C2410_IISFCON_TXENABLE       (1 << 13)
+#define S3C2410_IISFCON_RXENABLE       (1 << 12)
+#define S3C2410_IISFCON_TXMASK         (0x3f << 6)
+#define S3C2410_IISFCON_TXSHIFT                (6)
+#define S3C2410_IISFCON_RXMASK         (0x3f)
+#define S3C2410_IISFCON_RXSHIFT                (0)
+
+#define S3C2410_IISFIFO                        (0x10)
+
+#endif /* __ASM_ARCH_REGS_IIS_H */
diff --git a/arch/arm/plat-samsung/include/plat/regs-spi.h b/arch/arm/plat-samsung/include/plat/regs-spi.h
new file mode 100644 (file)
index 0000000..552fe7c
--- /dev/null
@@ -0,0 +1,48 @@
+/* arch/arm/plat-samsung/include/plat/regs-spi.h
+ *
+ * Copyright (c) 2004 Fetron GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * S3C2410 SPI register definition
+*/
+
+#ifndef __ASM_ARCH_REGS_SPI_H
+#define __ASM_ARCH_REGS_SPI_H
+
+#define S3C2410_SPI1           (0x20)
+#define S3C2412_SPI1           (0x100)
+
+#define S3C2410_SPCON          (0x00)
+
+#define S3C2410_SPCON_SMOD_DMA (2 << 5)        /* DMA mode */
+#define S3C2410_SPCON_SMOD_INT (1 << 5)        /* interrupt mode */
+#define S3C2410_SPCON_SMOD_POLL        (0 << 5)        /* polling mode */
+#define S3C2410_SPCON_ENSCK    (1 << 4)        /* Enable SCK */
+#define S3C2410_SPCON_MSTR     (1 << 3)        /* Master:1, Slave:0 select */
+#define S3C2410_SPCON_CPOL_HIGH        (1 << 2)        /* Clock polarity select */
+#define S3C2410_SPCON_CPOL_LOW (0 << 2)        /* Clock polarity select */
+
+#define S3C2410_SPCON_CPHA_FMTB        (1 << 1)        /* Clock Phase Select */
+#define S3C2410_SPCON_CPHA_FMTA        (0 << 1)        /* Clock Phase Select */
+
+#define S3C2410_SPSTA          (0x04)
+
+#define S3C2410_SPSTA_DCOL     (1 << 2)        /* Data Collision Error */
+#define S3C2410_SPSTA_MULD     (1 << 1)        /* Multi Master Error */
+#define S3C2410_SPSTA_READY    (1 << 0)        /* Data Tx/Rx ready */
+#define S3C2412_SPSTA_READY_ORG        (1 << 3)
+
+#define S3C2410_SPPIN          (0x08)
+
+#define S3C2410_SPPIN_ENMUL    (1 << 2)        /* Multi Master Error detect */
+#define S3C2410_SPPIN_RESERVED (1 << 1)
+#define S3C2410_SPPIN_KEEP     (1 << 0)        /* Master Out keep */
+
+#define S3C2410_SPPRE          (0x0C)
+#define S3C2410_SPTDAT         (0x10)
+#define S3C2410_SPRDAT         (0x14)
+
+#endif /* __ASM_ARCH_REGS_SPI_H */
similarity index 89%
rename from arch/arm/plat-s5p/include/plat/regs-srom.h
rename to arch/arm/plat-samsung/include/plat/regs-srom.h
index f121ab5..9b6729c 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/arch/arm/plat-s5p/include/plat/regs-srom.h
+/* linux/arch/arm/plat-samsung/include/plat/regs-srom.h
  *
  * Copyright (c) 2010 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com
@@ -10,8 +10,8 @@
  * published by the Free Software Foundation.
 */
 
-#ifndef __ASM_PLAT_S5P_REGS_SROM_H
-#define __ASM_PLAT_S5P_REGS_SROM_H __FILE__
+#ifndef __PLAT_SAMSUNG_REGS_SROM_H
+#define __PLAT_SAMSUNG_REGS_SROM_H __FILE__
 
 #include <mach/map.h>
 
@@ -51,4 +51,4 @@
 #define S5P_SROM_BCX__TCOS__SHIFT              24
 #define S5P_SROM_BCX__TACS__SHIFT              28
 
-#endif /* __ASM_PLAT_S5P_REGS_SROM_H */
+#endif /* __PLAT_SAMSUNG_REGS_SROM_H */
@@ -1,4 +1,4 @@
-/* arch/arm/mach-s3c2410/include/mach/regs-udc.h
+/* arch/arm/plat-samsung/include/plat/regs-udc.h
  *
  * Copyright (C) 2004 Herbert Poetzl <herbert@13thfloor.at>
  *
 #define S3C2410_UDC_OUT_FIFO_CNT1_REG  S3C2410_USBDREG(0x0198)
 #define S3C2410_UDC_OUT_FIFO_CNT2_REG  S3C2410_USBDREG(0x019c)
 
-#define S3C2410_UDC_FUNCADDR_UPDATE    (1<<7)
+#define S3C2410_UDC_FUNCADDR_UPDATE    (1 << 7)
 
-#define S3C2410_UDC_PWR_ISOUP          (1<<7) // R/W
-#define S3C2410_UDC_PWR_RESET          (1<<3) // R
-#define S3C2410_UDC_PWR_RESUME         (1<<2) // R/W
-#define S3C2410_UDC_PWR_SUSPEND                (1<<1) // R
-#define S3C2410_UDC_PWR_ENSUSPEND      (1<<0) // R/W
+#define S3C2410_UDC_PWR_ISOUP          (1 << 7) /* R/W */
+#define S3C2410_UDC_PWR_RESET          (1 << 3) /* R   */
+#define S3C2410_UDC_PWR_RESUME         (1 << 2) /* R/W */
+#define S3C2410_UDC_PWR_SUSPEND                (1 << 1) /* R   */
+#define S3C2410_UDC_PWR_ENSUSPEND      (1 << 0) /* R/W */
 
-#define S3C2410_UDC_PWR_DEFAULT                0x00
+#define S3C2410_UDC_PWR_DEFAULT                (0x00)
 
-#define S3C2410_UDC_INT_EP4            (1<<4) // R/W (clear only)
-#define S3C2410_UDC_INT_EP3            (1<<3) // R/W (clear only)
-#define S3C2410_UDC_INT_EP2            (1<<2) // R/W (clear only)
-#define S3C2410_UDC_INT_EP1            (1<<1) // R/W (clear only)
-#define S3C2410_UDC_INT_EP0            (1<<0) // R/W (clear only)
+#define S3C2410_UDC_INT_EP4            (1 << 4) /* R/W (clear only) */
+#define S3C2410_UDC_INT_EP3            (1 << 3) /* R/W (clear only) */
+#define S3C2410_UDC_INT_EP2            (1 << 2) /* R/W (clear only) */
+#define S3C2410_UDC_INT_EP1            (1 << 1) /* R/W (clear only) */
+#define S3C2410_UDC_INT_EP0            (1 << 0) /* R/W (clear only) */
 
-#define S3C2410_UDC_USBINT_RESET       (1<<2) // R/W (clear only)
-#define S3C2410_UDC_USBINT_RESUME      (1<<1) // R/W (clear only)
-#define S3C2410_UDC_USBINT_SUSPEND     (1<<0) // R/W (clear only)
+#define S3C2410_UDC_USBINT_RESET       (1 << 2) /* R/W (clear only) */
+#define S3C2410_UDC_USBINT_RESUME      (1 << 1) /* R/W (clear only) */
+#define S3C2410_UDC_USBINT_SUSPEND     (1 << 0) /* R/W (clear only) */
 
-#define S3C2410_UDC_INTE_EP4           (1<<4) // R/W
-#define S3C2410_UDC_INTE_EP3           (1<<3) // R/W
-#define S3C2410_UDC_INTE_EP2           (1<<2) // R/W
-#define S3C2410_UDC_INTE_EP1           (1<<1) // R/W
-#define S3C2410_UDC_INTE_EP0           (1<<0) // R/W
-
-#define S3C2410_UDC_USBINTE_RESET      (1<<2) // R/W
-#define S3C2410_UDC_USBINTE_SUSPEND    (1<<0) // R/W
+#define S3C2410_UDC_INTE_EP4           (1 << 4) /* R/W */
+#define S3C2410_UDC_INTE_EP3           (1 << 3) /* R/W */
+#define S3C2410_UDC_INTE_EP2           (1 << 2) /* R/W */
+#define S3C2410_UDC_INTE_EP1           (1 << 1) /* R/W */
+#define S3C2410_UDC_INTE_EP0           (1 << 0) /* R/W */
 
+#define S3C2410_UDC_USBINTE_RESET      (1 << 2) /* R/W */
+#define S3C2410_UDC_USBINTE_SUSPEND    (1 << 0) /* R/W */
 
 #define S3C2410_UDC_INDEX_EP0          (0x00)
-#define S3C2410_UDC_INDEX_EP1          (0x01) // ??
-#define S3C2410_UDC_INDEX_EP2          (0x02) // ??
-#define S3C2410_UDC_INDEX_EP3          (0x03) // ??
-#define S3C2410_UDC_INDEX_EP4          (0x04) // ??
-
-#define S3C2410_UDC_ICSR1_CLRDT                (1<<6) // R/W
-#define S3C2410_UDC_ICSR1_SENTSTL      (1<<5) // R/W (clear only)
-#define S3C2410_UDC_ICSR1_SENDSTL      (1<<4) // R/W
-#define S3C2410_UDC_ICSR1_FFLUSH       (1<<3) // W   (set only)
-#define S3C2410_UDC_ICSR1_UNDRUN       (1<<2) // R/W (clear only)
-#define S3C2410_UDC_ICSR1_PKTRDY       (1<<0) // R/W (set only)
-
-#define S3C2410_UDC_ICSR2_AUTOSET      (1<<7) // R/W
-#define S3C2410_UDC_ICSR2_ISO          (1<<6) // R/W
-#define S3C2410_UDC_ICSR2_MODEIN       (1<<5) // R/W
-#define S3C2410_UDC_ICSR2_DMAIEN       (1<<4) // R/W
-
-#define S3C2410_UDC_OCSR1_CLRDT                (1<<7) // R/W
-#define S3C2410_UDC_OCSR1_SENTSTL      (1<<6) // R/W (clear only)
-#define S3C2410_UDC_OCSR1_SENDSTL      (1<<5) // R/W
-#define S3C2410_UDC_OCSR1_FFLUSH       (1<<4) // R/W
-#define S3C2410_UDC_OCSR1_DERROR       (1<<3) // R
-#define S3C2410_UDC_OCSR1_OVRRUN       (1<<2) // R/W (clear only)
-#define S3C2410_UDC_OCSR1_PKTRDY       (1<<0) // R/W (clear only)
-
-#define S3C2410_UDC_OCSR2_AUTOCLR      (1<<7) // R/W
-#define S3C2410_UDC_OCSR2_ISO          (1<<6) // R/W
-#define S3C2410_UDC_OCSR2_DMAIEN       (1<<5) // R/W
-
-#define S3C2410_UDC_EP0_CSR_OPKRDY     (1<<0)
-#define S3C2410_UDC_EP0_CSR_IPKRDY     (1<<1)
-#define S3C2410_UDC_EP0_CSR_SENTSTL    (1<<2)
-#define S3C2410_UDC_EP0_CSR_DE         (1<<3)
-#define S3C2410_UDC_EP0_CSR_SE         (1<<4)
-#define S3C2410_UDC_EP0_CSR_SENDSTL    (1<<5)
-#define S3C2410_UDC_EP0_CSR_SOPKTRDY   (1<<6)
-#define S3C2410_UDC_EP0_CSR_SSE        (1<<7)
-
-#define S3C2410_UDC_MAXP_8             (1<<0)
-#define S3C2410_UDC_MAXP_16            (1<<1)
-#define S3C2410_UDC_MAXP_32            (1<<2)
-#define S3C2410_UDC_MAXP_64            (1<<3)
-
+#define S3C2410_UDC_INDEX_EP1          (0x01)
+#define S3C2410_UDC_INDEX_EP2          (0x02)
+#define S3C2410_UDC_INDEX_EP3          (0x03)
+#define S3C2410_UDC_INDEX_EP4          (0x04)
+
+#define S3C2410_UDC_ICSR1_CLRDT                (1 << 6) /* R/W */
+#define S3C2410_UDC_ICSR1_SENTSTL      (1 << 5) /* R/W (clear only) */
+#define S3C2410_UDC_ICSR1_SENDSTL      (1 << 4) /* R/W */
+#define S3C2410_UDC_ICSR1_FFLUSH       (1 << 3) /* W   (set only) */
+#define S3C2410_UDC_ICSR1_UNDRUN       (1 << 2) /* R/W (clear only) */
+#define S3C2410_UDC_ICSR1_PKTRDY       (1 << 0) /* R/W (set only) */
+
+#define S3C2410_UDC_ICSR2_AUTOSET      (1 << 7) /* R/W */
+#define S3C2410_UDC_ICSR2_ISO          (1 << 6) /* R/W */
+#define S3C2410_UDC_ICSR2_MODEIN       (1 << 5) /* R/W */
+#define S3C2410_UDC_ICSR2_DMAIEN       (1 << 4) /* R/W */
+
+#define S3C2410_UDC_OCSR1_CLRDT                (1 << 7) /* R/W */
+#define S3C2410_UDC_OCSR1_SENTSTL      (1 << 6) /* R/W (clear only) */
+#define S3C2410_UDC_OCSR1_SENDSTL      (1 << 5) /* R/W */
+#define S3C2410_UDC_OCSR1_FFLUSH       (1 << 4) /* R/W */
+#define S3C2410_UDC_OCSR1_DERROR       (1 << 3) /* R   */
+#define S3C2410_UDC_OCSR1_OVRRUN       (1 << 2) /* R/W (clear only) */
+#define S3C2410_UDC_OCSR1_PKTRDY       (1 << 0) /* R/W (clear only) */
+
+#define S3C2410_UDC_OCSR2_AUTOCLR      (1 << 7) /* R/W */
+#define S3C2410_UDC_OCSR2_ISO          (1 << 6) /* R/W */
+#define S3C2410_UDC_OCSR2_DMAIEN       (1 << 5) /* R/W */
+
+#define S3C2410_UDC_EP0_CSR_OPKRDY     (1 << 0)
+#define S3C2410_UDC_EP0_CSR_IPKRDY     (1 << 1)
+#define S3C2410_UDC_EP0_CSR_SENTSTL    (1 << 2)
+#define S3C2410_UDC_EP0_CSR_DE         (1 << 3)
+#define S3C2410_UDC_EP0_CSR_SE         (1 << 4)
+#define S3C2410_UDC_EP0_CSR_SENDSTL    (1 << 5)
+#define S3C2410_UDC_EP0_CSR_SOPKTRDY   (1 << 6)
+#define S3C2410_UDC_EP0_CSR_SSE                (1 << 7)
+
+#define S3C2410_UDC_MAXP_8             (1 << 0)
+#define S3C2410_UDC_MAXP_16            (1 << 1)
+#define S3C2410_UDC_MAXP_32            (1 << 2)
+#define S3C2410_UDC_MAXP_64            (1 << 3)
 
 #endif
similarity index 66%
rename from arch/arm/plat-s5p/include/plat/reset.h
rename to arch/arm/plat-samsung/include/plat/reset.h
index 335e978..32ca517 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/arch/arm/plat-s5p/include/plat/reset.h
+/* linux/arch/arm/plat-samsung/include/plat/reset.h
  *
  * Copyright (c) 2010 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com/
@@ -8,9 +8,9 @@
  * published by the Free Software Foundation.
 */
 
-#ifndef __ASM_PLAT_S5P_RESET_H
-#define __ASM_PLAT_S5P_RESET_H __FILE__
+#ifndef __PLAT_SAMSUNG_RESET_H
+#define __PLAT_SAMSUNG_RESET_H __FILE__
 
 extern void (*s5p_reset_hook)(void);
 
-#endif /* __ASM_PLAT_S5P_RESET_H */
+#endif /* __PLAT_SAMSUNG_RESET_H */
diff --git a/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h b/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h
deleted file mode 100644 (file)
index bf5e2a9..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/* linux/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h
- *
- * Copyright (C) 2010 Samsung Electronics Co. Ltd.
- *     Jaswinder Singh <jassi.brar@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __S3C_PL330_PDATA_H
-#define __S3C_PL330_PDATA_H
-
-#include <plat/s3c-dma-pl330.h>
-
-/*
- * Every PL330 DMAC has max 32 peripheral interfaces,
- * of which some may be not be really used in your
- * DMAC's configuration.
- * Populate this array of 32 peri i/fs with relevant
- * channel IDs for used peri i/f and DMACH_MAX for
- * those unused.
- *
- * The platforms just need to provide this info
- * to the S3C DMA API driver for PL330.
- */
-struct s3c_pl330_platdata {
-       enum dma_ch peri[32];
-};
-
-#endif /* __S3C_PL330_PDATA_H */
similarity index 93%
rename from arch/arm/plat-s3c24xx/include/plat/s3c2410.h
rename to arch/arm/plat-samsung/include/plat/s3c2410.h
index 82ab4aa..3986497 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/include/asm-arm/plat-s3c24xx/s3c2410.h
+/* linux/arch/arm/plat-samsung/include/plat/s3c2410.h
  *
  * Copyright (c) 2004 Simtec Electronics
  *     Ben Dooks <ben@simtec.co.uk>
similarity index 92%
rename from arch/arm/plat-s3c24xx/include/plat/s3c2412.h
rename to arch/arm/plat-samsung/include/plat/s3c2412.h
index bb15d3b..5bcfd14 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/include/asm-arm/plat-s3c24xx/s3c2412.h
+/* linux/arch/arm/plat-samsung/include/plat/s3c2412.h
  *
  * Copyright (c) 2006 Simtec Electronics
  *     Ben Dooks <ben@simtec.co.uk>
similarity index 92%
rename from arch/arm/plat-s3c24xx/include/plat/s3c2416.h
rename to arch/arm/plat-samsung/include/plat/s3c2416.h
index dc3c090..a764f85 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/include/asm-arm/plat-s3c24xx/s3c2443.h
+/* linux/arch/arm/plat-samsung/include/plat/s3c2416.h
  *
  * Copyright (c) 2009 Yauhen Kharuzhy <jekhor@gmail.com>
  *
similarity index 87%
rename from arch/arm/plat-s3c24xx/include/plat/s3c2443.h
rename to arch/arm/plat-samsung/include/plat/s3c2443.h
index a19715f..7fae1a0 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/include/asm-arm/plat-s3c24xx/s3c2443.h
+/* linux/arch/arm/plat-samsung/include/plat/s3c2443.h
  *
  * Copyright (c) 2004-2005 Simtec Electronics
  *     Ben Dooks <ben@simtec.co.uk>
@@ -37,10 +37,11 @@ extern  int s3c2443_baseclk_add(void);
 struct clk;    /* some files don't need clk.h otherwise */
 
 typedef unsigned int (*pll_fn)(unsigned int reg, unsigned int base);
-typedef unsigned int (*fdiv_fn)(unsigned long clkcon0);
 
-extern void s3c2443_common_setup_clocks(pll_fn get_mpll, fdiv_fn fdiv);
-extern void s3c2443_common_init_clocks(int xtal, pll_fn get_mpll, fdiv_fn fdiv);
+extern void s3c2443_common_setup_clocks(pll_fn get_mpll);
+extern void s3c2443_common_init_clocks(int xtal, pll_fn get_mpll,
+                                      unsigned int *divs, int nr_divs,
+                                      int divmask);
 
 extern int s3c2443_clkcon_enable_h(struct clk *clk, int enable);
 extern int s3c2443_clkcon_enable_p(struct clk *clk, int enable);
similarity index 94%
rename from arch/arm/plat-s3c24xx/include/plat/s3c244x.h
rename to arch/arm/plat-samsung/include/plat/s3c244x.h
index 89e8d0a..ea0c961 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/arch/arm/plat-s3c24xx/include/plat/s3c244x.h
+/* linux/arch/arm/plat-samsung/include/plat/s3c244x.h
  *
  * Copyright (c) 2004-2005 Simtec Electronics
  *     Ben Dooks <ben@simtec.co.uk>
similarity index 94%
rename from arch/arm/mach-s3c64xx/include/mach/s3c6400.h
rename to arch/arm/plat-samsung/include/plat/s3c6400.h
index f86958d..37d428a 100644 (file)
@@ -1,4 +1,4 @@
-/* arch/arm/mach-s3c64xx/include/macht/s3c6400.h
+/* linux/arch/arm/plat-samsung/include/plat/s3c6400.h
  *
  * Copyright 2008 Openmoko, Inc.
  * Copyright 2008 Simtec Electronics
similarity index 93%
rename from arch/arm/mach-s3c64xx/include/mach/s3c6410.h
rename to arch/arm/plat-samsung/include/plat/s3c6410.h
index 24f1141..20a6675 100644 (file)
@@ -1,4 +1,4 @@
-/* arch/arm/mach-s3c64xx/include/mach/s3c6410.h
+/* linux/arch/arm/plat-samsung/include/plat/s3c6410.h
  *
  * Copyright 2008 Openmoko,  Inc.
  * Copyright 2008 Simtec Electronics
similarity index 96%
rename from arch/arm/plat-s5p/include/plat/s5p-clock.h
rename to arch/arm/plat-samsung/include/plat/s5p-clock.h
index 769b5bd..984bf9e 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/arch/arm/plat-s5p/include/plat/s5p-clock.h
+/* linux/arch/arm/plat-samsung/include/plat/s5p-clock.h
  *
  * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com
similarity index 94%
rename from arch/arm/plat-s5p/include/plat/s5p-time.h
rename to arch/arm/plat-samsung/include/plat/s5p-time.h
index 575e881..3a70aeb 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/arch/arm/plat-s5p/include/plat/s5p-time.h
+/* linux/arch/arm/plat-samsung/include/plat/s5p-time.h
  *
  * Copyright 2011 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com/
similarity index 94%
rename from arch/arm/plat-s5p/include/plat/s5p6440.h
rename to arch/arm/plat-samsung/include/plat/s5p6440.h
index 528585d..bf85ebb 100644 (file)
@@ -1,4 +1,4 @@
-/* arch/arm/plat-s5p/include/plat/s5p6440.h
+/* linux/arch/arm/plat-samsung/include/plat/s5p6440.h
  *
  * Copyright (c) 2009 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com/
similarity index 94%
rename from arch/arm/plat-s5p/include/plat/s5p6450.h
rename to arch/arm/plat-samsung/include/plat/s5p6450.h
index 640a41c..da25f9a 100644 (file)
@@ -1,4 +1,4 @@
-/* arch/arm/plat-s5p/include/plat/s5p6450.h
+/* linux/arch/arm/plat-samsung/include/plat/s5p6450.h
  *
  * Copyright (c) 2010 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com
similarity index 94%
rename from arch/arm/plat-s5p/include/plat/s5pc100.h
rename to arch/arm/plat-samsung/include/plat/s5pc100.h
index 5f6099d..9a21aea 100644 (file)
@@ -1,4 +1,4 @@
-/* arch/arm/plat-s5p/include/plat/s5pc100.h
+/* linux/arch/arm/plat-samsung/include/plat/s5pc100.h
  *
  * Copyright (c) 2010 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com/
similarity index 94%
rename from arch/arm/plat-s5p/include/plat/s5pv210.h
rename to arch/arm/plat-samsung/include/plat/s5pv210.h
index 6c93a0c..b4bc6be 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/arch/arm/plat-s5p/include/plat/s5pv210.h
+/* linux/arch/arm/plat-samsung/include/plat/s5pv210.h
  *
  * Copyright (c) 2010 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com/
index 4a65520..e7b3c75 100644 (file)
@@ -55,10 +55,6 @@ enum clk_types {
  *              cd_type == S3C_SDHCI_CD_GPIO
  * @ext_cd_gpio_invert: invert values for external CD gpio line
  * @cfg_gpio: Configure the GPIO for a specific card bit-width
- * @cfg_card: Configure the interface for a specific card and speed. This
- *            is necessary the controllers and/or GPIO blocks require the
- *           changing of driver-strength and other controls dependent on
- *           the card and speed of operation.
  *
  * Initialisation data specific to either the machine or the platform
  * for the device driver to use or call-back when configuring gpio or
@@ -80,10 +76,6 @@ struct s3c_sdhci_platdata {
                                                      int state));
 
        void    (*cfg_gpio)(struct platform_device *dev, int width);
-       void    (*cfg_card)(struct platform_device *dev,
-                           void __iomem *regbase,
-                           struct mmc_ios *ios,
-                           struct mmc_card *card);
 };
 
 /* s3c_sdhci_set_platdata() - common helper for setting SDHCI platform data
@@ -139,17 +131,11 @@ extern void exynos4_setup_sdhci3_cfg_gpio(struct platform_device *, int w);
 #ifdef CONFIG_S3C2416_SETUP_SDHCI
 extern char *s3c2416_hsmmc_clksrcs[4];
 
-extern void s3c2416_setup_sdhci_cfg_card(struct platform_device *dev,
-                                          void __iomem *r,
-                                          struct mmc_ios *ios,
-                                          struct mmc_card *card);
-
 static inline void s3c2416_default_sdhci0(void)
 {
 #ifdef CONFIG_S3C_DEV_HSMMC
        s3c_hsmmc0_def_platdata.clocks = s3c2416_hsmmc_clksrcs;
        s3c_hsmmc0_def_platdata.cfg_gpio = s3c2416_setup_sdhci0_cfg_gpio;
-       s3c_hsmmc0_def_platdata.cfg_card = s3c2416_setup_sdhci_cfg_card;
 #endif /* CONFIG_S3C_DEV_HSMMC */
 }
 
@@ -158,7 +144,6 @@ static inline void s3c2416_default_sdhci1(void)
 #ifdef CONFIG_S3C_DEV_HSMMC1
        s3c_hsmmc1_def_platdata.clocks = s3c2416_hsmmc_clksrcs;
        s3c_hsmmc1_def_platdata.cfg_gpio = s3c2416_setup_sdhci1_cfg_gpio;
-       s3c_hsmmc1_def_platdata.cfg_card = s3c2416_setup_sdhci_cfg_card;
 #endif /* CONFIG_S3C_DEV_HSMMC1 */
 }
 
@@ -172,17 +157,11 @@ static inline void s3c2416_default_sdhci1(void) { }
 #ifdef CONFIG_S3C64XX_SETUP_SDHCI
 extern char *s3c64xx_hsmmc_clksrcs[4];
 
-extern void s3c6400_setup_sdhci_cfg_card(struct platform_device *dev,
-                                        void __iomem *r,
-                                        struct mmc_ios *ios,
-                                        struct mmc_card *card);
-
 static inline void s3c6400_default_sdhci0(void)
 {
 #ifdef CONFIG_S3C_DEV_HSMMC
        s3c_hsmmc0_def_platdata.clocks = s3c64xx_hsmmc_clksrcs;
        s3c_hsmmc0_def_platdata.cfg_gpio = s3c64xx_setup_sdhci0_cfg_gpio;
-       s3c_hsmmc0_def_platdata.cfg_card = s3c6400_setup_sdhci_cfg_card;
 #endif
 }
 
@@ -191,7 +170,6 @@ static inline void s3c6400_default_sdhci1(void)
 #ifdef CONFIG_S3C_DEV_HSMMC1
        s3c_hsmmc1_def_platdata.clocks = s3c64xx_hsmmc_clksrcs;
        s3c_hsmmc1_def_platdata.cfg_gpio = s3c64xx_setup_sdhci1_cfg_gpio;
-       s3c_hsmmc1_def_platdata.cfg_card = s3c6400_setup_sdhci_cfg_card;
 #endif
 }
 
@@ -200,21 +178,14 @@ static inline void s3c6400_default_sdhci2(void)
 #ifdef CONFIG_S3C_DEV_HSMMC2
        s3c_hsmmc2_def_platdata.clocks = s3c64xx_hsmmc_clksrcs;
        s3c_hsmmc2_def_platdata.cfg_gpio = s3c64xx_setup_sdhci2_cfg_gpio;
-       s3c_hsmmc2_def_platdata.cfg_card = s3c6400_setup_sdhci_cfg_card;
 #endif
 }
 
-extern void s3c6410_setup_sdhci_cfg_card(struct platform_device *dev,
-                                        void __iomem *r,
-                                        struct mmc_ios *ios,
-                                        struct mmc_card *card);
-
 static inline void s3c6410_default_sdhci0(void)
 {
 #ifdef CONFIG_S3C_DEV_HSMMC
        s3c_hsmmc0_def_platdata.clocks = s3c64xx_hsmmc_clksrcs;
        s3c_hsmmc0_def_platdata.cfg_gpio = s3c64xx_setup_sdhci0_cfg_gpio;
-       s3c_hsmmc0_def_platdata.cfg_card = s3c6410_setup_sdhci_cfg_card;
 #endif
 }
 
@@ -223,7 +194,6 @@ static inline void s3c6410_default_sdhci1(void)
 #ifdef CONFIG_S3C_DEV_HSMMC1
        s3c_hsmmc1_def_platdata.clocks = s3c64xx_hsmmc_clksrcs;
        s3c_hsmmc1_def_platdata.cfg_gpio = s3c64xx_setup_sdhci1_cfg_gpio;
-       s3c_hsmmc1_def_platdata.cfg_card = s3c6410_setup_sdhci_cfg_card;
 #endif
 }
 
@@ -232,7 +202,6 @@ static inline void s3c6410_default_sdhci2(void)
 #ifdef CONFIG_S3C_DEV_HSMMC2
        s3c_hsmmc2_def_platdata.clocks = s3c64xx_hsmmc_clksrcs;
        s3c_hsmmc2_def_platdata.cfg_gpio = s3c64xx_setup_sdhci2_cfg_gpio;
-       s3c_hsmmc2_def_platdata.cfg_card = s3c6410_setup_sdhci_cfg_card;
 #endif
 }
 
@@ -251,17 +220,11 @@ static inline void s3c6400_default_sdhci2(void) { }
 #ifdef CONFIG_S5PC100_SETUP_SDHCI
 extern char *s5pc100_hsmmc_clksrcs[4];
 
-extern void s5pc100_setup_sdhci0_cfg_card(struct platform_device *dev,
-                                          void __iomem *r,
-                                          struct mmc_ios *ios,
-                                          struct mmc_card *card);
-
 static inline void s5pc100_default_sdhci0(void)
 {
 #ifdef CONFIG_S3C_DEV_HSMMC
        s3c_hsmmc0_def_platdata.clocks = s5pc100_hsmmc_clksrcs;
        s3c_hsmmc0_def_platdata.cfg_gpio = s5pc100_setup_sdhci0_cfg_gpio;
-       s3c_hsmmc0_def_platdata.cfg_card = s5pc100_setup_sdhci0_cfg_card;
 #endif
 }
 
@@ -270,7 +233,6 @@ static inline void s5pc100_default_sdhci1(void)
 #ifdef CONFIG_S3C_DEV_HSMMC1
        s3c_hsmmc1_def_platdata.clocks = s5pc100_hsmmc_clksrcs;
        s3c_hsmmc1_def_platdata.cfg_gpio = s5pc100_setup_sdhci1_cfg_gpio;
-       s3c_hsmmc1_def_platdata.cfg_card = s5pc100_setup_sdhci0_cfg_card;
 #endif
 }
 
@@ -279,7 +241,6 @@ static inline void s5pc100_default_sdhci2(void)
 #ifdef CONFIG_S3C_DEV_HSMMC2
        s3c_hsmmc2_def_platdata.clocks = s5pc100_hsmmc_clksrcs;
        s3c_hsmmc2_def_platdata.cfg_gpio = s5pc100_setup_sdhci2_cfg_gpio;
-       s3c_hsmmc2_def_platdata.cfg_card = s5pc100_setup_sdhci0_cfg_card;
 #endif
 }
 
@@ -295,17 +256,11 @@ static inline void s5pc100_default_sdhci2(void) { }
 #ifdef CONFIG_S5PV210_SETUP_SDHCI
 extern char *s5pv210_hsmmc_clksrcs[4];
 
-extern void s5pv210_setup_sdhci_cfg_card(struct platform_device *dev,
-                                          void __iomem *r,
-                                          struct mmc_ios *ios,
-                                          struct mmc_card *card);
-
 static inline void s5pv210_default_sdhci0(void)
 {
 #ifdef CONFIG_S3C_DEV_HSMMC
        s3c_hsmmc0_def_platdata.clocks = s5pv210_hsmmc_clksrcs;
        s3c_hsmmc0_def_platdata.cfg_gpio = s5pv210_setup_sdhci0_cfg_gpio;
-       s3c_hsmmc0_def_platdata.cfg_card = s5pv210_setup_sdhci_cfg_card;
 #endif
 }
 
@@ -314,7 +269,6 @@ static inline void s5pv210_default_sdhci1(void)
 #ifdef CONFIG_S3C_DEV_HSMMC1
        s3c_hsmmc1_def_platdata.clocks = s5pv210_hsmmc_clksrcs;
        s3c_hsmmc1_def_platdata.cfg_gpio = s5pv210_setup_sdhci1_cfg_gpio;
-       s3c_hsmmc1_def_platdata.cfg_card = s5pv210_setup_sdhci_cfg_card;
 #endif
 }
 
@@ -323,7 +277,6 @@ static inline void s5pv210_default_sdhci2(void)
 #ifdef CONFIG_S3C_DEV_HSMMC2
        s3c_hsmmc2_def_platdata.clocks = s5pv210_hsmmc_clksrcs;
        s3c_hsmmc2_def_platdata.cfg_gpio = s5pv210_setup_sdhci2_cfg_gpio;
-       s3c_hsmmc2_def_platdata.cfg_card = s5pv210_setup_sdhci_cfg_card;
 #endif
 }
 
@@ -332,7 +285,6 @@ static inline void s5pv210_default_sdhci3(void)
 #ifdef CONFIG_S3C_DEV_HSMMC3
        s3c_hsmmc3_def_platdata.clocks = s5pv210_hsmmc_clksrcs;
        s3c_hsmmc3_def_platdata.cfg_gpio = s5pv210_setup_sdhci3_cfg_gpio;
-       s3c_hsmmc3_def_platdata.cfg_card = s5pv210_setup_sdhci_cfg_card;
 #endif
 }
 
@@ -348,17 +300,11 @@ static inline void s5pv210_default_sdhci3(void) { }
 #ifdef CONFIG_EXYNOS4_SETUP_SDHCI
 extern char *exynos4_hsmmc_clksrcs[4];
 
-extern void exynos4_setup_sdhci_cfg_card(struct platform_device *dev,
-                                          void __iomem *r,
-                                          struct mmc_ios *ios,
-                                          struct mmc_card *card);
-
 static inline void exynos4_default_sdhci0(void)
 {
 #ifdef CONFIG_S3C_DEV_HSMMC
        s3c_hsmmc0_def_platdata.clocks = exynos4_hsmmc_clksrcs;
        s3c_hsmmc0_def_platdata.cfg_gpio = exynos4_setup_sdhci0_cfg_gpio;
-       s3c_hsmmc0_def_platdata.cfg_card = exynos4_setup_sdhci_cfg_card;
 #endif
 }
 
@@ -367,7 +313,6 @@ static inline void exynos4_default_sdhci1(void)
 #ifdef CONFIG_S3C_DEV_HSMMC1
        s3c_hsmmc1_def_platdata.clocks = exynos4_hsmmc_clksrcs;
        s3c_hsmmc1_def_platdata.cfg_gpio = exynos4_setup_sdhci1_cfg_gpio;
-       s3c_hsmmc1_def_platdata.cfg_card = exynos4_setup_sdhci_cfg_card;
 #endif
 }
 
@@ -376,7 +321,6 @@ static inline void exynos4_default_sdhci2(void)
 #ifdef CONFIG_S3C_DEV_HSMMC2
        s3c_hsmmc2_def_platdata.clocks = exynos4_hsmmc_clksrcs;
        s3c_hsmmc2_def_platdata.cfg_gpio = exynos4_setup_sdhci2_cfg_gpio;
-       s3c_hsmmc2_def_platdata.cfg_card = exynos4_setup_sdhci_cfg_card;
 #endif
 }
 
@@ -385,7 +329,6 @@ static inline void exynos4_default_sdhci3(void)
 #ifdef CONFIG_S3C_DEV_HSMMC3
        s3c_hsmmc3_def_platdata.clocks = exynos4_hsmmc_clksrcs;
        s3c_hsmmc3_def_platdata.cfg_gpio = exynos4_setup_sdhci3_cfg_gpio;
-       s3c_hsmmc3_def_platdata.cfg_card = exynos4_setup_sdhci_cfg_card;
 #endif
 }
 
similarity index 96%
rename from arch/arm/plat-s5p/include/plat/sysmmu.h
rename to arch/arm/plat-samsung/include/plat/sysmmu.h
index bf5283c..5fe8ee0 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/arch/arm/plat-s5p/include/plat/sysmmu.h
+/* linux/arch/arm/plat-samsung/include/plat/sysmmu.h
  *
  * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com
@@ -10,8 +10,8 @@
  * published by the Free Software Foundation.
 */
 
-#ifndef __ASM__PLAT_SYSMMU_H
-#define __ASM__PLAT_SYSMMU_H __FILE__
+#ifndef __PLAT_SAMSUNG_SYSMMU_H
+#define __PLAT_SAMSUNG_SYSMMU_H __FILE__
 
 enum S5P_SYSMMU_INTERRUPT_TYPE {
        SYSMMU_PAGEFAULT,
@@ -1,4 +1,4 @@
-/* linux/arch/arm/plat-s5p/include/plat/system-reset.h
+/* linux/arch/arm/plat-samsung/include/plat/system-reset.h
  *
  * Copyright (c) 2010 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com
diff --git a/arch/arm/plat-samsung/include/plat/tv-core.h b/arch/arm/plat-samsung/include/plat/tv-core.h
new file mode 100644 (file)
index 0000000..3bc34f3
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * arch/arm/plat-samsung/include/plat/tv.h
+ *
+ * Copyright 2011 Samsung Electronics Co., Ltd.
+ *     Tomasz Stanislawski <t.stanislaws@samsung.com>
+ *
+ * Samsung TV driver core functions
+ *
+ * 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 __SAMSUNG_PLAT_TV_H
+#define __SAMSUNG_PLAT_TV_H __FILE__
+
+/*
+ * These functions are only for use with the core support code, such as
+ * the CPU-specific initialization code.
+ */
+
+/* Re-define device name to differentiate the subsystem in various SoCs. */
+static inline void s5p_hdmi_setname(char *name)
+{
+#ifdef CONFIG_S5P_DEV_TV
+       s5p_device_hdmi.name = name;
+#endif
+}
+
+static inline void s5p_mixer_setname(char *name)
+{
+#ifdef CONFIG_S5P_DEV_TV
+       s5p_device_mixer.name = name;
+#endif
+}
+
+static inline void s5p_sdo_setname(char *name)
+{
+#ifdef CONFIG_S5P_DEV_TV
+       s5p_device_sdo.name = name;
+#endif
+}
+
+#endif /* __SAMSUNG_PLAT_TV_H */
similarity index 95%
rename from arch/arm/plat-s3c24xx/include/plat/udc.h
rename to arch/arm/plat-samsung/include/plat/udc.h
index f638842..8c22d58 100644 (file)
@@ -1,4 +1,4 @@
-/* arch/arm/mach-s3c2410/include/mach/udc.h
+/* arch/arm/plat-samsung/include/plat/udc.h
  *
  * Copyright (c) 2005 Arnaud Patard <arnaud.patard@rtp-net.org>
  *
@@ -26,7 +26,7 @@ enum s3c2410_udc_cmd_e {
 
 struct s3c2410_udc_mach_info {
        void    (*udc_command)(enum s3c2410_udc_cmd_e);
-       void    (*vbus_draw)(unsigned int ma);
+       void    (*vbus_draw)(unsigned int ma);
 
        unsigned int pullup_pin;
        unsigned int pullup_pin_inverted;
similarity index 83%
rename from arch/arm/plat-s5p/include/plat/usb-phy.h
rename to arch/arm/plat-samsung/include/plat/usb-phy.h
index 6dd6bcf..959bcdb 100644 (file)
@@ -8,8 +8,8 @@
  * option) any later version.
  */
 
-#ifndef __PLAT_S5P_USB_PHY_H
-#define __PLAT_S5P_USB_PHY_H
+#ifndef __PLAT_SAMSUNG_USB_PHY_H
+#define __PLAT_SAMSUNG_USB_PHY_H __FILE__
 
 enum s5p_usb_phy_type {
        S5P_USB_PHY_DEVICE,
@@ -19,4 +19,4 @@ enum s5p_usb_phy_type {
 extern int s5p_usb_phy_init(struct platform_device *pdev, int type);
 extern int s5p_usb_phy_exit(struct platform_device *pdev, int type);
 
-#endif /* __PLAT_S5P_REGS_USB_PHY_H */
+#endif /* __PLAT_SAMSUNG_USB_PHY_H */
index 6de1a38..4c9a207 100644 (file)
@@ -50,8 +50,6 @@ void s3c_sdhci_set_platdata(struct s3c_sdhci_platdata *pd,
                set->max_width = pd->max_width;
        if (pd->cfg_gpio)
                set->cfg_gpio = pd->cfg_gpio;
-       if (pd->cfg_card)
-               set->cfg_card = pd->cfg_card;
        if (pd->host_caps)
                set->host_caps |= pd->host_caps;
        if (pd->clk_type)
index 9652820..4be016e 100644 (file)
 #define OFFS_DAT       (0x04)
 #define OFFS_UP                (0x08)
 
-static void s3c_gpio_pm_1bit_save(struct s3c_gpio_chip *chip)
+static void samsung_gpio_pm_1bit_save(struct samsung_gpio_chip *chip)
 {
        chip->pm_save[0] = __raw_readl(chip->base + OFFS_CON);
        chip->pm_save[1] = __raw_readl(chip->base + OFFS_DAT);
 }
 
-static void s3c_gpio_pm_1bit_resume(struct s3c_gpio_chip *chip)
+static void samsung_gpio_pm_1bit_resume(struct samsung_gpio_chip *chip)
 {
        void __iomem *base = chip->base;
        u32 old_gpcon = __raw_readl(base + OFFS_CON);
@@ -60,12 +60,12 @@ static void s3c_gpio_pm_1bit_resume(struct s3c_gpio_chip *chip)
                  chip->chip.label, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat);
 }
 
-struct s3c_gpio_pm s3c_gpio_pm_1bit = {
-       .save   = s3c_gpio_pm_1bit_save,
-       .resume = s3c_gpio_pm_1bit_resume,
+struct samsung_gpio_pm samsung_gpio_pm_1bit = {
+       .save   = samsung_gpio_pm_1bit_save,
+       .resume = samsung_gpio_pm_1bit_resume,
 };
 
-static void s3c_gpio_pm_2bit_save(struct s3c_gpio_chip *chip)
+static void samsung_gpio_pm_2bit_save(struct samsung_gpio_chip *chip)
 {
        chip->pm_save[0] = __raw_readl(chip->base + OFFS_CON);
        chip->pm_save[1] = __raw_readl(chip->base + OFFS_DAT);
@@ -95,7 +95,7 @@ static inline int is_out(unsigned long con)
 }
 
 /**
- * s3c_gpio_pm_2bit_resume() - restore the given GPIO bank
+ * samsung_gpio_pm_2bit_resume() - restore the given GPIO bank
  * @chip: The chip information to resume.
  *
  * Restore one of the GPIO banks that was saved during suspend. This is
@@ -121,7 +121,7 @@ static inline int is_out(unsigned long con)
  * [1] this assumes that writing to a pin DAT whilst in SFN will set the
  *     state for when it is next output.
  */
-static void s3c_gpio_pm_2bit_resume(struct s3c_gpio_chip *chip)
+static void samsung_gpio_pm_2bit_resume(struct samsung_gpio_chip *chip)
 {
        void __iomem *base = chip->base;
        u32 old_gpcon = __raw_readl(base + OFFS_CON);
@@ -187,13 +187,13 @@ static void s3c_gpio_pm_2bit_resume(struct s3c_gpio_chip *chip)
                  chip->chip.label, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat);
 }
 
-struct s3c_gpio_pm s3c_gpio_pm_2bit = {
-       .save   = s3c_gpio_pm_2bit_save,
-       .resume = s3c_gpio_pm_2bit_resume,
+struct samsung_gpio_pm samsung_gpio_pm_2bit = {
+       .save   = samsung_gpio_pm_2bit_save,
+       .resume = samsung_gpio_pm_2bit_resume,
 };
 
 #if defined(CONFIG_ARCH_S3C64XX) || defined(CONFIG_PLAT_S5P)
-static void s3c_gpio_pm_4bit_save(struct s3c_gpio_chip *chip)
+static void samsung_gpio_pm_4bit_save(struct samsung_gpio_chip *chip)
 {
        chip->pm_save[1] = __raw_readl(chip->base + OFFS_CON);
        chip->pm_save[2] = __raw_readl(chip->base + OFFS_DAT);
@@ -203,7 +203,7 @@ static void s3c_gpio_pm_4bit_save(struct s3c_gpio_chip *chip)
                chip->pm_save[0] = __raw_readl(chip->base - 4);
 }
 
-static u32 s3c_gpio_pm_4bit_mask(u32 old_gpcon, u32 gps_gpcon)
+static u32 samsung_gpio_pm_4bit_mask(u32 old_gpcon, u32 gps_gpcon)
 {
        u32 old, new, mask;
        u32 change_mask = 0x0;
@@ -242,14 +242,14 @@ static u32 s3c_gpio_pm_4bit_mask(u32 old_gpcon, u32 gps_gpcon)
        return change_mask;
 }
 
-static void s3c_gpio_pm_4bit_con(struct s3c_gpio_chip *chip, int index)
+static void samsung_gpio_pm_4bit_con(struct samsung_gpio_chip *chip, int index)
 {
        void __iomem *con = chip->base + (index * 4);
        u32 old_gpcon = __raw_readl(con);
        u32 gps_gpcon = chip->pm_save[index + 1];
        u32 gpcon, mask;
 
-       mask = s3c_gpio_pm_4bit_mask(old_gpcon, gps_gpcon);
+       mask = samsung_gpio_pm_4bit_mask(old_gpcon, gps_gpcon);
 
        gpcon = old_gpcon & ~mask;
        gpcon |= gps_gpcon & mask;
@@ -257,7 +257,7 @@ static void s3c_gpio_pm_4bit_con(struct s3c_gpio_chip *chip, int index)
        __raw_writel(gpcon, con);
 }
 
-static void s3c_gpio_pm_4bit_resume(struct s3c_gpio_chip *chip)
+static void samsung_gpio_pm_4bit_resume(struct samsung_gpio_chip *chip)
 {
        void __iomem *base = chip->base;
        u32 old_gpcon[2];
@@ -269,10 +269,10 @@ static void s3c_gpio_pm_4bit_resume(struct s3c_gpio_chip *chip)
        old_gpcon[0] = 0;
        old_gpcon[1] = __raw_readl(base + OFFS_CON);
 
-       s3c_gpio_pm_4bit_con(chip, 0);
+       samsung_gpio_pm_4bit_con(chip, 0);
        if (chip->chip.ngpio > 8) {
                old_gpcon[0] = __raw_readl(base - 4);
-               s3c_gpio_pm_4bit_con(chip, -1);
+               samsung_gpio_pm_4bit_con(chip, -1);
        }
 
        /* Now change the configurations that require DAT,CON */
@@ -298,19 +298,19 @@ static void s3c_gpio_pm_4bit_resume(struct s3c_gpio_chip *chip)
                          old_gpdat, gps_gpdat);
 }
 
-struct s3c_gpio_pm s3c_gpio_pm_4bit = {
-       .save   = s3c_gpio_pm_4bit_save,
-       .resume = s3c_gpio_pm_4bit_resume,
+struct samsung_gpio_pm samsung_gpio_pm_4bit = {
+       .save   = samsung_gpio_pm_4bit_save,
+       .resume = samsung_gpio_pm_4bit_resume,
 };
 #endif /* CONFIG_ARCH_S3C64XX || CONFIG_PLAT_S5P */
 
 /**
- * s3c_pm_save_gpio() - save gpio chip data for suspend
+ * samsung_pm_save_gpio() - save gpio chip data for suspend
  * @ourchip: The chip for suspend.
  */
-static void s3c_pm_save_gpio(struct s3c_gpio_chip *ourchip)
+static void samsung_pm_save_gpio(struct samsung_gpio_chip *ourchip)
 {
-       struct s3c_gpio_pm *pm = ourchip->pm;
+       struct samsung_gpio_pm *pm = ourchip->pm;
 
        if (pm == NULL || pm->save == NULL)
                S3C_PMDBG("%s: no pm for %s\n", __func__, ourchip->chip.label);
@@ -319,24 +319,24 @@ static void s3c_pm_save_gpio(struct s3c_gpio_chip *ourchip)
 }
 
 /**
- * s3c_pm_save_gpios() - Save the state of the GPIO banks.
+ * samsung_pm_save_gpios() - Save the state of the GPIO banks.
  *
  * For all the GPIO banks, save the state of each one ready for going
  * into a suspend mode.
  */
-void s3c_pm_save_gpios(void)
+void samsung_pm_save_gpios(void)
 {
-       struct s3c_gpio_chip *ourchip;
+       struct samsung_gpio_chip *ourchip;
        unsigned int gpio_nr;
 
        for (gpio_nr = 0; gpio_nr < S3C_GPIO_END;) {
-               ourchip = s3c_gpiolib_getchip(gpio_nr);
+               ourchip = samsung_gpiolib_getchip(gpio_nr);
                if (!ourchip) {
                        gpio_nr++;
                        continue;
                }
 
-               s3c_pm_save_gpio(ourchip);
+               samsung_pm_save_gpio(ourchip);
 
                S3C_PMDBG("%s: save %08x,%08x,%08x,%08x\n",
                          ourchip->chip.label,
@@ -351,12 +351,12 @@ void s3c_pm_save_gpios(void)
 }
 
 /**
- * s3c_pm_resume_gpio() - restore gpio chip data after suspend
+ * samsung_pm_resume_gpio() - restore gpio chip data after suspend
  * @ourchip: The suspended chip.
  */
-static void s3c_pm_resume_gpio(struct s3c_gpio_chip *ourchip)
+static void samsung_pm_resume_gpio(struct samsung_gpio_chip *ourchip)
 {
-       struct s3c_gpio_pm *pm = ourchip->pm;
+       struct samsung_gpio_pm *pm = ourchip->pm;
 
        if (pm == NULL || pm->resume == NULL)
                S3C_PMDBG("%s: no pm for %s\n", __func__, ourchip->chip.label);
@@ -364,19 +364,19 @@ static void s3c_pm_resume_gpio(struct s3c_gpio_chip *ourchip)
                pm->resume(ourchip);
 }
 
-void s3c_pm_restore_gpios(void)
+void samsung_pm_restore_gpios(void)
 {
-       struct s3c_gpio_chip *ourchip;
+       struct samsung_gpio_chip *ourchip;
        unsigned int gpio_nr;
 
        for (gpio_nr = 0; gpio_nr < S3C_GPIO_END;) {
-               ourchip = s3c_gpiolib_getchip(gpio_nr);
+               ourchip = samsung_gpiolib_getchip(gpio_nr);
                if (!ourchip) {
                        gpio_nr++;
                        continue;
                }
 
-               s3c_pm_resume_gpio(ourchip);
+               samsung_pm_resume_gpio(ourchip);
 
                gpio_nr += ourchip->chip.ngpio;
                gpio_nr += CONFIG_S3C_GPIO_SPACE;
index ae6f998..64ab65f 100644 (file)
@@ -268,8 +268,8 @@ 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();
+       samsung_pm_save_gpios();
+       samsung_pm_saved_gpios();
        s3c_pm_save_uarts();
        s3c_pm_save_core();
 
@@ -306,7 +306,7 @@ static int s3c_pm_enter(suspend_state_t state)
 
        s3c_pm_restore_core();
        s3c_pm_restore_uarts();
-       s3c_pm_restore_gpios();
+       samsung_pm_restore_gpios();
        s3c_pm_restored_gpios();
 
        s3c_pm_debug_init();
index f1bba88..a35ff3b 100644 (file)
@@ -27,7 +27,7 @@
 #include <plat/cpu.h>
 
 #include <plat/regs-timer.h>
-#include <mach/pwm-clock.h>
+#include <plat/pwm-clock.h>
 
 /* Each of the timers 0 through 5 go through the following
  * clock tree, with the inputs depending on the timers.
@@ -339,8 +339,17 @@ static int clk_pwm_tin_set_parent(struct clk *clk, struct clk *parent)
        unsigned long bits;
        unsigned long shift = S3C2410_TCFG1_SHIFT(id);
 
+       unsigned long mux_tclk;
+
+       if (soc_is_s3c24xx())
+               mux_tclk = S3C2410_TCFG1_MUX_TCLK;
+       else if (soc_is_s5p6440() || soc_is_s5p6450())
+               mux_tclk = 0;
+       else
+               mux_tclk = S3C64XX_TCFG1_MUX_TCLK;
+
        if (parent == s3c24xx_pwmclk_tclk(id))
-               bits = S3C_TCFG1_MUX_TCLK << shift;
+               bits = mux_tclk << shift;
        else if (parent == s3c24xx_pwmclk_tdiv(id))
                bits = clk_pwm_tdiv_bits(to_tdiv(parent)) << shift;
        else
index f37457c..dc1185d 100644 (file)
@@ -299,6 +299,9 @@ static int s3c_pwm_probe(struct platform_device *pdev)
                goto err_clk_tin;
        }
 
+       clk_enable(pwm->clk);
+       clk_enable(pwm->clk_div);
+
        local_irq_save(flags);
 
        tcon = __raw_readl(S3C2410_TCON);
@@ -326,6 +329,8 @@ static int s3c_pwm_probe(struct platform_device *pdev)
        return 0;
 
  err_clk_tdiv:
+       clk_disable(pwm->clk_div);
+       clk_disable(pwm->clk);
        clk_put(pwm->clk_div);
 
  err_clk_tin:
@@ -340,6 +345,8 @@ static int __devexit s3c_pwm_remove(struct platform_device *pdev)
 {
        struct pwm_device *pwm = platform_get_drvdata(pdev);
 
+       clk_disable(pwm->clk_div);
+       clk_disable(pwm->clk);
        clk_put(pwm->clk_div);
        clk_put(pwm->clk);
        kfree(pwm);
diff --git a/arch/arm/plat-samsung/s3c-dma-ops.c b/arch/arm/plat-samsung/s3c-dma-ops.c
new file mode 100644 (file)
index 0000000..582333c
--- /dev/null
@@ -0,0 +1,130 @@
+/* linux/arch/arm/plat-samsung/s3c-dma-ops.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Samsung S3C-DMA Operations
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#include <mach/dma.h>
+
+struct cb_data {
+       void (*fp) (void *);
+       void *fp_param;
+       unsigned ch;
+       struct list_head node;
+};
+
+static LIST_HEAD(dma_list);
+
+static void s3c_dma_cb(struct s3c2410_dma_chan *channel, void *param,
+                      int size, enum s3c2410_dma_buffresult res)
+{
+       struct cb_data *data = param;
+
+       data->fp(data->fp_param);
+}
+
+static unsigned s3c_dma_request(enum dma_ch dma_ch,
+                                struct samsung_dma_info *info)
+{
+       struct cb_data *data;
+
+       if (s3c2410_dma_request(dma_ch, info->client, NULL) < 0) {
+               s3c2410_dma_free(dma_ch, info->client);
+               return 0;
+       }
+
+       data = kzalloc(sizeof(struct cb_data), GFP_KERNEL);
+       data->ch = dma_ch;
+       list_add_tail(&data->node, &dma_list);
+
+       s3c2410_dma_devconfig(dma_ch, info->direction, info->fifo);
+
+       if (info->cap == DMA_CYCLIC)
+               s3c2410_dma_setflags(dma_ch, S3C2410_DMAF_CIRCULAR);
+
+       s3c2410_dma_config(dma_ch, info->width);
+
+       return (unsigned)dma_ch;
+}
+
+static int s3c_dma_release(unsigned ch, struct s3c2410_dma_client *client)
+{
+       struct cb_data *data;
+
+       list_for_each_entry(data, &dma_list, node)
+               if (data->ch == ch)
+                       break;
+       list_del(&data->node);
+
+       s3c2410_dma_free(ch, client);
+       kfree(data);
+
+       return 0;
+}
+
+static int s3c_dma_prepare(unsigned ch, struct samsung_dma_prep_info *info)
+{
+       struct cb_data *data;
+       int len = (info->cap == DMA_CYCLIC) ? info->period : info->len;
+
+       list_for_each_entry(data, &dma_list, node)
+               if (data->ch == ch)
+                       break;
+
+       if (!data->fp) {
+               s3c2410_dma_set_buffdone_fn(ch, s3c_dma_cb);
+               data->fp = info->fp;
+               data->fp_param = info->fp_param;
+       }
+
+       s3c2410_dma_enqueue(ch, (void *)data, info->buf, len);
+
+       return 0;
+}
+
+static inline int s3c_dma_trigger(unsigned ch)
+{
+       return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_START);
+}
+
+static inline int s3c_dma_started(unsigned ch)
+{
+       return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STARTED);
+}
+
+static inline int s3c_dma_flush(unsigned ch)
+{
+       return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_FLUSH);
+}
+
+static inline int s3c_dma_stop(unsigned ch)
+{
+       return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STOP);
+}
+
+static struct samsung_dma_ops s3c_dma_ops = {
+       .request        = s3c_dma_request,
+       .release        = s3c_dma_release,
+       .prepare        = s3c_dma_prepare,
+       .trigger        = s3c_dma_trigger,
+       .started        = s3c_dma_started,
+       .flush          = s3c_dma_flush,
+       .stop           = s3c_dma_stop,
+};
+
+void *s3c_dma_get_ops(void)
+{
+       return &s3c_dma_ops;
+}
+EXPORT_SYMBOL(s3c_dma_get_ops);
diff --git a/arch/arm/plat-samsung/s3c-pl330.c b/arch/arm/plat-samsung/s3c-pl330.c
deleted file mode 100644 (file)
index f85638c..0000000
+++ /dev/null
@@ -1,1244 +0,0 @@
-/* linux/arch/arm/plat-samsung/s3c-pl330.c
- *
- * Copyright (C) 2010 Samsung Electronics Co. Ltd.
- *     Jaswinder Singh <jassi.brar@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-
-#include <asm/hardware/pl330.h>
-
-#include <plat/s3c-pl330-pdata.h>
-
-/**
- * struct s3c_pl330_dmac - Logical representation of a PL330 DMAC.
- * @busy_chan: Number of channels currently busy.
- * @peri: List of IDs of peripherals this DMAC can work with.
- * @node: To attach to the global list of DMACs.
- * @pi: PL330 configuration info for the DMAC.
- * @kmcache: Pool to quickly allocate xfers for all channels in the dmac.
- * @clk: Pointer of DMAC operation clock.
- */
-struct s3c_pl330_dmac {
-       unsigned                busy_chan;
-       enum dma_ch             *peri;
-       struct list_head        node;
-       struct pl330_info       *pi;
-       struct kmem_cache       *kmcache;
-       struct clk              *clk;
-};
-
-/**
- * struct s3c_pl330_xfer - A request submitted by S3C DMA clients.
- * @token: Xfer ID provided by the client.
- * @node: To attach to the list of xfers on a channel.
- * @px: Xfer for PL330 core.
- * @chan: Owner channel of this xfer.
- */
-struct s3c_pl330_xfer {
-       void                    *token;
-       struct list_head        node;
-       struct pl330_xfer       px;
-       struct s3c_pl330_chan   *chan;
-};
-
-/**
- * struct s3c_pl330_chan - Logical channel to communicate with
- *     a Physical peripheral.
- * @pl330_chan_id: Token of a hardware channel thread of PL330 DMAC.
- *     NULL if the channel is available to be acquired.
- * @id: ID of the peripheral that this channel can communicate with.
- * @options: Options specified by the client.
- * @sdaddr: Address provided via s3c2410_dma_devconfig.
- * @node: To attach to the global list of channels.
- * @lrq: Pointer to the last submitted pl330_req to PL330 core.
- * @xfer_list: To manage list of xfers enqueued.
- * @req: Two requests to communicate with the PL330 engine.
- * @callback_fn: Callback function to the client.
- * @rqcfg: Channel configuration for the xfers.
- * @xfer_head: Pointer to the xfer to be next executed.
- * @dmac: Pointer to the DMAC that manages this channel, NULL if the
- *     channel is available to be acquired.
- * @client: Client of this channel. NULL if the
- *     channel is available to be acquired.
- */
-struct s3c_pl330_chan {
-       void                            *pl330_chan_id;
-       enum dma_ch                     id;
-       unsigned int                    options;
-       unsigned long                   sdaddr;
-       struct list_head                node;
-       struct pl330_req                *lrq;
-       struct list_head                xfer_list;
-       struct pl330_req                req[2];
-       s3c2410_dma_cbfn_t              callback_fn;
-       struct pl330_reqcfg             rqcfg;
-       struct s3c_pl330_xfer           *xfer_head;
-       struct s3c_pl330_dmac           *dmac;
-       struct s3c2410_dma_client       *client;
-};
-
-/* All DMACs in the platform */
-static LIST_HEAD(dmac_list);
-
-/* All channels to peripherals in the platform */
-static LIST_HEAD(chan_list);
-
-/*
- * Since we add resources(DMACs and Channels) to the global pool,
- * we need to guard access to the resources using a global lock
- */
-static DEFINE_SPINLOCK(res_lock);
-
-/* Returns the channel with ID 'id' in the chan_list */
-static struct s3c_pl330_chan *id_to_chan(const enum dma_ch id)
-{
-       struct s3c_pl330_chan *ch;
-
-       list_for_each_entry(ch, &chan_list, node)
-               if (ch->id == id)
-                       return ch;
-
-       return NULL;
-}
-
-/* Allocate a new channel with ID 'id' and add to chan_list */
-static void chan_add(const enum dma_ch id)
-{
-       struct s3c_pl330_chan *ch = id_to_chan(id);
-
-       /* Return if the channel already exists */
-       if (ch)
-               return;
-
-       ch = kmalloc(sizeof(*ch), GFP_KERNEL);
-       /* Return silently to work with other channels */
-       if (!ch)
-               return;
-
-       ch->id = id;
-       ch->dmac = NULL;
-
-       list_add_tail(&ch->node, &chan_list);
-}
-
-/* If the channel is not yet acquired by any client */
-static bool chan_free(struct s3c_pl330_chan *ch)
-{
-       if (!ch)
-               return false;
-
-       /* Channel points to some DMAC only when it's acquired */
-       return ch->dmac ? false : true;
-}
-
-/*
- * Returns 0 is peripheral i/f is invalid or not present on the dmac.
- * Index + 1, otherwise.
- */
-static unsigned iface_of_dmac(struct s3c_pl330_dmac *dmac, enum dma_ch ch_id)
-{
-       enum dma_ch *id = dmac->peri;
-       int i;
-
-       /* Discount invalid markers */
-       if (ch_id == DMACH_MAX)
-               return 0;
-
-       for (i = 0; i < PL330_MAX_PERI; i++)
-               if (id[i] == ch_id)
-                       return i + 1;
-
-       return 0;
-}
-
-/* If all channel threads of the DMAC are busy */
-static inline bool dmac_busy(struct s3c_pl330_dmac *dmac)
-{
-       struct pl330_info *pi = dmac->pi;
-
-       return (dmac->busy_chan < pi->pcfg.num_chan) ? false : true;
-}
-
-/*
- * Returns the number of free channels that
- * can be handled by this dmac only.
- */
-static unsigned ch_onlyby_dmac(struct s3c_pl330_dmac *dmac)
-{
-       enum dma_ch *id = dmac->peri;
-       struct s3c_pl330_dmac *d;
-       struct s3c_pl330_chan *ch;
-       unsigned found, count = 0;
-       enum dma_ch p;
-       int i;
-
-       for (i = 0; i < PL330_MAX_PERI; i++) {
-               p = id[i];
-               ch = id_to_chan(p);
-
-               if (p == DMACH_MAX || !chan_free(ch))
-                       continue;
-
-               found = 0;
-               list_for_each_entry(d, &dmac_list, node) {
-                       if (d != dmac && iface_of_dmac(d, ch->id)) {
-                               found = 1;
-                               break;
-                       }
-               }
-               if (!found)
-                       count++;
-       }
-
-       return count;
-}
-
-/*
- * Measure of suitability of 'dmac' handling 'ch'
- *
- * 0 indicates 'dmac' can not handle 'ch' either
- * because it is not supported by the hardware or
- * because all dmac channels are currently busy.
- *
- * >0 vlaue indicates 'dmac' has the capability.
- * The bigger the value the more suitable the dmac.
- */
-#define MAX_SUIT       UINT_MAX
-#define MIN_SUIT       0
-
-static unsigned suitablility(struct s3c_pl330_dmac *dmac,
-               struct s3c_pl330_chan *ch)
-{
-       struct pl330_info *pi = dmac->pi;
-       enum dma_ch *id = dmac->peri;
-       struct s3c_pl330_dmac *d;
-       unsigned s;
-       int i;
-
-       s = MIN_SUIT;
-       /* If all the DMAC channel threads are busy */
-       if (dmac_busy(dmac))
-               return s;
-
-       for (i = 0; i < PL330_MAX_PERI; i++)
-               if (id[i] == ch->id)
-                       break;
-
-       /* If the 'dmac' can't talk to 'ch' */
-       if (i == PL330_MAX_PERI)
-               return s;
-
-       s = MAX_SUIT;
-       list_for_each_entry(d, &dmac_list, node) {
-               /*
-                * If some other dmac can talk to this
-                * peri and has some channel free.
-                */
-               if (d != dmac && iface_of_dmac(d, ch->id) && !dmac_busy(d)) {
-                       s = 0;
-                       break;
-               }
-       }
-       if (s)
-               return s;
-
-       s = 100;
-
-       /* Good if free chans are more, bad otherwise */
-       s += (pi->pcfg.num_chan - dmac->busy_chan) - ch_onlyby_dmac(dmac);
-
-       return s;
-}
-
-/* More than one DMAC may have capability to transfer data with the
- * peripheral. This function assigns most suitable DMAC to manage the
- * channel and hence communicate with the peripheral.
- */
-static struct s3c_pl330_dmac *map_chan_to_dmac(struct s3c_pl330_chan *ch)
-{
-       struct s3c_pl330_dmac *d, *dmac = NULL;
-       unsigned sn, sl = MIN_SUIT;
-
-       list_for_each_entry(d, &dmac_list, node) {
-               sn = suitablility(d, ch);
-
-               if (sn == MAX_SUIT)
-                       return d;
-
-               if (sn > sl)
-                       dmac = d;
-       }
-
-       return dmac;
-}
-
-/* Acquire the channel for peripheral 'id' */
-static struct s3c_pl330_chan *chan_acquire(const enum dma_ch id)
-{
-       struct s3c_pl330_chan *ch = id_to_chan(id);
-       struct s3c_pl330_dmac *dmac;
-
-       /* If the channel doesn't exist or is already acquired */
-       if (!ch || !chan_free(ch)) {
-               ch = NULL;
-               goto acq_exit;
-       }
-
-       dmac = map_chan_to_dmac(ch);
-       /* If couldn't map */
-       if (!dmac) {
-               ch = NULL;
-               goto acq_exit;
-       }
-
-       dmac->busy_chan++;
-       ch->dmac = dmac;
-
-acq_exit:
-       return ch;
-}
-
-/* Delete xfer from the queue */
-static inline void del_from_queue(struct s3c_pl330_xfer *xfer)
-{
-       struct s3c_pl330_xfer *t;
-       struct s3c_pl330_chan *ch;
-       int found;
-
-       if (!xfer)
-               return;
-
-       ch = xfer->chan;
-
-       /* Make sure xfer is in the queue */
-       found = 0;
-       list_for_each_entry(t, &ch->xfer_list, node)
-               if (t == xfer) {
-                       found = 1;
-                       break;
-               }
-
-       if (!found)
-               return;
-
-       /* If xfer is last entry in the queue */
-       if (xfer->node.next == &ch->xfer_list)
-               t = list_entry(ch->xfer_list.next,
-                               struct s3c_pl330_xfer, node);
-       else
-               t = list_entry(xfer->node.next,
-                               struct s3c_pl330_xfer, node);
-
-       /* If there was only one node left */
-       if (t == xfer)
-               ch->xfer_head = NULL;
-       else if (ch->xfer_head == xfer)
-               ch->xfer_head = t;
-
-       list_del(&xfer->node);
-}
-
-/* Provides pointer to the next xfer in the queue.
- * If CIRCULAR option is set, the list is left intact,
- * otherwise the xfer is removed from the list.
- * Forced delete 'pluck' can be set to override the CIRCULAR option.
- */
-static struct s3c_pl330_xfer *get_from_queue(struct s3c_pl330_chan *ch,
-               int pluck)
-{
-       struct s3c_pl330_xfer *xfer = ch->xfer_head;
-
-       if (!xfer)
-               return NULL;
-
-       /* If xfer is last entry in the queue */
-       if (xfer->node.next == &ch->xfer_list)
-               ch->xfer_head = list_entry(ch->xfer_list.next,
-                                       struct s3c_pl330_xfer, node);
-       else
-               ch->xfer_head = list_entry(xfer->node.next,
-                                       struct s3c_pl330_xfer, node);
-
-       if (pluck || !(ch->options & S3C2410_DMAF_CIRCULAR))
-               del_from_queue(xfer);
-
-       return xfer;
-}
-
-static inline void add_to_queue(struct s3c_pl330_chan *ch,
-               struct s3c_pl330_xfer *xfer, int front)
-{
-       struct pl330_xfer *xt;
-
-       /* If queue empty */
-       if (ch->xfer_head == NULL)
-               ch->xfer_head = xfer;
-
-       xt = &ch->xfer_head->px;
-       /* If the head already submitted (CIRCULAR head) */
-       if (ch->options & S3C2410_DMAF_CIRCULAR &&
-               (xt == ch->req[0].x || xt == ch->req[1].x))
-               ch->xfer_head = xfer;
-
-       /* If this is a resubmission, it should go at the head */
-       if (front) {
-               ch->xfer_head = xfer;
-               list_add(&xfer->node, &ch->xfer_list);
-       } else {
-               list_add_tail(&xfer->node, &ch->xfer_list);
-       }
-}
-
-static inline void _finish_off(struct s3c_pl330_xfer *xfer,
-               enum s3c2410_dma_buffresult res, int ffree)
-{
-       struct s3c_pl330_chan *ch;
-
-       if (!xfer)
-               return;
-
-       ch = xfer->chan;
-
-       /* Do callback */
-       if (ch->callback_fn)
-               ch->callback_fn(NULL, xfer->token, xfer->px.bytes, res);
-
-       /* Force Free or if buffer is not needed anymore */
-       if (ffree || !(ch->options & S3C2410_DMAF_CIRCULAR))
-               kmem_cache_free(ch->dmac->kmcache, xfer);
-}
-
-static inline int s3c_pl330_submit(struct s3c_pl330_chan *ch,
-               struct pl330_req *r)
-{
-       struct s3c_pl330_xfer *xfer;
-       int ret = 0;
-
-       /* If already submitted */
-       if (r->x)
-               return 0;
-
-       xfer = get_from_queue(ch, 0);
-       if (xfer) {
-               r->x = &xfer->px;
-
-               /* Use max bandwidth for M<->M xfers */
-               if (r->rqtype == MEMTOMEM) {
-                       struct pl330_info *pi = xfer->chan->dmac->pi;
-                       int burst = 1 << ch->rqcfg.brst_size;
-                       u32 bytes = r->x->bytes;
-                       int bl;
-
-                       bl = pi->pcfg.data_bus_width / 8;
-                       bl *= pi->pcfg.data_buf_dep;
-                       bl /= burst;
-
-                       /* src/dst_burst_len can't be more than 16 */
-                       if (bl > 16)
-                               bl = 16;
-
-                       while (bl > 1) {
-                               if (!(bytes % (bl * burst)))
-                                       break;
-                               bl--;
-                       }
-
-                       ch->rqcfg.brst_len = bl;
-               } else {
-                       ch->rqcfg.brst_len = 1;
-               }
-
-               ret = pl330_submit_req(ch->pl330_chan_id, r);
-
-               /* If submission was successful */
-               if (!ret) {
-                       ch->lrq = r; /* latest submitted req */
-                       return 0;
-               }
-
-               r->x = NULL;
-
-               /* If both of the PL330 ping-pong buffers filled */
-               if (ret == -EAGAIN) {
-                       dev_err(ch->dmac->pi->dev, "%s:%d!\n",
-                               __func__, __LINE__);
-                       /* Queue back again */
-                       add_to_queue(ch, xfer, 1);
-                       ret = 0;
-               } else {
-                       dev_err(ch->dmac->pi->dev, "%s:%d!\n",
-                               __func__, __LINE__);
-                       _finish_off(xfer, S3C2410_RES_ERR, 0);
-               }
-       }
-
-       return ret;
-}
-
-static void s3c_pl330_rq(struct s3c_pl330_chan *ch,
-       struct pl330_req *r, enum pl330_op_err err)
-{
-       unsigned long flags;
-       struct s3c_pl330_xfer *xfer;
-       struct pl330_xfer *xl = r->x;
-       enum s3c2410_dma_buffresult res;
-
-       spin_lock_irqsave(&res_lock, flags);
-
-       r->x = NULL;
-
-       s3c_pl330_submit(ch, r);
-
-       spin_unlock_irqrestore(&res_lock, flags);
-
-       /* Map result to S3C DMA API */
-       if (err == PL330_ERR_NONE)
-               res = S3C2410_RES_OK;
-       else if (err == PL330_ERR_ABORT)
-               res = S3C2410_RES_ABORT;
-       else
-               res = S3C2410_RES_ERR;
-
-       /* If last request had some xfer */
-       if (xl) {
-               xfer = container_of(xl, struct s3c_pl330_xfer, px);
-               _finish_off(xfer, res, 0);
-       } else {
-               dev_info(ch->dmac->pi->dev, "%s:%d No Xfer?!\n",
-                       __func__, __LINE__);
-       }
-}
-
-static void s3c_pl330_rq0(void *token, enum pl330_op_err err)
-{
-       struct pl330_req *r = token;
-       struct s3c_pl330_chan *ch = container_of(r,
-                                       struct s3c_pl330_chan, req[0]);
-       s3c_pl330_rq(ch, r, err);
-}
-
-static void s3c_pl330_rq1(void *token, enum pl330_op_err err)
-{
-       struct pl330_req *r = token;
-       struct s3c_pl330_chan *ch = container_of(r,
-                                       struct s3c_pl330_chan, req[1]);
-       s3c_pl330_rq(ch, r, err);
-}
-
-/* Release an acquired channel */
-static void chan_release(struct s3c_pl330_chan *ch)
-{
-       struct s3c_pl330_dmac *dmac;
-
-       if (chan_free(ch))
-               return;
-
-       dmac = ch->dmac;
-       ch->dmac = NULL;
-       dmac->busy_chan--;
-}
-
-int s3c2410_dma_ctrl(enum dma_ch id, enum s3c2410_chan_op op)
-{
-       struct s3c_pl330_xfer *xfer;
-       enum pl330_chan_op pl330op;
-       struct s3c_pl330_chan *ch;
-       unsigned long flags;
-       int idx, ret;
-
-       spin_lock_irqsave(&res_lock, flags);
-
-       ch = id_to_chan(id);
-
-       if (!ch || chan_free(ch)) {
-               ret = -EINVAL;
-               goto ctrl_exit;
-       }
-
-       switch (op) {
-       case S3C2410_DMAOP_START:
-               /* Make sure both reqs are enqueued */
-               idx = (ch->lrq == &ch->req[0]) ? 1 : 0;
-               s3c_pl330_submit(ch, &ch->req[idx]);
-               s3c_pl330_submit(ch, &ch->req[1 - idx]);
-               pl330op = PL330_OP_START;
-               break;
-
-       case S3C2410_DMAOP_STOP:
-               pl330op = PL330_OP_ABORT;
-               break;
-
-       case S3C2410_DMAOP_FLUSH:
-               pl330op = PL330_OP_FLUSH;
-               break;
-
-       case S3C2410_DMAOP_PAUSE:
-       case S3C2410_DMAOP_RESUME:
-       case S3C2410_DMAOP_TIMEOUT:
-       case S3C2410_DMAOP_STARTED:
-               spin_unlock_irqrestore(&res_lock, flags);
-               return 0;
-
-       default:
-               spin_unlock_irqrestore(&res_lock, flags);
-               return -EINVAL;
-       }
-
-       ret = pl330_chan_ctrl(ch->pl330_chan_id, pl330op);
-
-       if (pl330op == PL330_OP_START) {
-               spin_unlock_irqrestore(&res_lock, flags);
-               return ret;
-       }
-
-       idx = (ch->lrq == &ch->req[0]) ? 1 : 0;
-
-       /* Abort the current xfer */
-       if (ch->req[idx].x) {
-               xfer = container_of(ch->req[idx].x,
-                               struct s3c_pl330_xfer, px);
-
-               /* Drop xfer during FLUSH */
-               if (pl330op == PL330_OP_FLUSH)
-                       del_from_queue(xfer);
-
-               ch->req[idx].x = NULL;
-
-               spin_unlock_irqrestore(&res_lock, flags);
-               _finish_off(xfer, S3C2410_RES_ABORT,
-                               pl330op == PL330_OP_FLUSH ? 1 : 0);
-               spin_lock_irqsave(&res_lock, flags);
-       }
-
-       /* Flush the whole queue */
-       if (pl330op == PL330_OP_FLUSH) {
-
-               if (ch->req[1 - idx].x) {
-                       xfer = container_of(ch->req[1 - idx].x,
-                                       struct s3c_pl330_xfer, px);
-
-                       del_from_queue(xfer);
-
-                       ch->req[1 - idx].x = NULL;
-
-                       spin_unlock_irqrestore(&res_lock, flags);
-                       _finish_off(xfer, S3C2410_RES_ABORT, 1);
-                       spin_lock_irqsave(&res_lock, flags);
-               }
-
-               /* Finish off the remaining in the queue */
-               xfer = ch->xfer_head;
-               while (xfer) {
-
-                       del_from_queue(xfer);
-
-                       spin_unlock_irqrestore(&res_lock, flags);
-                       _finish_off(xfer, S3C2410_RES_ABORT, 1);
-                       spin_lock_irqsave(&res_lock, flags);
-
-                       xfer = ch->xfer_head;
-               }
-       }
-
-ctrl_exit:
-       spin_unlock_irqrestore(&res_lock, flags);
-
-       return ret;
-}
-EXPORT_SYMBOL(s3c2410_dma_ctrl);
-
-int s3c2410_dma_enqueue(enum dma_ch id, void *token,
-                       dma_addr_t addr, int size)
-{
-       struct s3c_pl330_chan *ch;
-       struct s3c_pl330_xfer *xfer;
-       unsigned long flags;
-       int idx, ret = 0;
-
-       spin_lock_irqsave(&res_lock, flags);
-
-       ch = id_to_chan(id);
-
-       /* Error if invalid or free channel */
-       if (!ch || chan_free(ch)) {
-               ret = -EINVAL;
-               goto enq_exit;
-       }
-
-       /* Error if size is unaligned */
-       if (ch->rqcfg.brst_size && size % (1 << ch->rqcfg.brst_size)) {
-               ret = -EINVAL;
-               goto enq_exit;
-       }
-
-       xfer = kmem_cache_alloc(ch->dmac->kmcache, GFP_ATOMIC);
-       if (!xfer) {
-               ret = -ENOMEM;
-               goto enq_exit;
-       }
-
-       xfer->token = token;
-       xfer->chan = ch;
-       xfer->px.bytes = size;
-       xfer->px.next = NULL; /* Single request */
-
-       /* For S3C DMA API, direction is always fixed for all xfers */
-       if (ch->req[0].rqtype == MEMTODEV) {
-               xfer->px.src_addr = addr;
-               xfer->px.dst_addr = ch->sdaddr;
-       } else {
-               xfer->px.src_addr = ch->sdaddr;
-               xfer->px.dst_addr = addr;
-       }
-
-       add_to_queue(ch, xfer, 0);
-
-       /* Try submitting on either request */
-       idx = (ch->lrq == &ch->req[0]) ? 1 : 0;
-
-       if (!ch->req[idx].x)
-               s3c_pl330_submit(ch, &ch->req[idx]);
-       else
-               s3c_pl330_submit(ch, &ch->req[1 - idx]);
-
-       spin_unlock_irqrestore(&res_lock, flags);
-
-       if (ch->options & S3C2410_DMAF_AUTOSTART)
-               s3c2410_dma_ctrl(id, S3C2410_DMAOP_START);
-
-       return 0;
-
-enq_exit:
-       spin_unlock_irqrestore(&res_lock, flags);
-
-       return ret;
-}
-EXPORT_SYMBOL(s3c2410_dma_enqueue);
-
-int s3c2410_dma_request(enum dma_ch id,
-                       struct s3c2410_dma_client *client,
-                       void *dev)
-{
-       struct s3c_pl330_dmac *dmac;
-       struct s3c_pl330_chan *ch;
-       unsigned long flags;
-       int ret = 0;
-
-       spin_lock_irqsave(&res_lock, flags);
-
-       ch = chan_acquire(id);
-       if (!ch) {
-               ret = -EBUSY;
-               goto req_exit;
-       }
-
-       dmac = ch->dmac;
-
-       ch->pl330_chan_id = pl330_request_channel(dmac->pi);
-       if (!ch->pl330_chan_id) {
-               chan_release(ch);
-               ret = -EBUSY;
-               goto req_exit;
-       }
-
-       ch->client = client;
-       ch->options = 0; /* Clear any option */
-       ch->callback_fn = NULL; /* Clear any callback */
-       ch->lrq = NULL;
-
-       ch->rqcfg.brst_size = 2; /* Default word size */
-       ch->rqcfg.swap = SWAP_NO;
-       ch->rqcfg.scctl = SCCTRL0; /* Noncacheable and nonbufferable */
-       ch->rqcfg.dcctl = DCCTRL0; /* Noncacheable and nonbufferable */
-       ch->rqcfg.privileged = 0;
-       ch->rqcfg.insnaccess = 0;
-
-       /* Set invalid direction */
-       ch->req[0].rqtype = DEVTODEV;
-       ch->req[1].rqtype = ch->req[0].rqtype;
-
-       ch->req[0].cfg = &ch->rqcfg;
-       ch->req[1].cfg = ch->req[0].cfg;
-
-       ch->req[0].peri = iface_of_dmac(dmac, id) - 1; /* Original index */
-       ch->req[1].peri = ch->req[0].peri;
-
-       ch->req[0].token = &ch->req[0];
-       ch->req[0].xfer_cb = s3c_pl330_rq0;
-       ch->req[1].token = &ch->req[1];
-       ch->req[1].xfer_cb = s3c_pl330_rq1;
-
-       ch->req[0].x = NULL;
-       ch->req[1].x = NULL;
-
-       /* Reset xfer list */
-       INIT_LIST_HEAD(&ch->xfer_list);
-       ch->xfer_head = NULL;
-
-req_exit:
-       spin_unlock_irqrestore(&res_lock, flags);
-
-       return ret;
-}
-EXPORT_SYMBOL(s3c2410_dma_request);
-
-int s3c2410_dma_free(enum dma_ch id, struct s3c2410_dma_client *client)
-{
-       struct s3c_pl330_chan *ch;
-       struct s3c_pl330_xfer *xfer;
-       unsigned long flags;
-       int ret = 0;
-       unsigned idx;
-
-       spin_lock_irqsave(&res_lock, flags);
-
-       ch = id_to_chan(id);
-
-       if (!ch || chan_free(ch))
-               goto free_exit;
-
-       /* Refuse if someone else wanted to free the channel */
-       if (ch->client != client) {
-               ret = -EBUSY;
-               goto free_exit;
-       }
-
-       /* Stop any active xfer, Flushe the queue and do callbacks */
-       pl330_chan_ctrl(ch->pl330_chan_id, PL330_OP_FLUSH);
-
-       /* Abort the submitted requests */
-       idx = (ch->lrq == &ch->req[0]) ? 1 : 0;
-
-       if (ch->req[idx].x) {
-               xfer = container_of(ch->req[idx].x,
-                               struct s3c_pl330_xfer, px);
-
-               ch->req[idx].x = NULL;
-               del_from_queue(xfer);
-
-               spin_unlock_irqrestore(&res_lock, flags);
-               _finish_off(xfer, S3C2410_RES_ABORT, 1);
-               spin_lock_irqsave(&res_lock, flags);
-       }
-
-       if (ch->req[1 - idx].x) {
-               xfer = container_of(ch->req[1 - idx].x,
-                               struct s3c_pl330_xfer, px);
-
-               ch->req[1 - idx].x = NULL;
-               del_from_queue(xfer);
-
-               spin_unlock_irqrestore(&res_lock, flags);
-               _finish_off(xfer, S3C2410_RES_ABORT, 1);
-               spin_lock_irqsave(&res_lock, flags);
-       }
-
-       /* Pluck and Abort the queued requests in order */
-       do {
-               xfer = get_from_queue(ch, 1);
-
-               spin_unlock_irqrestore(&res_lock, flags);
-               _finish_off(xfer, S3C2410_RES_ABORT, 1);
-               spin_lock_irqsave(&res_lock, flags);
-       } while (xfer);
-
-       ch->client = NULL;
-
-       pl330_release_channel(ch->pl330_chan_id);
-
-       ch->pl330_chan_id = NULL;
-
-       chan_release(ch);
-
-free_exit:
-       spin_unlock_irqrestore(&res_lock, flags);
-
-       return ret;
-}
-EXPORT_SYMBOL(s3c2410_dma_free);
-
-int s3c2410_dma_config(enum dma_ch id, int xferunit)
-{
-       struct s3c_pl330_chan *ch;
-       struct pl330_info *pi;
-       unsigned long flags;
-       int i, dbwidth, ret = 0;
-
-       spin_lock_irqsave(&res_lock, flags);
-
-       ch = id_to_chan(id);
-
-       if (!ch || chan_free(ch)) {
-               ret = -EINVAL;
-               goto cfg_exit;
-       }
-
-       pi = ch->dmac->pi;
-       dbwidth = pi->pcfg.data_bus_width / 8;
-
-       /* Max size of xfer can be pcfg.data_bus_width */
-       if (xferunit > dbwidth) {
-               ret = -EINVAL;
-               goto cfg_exit;
-       }
-
-       i = 0;
-       while (xferunit != (1 << i))
-               i++;
-
-       /* If valid value */
-       if (xferunit == (1 << i))
-               ch->rqcfg.brst_size = i;
-       else
-               ret = -EINVAL;
-
-cfg_exit:
-       spin_unlock_irqrestore(&res_lock, flags);
-
-       return ret;
-}
-EXPORT_SYMBOL(s3c2410_dma_config);
-
-/* Options that are supported by this driver */
-#define S3C_PL330_FLAGS (S3C2410_DMAF_CIRCULAR | S3C2410_DMAF_AUTOSTART)
-
-int s3c2410_dma_setflags(enum dma_ch id, unsigned int options)
-{
-       struct s3c_pl330_chan *ch;
-       unsigned long flags;
-       int ret = 0;
-
-       spin_lock_irqsave(&res_lock, flags);
-
-       ch = id_to_chan(id);
-
-       if (!ch || chan_free(ch) || options & ~(S3C_PL330_FLAGS))
-               ret = -EINVAL;
-       else
-               ch->options = options;
-
-       spin_unlock_irqrestore(&res_lock, flags);
-
-       return 0;
-}
-EXPORT_SYMBOL(s3c2410_dma_setflags);
-
-int s3c2410_dma_set_buffdone_fn(enum dma_ch id, s3c2410_dma_cbfn_t rtn)
-{
-       struct s3c_pl330_chan *ch;
-       unsigned long flags;
-       int ret = 0;
-
-       spin_lock_irqsave(&res_lock, flags);
-
-       ch = id_to_chan(id);
-
-       if (!ch || chan_free(ch))
-               ret = -EINVAL;
-       else
-               ch->callback_fn = rtn;
-
-       spin_unlock_irqrestore(&res_lock, flags);
-
-       return ret;
-}
-EXPORT_SYMBOL(s3c2410_dma_set_buffdone_fn);
-
-int s3c2410_dma_devconfig(enum dma_ch id, enum s3c2410_dmasrc source,
-                         unsigned long address)
-{
-       struct s3c_pl330_chan *ch;
-       unsigned long flags;
-       int ret = 0;
-
-       spin_lock_irqsave(&res_lock, flags);
-
-       ch = id_to_chan(id);
-
-       if (!ch || chan_free(ch)) {
-               ret = -EINVAL;
-               goto devcfg_exit;
-       }
-
-       switch (source) {
-       case S3C2410_DMASRC_HW: /* P->M */
-               ch->req[0].rqtype = DEVTOMEM;
-               ch->req[1].rqtype = DEVTOMEM;
-               ch->rqcfg.src_inc = 0;
-               ch->rqcfg.dst_inc = 1;
-               break;
-       case S3C2410_DMASRC_MEM: /* M->P */
-               ch->req[0].rqtype = MEMTODEV;
-               ch->req[1].rqtype = MEMTODEV;
-               ch->rqcfg.src_inc = 1;
-               ch->rqcfg.dst_inc = 0;
-               break;
-       default:
-               ret = -EINVAL;
-               goto devcfg_exit;
-       }
-
-       ch->sdaddr = address;
-
-devcfg_exit:
-       spin_unlock_irqrestore(&res_lock, flags);
-
-       return ret;
-}
-EXPORT_SYMBOL(s3c2410_dma_devconfig);
-
-int s3c2410_dma_getposition(enum dma_ch id, dma_addr_t *src, dma_addr_t *dst)
-{
-       struct s3c_pl330_chan *ch = id_to_chan(id);
-       struct pl330_chanstatus status;
-       int ret;
-
-       if (!ch || chan_free(ch))
-               return -EINVAL;
-
-       ret = pl330_chan_status(ch->pl330_chan_id, &status);
-       if (ret < 0)
-               return ret;
-
-       *src = status.src_addr;
-       *dst = status.dst_addr;
-
-       return 0;
-}
-EXPORT_SYMBOL(s3c2410_dma_getposition);
-
-static irqreturn_t pl330_irq_handler(int irq, void *data)
-{
-       if (pl330_update(data))
-               return IRQ_HANDLED;
-       else
-               return IRQ_NONE;
-}
-
-static int pl330_probe(struct platform_device *pdev)
-{
-       struct s3c_pl330_dmac *s3c_pl330_dmac;
-       struct s3c_pl330_platdata *pl330pd;
-       struct pl330_info *pl330_info;
-       struct resource *res;
-       int i, ret, irq;
-
-       pl330pd = pdev->dev.platform_data;
-
-       /* Can't do without the list of _32_ peripherals */
-       if (!pl330pd || !pl330pd->peri) {
-               dev_err(&pdev->dev, "platform data missing!\n");
-               return -ENODEV;
-       }
-
-       pl330_info = kzalloc(sizeof(*pl330_info), GFP_KERNEL);
-       if (!pl330_info)
-               return -ENOMEM;
-
-       pl330_info->pl330_data = NULL;
-       pl330_info->dev = &pdev->dev;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               ret = -ENODEV;
-               goto probe_err1;
-       }
-
-       request_mem_region(res->start, resource_size(res), pdev->name);
-
-       pl330_info->base = ioremap(res->start, resource_size(res));
-       if (!pl330_info->base) {
-               ret = -ENXIO;
-               goto probe_err2;
-       }
-
-       irq = platform_get_irq(pdev, 0);
-       if (irq < 0) {
-               ret = irq;
-               goto probe_err3;
-       }
-
-       ret = request_irq(irq, pl330_irq_handler, 0,
-                       dev_name(&pdev->dev), pl330_info);
-       if (ret)
-               goto probe_err4;
-
-       /* Allocate a new DMAC */
-       s3c_pl330_dmac = kmalloc(sizeof(*s3c_pl330_dmac), GFP_KERNEL);
-       if (!s3c_pl330_dmac) {
-               ret = -ENOMEM;
-               goto probe_err5;
-       }
-
-       /* Get operation clock and enable it */
-       s3c_pl330_dmac->clk = clk_get(&pdev->dev, "pdma");
-       if (IS_ERR(s3c_pl330_dmac->clk)) {
-               dev_err(&pdev->dev, "Cannot get operation clock.\n");
-               ret = -EINVAL;
-               goto probe_err6;
-       }
-       clk_enable(s3c_pl330_dmac->clk);
-
-       ret = pl330_add(pl330_info);
-       if (ret)
-               goto probe_err7;
-
-       /* Hook the info */
-       s3c_pl330_dmac->pi = pl330_info;
-
-       /* No busy channels */
-       s3c_pl330_dmac->busy_chan = 0;
-
-       s3c_pl330_dmac->kmcache = kmem_cache_create(dev_name(&pdev->dev),
-                               sizeof(struct s3c_pl330_xfer), 0, 0, NULL);
-
-       if (!s3c_pl330_dmac->kmcache) {
-               ret = -ENOMEM;
-               goto probe_err8;
-       }
-
-       /* Get the list of peripherals */
-       s3c_pl330_dmac->peri = pl330pd->peri;
-
-       /* Attach to the list of DMACs */
-       list_add_tail(&s3c_pl330_dmac->node, &dmac_list);
-
-       /* Create a channel for each peripheral in the DMAC
-        * that is, if it doesn't already exist
-        */
-       for (i = 0; i < PL330_MAX_PERI; i++)
-               if (s3c_pl330_dmac->peri[i] != DMACH_MAX)
-                       chan_add(s3c_pl330_dmac->peri[i]);
-
-       printk(KERN_INFO
-               "Loaded driver for PL330 DMAC-%d %s\n", pdev->id, pdev->name);
-       printk(KERN_INFO
-               "\tDBUFF-%ux%ubytes Num_Chans-%u Num_Peri-%u Num_Events-%u\n",
-               pl330_info->pcfg.data_buf_dep,
-               pl330_info->pcfg.data_bus_width / 8, pl330_info->pcfg.num_chan,
-               pl330_info->pcfg.num_peri, pl330_info->pcfg.num_events);
-
-       return 0;
-
-probe_err8:
-       pl330_del(pl330_info);
-probe_err7:
-       clk_disable(s3c_pl330_dmac->clk);
-       clk_put(s3c_pl330_dmac->clk);
-probe_err6:
-       kfree(s3c_pl330_dmac);
-probe_err5:
-       free_irq(irq, pl330_info);
-probe_err4:
-probe_err3:
-       iounmap(pl330_info->base);
-probe_err2:
-       release_mem_region(res->start, resource_size(res));
-probe_err1:
-       kfree(pl330_info);
-
-       return ret;
-}
-
-static int pl330_remove(struct platform_device *pdev)
-{
-       struct s3c_pl330_dmac *dmac, *d;
-       struct s3c_pl330_chan *ch;
-       unsigned long flags;
-       int del, found;
-
-       if (!pdev->dev.platform_data)
-               return -EINVAL;
-
-       spin_lock_irqsave(&res_lock, flags);
-
-       found = 0;
-       list_for_each_entry(d, &dmac_list, node)
-               if (d->pi->dev == &pdev->dev) {
-                       found = 1;
-                       break;
-               }
-
-       if (!found) {
-               spin_unlock_irqrestore(&res_lock, flags);
-               return 0;
-       }
-
-       dmac = d;
-
-       /* Remove all Channels that are managed only by this DMAC */
-       list_for_each_entry(ch, &chan_list, node) {
-
-               /* Only channels that are handled by this DMAC */
-               if (iface_of_dmac(dmac, ch->id))
-                       del = 1;
-               else
-                       continue;
-
-               /* Don't remove if some other DMAC has it too */
-               list_for_each_entry(d, &dmac_list, node)
-                       if (d != dmac && iface_of_dmac(d, ch->id)) {
-                               del = 0;
-                               break;
-                       }
-
-               if (del) {
-                       spin_unlock_irqrestore(&res_lock, flags);
-                       s3c2410_dma_free(ch->id, ch->client);
-                       spin_lock_irqsave(&res_lock, flags);
-                       list_del(&ch->node);
-                       kfree(ch);
-               }
-       }
-
-       /* Disable operation clock */
-       clk_disable(dmac->clk);
-       clk_put(dmac->clk);
-
-       /* Remove the DMAC */
-       list_del(&dmac->node);
-       kfree(dmac);
-
-       spin_unlock_irqrestore(&res_lock, flags);
-
-       return 0;
-}
-
-static struct platform_driver pl330_driver = {
-       .driver         = {
-               .owner  = THIS_MODULE,
-               .name   = "s3c-pl330",
-       },
-       .probe          = pl330_probe,
-       .remove         = pl330_remove,
-};
-
-static int __init pl330_init(void)
-{
-       return platform_driver_register(&pl330_driver);
-}
-module_init(pl330_init);
-
-static void __exit pl330_exit(void)
-{
-       platform_driver_unregister(&pl330_driver);
-       return;
-}
-module_exit(pl330_exit);
-
-MODULE_AUTHOR("Jaswinder Singh <jassi.brar@samsung.com>");
-MODULE_DESCRIPTION("Driver for PL330 DMA Controller");
-MODULE_LICENSE("GPL");
index 7c928da..7617248 100644 (file)
 #define __NR_syncfs                    1329
 #define __NR_setns                     1330
 #define __NR_sendmmsg                  1331
+#define __NR_process_vm_readv          1332
+#define __NR_process_vm_writev         1333
 
 #ifdef __KERNEL__
 
 
-#define NR_syscalls                    308 /* length of syscall table */
+#define NR_syscalls                    310 /* length of syscall table */
 
 /*
  * The following defines stop scripts/checksyscalls.sh from complaining about
index 198c753..5b31d46 100644 (file)
@@ -1777,6 +1777,8 @@ sys_call_table:
        data8 sys_syncfs
        data8 sys_setns                         // 1330
        data8 sys_sendmmsg
+       data8 sys_process_vm_readv
+       data8 sys_process_vm_writev
 
        .org sys_call_table + 8*NR_syscalls     // guard against failures to increase NR_syscalls
 #endif /* __IA64_ASM_PARAVIRTUALIZED_NATIVE */
index 48e50f8..e301133 100644 (file)
@@ -59,7 +59,7 @@ struct nfhd_device {
        struct gendisk *disk;
 };
 
-static int nfhd_make_request(struct request_queue *queue, struct bio *bio)
+static void nfhd_make_request(struct request_queue *queue, struct bio *bio)
 {
        struct nfhd_device *dev = queue->queuedata;
        struct bio_vec *bvec;
@@ -76,7 +76,6 @@ static int nfhd_make_request(struct request_queue *queue, struct bio *bio)
                sec += len;
        }
        bio_endio(bio, 0);
-       return 0;
 }
 
 static int nfhd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
index 47682b6..85195e4 100644 (file)
@@ -323,7 +323,7 @@ config SWIOTLB
 
 config HOTPLUG_CPU
        bool "Support for enabling/disabling CPUs"
-       depends on SMP && HOTPLUG && EXPERIMENTAL && (PPC_PSERIES || PPC_PMAC)
+       depends on SMP && HOTPLUG && EXPERIMENTAL && (PPC_PSERIES || PPC_PMAC || PPC_POWERNV)
        ---help---
          Say Y here to be able to disable and re-enable individual
          CPUs at runtime on SMP machines.
@@ -345,7 +345,7 @@ config ARCH_ENABLE_MEMORY_HOTREMOVE
 
 config KEXEC
        bool "kexec system call (EXPERIMENTAL)"
-       depends on (PPC_BOOK3S || FSL_BOOKE) && EXPERIMENTAL
+       depends on (PPC_BOOK3S || FSL_BOOKE || (44x && !SMP && !47x)) && EXPERIMENTAL
        help
          kexec is a system call that implements the ability to shutdown your
          current kernel, and to start another kernel.  It is like a reboot
@@ -429,8 +429,7 @@ config ARCH_POPULATES_NODE_MAP
        def_bool y
 
 config SYS_SUPPORTS_HUGETLBFS
-       def_bool y
-       depends on PPC_BOOK3S_64
+       bool
 
 source "mm/Kconfig"
 
index 067cb84..1b8a9c9 100644 (file)
@@ -141,9 +141,6 @@ config BOOTX_TEXT
 
 config PPC_EARLY_DEBUG
        bool "Early debugging (dangerous)"
-       # PPC_EARLY_DEBUG on 440 leaves AS=1 mappings above the TLB high water
-       # mark, which doesn't work with current 440 KVM.
-       depends on !KVM
        help
          Say Y to enable some early debugging facilities that may be available
          for your processor/board combination. Those facilities are hacks
@@ -222,7 +219,9 @@ config PPC_EARLY_DEBUG_BEAT
 
 config PPC_EARLY_DEBUG_44x
        bool "Early serial debugging for IBM/AMCC 44x CPUs"
-       depends on 44x
+       # PPC_EARLY_DEBUG on 440 leaves AS=1 mappings above the TLB high water
+       # mark, which doesn't work with current 440 KVM.
+       depends on 44x && !KVM
        help
          Select this to enable early debugging for IBM 44x chips via the
          inbuilt serial port.  If you enable this, ensure you set
@@ -258,8 +257,35 @@ config PPC_EARLY_DEBUG_WSP
        depends on PPC_WSP
        select PPC_UDBG_16550
 
+config PPC_EARLY_DEBUG_PS3GELIC
+       bool "Early debugging through the PS3 Ethernet port"
+       depends on PPC_PS3
+       select PS3GELIC_UDBG
+       help
+         Select this to enable early debugging for the PlayStation3 via
+         UDP broadcasts sent out through the Ethernet port.
+
+config PPC_EARLY_DEBUG_OPAL_RAW
+       bool "OPAL raw console"
+       depends on HVC_OPAL
+       help
+         Select this to enable early debugging for the PowerNV platform
+         using a "raw" console
+
+config PPC_EARLY_DEBUG_OPAL_HVSI
+       bool "OPAL hvsi console"
+       depends on HVC_OPAL
+       help
+         Select this to enable early debugging for the PowerNV platform
+         using an "hvsi" console
+
 endchoice
 
+config PPC_EARLY_DEBUG_OPAL
+       def_bool y
+       depends on PPC_EARLY_DEBUG_OPAL_RAW || PPC_EARLY_DEBUG_OPAL_HVSI
+
+
 config PPC_EARLY_DEBUG_HVSI_VTERMNO
        hex "vterm number to use with early debug HVSI"
        depends on PPC_EARLY_DEBUG_LPAR_HVSI
@@ -268,6 +294,18 @@ config PPC_EARLY_DEBUG_HVSI_VTERMNO
          You probably want 0x30000000 for your first serial port and
          0x30000001 for your second one
 
+config PPC_EARLY_DEBUG_OPAL_VTERMNO
+       hex "vterm number to use with OPAL early debug"
+       depends on PPC_EARLY_DEBUG_OPAL
+       default "0"
+       help
+         This correspond to which /dev/hvcN you want to use for early
+         debug.
+
+         On OPAL v1 (takeover) this should always be 0
+         On OPAL v2, this will be 0 for network console and 1 or 2 for
+         the machine built-in serial ports.
+
 config PPC_EARLY_DEBUG_44x_PHYSLOW
        hex "Low 32 bits of early debug UART physical address"
        depends on PPC_EARLY_DEBUG_44x
index c26200b..72ee8c1 100644 (file)
@@ -58,7 +58,7 @@ $(addprefix $(obj)/,$(zlib) cuboot-c2k.o gunzip_util.o main.o prpmc2800.o): \
 libfdt       := fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c
 libfdtheader := fdt.h libfdt.h libfdt_internal.h
 
-$(addprefix $(obj)/,$(libfdt) libfdt-wrapper.o simpleboot.o): \
+$(addprefix $(obj)/,$(libfdt) libfdt-wrapper.o simpleboot.o epapr.o): \
        $(addprefix $(obj)/,$(libfdtheader))
 
 src-wlib := string.S crt0.S crtsavres.S stdio.c main.c \
@@ -171,6 +171,7 @@ quiet_cmd_wrap      = WRAP    $@
                $(if $3, -s $3)$(if $4, -d $4)$(if $5, -i $5) vmlinux
 
 image-$(CONFIG_PPC_PSERIES)            += zImage.pseries
+image-$(CONFIG_PPC_POWERNV)            += zImage.pseries
 image-$(CONFIG_PPC_MAPLE)              += zImage.maple
 image-$(CONFIG_PPC_IBM_CELL_BLADE)     += zImage.pseries
 image-$(CONFIG_PPC_PS3)                        += dtbImage.ps3
index 27bd267..a7511f2 100644 (file)
 
        soc5200@f0000000 {
                timer@600 {     // General Purpose Timer
+                       #gpio-cells = <2>;
                        fsl,has-wdt;
+                       gpio-controller;
                };
 
-               rtc@800 {
-                       status = "disabled";
+               timer@610 {
+                       #gpio-cells = <2>;
+                       gpio-controller;
                };
 
-               can@900 {
+               rtc@800 {
                        status = "disabled";
                };
 
-               can@980 {
-                       status = "disabled";
+               spi@f00 {
+                       msp430@0 {
+                               compatible = "spidev";
+                               spi-max-frequency = <32000>;
+                               reg = <0>;
+                       };
                };
 
                psc@2000 {              // PSC1
                };
 
                i2c@3d00 {
-                       rtc@50 {
+                       eeprom@50 {
                                compatible = "at,24c08";
                                reg = <0x50>;
                        };
 
+                       rtc@56 {
+                               compatible = "mc,rv3029c2";
+                               reg = <0x56>;
+                       };
+
                        rtc@68 {
                                compatible = "dallas,ds1339";
                                reg = <0x68>;
        };
 
        pci@f0000d00 {
-               status = "disabled";
+               interrupt-map-mask = <0xf800 0 0 7>;
+               interrupt-map = <0xc000 0 0 1 &mpc5200_pic 0 0 3
+                                0xc000 0 0 2 &mpc5200_pic 0 0 3
+                                0xc000 0 0 3 &mpc5200_pic 0 0 3
+                                0xc000 0 0 4 &mpc5200_pic 0 0 3>;
+               clock-frequency = <0>; // From boot loader
+               interrupts = <2 8 0 2 9 0 2 10 0>;
+               bus-range = <0 0>;
+               ranges = <0x42000000 0 0x80000000 0x80000000 0 0x10000000
+                         0x02000000 0 0x90000000 0x90000000 0 0x10000000
+                         0x01000000 0 0x00000000 0xa0000000 0 0x01000000>;
        };
 
        localbus {
-               ranges = <0 0 0xff000000 0x1000000>;
+               ranges = <0 0 0xff000000 0x1000000
+                         4 0 0x60000000 0x0001000>;
 
                // 16-bit flash device at LocalPlus Bus CS0
                flash@0,0 {
                                reg = <0x00f00000 0x100000>;
                        };
                };
+
+               can@4,0 {
+                       compatible = "nxp,sja1000";
+                       reg = <4 0x000 0x80>;
+                       nxp,external-clock-frequency = <24000000>;
+                       interrupts = <1 2 3>; // Level-low
+               };
+
+               can@4,100 {
+                       compatible = "nxp,sja1000";
+                       reg = <4 0x100 0x80>;
+                       nxp,external-clock-frequency = <24000000>;
+                       interrupts = <1 2 3>;  // Level-low
+               };
+
+               serial@4,200 {
+                       compatible = "nxp,sc28l92";
+                       reg = <4 0x200 0x10>;
+                       interrupts = <1 3 3>;
+               };
        };
 };
index 83f4b79..2266bbb 100644 (file)
                enet0: ethernet@24000 {
                        #address-cells = <1>;
                        #size-cells = <1>;
+                       cell-index = <0>;
                        device_type = "network";
-                       model = "eTSEC";
+                       model = "TSEC";
                        compatible = "gianfar";
                        reg = <0x24000 0x1000>;
                        ranges = <0x0 0x24000 0x1000>;
                        local-mac-address = [ 00 00 00 00 00 00 ];
-                       interrupts = <0x1d 0x2 0x1e 0x2 0x22 0x2>;
+                       interrupts = <29 2 30  2 34 2>;
                        interrupt-parent = <&mpic>;
+                       tbi-handle = <&tbi0>;
                        phy-handle = <&phy0>;
                        phy-connection-type = "gmii";
 
                                        interrupt-parent = <&gef_pic>;
                                        interrupts = <0x9 0x4>;
                                        reg = <1>;
+                                       device_type = "ethernet-phy";
                                };
                                phy2: ethernet-phy@2 {
                                        interrupt-parent = <&gef_pic>;
                                        interrupts = <0x8 0x4>;
                                        reg = <3>;
+                                       device_type = "ethernet-phy";
+                               };
+                               tbi0: tbi-phy@11 {
+                                       reg = <0x11>;
+                                       device_type = "tbi-phy";
                                };
                        };
                };
 
                enet1: ethernet@26000 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       cell-index = <2>;
                        device_type = "network";
-                       model = "eTSEC";
+                       model = "TSEC";
                        compatible = "gianfar";
                        reg = <0x26000 0x1000>;
+                       ranges = <0x0 0x26000 0x1000>;
                        local-mac-address = [ 00 00 00 00 00 00 ];
-                       interrupts = <0x1f 0x2 0x20 0x2 0x21 0x2>;
+                       interrupts = <31 2 32 2 33 2>;
                        interrupt-parent = <&mpic>;
+                       tbi-handle = <&tbi2>;
                        phy-handle = <&phy2>;
                        phy-connection-type = "gmii";
+
+                       mdio@520 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               compatible = "fsl,gianfar-tbi";
+                               reg = <0x520 0x20>;
+
+                               tbi2: tbi-phy@11 {
+                                       reg = <0x11>;
+                                       device_type = "tbi-phy";
+                               };
+                       };
                };
 
                serial0: serial@4500 {
index fc3a331..429e87d 100644 (file)
                enet0: ethernet@24000 {
                        #address-cells = <1>;
                        #size-cells = <1>;
+                       cell-index = <0>;
                        device_type = "network";
-                       model = "eTSEC";
+                       model = "TSEC";
                        compatible = "gianfar";
                        reg = <0x24000 0x1000>;
                        ranges = <0x0 0x24000 0x1000>;
                        local-mac-address = [ 00 00 00 00 00 00 ];
-                       interrupts = <0x1d 0x2 0x1e 0x2 0x22 0x2>;
+                       interrupts = <29 2 30  2 34 2>;
                        interrupt-parent = <&mpic>;
+                       tbi-handle = <&tbi0>;
                        phy-handle = <&phy0>;
                        phy-connection-type = "gmii";
 
                                        interrupt-parent = <&gef_pic>;
                                        interrupts = <0x9 0x4>;
                                        reg = <1>;
+                                       device_type = "ethernet-phy";
                                };
                                phy2: ethernet-phy@2 {
                                        interrupt-parent = <&gef_pic>;
                                        interrupts = <0x8 0x4>;
                                        reg = <3>;
+                                       device_type = "ethernet-phy";
+                               };
+                               tbi0: tbi-phy@11 {
+                                       reg = <0x11>;
+                                       device_type = "tbi-phy";
                                };
                        };
                };
 
                enet1: ethernet@26000 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       cell-index = <2>;
                        device_type = "network";
-                       model = "eTSEC";
+                       model = "TSEC";
                        compatible = "gianfar";
                        reg = <0x26000 0x1000>;
+                       ranges = <0x0 0x26000 0x1000>;
                        local-mac-address = [ 00 00 00 00 00 00 ];
-                       interrupts = <0x1f 0x2 0x20 0x2 0x21 0x2>;
+                       interrupts = <31 2 32 2 33 2>;
                        interrupt-parent = <&mpic>;
+                       tbi-handle = <&tbi2>;
                        phy-handle = <&phy2>;
                        phy-connection-type = "gmii";
+
+                       mdio@520 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               compatible = "fsl,gianfar-tbi";
+                               reg = <0x520 0x20>;
+
+                               tbi2: tbi-phy@11 {
+                                       reg = <0x11>;
+                                       device_type = "tbi-phy";
+                               };
+                       };
                };
 
                serial0: serial@4500 {
index c0671cc..d81201a 100644 (file)
                enet0: ethernet@24000 {
                        #address-cells = <1>;
                        #size-cells = <1>;
+                       cell-index = <0>;
                        device_type = "network";
-                       model = "eTSEC";
+                       model = "TSEC";
                        compatible = "gianfar";
                        reg = <0x24000 0x1000>;
                        ranges = <0x0 0x24000 0x1000>;
                        local-mac-address = [ 00 00 00 00 00 00 ];
-                       interrupts = <0x1d 0x2 0x1e 0x2 0x22 0x2>;
+                       interrupts = <29 2 30  2 34 2>;
                        interrupt-parent = <&mpic>;
+                       tbi-handle = <&tbi0>;
                        phy-handle = <&phy0>;
                        phy-connection-type = "gmii";
 
                                        interrupt-parent = <&gef_pic>;
                                        interrupts = <0x9 0x4>;
                                        reg = <1>;
+                                       device_type = "ethernet-phy";
                                };
                                phy2: ethernet-phy@2 {
                                        interrupt-parent = <&gef_pic>;
                                        interrupts = <0x8 0x4>;
                                        reg = <3>;
+                                       device_type = "ethernet-phy";
+                               };
+                               tbi0: tbi-phy@11 {
+                                       reg = <0x11>;
+                                       device_type = "tbi-phy";
                                };
                        };
                };
 
                enet1: ethernet@26000 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       cell-index = <2>;
                        device_type = "network";
-                       model = "eTSEC";
+                       model = "TSEC";
                        compatible = "gianfar";
                        reg = <0x26000 0x1000>;
+                       ranges = <0x0 0x26000 0x1000>;
                        local-mac-address = [ 00 00 00 00 00 00 ];
-                       interrupts = <0x1f 0x2 0x20 0x2 0x21 0x2>;
+                       interrupts = <31 2 32 2 33 2>;
                        interrupt-parent = <&mpic>;
+                       tbi-handle = <&tbi2>;
                        phy-handle = <&phy2>;
                        phy-connection-type = "gmii";
+
+                       mdio@520 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               compatible = "fsl,gianfar-tbi";
+                               reg = <0x520 0x20>;
+
+                               tbi2: tbi-phy@11 {
+                                       reg = <0x11>;
+                                       device_type = "tbi-phy";
+                               };
+                       };
                };
 
                serial0: serial@4500 {
diff --git a/arch/powerpc/boot/dts/hcu4.dts b/arch/powerpc/boot/dts/hcu4.dts
deleted file mode 100644 (file)
index 7988598..0000000
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
-* Device Tree Source for Netstal Maschinen HCU4
-* based on the IBM Walnut
-*
-* Copyright 2008
-* Niklaus Giger <niklaus.giger@member.fsf.org>
-*
-* Copyright 2007 IBM Corp.
-* Josh Boyer <jwboyer@linux.vnet.ibm.com>
-*
-* This file is licensed under the terms of the GNU General Public
-* License version 2.  This program is licensed "as is" without
-* any warranty of any kind, whether express or implied.
-*/
-
-/dts-v1/;
-
-/ {
-       #address-cells = <0x1>;
-       #size-cells = <0x1>;
-       model = "netstal,hcu4";
-       compatible = "netstal,hcu4";
-       dcr-parent = <0x1>;
-
-       aliases {
-               ethernet0 = "/plb/opb/ethernet@ef600800";
-               serial0 = "/plb/opb/serial@ef600300";
-       };
-
-       cpus {
-               #address-cells = <0x1>;
-               #size-cells = <0x0>;
-
-               cpu@0 {
-                       device_type = "cpu";
-                       model = "PowerPC,405GPr";
-                       reg = <0x0>;
-                       clock-frequency = <0>;          /* Filled in by U-Boot */
-                       timebase-frequency = <0x0>;     /* Filled in by U-Boot */
-                       i-cache-line-size = <0x20>;
-                       d-cache-line-size = <0x20>;
-                       i-cache-size = <0x4000>;
-                       d-cache-size = <0x4000>;
-                       dcr-controller;
-                       dcr-access-method = "native";
-                       linux,phandle = <0x1>;
-               };
-       };
-
-       memory {
-               device_type = "memory";
-               reg = <0x0 0x0>;        /* Filled in by U-Boot */
-       };
-
-       UIC0: interrupt-controller {
-               compatible = "ibm,uic";
-               interrupt-controller;
-               cell-index = <0x0>;
-               dcr-reg = <0xc0 0x9>;
-               #address-cells = <0x0>;
-               #size-cells = <0x0>;
-               #interrupt-cells = <0x2>;
-               linux,phandle = <0x2>;
-       };
-
-       plb {
-               compatible = "ibm,plb3";
-               #address-cells = <0x1>;
-               #size-cells = <0x1>;
-               ranges;
-               clock-frequency = <0x0>;        /* Filled in by U-Boot */
-
-               SDRAM0: memory-controller {
-                       compatible = "ibm,sdram-405gp";
-                       dcr-reg = <0x10 0x2>;
-               };
-
-               MAL: mcmal {
-                       compatible = "ibm,mcmal-405gp", "ibm,mcmal";
-                       dcr-reg = <0x180 0x62>;
-                       num-tx-chans = <0x1>;
-                       num-rx-chans = <0x1>;
-                       interrupt-parent = <0x2>;
-                       interrupts = <0xb 0x4 0xc 0x4 0xa 0x4 0xd 0x4 0xe 0x4>;
-                       linux,phandle = <0x3>;
-               };
-
-               POB0: opb {
-                       compatible = "ibm,opb-405gp", "ibm,opb";
-                       #address-cells = <0x1>;
-                       #size-cells = <0x1>;
-                       ranges = <0xef600000 0xef600000 0xa00000>;
-                       dcr-reg = <0xa0 0x5>;
-                       clock-frequency = <0x0>;        /* Filled in by U-Boot */
-
-                       UART0: serial@ef600300 {
-                               device_type = "serial";
-                               compatible = "ns16550";
-                               reg = <0xef600300 0x8>;
-                               virtual-reg = <0xef600300>;
-                               clock-frequency = <0x0>;/* Filled in by U-Boot */
-                               current-speed = <0>;    /* Filled in by U-Boot */
-                               interrupt-parent = <0x2>;
-                               interrupts = <0x0 0x4>;
-                       };
-
-                       IIC: i2c@ef600500 {
-                               compatible = "ibm,iic-405gp", "ibm,iic";
-                               reg = <0xef600500 0x11>;
-                               interrupt-parent = <0x2>;
-                               interrupts = <0x2 0x4>;
-                       };
-
-                       GPIO: gpio@ef600700 {
-                               compatible = "ibm,gpio-405gp";
-                               reg = <0xef600700 0x20>;
-                       };
-
-                       EMAC: ethernet@ef600800 {
-                               device_type = "network";
-                               compatible = "ibm,emac-405gp", "ibm,emac";
-                               interrupt-parent = <0x2>;
-                               interrupts = <0xf 0x4 0x9 0x4>;
-                               local-mac-address = [00 00 00 00 00 00];
-                               reg = <0xef600800 0x70>;
-                               mal-device = <0x3>;
-                               mal-tx-channel = <0x0>;
-                               mal-rx-channel = <0x0>;
-                               cell-index = <0x0>;
-                               max-frame-size = <0x5dc>;
-                               rx-fifo-size = <0x1000>;
-                               tx-fifo-size = <0x800>;
-                               phy-mode = "rmii";
-                               phy-map = <0x1>;
-                       };
-               };
-
-               EBC0: ebc {
-                       compatible = "ibm,ebc-405gp", "ibm,ebc";
-                       dcr-reg = <0x12 0x2>;
-                       #address-cells = <0x2>;
-                       #size-cells = <0x1>;
-                       clock-frequency = <0x0>;        /* Filled in by U-Boot */
-
-                       sram@0,0 {
-                               reg = <0x0 0x0 0x80000>;
-                       };
-
-                       flash@0,80000 {
-                               compatible = "jedec-flash";
-                               bank-width = <0x1>;
-                               reg = <0x0 0x80000 0x80000>;
-                               #address-cells = <0x1>;
-                               #size-cells = <0x1>;
-
-                               partition@0 {
-                                       label = "OpenBIOS";
-                                       reg = <0x0 0x80000>;
-                                       read-only;
-                               };
-                       };
-               };
-       };
-
-       chosen {
-               linux,stdout-path = "/plb/opb/serial@ef600300";
-       };
-};
index bdb7fc0..296c572 100644 (file)
        localbus@fdf05000 {
                #address-cells = <2>;
                #size-cells = <1>;
-               compatible = "fsl,mpc8560-localbus";
+               compatible = "fsl,mpc8560-localbus", "simple-bus";
                reg = <0xfdf05000 0x68>;
 
                ranges = <0x0 0x0 0xe0000000 0x00800000
index 1360d2f..ededaf5 100644 (file)
                                linux,network-index = <2>;
                                fsl,cpm-command = <0x16200300>;
                        };
+
+                       usb@11b60 {
+                               compatible = "fsl,mpc8272-cpm-usb";
+                               mode = "peripheral";
+                               reg = <0x11b60 0x40 0x8b00 0x100>;
+                               interrupts = <11 8>;
+                               interrupt-parent = <&PIC>;
+                               usb-clock = <5>;
+                       };
                };
 
                cpm2_pio_c: gpio-controller@10d40 {
index bc27548..7ab286a 100644 (file)
                };
 
                spi@f00 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
                        compatible = "fsl,mpc5200b-spi","fsl,mpc5200-spi";
                        reg = <0xf00 0x20>;
                        interrupts = <2 13 0 2 14 0>;
index b53d1df..505dc84 100644 (file)
                #address-cells = <2>;
                #size-cells = <1>;
                compatible = "fsl,mpc8349e-localbus",
-                            "fsl,pq2pro-localbus";
+                            "fsl,pq2pro-localbus",
+                            "simple-bus";
                reg = <0xe0005000 0xd8>;
                ranges = <0x0 0x0 0xfe000000 0x1000000  /* flash */
                          0x1 0x0 0xf8000000 0x20000    /* VSC 7385 */
index 1be9743..b9b8719 100644 (file)
                };
 
                board-control@3,0 {
-                       compatible = "fsl,p1022ds-pixis";
+                       compatible = "fsl,p1022ds-fpga", "fsl,fpga-ngpixis";
                        reg = <3 0 0x30>;
                        interrupt-parent = <&mpic>;
                        /*
index dae4031..66f03d6 100644 (file)
                        };
                };
 
+               board-control@3,0 {
+                       compatible = "fsl,p2020ds-fpga", "fsl,fpga-ngpixis";
+                       reg = <0x3 0x0 0x30>;
+               };
+
                nand@4,0 {
                        compatible = "fsl,elbc-fcm-nand";
                        reg = <0x4 0x0 0x40000>;
similarity index 95%
rename from arch/powerpc/boot/dts/p2040rdb.dts
rename to arch/powerpc/boot/dts/p2041rdb.dts
index 7d84e39..79b6895 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * P2040RDB Device Tree Source
+ * P2041RDB Device Tree Source
  *
  * Copyright 2011 Freescale Semiconductor Inc.
  *
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-/include/ "p2040si.dtsi"
+/include/ "p2041si.dtsi"
 
 / {
-       model = "fsl,P2040RDB";
-       compatible = "fsl,P2040RDB";
+       model = "fsl,P2041RDB";
+       compatible = "fsl,P2041RDB";
        #address-cells = <2>;
        #size-cells = <2>;
        interrupt-parent = <&mpic>;
                device_type = "memory";
        };
 
+       dcsr: dcsr@f00000000 {
+               ranges = <0x00000000 0xf 0x00000000 0x01008000>;
+       };
+
        soc: soc@ffe000000 {
                spi@110000 {
                        flash@0 {
                        };
                };
 
-               usb0: usb@210000 {
-                       phy_type = "utmi";
-               };
-
                usb1: usb@211000 {
                        dr_mode = "host";
-                       phy_type = "utmi";
                };
        };
 
similarity index 80%
rename from arch/powerpc/boot/dts/p2040si.dtsi
rename to arch/powerpc/boot/dts/p2041si.dtsi
index 5fdbb24..f7492ed 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * P2040 Silicon Device Tree Source
+ * P2041 Silicon Device Tree Source
  *
  * Copyright 2011 Freescale Semiconductor Inc.
  *
 /dts-v1/;
 
 / {
-       compatible = "fsl,P2040";
+       compatible = "fsl,P2041";
        #address-cells = <2>;
        #size-cells = <2>;
        interrupt-parent = <&mpic>;
 
        aliases {
                ccsr = &soc;
+               dcsr = &dcsr;
 
                serial0 = &serial0;
                serial1 = &serial1;
                };
        };
 
+       dcsr: dcsr@f00000000 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "fsl,dcsr", "simple-bus";
+
+               dcsr-epu@0 {
+                       compatible = "fsl,dcsr-epu";
+                       interrupts = <52 2 0 0
+                                     84 2 0 0
+                                     85 2 0 0>;
+                       interrupt-parent = <&mpic>;
+                       reg = <0x0 0x1000>;
+               };
+               dcsr-npc {
+                       compatible = "fsl,dcsr-npc";
+                       reg = <0x1000 0x1000 0x1000000 0x8000>;
+               };
+               dcsr-nxc@2000 {
+                       compatible = "fsl,dcsr-nxc";
+                       reg = <0x2000 0x1000>;
+               };
+               dcsr-corenet {
+                       compatible = "fsl,dcsr-corenet";
+                       reg = <0x8000 0x1000 0xB0000 0x1000>;
+               };
+               dcsr-dpaa@9000 {
+                       compatible = "fsl,p2041-dcsr-dpaa", "fsl,dcsr-dpaa";
+                       reg = <0x9000 0x1000>;
+               };
+               dcsr-ocn@11000 {
+                       compatible = "fsl,p2041-dcsr-ocn", "fsl,dcsr-ocn";
+                       reg = <0x11000 0x1000>;
+               };
+               dcsr-ddr@12000 {
+                       compatible = "fsl,dcsr-ddr";
+                       dev-handle = <&ddr>;
+                       reg = <0x12000 0x1000>;
+               };
+               dcsr-nal@18000 {
+                       compatible = "fsl,p2041-dcsr-nal", "fsl,dcsr-nal";
+                       reg = <0x18000 0x1000>;
+               };
+               dcsr-rcpm@22000 {
+                       compatible = "fsl,p2041-dcsr-rcpm", "fsl,dcsr-rcpm";
+                       reg = <0x22000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@40000 {
+                       compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu0>;
+                       reg = <0x40000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@41000 {
+                       compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu1>;
+                       reg = <0x41000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@42000 {
+                       compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu2>;
+                       reg = <0x42000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@43000 {
+                       compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu3>;
+                       reg = <0x43000 0x1000>;
+               };
+       };
+
        soc: soc@ffe000000 {
                #address-cells = <1>;
                #size-cells = <1>;
                        fsl,num-laws = <32>;
                };
 
-               memory-controller@8000 {
+               ddr: memory-controller@8000 {
                        compatible = "fsl,qoriq-memory-controller-v4.5", "fsl,qoriq-memory-controller";
                        reg = <0x8000 0x1000>;
                        interrupts = <16 2 1 23>;
                };
 
                cpc: l3-cache-controller@10000 {
-                       compatible = "fsl,p2040-l3-cache-controller", "fsl,p4080-l3-cache-controller", "cache";
+                       compatible = "fsl,p2041-l3-cache-controller", "fsl,p4080-l3-cache-controller", "cache";
                        reg = <0x10000 0x1000>;
                        interrupts = <16 2 1 27>;
                };
                };
 
                clockgen: global-utilities@e1000 {
-                       compatible = "fsl,p2040-clockgen", "fsl,qoriq-clockgen-1.0";
+                       compatible = "fsl,p2041-clockgen", "fsl,qoriq-clockgen-1.0";
                        reg = <0xe1000 0x1000>;
                        clock-frequency = <0>;
                };
                };
 
                sfp: sfp@e8000 {
-                       compatible = "fsl,p2040-sfp", "fsl,qoriq-sfp-1.0";
+                       compatible = "fsl,p2041-sfp", "fsl,qoriq-sfp-1.0";
                        reg        = <0xe8000 0x1000>;
                };
 
                serdes: serdes@ea000 {
-                       compatible = "fsl,p2040-serdes";
+                       compatible = "fsl,p2041-serdes";
                        reg        = <0xea000 0x1000>;
                };
 
                dma0: dma@100300 {
                        #address-cells = <1>;
                        #size-cells = <1>;
-                       compatible = "fsl,p2040-dma", "fsl,eloplus-dma";
+                       compatible = "fsl,p2041-dma", "fsl,eloplus-dma";
                        reg = <0x100300 0x4>;
                        ranges = <0x0 0x100100 0x200>;
                        cell-index = <0>;
                        dma-channel@0 {
-                               compatible = "fsl,p2040-dma-channel",
+                               compatible = "fsl,p2041-dma-channel",
                                                "fsl,eloplus-dma-channel";
                                reg = <0x0 0x80>;
                                cell-index = <0>;
                                interrupts = <28 2 0 0>;
                        };
                        dma-channel@80 {
-                               compatible = "fsl,p2040-dma-channel",
+                               compatible = "fsl,p2041-dma-channel",
                                                "fsl,eloplus-dma-channel";
                                reg = <0x80 0x80>;
                                cell-index = <1>;
                                interrupts = <29 2 0 0>;
                        };
                        dma-channel@100 {
-                               compatible = "fsl,p2040-dma-channel",
+                               compatible = "fsl,p2041-dma-channel",
                                                "fsl,eloplus-dma-channel";
                                reg = <0x100 0x80>;
                                cell-index = <2>;
                                interrupts = <30 2 0 0>;
                        };
                        dma-channel@180 {
-                               compatible = "fsl,p2040-dma-channel",
+                               compatible = "fsl,p2041-dma-channel",
                                                "fsl,eloplus-dma-channel";
                                reg = <0x180 0x80>;
                                cell-index = <3>;
                dma1: dma@101300 {
                        #address-cells = <1>;
                        #size-cells = <1>;
-                       compatible = "fsl,p2040-dma", "fsl,eloplus-dma";
+                       compatible = "fsl,p2041-dma", "fsl,eloplus-dma";
                        reg = <0x101300 0x4>;
                        ranges = <0x0 0x101100 0x200>;
                        cell-index = <1>;
                        dma-channel@0 {
-                               compatible = "fsl,p2040-dma-channel",
+                               compatible = "fsl,p2041-dma-channel",
                                                "fsl,eloplus-dma-channel";
                                reg = <0x0 0x80>;
                                cell-index = <0>;
                                interrupts = <32 2 0 0>;
                        };
                        dma-channel@80 {
-                               compatible = "fsl,p2040-dma-channel",
+                               compatible = "fsl,p2041-dma-channel",
                                                "fsl,eloplus-dma-channel";
                                reg = <0x80 0x80>;
                                cell-index = <1>;
                                interrupts = <33 2 0 0>;
                        };
                        dma-channel@100 {
-                               compatible = "fsl,p2040-dma-channel",
+                               compatible = "fsl,p2041-dma-channel",
                                                "fsl,eloplus-dma-channel";
                                reg = <0x100 0x80>;
                                cell-index = <2>;
                                interrupts = <34 2 0 0>;
                        };
                        dma-channel@180 {
-                               compatible = "fsl,p2040-dma-channel",
+                               compatible = "fsl,p2041-dma-channel",
                                                "fsl,eloplus-dma-channel";
                                reg = <0x180 0x80>;
                                cell-index = <3>;
                spi@110000 {
                        #address-cells = <1>;
                        #size-cells = <0>;
-                       compatible = "fsl,p2040-espi", "fsl,mpc8536-espi";
+                       compatible = "fsl,p2041-espi", "fsl,mpc8536-espi";
                        reg = <0x110000 0x1000>;
                        interrupts = <53 0x2 0 0>;
                        fsl,espi-num-chipselects = <4>;
-
                };
 
                sdhc: sdhc@114000 {
-                       compatible = "fsl,p2040-esdhc", "fsl,esdhc";
+                       compatible = "fsl,p2041-esdhc", "fsl,esdhc";
                        reg = <0x114000 0x1000>;
                        interrupts = <48 2 0 0>;
                        sdhci,auto-cmd12;
                        clock-frequency = <0>;
                };
 
-
                i2c@118000 {
                        #address-cells = <1>;
                        #size-cells = <0>;
                };
 
                gpio0: gpio@130000 {
-                       compatible = "fsl,p2040-gpio", "fsl,qoriq-gpio";
+                       compatible = "fsl,p2041-gpio", "fsl,qoriq-gpio";
                        reg = <0x130000 0x1000>;
                        interrupts = <55 2 0 0>;
                        #gpio-cells = <2>;
                };
 
                usb0: usb@210000 {
-                       compatible = "fsl,p2040-usb2-mph",
+                       compatible = "fsl,p2041-usb2-mph",
                                        "fsl,mpc85xx-usb2-mph", "fsl-usb2-mph";
                        reg = <0x210000 0x1000>;
                        #address-cells = <1>;
                        #size-cells = <0>;
                        interrupts = <44 0x2 0 0>;
+                       phy_type = "utmi";
                        port0;
                };
 
                usb1: usb@211000 {
-                       compatible = "fsl,p2040-usb2-dr",
+                       compatible = "fsl,p2041-usb2-dr",
                                        "fsl,mpc85xx-usb2-dr", "fsl-usb2-dr";
                        reg = <0x211000 0x1000>;
                        #address-cells = <1>;
                        #size-cells = <0>;
                        interrupts = <45 0x2 0 0>;
+                       phy_type = "utmi";
                };
 
                sata@220000 {
-                       compatible = "fsl,p2040-sata", "fsl,pq-sata-v2";
+                       compatible = "fsl,p2041-sata", "fsl,pq-sata-v2";
                        reg = <0x220000 0x1000>;
                        interrupts = <68 0x2 0 0>;
                };
 
                sata@221000 {
-                       compatible = "fsl,p2040-sata", "fsl,pq-sata-v2";
+                       compatible = "fsl,p2041-sata", "fsl,pq-sata-v2";
                        reg = <0x221000 0x1000>;
                        interrupts = <69 0x2 0 0>;
                };
        };
 
        localbus@ffe124000 {
-               compatible = "fsl,p2040-elbc", "fsl,elbc", "simple-bus";
+               compatible = "fsl,p2041-elbc", "fsl,elbc", "simple-bus";
                interrupts = <25 2 0 0>;
                #address-cells = <2>;
                #size-cells = <1>;
        };
 
        pci0: pcie@ffe200000 {
-               compatible = "fsl,p2040-pcie", "fsl,qoriq-pcie-v2.2";
+               compatible = "fsl,p2041-pcie", "fsl,qoriq-pcie-v2.2";
                device_type = "pci";
                #size-cells = <2>;
                #address-cells = <3>;
                bus-range = <0x0 0xff>;
-               clock-frequency = <0x1fca055>;
+               clock-frequency = <33333333>;
                fsl,msi = <&msi0>;
                interrupts = <16 2 1 15>;
                pcie@0 {
        };
 
        pci1: pcie@ffe201000 {
-               compatible = "fsl,p2040-pcie", "fsl,qoriq-pcie-v2.2";
+               compatible = "fsl,p2041-pcie", "fsl,qoriq-pcie-v2.2";
                device_type = "pci";
                #size-cells = <2>;
                #address-cells = <3>;
                bus-range = <0 0xff>;
-               clock-frequency = <0x1fca055>;
+               clock-frequency = <33333333>;
                fsl,msi = <&msi1>;
                interrupts = <16 2 1 14>;
                pcie@0 {
        };
 
        pci2: pcie@ffe202000 {
-               compatible = "fsl,p2040-pcie", "fsl,qoriq-pcie-v2.2";
+               compatible = "fsl,p2041-pcie", "fsl,qoriq-pcie-v2.2";
                device_type = "pci";
                #size-cells = <2>;
                #address-cells = <3>;
                bus-range = <0x0 0xff>;
-               clock-frequency = <0x1fca055>;
+               clock-frequency = <33333333>;
                fsl,msi = <&msi2>;
                interrupts = <16 2 1 13>;
                pcie@0 {
index 69cae67..bbd113b 100644 (file)
                device_type = "memory";
        };
 
+       dcsr: dcsr@f00000000 {
+               ranges = <0x00000000 0xf 0x00000000 0x01008000>;
+       };
+
        soc: soc@ffe000000 {
                spi@110000 {
                        flash@0 {
                };
 
                board-control@3,0 {
-                       compatible = "fsl,p3041ds-pixis";
-                       reg = <3 0 0x20>;
+                       compatible = "fsl,p3041ds-fpga", "fsl,fpga-ngpixis";
+                       reg = <3 0 0x30>;
                };
        };
 
index 8b69580..87130b7 100644 (file)
@@ -42,6 +42,7 @@
 
        aliases {
                ccsr = &soc;
+               dcsr = &dcsr;
 
                serial0 = &serial0;
                serial1 = &serial1;
                };
        };
 
+       dcsr: dcsr@f00000000 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "fsl,dcsr", "simple-bus";
+
+               dcsr-epu@0 {
+                       compatible = "fsl,dcsr-epu";
+                       interrupts = <52 2 0 0
+                                     84 2 0 0
+                                     85 2 0 0>;
+                       interrupt-parent = <&mpic>;
+                       reg = <0x0 0x1000>;
+               };
+               dcsr-npc {
+                       compatible = "fsl,dcsr-npc";
+                       reg = <0x1000 0x1000 0x1000000 0x8000>;
+               };
+               dcsr-nxc@2000 {
+                       compatible = "fsl,dcsr-nxc";
+                       reg = <0x2000 0x1000>;
+               };
+               dcsr-corenet {
+                       compatible = "fsl,dcsr-corenet";
+                       reg = <0x8000 0x1000 0xB0000 0x1000>;
+               };
+               dcsr-dpaa@9000 {
+                       compatible = "fsl,p43041-dcsr-dpaa", "fsl,dcsr-dpaa";
+                       reg = <0x9000 0x1000>;
+               };
+               dcsr-ocn@11000 {
+                       compatible = "fsl,p43041-dcsr-ocn", "fsl,dcsr-ocn";
+                       reg = <0x11000 0x1000>;
+               };
+               dcsr-ddr@12000 {
+                       compatible = "fsl,dcsr-ddr";
+                       dev-handle = <&ddr>;
+                       reg = <0x12000 0x1000>;
+               };
+               dcsr-nal@18000 {
+                       compatible = "fsl,p43041-dcsr-nal", "fsl,dcsr-nal";
+                       reg = <0x18000 0x1000>;
+               };
+               dcsr-rcpm@22000 {
+                       compatible = "fsl,p43041-dcsr-rcpm", "fsl,dcsr-rcpm";
+                       reg = <0x22000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@40000 {
+                       compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu0>;
+                       reg = <0x40000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@41000 {
+                       compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu1>;
+                       reg = <0x41000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@42000 {
+                       compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu2>;
+                       reg = <0x42000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@43000 {
+                       compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu3>;
+                       reg = <0x43000 0x1000>;
+               };
+       };
+
        soc: soc@ffe000000 {
                #address-cells = <1>;
                #size-cells = <1>;
                        fsl,num-laws = <32>;
                };
 
-               memory-controller@8000 {
+               ddr: memory-controller@8000 {
                        compatible = "fsl,qoriq-memory-controller-v4.5", "fsl,qoriq-memory-controller";
                        reg = <0x8000 0x1000>;
                        interrupts = <16 2 1 23>;
diff --git a/arch/powerpc/boot/dts/p3060qds.dts b/arch/powerpc/boot/dts/p3060qds.dts
new file mode 100644 (file)
index 0000000..08b9193
--- /dev/null
@@ -0,0 +1,238 @@
+/*
+ * P3060QDS Device Tree Source
+ *
+ * Copyright 2011 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/include/ "p3060si.dtsi"
+
+/ {
+       model = "fsl,P3060QDS";
+       compatible = "fsl,P3060QDS";
+       #address-cells = <2>;
+       #size-cells = <2>;
+       interrupt-parent = <&mpic>;
+
+       memory {
+               device_type = "memory";
+       };
+
+       dcsr: dcsr@f00000000 {
+               ranges = <0x00000000 0xf 0x00000000 0x01008000>;
+       };
+
+       soc: soc@ffe000000 {
+               spi@110000 {
+                       flash@0 {
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               compatible = "spansion,s25sl12801";
+                               reg = <0>;
+                               spi-max-frequency = <40000000>; /* input clock */
+                               partition@u-boot {
+                                       label = "u-boot";
+                                       reg = <0x00000000 0x00100000>;
+                                       read-only;
+                               };
+                               partition@kernel {
+                                       label = "kernel";
+                                       reg = <0x00100000 0x00500000>;
+                                       read-only;
+                               };
+                               partition@dtb {
+                                       label = "dtb";
+                                       reg = <0x00600000 0x00100000>;
+                                       read-only;
+                               };
+                               partition@fs {
+                                       label = "file system";
+                                       reg = <0x00700000 0x00900000>;
+                               };
+                       };
+                       flash@1 {
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               compatible = "spansion,en25q32b";
+                               reg = <1>;
+                               spi-max-frequency = <40000000>; /* input clock */
+                               partition@spi1 {
+                                       label = "spi1";
+                                       reg = <0x00000000 0x00400000>;
+                               };
+                       };
+                       flash@2 {
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               compatible = "atmel,at45db081d";
+                               reg = <2>;
+                               spi-max-frequency = <40000000>; /* input clock */
+                               partition@spi1 {
+                                       label = "spi2";
+                                       reg = <0x00000000 0x00100000>;
+                               };
+                       };
+                       flash@3 {
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               compatible = "spansion,sst25wf040";
+                               reg = <3>;
+                               spi-max-frequency = <40000000>; /* input clock */
+                               partition@spi3 {
+                                       label = "spi3";
+                                       reg = <0x00000000 0x00080000>;
+                               };
+                       };
+               };
+
+               i2c@118000 {
+                       eeprom@51 {
+                               compatible = "at24,24c256";
+                               reg = <0x51>;
+                       };
+                       eeprom@53 {
+                               compatible = "at24,24c256";
+                               reg = <0x53>;
+                       };
+                       rtc@68 {
+                               compatible = "dallas,ds3232";
+                               reg = <0x68>;
+                               interrupts = <0x1 0x1 0 0>;
+                       };
+               };
+
+               usb0: usb@210000 {
+                       phy_type = "ulpi";
+               };
+
+               usb1: usb@211000 {
+                       dr_mode = "host";
+                       phy_type = "ulpi";
+               };
+       };
+
+       rapidio@ffe0c0000 {
+               reg = <0xf 0xfe0c0000 0 0x11000>;
+
+               port1 {
+                       ranges = <0 0 0xc 0x20000000 0 0x10000000>;
+               };
+               port2 {
+                       ranges = <0 0 0xc 0x30000000 0 0x10000000>;
+               };
+       };
+
+       localbus@ffe124000 {
+               reg = <0xf 0xfe124000 0 0x1000>;
+               ranges = <0 0 0xf 0xe8000000 0x08000000
+                         2 0 0xf 0xffa00000 0x00040000
+                         3 0 0xf 0xffdf0000 0x00008000>;
+
+               flash@0,0 {
+                       compatible = "cfi-flash";
+                       reg = <0 0 0x08000000>;
+                       bank-width = <2>;
+                       device-width = <2>;
+               };
+
+               nand@2,0 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       compatible = "fsl,elbc-fcm-nand";
+                       reg = <0x2 0x0 0x40000>;
+
+                       partition@0 {
+                               label = "NAND U-Boot Image";
+                               reg = <0x0 0x02000000>;
+                               read-only;
+                       };
+
+                       partition@2000000 {
+                               label = "NAND Root File System";
+                               reg = <0x02000000 0x10000000>;
+                       };
+
+                       partition@12000000 {
+                               label = "NAND Compressed RFS Image";
+                               reg = <0x12000000 0x08000000>;
+                       };
+
+                       partition@1a000000 {
+                               label = "NAND Linux Kernel Image";
+                               reg = <0x1a000000 0x04000000>;
+                       };
+
+                       partition@1e000000 {
+                               label = "NAND DTB Image";
+                               reg = <0x1e000000 0x01000000>;
+                       };
+
+                       partition@1f000000 {
+                               label = "NAND Writable User area";
+                               reg = <0x1f000000 0x21000000>;
+                       };
+               };
+
+               board-control@3,0 {
+                       compatible = "fsl,p3060qds-fpga", "fsl,fpga-qixis";
+                       reg = <3 0 0x100>;
+               };
+       };
+
+       pci0: pcie@ffe200000 {
+               reg = <0xf 0xfe200000 0 0x1000>;
+               ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000
+                         0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>;
+               pcie@0 {
+                       ranges = <0x02000000 0 0xe0000000
+                                 0x02000000 0 0xe0000000
+                                 0 0x20000000
+
+                                 0x01000000 0 0x00000000
+                                 0x01000000 0 0x00000000
+                                 0 0x00010000>;
+               };
+       };
+
+       pci1: pcie@ffe201000 {
+               reg = <0xf 0xfe201000 0 0x1000>;
+               ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000
+                         0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>;
+               pcie@0 {
+                       ranges = <0x02000000 0 0xe0000000
+                                 0x02000000 0 0xe0000000
+                                 0 0x20000000
+
+                                 0x01000000 0 0x00000000
+                                 0x01000000 0 0x00000000
+                                 0 0x00010000>;
+               };
+       };
+};
diff --git a/arch/powerpc/boot/dts/p3060si.dtsi b/arch/powerpc/boot/dts/p3060si.dtsi
new file mode 100644 (file)
index 0000000..68947e1
--- /dev/null
@@ -0,0 +1,719 @@
+/*
+ * P3060 Silicon Device Tree Source
+ *
+ * Copyright 2011 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/dts-v1/;
+
+/ {
+       compatible = "fsl,P3060";
+       #address-cells = <2>;
+       #size-cells = <2>;
+       interrupt-parent = <&mpic>;
+
+       aliases {
+               ccsr = &soc;
+               dcsr = &dcsr;
+
+               serial0 = &serial0;
+               serial1 = &serial1;
+               serial2 = &serial2;
+               serial3 = &serial3;
+               pci0 = &pci0;
+               pci1 = &pci1;
+               usb0 = &usb0;
+               usb1 = &usb1;
+               dma0 = &dma0;
+               dma1 = &dma1;
+               msi0 = &msi0;
+               msi1 = &msi1;
+               msi2 = &msi2;
+
+               crypto = &crypto;
+               sec_jr0 = &sec_jr0;
+               sec_jr1 = &sec_jr1;
+               sec_jr2 = &sec_jr2;
+               sec_jr3 = &sec_jr3;
+               rtic_a = &rtic_a;
+               rtic_b = &rtic_b;
+               rtic_c = &rtic_c;
+               rtic_d = &rtic_d;
+               sec_mon = &sec_mon;
+       };
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               cpu0: PowerPC,e500mc@0 {
+                       device_type = "cpu";
+                       reg = <0>;
+                       next-level-cache = <&L2_0>;
+                       L2_0: l2-cache {
+                               next-level-cache = <&cpc>;
+                       };
+               };
+               cpu1: PowerPC,e500mc@1 {
+                       device_type = "cpu";
+                       reg = <1>;
+                       next-level-cache = <&L2_1>;
+                       L2_1: l2-cache {
+                               next-level-cache = <&cpc>;
+                       };
+               };
+               cpu4: PowerPC,e500mc@4 {
+                       device_type = "cpu";
+                       reg = <4>;
+                       next-level-cache = <&L2_4>;
+                       L2_4: l2-cache {
+                               next-level-cache = <&cpc>;
+                       };
+               };
+               cpu5: PowerPC,e500mc@5 {
+                       device_type = "cpu";
+                       reg = <5>;
+                       next-level-cache = <&L2_5>;
+                       L2_5: l2-cache {
+                               next-level-cache = <&cpc>;
+                       };
+               };
+               cpu6: PowerPC,e500mc@6 {
+                       device_type = "cpu";
+                       reg = <6>;
+                       next-level-cache = <&L2_6>;
+                       L2_6: l2-cache {
+                               next-level-cache = <&cpc>;
+                       };
+               };
+               cpu7: PowerPC,e500mc@7 {
+                       device_type = "cpu";
+                       reg = <7>;
+                       next-level-cache = <&L2_7>;
+                       L2_7: l2-cache {
+                               next-level-cache = <&cpc>;
+                       };
+               };
+       };
+
+       dcsr: dcsr@f00000000 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "fsl,dcsr", "simple-bus";
+
+               dcsr-epu@0 {
+                       compatible = "fsl,dcsr-epu";
+                       interrupts = <52 2 0 0
+                                     84 2 0 0
+                                     85 2 0 0>;
+                       interrupt-parent = <&mpic>;
+                       reg = <0x0 0x1000>;
+               };
+               dcsr-npc {
+                       compatible = "fsl,dcsr-npc";
+                       reg = <0x1000 0x1000 0x1000000 0x8000>;
+               };
+               dcsr-nxc@2000 {
+                       compatible = "fsl,dcsr-nxc";
+                       reg = <0x2000 0x1000>;
+               };
+               dcsr-corenet {
+                       compatible = "fsl,dcsr-corenet";
+                       reg = <0x8000 0x1000 0xB0000 0x1000>;
+               };
+               dcsr-dpaa@9000 {
+                       compatible = "fsl,p3060-dcsr-dpaa", "fsl,dcsr-dpaa";
+                       reg = <0x9000 0x1000>;
+               };
+               dcsr-ocn@11000 {
+                       compatible = "fsl,p3060-dcsr-ocn", "fsl,dcsr-ocn";
+                       reg = <0x11000 0x1000>;
+               };
+               dcsr-ddr@12000 {
+                       compatible = "fsl,dcsr-ddr";
+                       dev-handle = <&ddr>;
+                       reg = <0x12000 0x1000>;
+               };
+               dcsr-nal@18000 {
+                       compatible = "fsl,p3060-dcsr-nal", "fsl,dcsr-nal";
+                       reg = <0x18000 0x1000>;
+               };
+               dcsr-rcpm@22000 {
+                       compatible = "fsl,p3060-dcsr-rcpm", "fsl,dcsr-rcpm";
+                       reg = <0x22000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@40000 {
+                       compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu0>;
+                       reg = <0x40000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@41000 {
+                       compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu1>;
+                       reg = <0x41000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@44000 {
+                       compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu4>;
+                       reg = <0x44000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@45000 {
+                       compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu5>;
+                       reg = <0x45000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@46000 {
+                       compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu6>;
+                       reg = <0x46000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@47000 {
+                       compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu7>;
+                       reg = <0x47000 0x1000>;
+               };
+       };
+
+       soc: soc@ffe000000 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               device_type = "soc";
+               compatible = "simple-bus";
+               ranges = <0x00000000 0xf 0xfe000000 0x1000000>;
+               reg = <0xf 0xfe000000 0 0x00001000>;
+
+               soc-sram-error {
+                       compatible = "fsl,soc-sram-error";
+                       interrupts = <16 2 1 29>;
+               };
+
+               corenet-law@0 {
+                       compatible = "fsl,corenet-law";
+                       reg = <0x0 0x1000>;
+                       fsl,num-laws = <32>;
+               };
+
+               ddr: memory-controller@8000 {
+                       compatible = "fsl,qoriq-memory-controller-v4.4", "fsl,qoriq-memory-controller";
+                       reg = <0x8000 0x1000>;
+                       interrupts = <16 2 1 23>;
+               };
+
+               cpc: l3-cache-controller@10000 {
+                       compatible = "fsl,p3060-l3-cache-controller", "cache";
+                       reg = <0x10000 0x1000
+                              0x11000 0x1000>;
+                       interrupts = <16 2 1 27>;
+               };
+
+               corenet-cf@18000 {
+                       compatible = "fsl,corenet-cf";
+                       reg = <0x18000 0x1000>;
+                       interrupts = <16 2 1 31>;
+                       fsl,ccf-num-csdids = <32>;
+                       fsl,ccf-num-snoopids = <32>;
+               };
+
+               iommu@20000 {
+                       compatible = "fsl,pamu-v1.0", "fsl,pamu";
+                       reg = <0x20000 0x5000>;
+                       interrupts = <
+                               24 2 0 0
+                               16 2 1 30>;
+               };
+
+               mpic: pic@40000 {
+                       clock-frequency = <0>;
+                       interrupt-controller;
+                       #address-cells = <0>;
+                       #interrupt-cells = <4>;
+                       reg = <0x40000 0x40000>;
+                       compatible = "fsl,mpic", "chrp,open-pic";
+                       device_type = "open-pic";
+               };
+
+               msi0: msi@41600 {
+                       compatible = "fsl,mpic-msi";
+                       reg = <0x41600 0x200>;
+                       msi-available-ranges = <0 0x100>;
+                       interrupts = <
+                               0xe0 0 0 0
+                               0xe1 0 0 0
+                               0xe2 0 0 0
+                               0xe3 0 0 0
+                               0xe4 0 0 0
+                               0xe5 0 0 0
+                               0xe6 0 0 0
+                               0xe7 0 0 0>;
+               };
+
+               msi1: msi@41800 {
+                       compatible = "fsl,mpic-msi";
+                       reg = <0x41800 0x200>;
+                       msi-available-ranges = <0 0x100>;
+                       interrupts = <
+                               0xe8 0 0 0
+                               0xe9 0 0 0
+                               0xea 0 0 0
+                               0xeb 0 0 0
+                               0xec 0 0 0
+                               0xed 0 0 0
+                               0xee 0 0 0
+                               0xef 0 0 0>;
+               };
+
+               msi2: msi@41a00 {
+                       compatible = "fsl,mpic-msi";
+                       reg = <0x41a00 0x200>;
+                       msi-available-ranges = <0 0x100>;
+                       interrupts = <
+                               0xf0 0 0 0
+                               0xf1 0 0 0
+                               0xf2 0 0 0
+                               0xf3 0 0 0
+                               0xf4 0 0 0
+                               0xf5 0 0 0
+                               0xf6 0 0 0
+                               0xf7 0 0 0>;
+               };
+
+               rmu: rmu@d3000 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       compatible = "fsl,srio-rmu";
+                       reg = <0xd3000 0x500>;
+                       ranges = <0x0 0xd3000 0x500>;
+
+                       message-unit@0 {
+                               compatible = "fsl,srio-msg-unit";
+                               reg = <0x0 0x100>;
+                               interrupts = <
+                                       60 2 0 0  /* msg1_tx_irq */
+                                       61 2 0 0>;/* msg1_rx_irq */
+                       };
+                       message-unit@100 {
+                               compatible = "fsl,srio-msg-unit";
+                               reg = <0x100 0x100>;
+                               interrupts = <
+                                       62 2 0 0  /* msg2_tx_irq */
+                                       63 2 0 0>;/* msg2_rx_irq */
+                       };
+                       doorbell-unit@400 {
+                               compatible = "fsl,srio-dbell-unit";
+                               reg = <0x400 0x80>;
+                               interrupts = <
+                                       56 2 0 0  /* bell_outb_irq */
+                                       57 2 0 0>;/* bell_inb_irq */
+                       };
+                       port-write-unit@4e0 {
+                               compatible = "fsl,srio-port-write-unit";
+                               reg = <0x4e0 0x20>;
+                               interrupts = <16 2 1 11>;
+                       };
+               };
+
+               guts: global-utilities@e0000 {
+                       compatible = "fsl,qoriq-device-config-1.0";
+                       reg = <0xe0000 0xe00>;
+                       fsl,has-rstcr;
+                       #sleep-cells = <1>;
+                       fsl,liodn-bits = <12>;
+               };
+
+               pins: global-utilities@e0e00 {
+                       compatible = "fsl,qoriq-pin-control-1.0";
+                       reg = <0xe0e00 0x200>;
+                       #sleep-cells = <2>;
+               };
+
+               clockgen: global-utilities@e1000 {
+                       compatible = "fsl,p3060-clockgen", "fsl,qoriq-clockgen-1.0";
+                       reg = <0xe1000 0x1000>;
+                       clock-frequency = <0>;
+               };
+
+               rcpm: global-utilities@e2000 {
+                       compatible = "fsl,qoriq-rcpm-1.0";
+                       reg = <0xe2000 0x1000>;
+                       #sleep-cells = <1>;
+               };
+
+               sfp: sfp@e8000 {
+                       compatible = "fsl,p3060-sfp", "fsl,qoriq-sfp-1.0";
+                       reg        = <0xe8000 0x1000>;
+               };
+
+               serdes: serdes@ea000 {
+                       compatible = "fsl,p3060-serdes";
+                       reg        = <0xea000 0x1000>;
+               };
+
+               dma0: dma@100300 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       compatible = "fsl,p3060-dma", "fsl,eloplus-dma";
+                       reg = <0x100300 0x4>;
+                       ranges = <0x0 0x100100 0x200>;
+                       cell-index = <0>;
+                       dma-channel@0 {
+                               compatible = "fsl,p3060-dma-channel",
+                                               "fsl,eloplus-dma-channel";
+                               reg = <0x0 0x80>;
+                               cell-index = <0>;
+                               interrupts = <28 2 0 0>;
+                       };
+                       dma-channel@80 {
+                               compatible = "fsl,p3060-dma-channel",
+                                               "fsl,eloplus-dma-channel";
+                               reg = <0x80 0x80>;
+                               cell-index = <1>;
+                               interrupts = <29 2 0 0>;
+                       };
+                       dma-channel@100 {
+                               compatible = "fsl,p3060-dma-channel",
+                                               "fsl,eloplus-dma-channel";
+                               reg = <0x100 0x80>;
+                               cell-index = <2>;
+                               interrupts = <30 2 0 0>;
+                       };
+                       dma-channel@180 {
+                               compatible = "fsl,p3060-dma-channel",
+                                               "fsl,eloplus-dma-channel";
+                               reg = <0x180 0x80>;
+                               cell-index = <3>;
+                               interrupts = <31 2 0 0>;
+                       };
+               };
+
+               dma1: dma@101300 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       compatible = "fsl,p3060-dma", "fsl,eloplus-dma";
+                       reg = <0x101300 0x4>;
+                       ranges = <0x0 0x101100 0x200>;
+                       cell-index = <1>;
+                       dma-channel@0 {
+                               compatible = "fsl,p3060-dma-channel",
+                                               "fsl,eloplus-dma-channel";
+                               reg = <0x0 0x80>;
+                               cell-index = <0>;
+                               interrupts = <32 2 0 0>;
+                       };
+                       dma-channel@80 {
+                               compatible = "fsl,p3060-dma-channel",
+                                               "fsl,eloplus-dma-channel";
+                               reg = <0x80 0x80>;
+                               cell-index = <1>;
+                               interrupts = <33 2 0 0>;
+                       };
+                       dma-channel@100 {
+                               compatible = "fsl,p3060-dma-channel",
+                                               "fsl,eloplus-dma-channel";
+                               reg = <0x100 0x80>;
+                               cell-index = <2>;
+                               interrupts = <34 2 0 0>;
+                       };
+                       dma-channel@180 {
+                               compatible = "fsl,p3060-dma-channel",
+                                               "fsl,eloplus-dma-channel";
+                               reg = <0x180 0x80>;
+                               cell-index = <3>;
+                               interrupts = <35 2 0 0>;
+                       };
+               };
+
+               spi@110000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "fsl,p3060-espi", "fsl,mpc8536-espi";
+                       reg = <0x110000 0x1000>;
+                       interrupts = <53 0x2 0 0>;
+                       fsl,espi-num-chipselects = <4>;
+               };
+
+               i2c@118000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       cell-index = <0>;
+                       compatible = "fsl-i2c";
+                       reg = <0x118000 0x100>;
+                       interrupts = <38 2 0 0>;
+                       dfsrr;
+               };
+
+               i2c@118100 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       cell-index = <1>;
+                       compatible = "fsl-i2c";
+                       reg = <0x118100 0x100>;
+                       interrupts = <38 2 0 0>;
+                       dfsrr;
+               };
+
+               i2c@119000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       cell-index = <2>;
+                       compatible = "fsl-i2c";
+                       reg = <0x119000 0x100>;
+                       interrupts = <39 2 0 0>;
+                       dfsrr;
+               };
+
+               i2c@119100 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       cell-index = <3>;
+                       compatible = "fsl-i2c";
+                       reg = <0x119100 0x100>;
+                       interrupts = <39 2 0 0>;
+                       dfsrr;
+               };
+
+               serial0: serial@11c500 {
+                       cell-index = <0>;
+                       device_type = "serial";
+                       compatible = "ns16550";
+                       reg = <0x11c500 0x100>;
+                       clock-frequency = <0>;
+                       interrupts = <36 2 0 0>;
+               };
+
+               serial1: serial@11c600 {
+                       cell-index = <1>;
+                       device_type = "serial";
+                       compatible = "ns16550";
+                       reg = <0x11c600 0x100>;
+                       clock-frequency = <0>;
+                       interrupts = <36 2 0 0>;
+               };
+
+               serial2: serial@11d500 {
+                       cell-index = <2>;
+                       device_type = "serial";
+                       compatible = "ns16550";
+                       reg = <0x11d500 0x100>;
+                       clock-frequency = <0>;
+                       interrupts = <37 2 0 0>;
+               };
+
+               serial3: serial@11d600 {
+                       cell-index = <3>;
+                       device_type = "serial";
+                       compatible = "ns16550";
+                       reg = <0x11d600 0x100>;
+                       clock-frequency = <0>;
+                       interrupts = <37 2 0 0>;
+               };
+
+               gpio0: gpio@130000 {
+                       compatible = "fsl,p3060-gpio", "fsl,qoriq-gpio";
+                       reg = <0x130000 0x1000>;
+                       interrupts = <55 2 0 0>;
+                       #gpio-cells = <2>;
+                       gpio-controller;
+               };
+
+               usb0: usb@210000 {
+                       compatible = "fsl,p3060-usb2-mph",
+                                       "fsl,mpc85xx-usb2-mph", "fsl-usb2-mph";
+                       reg = <0x210000 0x1000>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       interrupts = <44 0x2 0 0>;
+               };
+
+               usb1: usb@211000 {
+                       compatible = "fsl,p3060-usb2-dr",
+                                       "fsl,mpc85xx-usb2-dr", "fsl-usb2-dr";
+                       reg = <0x211000 0x1000>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       interrupts = <45 0x2 0 0>;
+               };
+
+               crypto: crypto@300000 {
+                       compatible = "fsl,sec-v4.1", "fsl,sec-v4.0";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       reg = <0x300000 0x10000>;
+                       ranges = <0 0x300000 0x10000>;
+                       interrupt-parent = <&mpic>;
+                       interrupts = <92 2 0 0>;
+
+                       sec_jr0: jr@1000 {
+                               compatible = "fsl,sec-v4.1-job-ring", "fsl,sec-v4.0-job-ring";
+                               reg = <0x1000 0x1000>;
+                               interrupt-parent = <&mpic>;
+                               interrupts = <88 2 0 0>;
+                       };
+
+                       sec_jr1: jr@2000 {
+                               compatible = "fsl,sec-v4.1-job-ring", "fsl,sec-v4.0-job-ring";
+                               reg = <0x2000 0x1000>;
+                               interrupt-parent = <&mpic>;
+                               interrupts = <89 2 0 0>;
+                       };
+
+                       sec_jr2: jr@3000 {
+                               compatible = "fsl,sec-v4.1-job-ring", "fsl,sec-v4.0-job-ring";
+                               reg = <0x3000 0x1000>;
+                               interrupt-parent = <&mpic>;
+                               interrupts = <90 2 0 0>;
+                       };
+
+                       sec_jr3: jr@4000 {
+                               compatible = "fsl,sec-v4.1-job-ring", "fsl,sec-v4.0-job-ring";
+                               reg = <0x4000 0x1000>;
+                               interrupt-parent = <&mpic>;
+                               interrupts = <91 2 0 0>;
+                       };
+
+                       rtic@6000 {
+                               compatible = "fsl,sec-v4.1-rtic", "fsl,sec-v4.0-rtic";
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               reg = <0x6000 0x100>;
+                               ranges = <0x0 0x6100 0xe00>;
+
+                               rtic_a: rtic-a@0 {
+                                       compatible = "fsl,sec-v4.1-rtic-memory", "fsl,sec-v4.0-rtic-memory";
+                                       reg = <0x00 0x20 0x100 0x80>;
+                               };
+
+                               rtic_b: rtic-b@20 {
+                                       compatible = "fsl,sec-v4.1-rtic-memory", "fsl,sec-v4.0-rtic-memory";
+                                       reg = <0x20 0x20 0x200 0x80>;
+                               };
+
+                               rtic_c: rtic-c@40 {
+                                       compatible = "fsl,sec-v4.1-rtic-memory", "fsl,sec-v4.0-rtic-memory";
+                                       reg = <0x40 0x20 0x300 0x80>;
+                               };
+
+                               rtic_d: rtic-d@60 {
+                                       compatible = "fsl,sec-v4.1-rtic-memory", "fsl,sec-v4.0-rtic-memory";
+                                       reg = <0x60 0x20 0x500 0x80>;
+                               };
+                       };
+               };
+
+               sec_mon: sec_mon@314000 {
+                       compatible = "fsl,sec-v4.1-mon", "fsl,sec-v4.0-mon";
+                       reg = <0x314000 0x1000>;
+                       interrupt-parent = <&mpic>;
+                       interrupts = <93 2 0 0>;
+               };
+       };
+
+       rapidio@ffe0c0000 {
+               compatible = "fsl,srio";
+               interrupts = <16 2 1 11>;
+               #address-cells = <2>;
+               #size-cells = <2>;
+               fsl,srio-rmu-handle = <&rmu>;
+               ranges;
+
+               port1 {
+                       #address-cells = <2>;
+                       #size-cells = <2>;
+                       cell-index = <1>;
+               };
+
+               port2 {
+                       #address-cells = <2>;
+                       #size-cells = <2>;
+                       cell-index = <2>;
+               };
+       };
+
+       localbus@ffe124000 {
+               compatible = "fsl,p3060-elbc", "fsl,elbc", "simple-bus";
+               interrupts = <25 2 0 0>;
+               #address-cells = <2>;
+               #size-cells = <1>;
+       };
+
+       pci0: pcie@ffe200000 {
+               compatible = "fsl,p3060-pcie", "fsl,qoriq-pcie-v2.2";
+               device_type = "pci";
+               #size-cells = <2>;
+               #address-cells = <3>;
+               bus-range = <0x0 0xff>;
+               clock-frequency = <33333333>;
+               fsl,msi = <&msi0>;
+               interrupts = <16 2 1 15>;
+               pcie@0 {
+                       reg = <0 0 0 0 0>;
+                       #interrupt-cells = <1>;
+                       #size-cells = <2>;
+                       #address-cells = <3>;
+                       device_type = "pci";
+                       interrupts = <16 2 1 15>;
+                       interrupt-map-mask = <0xf800 0 0 7>;
+                       interrupt-map = <
+                               /* IDSEL 0x0 */
+                               0000 0 0 1 &mpic 40 1 0 0
+                               0000 0 0 2 &mpic 1 1 0 0
+                               0000 0 0 3 &mpic 2 1 0 0
+                               0000 0 0 4 &mpic 3 1 0 0
+                               >;
+               };
+       };
+
+       pci1: pcie@ffe201000 {
+               compatible = "fsl,p3060-pcie", "fsl,qoriq-pcie-v2.2";
+               device_type = "pci";
+               #size-cells = <2>;
+               #address-cells = <3>;
+               bus-range = <0 0xff>;
+               clock-frequency = <33333333>;
+               fsl,msi = <&msi1>;
+               interrupts = <16 2 1 14>;
+               pcie@0 {
+                       reg = <0 0 0 0 0>;
+                       #interrupt-cells = <1>;
+                       #size-cells = <2>;
+                       #address-cells = <3>;
+                       device_type = "pci";
+                       interrupts = <16 2 1 14>;
+                       interrupt-map-mask = <0xf800 0 0 7>;
+                       interrupt-map = <
+                               /* IDSEL 0x0 */
+                               0000 0 0 1 &mpic 41 1 0 0
+                               0000 0 0 2 &mpic 5 1 0 0
+                               0000 0 0 3 &mpic 6 1 0 0
+                               0000 0 0 4 &mpic 7 1 0 0
+                               >;
+               };
+       };
+};
index eb11098..c7916dc 100644 (file)
                device_type = "memory";
        };
 
+       dcsr: dcsr@f00000000 {
+               ranges = <0x00000000 0xf 0x00000000 0x01008000>;
+       };
+
        soc: soc@ffe000000 {
                spi@110000 {
                        flash@0 {
 
        localbus@ffe124000 {
                reg = <0xf 0xfe124000 0 0x1000>;
-               ranges = <0 0 0xf 0xe8000000 0x08000000>;
+               ranges = <0 0 0xf 0xe8000000 0x08000000
+                         3 0 0xf 0xffdf0000 0x00008000>;
 
                flash@0,0 {
                        compatible = "cfi-flash";
                        bank-width = <2>;
                        device-width = <2>;
                };
+
+               board-control@3,0 {
+                       compatible = "fsl,p4080ds-fpga", "fsl,fpga-ngpixis";
+                       reg = <3 0 0x30>;
+               };
        };
 
        pci0: pcie@ffe200000 {
index b71051f..f20c01a 100644 (file)
@@ -42,6 +42,7 @@
 
        aliases {
                ccsr = &soc;
+               dcsr = &dcsr;
 
                serial0 = &serial0;
                serial1 = &serial1;
@@ -77,7 +78,7 @@
                #address-cells = <1>;
                #size-cells = <0>;
 
-               cpu0: PowerPC,4080@0 {
+               cpu0: PowerPC,e500mc@0 {
                        device_type = "cpu";
                        reg = <0>;
                        next-level-cache = <&L2_0>;
@@ -85,7 +86,7 @@
                                next-level-cache = <&cpc>;
                        };
                };
-               cpu1: PowerPC,4080@1 {
+               cpu1: PowerPC,e500mc@1 {
                        device_type = "cpu";
                        reg = <1>;
                        next-level-cache = <&L2_1>;
@@ -93,7 +94,7 @@
                                next-level-cache = <&cpc>;
                        };
                };
-               cpu2: PowerPC,4080@2 {
+               cpu2: PowerPC,e500mc@2 {
                        device_type = "cpu";
                        reg = <2>;
                        next-level-cache = <&L2_2>;
                                next-level-cache = <&cpc>;
                        };
                };
-               cpu3: PowerPC,4080@3 {
+               cpu3: PowerPC,e500mc@3 {
                        device_type = "cpu";
                        reg = <3>;
                        next-level-cache = <&L2_3>;
                                next-level-cache = <&cpc>;
                        };
                };
-               cpu4: PowerPC,4080@4 {
+               cpu4: PowerPC,e500mc@4 {
                        device_type = "cpu";
                        reg = <4>;
                        next-level-cache = <&L2_4>;
                                next-level-cache = <&cpc>;
                        };
                };
-               cpu5: PowerPC,4080@5 {
+               cpu5: PowerPC,e500mc@5 {
                        device_type = "cpu";
                        reg = <5>;
                        next-level-cache = <&L2_5>;
                                next-level-cache = <&cpc>;
                        };
                };
-               cpu6: PowerPC,4080@6 {
+               cpu6: PowerPC,e500mc@6 {
                        device_type = "cpu";
                        reg = <6>;
                        next-level-cache = <&L2_6>;
                                next-level-cache = <&cpc>;
                        };
                };
-               cpu7: PowerPC,4080@7 {
+               cpu7: PowerPC,e500mc@7 {
                        device_type = "cpu";
                        reg = <7>;
                        next-level-cache = <&L2_7>;
                };
        };
 
+       dcsr: dcsr@f00000000 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "fsl,dcsr", "simple-bus";
+
+               dcsr-epu@0 {
+                       compatible = "fsl,dcsr-epu";
+                       interrupts = <52 2 0 0
+                                     84 2 0 0
+                                     85 2 0 0>;
+                       interrupt-parent = <&mpic>;
+                       reg = <0x0 0x1000>;
+               };
+               dcsr-npc {
+                       compatible = "fsl,dcsr-npc";
+                       reg = <0x1000 0x1000 0x1000000 0x8000>;
+               };
+               dcsr-nxc@2000 {
+                       compatible = "fsl,dcsr-nxc";
+                       reg = <0x2000 0x1000>;
+               };
+               dcsr-corenet {
+                       compatible = "fsl,dcsr-corenet";
+                       reg = <0x8000 0x1000 0xB0000 0x1000>;
+               };
+               dcsr-dpaa@9000 {
+                       compatible = "fsl,p4080-dcsr-dpaa", "fsl,dcsr-dpaa";
+                       reg = <0x9000 0x1000>;
+               };
+               dcsr-ocn@11000 {
+                       compatible = "fsl,p4080-dcsr-ocn", "fsl,dcsr-ocn";
+                       reg = <0x11000 0x1000>;
+               };
+               dcsr-ddr@12000 {
+                       compatible = "fsl,dcsr-ddr";
+                       dev-handle = <&ddr1>;
+                       reg = <0x12000 0x1000>;
+               };
+               dcsr-ddr@13000 {
+                       compatible = "fsl,dcsr-ddr";
+                       dev-handle = <&ddr2>;
+                       reg = <0x13000 0x1000>;
+               };
+               dcsr-nal@18000 {
+                       compatible = "fsl,p4080-dcsr-nal", "fsl,dcsr-nal";
+                       reg = <0x18000 0x1000>;
+               };
+               dcsr-rcpm@22000 {
+                       compatible = "fsl,p4080-dcsr-rcpm", "fsl,dcsr-rcpm";
+                       reg = <0x22000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@40000 {
+                       compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu0>;
+                       reg = <0x40000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@41000 {
+                       compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu1>;
+                       reg = <0x41000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@42000 {
+                       compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu2>;
+                       reg = <0x42000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@43000 {
+                       compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu3>;
+                       reg = <0x43000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@44000 {
+                       compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu4>;
+                       reg = <0x44000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@45000 {
+                       compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu5>;
+                       reg = <0x45000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@46000 {
+                       compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu6>;
+                       reg = <0x46000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@47000 {
+                       compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu7>;
+                       reg = <0x47000 0x1000>;
+               };
+       };
+
        soc: soc@ffe000000 {
                #address-cells = <1>;
                #size-cells = <1>;
                        fsl,num-laws = <32>;
                };
 
-               memory-controller@8000 {
+               ddr1: memory-controller@8000 {
                        compatible = "fsl,qoriq-memory-controller-v4.4", "fsl,qoriq-memory-controller";
                        reg = <0x8000 0x1000>;
                        interrupts = <16 2 1 23>;
                };
 
-               memory-controller@9000 {
+               ddr2: memory-controller@9000 {
                        compatible = "fsl,qoriq-memory-controller-v4.4","fsl,qoriq-memory-controller";
                        reg = <0x9000 0x1000>;
                        interrupts = <16 2 1 22>;
index 8366e2f..e6d4099 100644 (file)
                device_type = "memory";
        };
 
+       dcsr: dcsr@f00000000 {
+               ranges = <0x00000000 0xf 0x00000000 0x01008000>;
+       };
+
        soc: soc@ffe000000 {
                spi@110000 {
                        flash@0 {
                };
 
                board-control@3,0 {
-                       compatible = "fsl,p5020ds-pixis";
-                       reg = <3 0 0x20>;
+                       compatible = "fsl,p5020ds-fpga", "fsl,fpga-ngpixis";
+                       reg = <3 0 0x30>;
                };
        };
 
index 5e6048e..e7948ad 100644 (file)
@@ -42,6 +42,7 @@
 
        aliases {
                ccsr = &soc;
+               dcsr = &dcsr;
 
                serial0 = &serial0;
                serial1 = &serial1;
                };
        };
 
+       dcsr: dcsr@f00000000 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "fsl,dcsr", "simple-bus";
+
+               dcsr-epu@0 {
+                       compatible = "fsl,dcsr-epu";
+                       interrupts = <52 2 0 0
+                                     84 2 0 0
+                                     85 2 0 0>;
+                       interrupt-parent = <&mpic>;
+                       reg = <0x0 0x1000>;
+               };
+               dcsr-npc {
+                       compatible = "fsl,dcsr-npc";
+                       reg = <0x1000 0x1000 0x1000000 0x8000>;
+               };
+               dcsr-nxc@2000 {
+                       compatible = "fsl,dcsr-nxc";
+                       reg = <0x2000 0x1000>;
+               };
+               dcsr-corenet {
+                       compatible = "fsl,dcsr-corenet";
+                       reg = <0x8000 0x1000 0xB0000 0x1000>;
+               };
+               dcsr-dpaa@9000 {
+                       compatible = "fsl,p5020-dcsr-dpaa", "fsl,dcsr-dpaa";
+                       reg = <0x9000 0x1000>;
+               };
+               dcsr-ocn@11000 {
+                       compatible = "fsl,p5020-dcsr-ocn", "fsl,dcsr-ocn";
+                       reg = <0x11000 0x1000>;
+               };
+               dcsr-ddr@12000 {
+                       compatible = "fsl,dcsr-ddr";
+                       dev-handle = <&ddr1>;
+                       reg = <0x12000 0x1000>;
+               };
+               dcsr-ddr@13000 {
+                       compatible = "fsl,dcsr-ddr";
+                       dev-handle = <&ddr2>;
+                       reg = <0x13000 0x1000>;
+               };
+               dcsr-nal@18000 {
+                       compatible = "fsl,p5020-dcsr-nal", "fsl,dcsr-nal";
+                       reg = <0x18000 0x1000>;
+               };
+               dcsr-rcpm@22000 {
+                       compatible = "fsl,p5020-dcsr-rcpm", "fsl,dcsr-rcpm";
+                       reg = <0x22000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@40000 {
+                       compatible = "fsl,dcsr-e5500-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu0>;
+                       reg = <0x40000 0x1000>;
+               };
+               dcsr-cpu-sb-proxy@41000 {
+                       compatible = "fsl,dcsr-e5500-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+                       cpu-handle = <&cpu1>;
+                       reg = <0x41000 0x1000>;
+               };
+       };
+
        soc: soc@ffe000000 {
                #address-cells = <1>;
                #size-cells = <1>;
                        fsl,num-laws = <32>;
                };
 
-               memory-controller@8000 {
+               ddr1: memory-controller@8000 {
                        compatible = "fsl,qoriq-memory-controller-v4.5", "fsl,qoriq-memory-controller";
                        reg = <0x8000 0x1000>;
                        interrupts = <16 2 1 23>;
                };
 
-               memory-controller@9000 {
+               ddr2: memory-controller@9000 {
                        compatible = "fsl,qoriq-memory-controller-v4.5", "fsl,qoriq-memory-controller";
                        reg = <0x9000 0x1000>;
                        interrupts = <16 2 1 22>;
index 9e13ed8..72078eb 100644 (file)
        };
 
        localbus@ff705000 {
-               compatible = "fsl,mpc8560-localbus";
+               compatible = "fsl,mpc8560-localbus", "simple-bus";
                #address-cells = <2>;
                #size-cells = <1>;
                reg = <0xff705000 0x100>;       // BRx, ORx, etc.
index 6492324..30bb475 100644 (file)
                                clock-frequency = <0>; /* Filled in by zImage */
                                interrupts = <0x5 0x1>;
                                interrupt-parent = <&UIC1>;
+
+                               nor_flash@0,0 {
+                                       compatible = "amd,s29gl256n", "cfi-flash";
+                                       bank-width = <2>;
+                                       reg = <0x00000000 0x00000000 0x04000000>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+                                       partition@0 {
+                                               label = "kernel";
+                                               reg = <0x00000000 0x001e0000>;
+                                       };
+                                       partition@1e0000 {
+                                               label = "dtb";
+                                               reg = <0x001e0000 0x00020000>;
+                                       };
+                                       partition@200000 {
+                                               label = "ramdisk";
+                                               reg = <0x00200000 0x01400000>;
+                                       };
+                                       partition@1600000 {
+                                               label = "jffs2";
+                                               reg = <0x01600000 0x00400000>;
+                                       };
+                                       partition@1a00000 {
+                                               label = "user";
+                                               reg = <0x01a00000 0x02540000>;
+                                       };
+                                       partition@3f40000 {
+                                               label = "env";
+                                               reg = <0x03f40000 0x00040000>;
+                                       };
+                                       partition@3f80000 {
+                                               label = "u-boot";
+                                               reg = <0x03f80000 0x00080000>;
+                                       };
+                               };
                        };
 
                        UART0: serial@ef600300 {
diff --git a/arch/powerpc/configs/40x/hcu4_defconfig b/arch/powerpc/configs/40x/hcu4_defconfig
deleted file mode 100644 (file)
index dba263c..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-CONFIG_40x=y
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EXPERT=y
-CONFIG_KALLSYMS_ALL=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_HCU4=y
-# CONFIG_WALNUT is not set
-CONFIG_SPARSE_IRQ=y
-CONFIG_PCI=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_IPV6 is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_CONNECTOR=y
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_OF_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=m
-CONFIG_MTD_CFI=y
-CONFIG_MTD_JEDECPROBE=y
-CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_PHYSMAP_OF=y
-CONFIG_PROC_DEVICETREE=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=35000
-CONFIG_NETDEVICES=y
-CONFIG_ETHERNET=y
-CONFIG_NET_VENDOR_IBM=y
-CONFIG_IBM_EMAC=y
-# CONFIG_INPUT is not set
-# CONFIG_SERIO is not set
-# CONFIG_VT is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_EXTENDED=y
-CONFIG_SERIAL_8250_SHARE_IRQ=y
-CONFIG_SERIAL_OF_PLATFORM=y
-# CONFIG_HW_RANDOM is not set
-# CONFIG_HWMON is not set
-CONFIG_VIDEO_OUTPUT_CONTROL=m
-# CONFIG_USB_SUPPORT is not set
-CONFIG_EXT2_FS=y
-CONFIG_INOTIFY=y
-CONFIG_PROC_KCORE=y
-CONFIG_TMPFS=y
-CONFIG_CRAMFS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_ROOT_NFS=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DETECT_HUNG_TASK=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_CBC=y
-CONFIG_CRYPTO_ECB=y
-CONFIG_CRYPTO_PCBC=y
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_DES=y
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
index 3ff5a81..c091aaf 100644 (file)
@@ -24,7 +24,7 @@ CONFIG_P1023_RDS=y
 CONFIG_QUICC_ENGINE=y
 CONFIG_QE_GPIO=y
 CONFIG_CPM2=y
-CONFIG_MPC8xxx_GPIO=y
+CONFIG_GPIO_MPC8XXX=y
 CONFIG_HIGHMEM=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
index 5ea3124..1cd6fcb 100644 (file)
@@ -20,7 +20,7 @@ CONFIG_MODULE_FORCE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 # CONFIG_BLK_DEV_BSG is not set
 CONFIG_XES_MPC85xx=y
-CONFIG_MPC8xxx_GPIO=y
+CONFIG_GPIO_MPC8XXX=y
 CONFIG_HIGHMEM=y
 CONFIG_MATH_EMULATION=y
 CONFIG_SPARSE_IRQ=y
index 4311d02..f087de6 100644 (file)
@@ -12,9 +12,7 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_KALLSYMS_ALL=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
 CONFIG_EMBEDDED=y
 CONFIG_PERF_EVENTS=y
 CONFIG_SLAB=y
@@ -23,8 +21,9 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 # CONFIG_BLK_DEV_BSG is not set
-CONFIG_P2040_RDB=y
+CONFIG_P2041_RDB=y
 CONFIG_P3041_DS=y
+CONFIG_P3060_QDS=y
 CONFIG_P4080_DS=y
 CONFIG_P5020_DS=y
 CONFIG_HIGHMEM=y
@@ -69,7 +68,6 @@ CONFIG_IPV6=y
 CONFIG_IP_SCTP=m
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
@@ -107,7 +105,6 @@ CONFIG_FSL_PQ_MDIO=y
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_SERIO_LIBPS2=y
 # CONFIG_LEGACY_PTYS is not set
-CONFIG_PPC_EPAPR_HV_BYTECHAN=y
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_EXTENDED=y
@@ -136,8 +133,6 @@ CONFIG_USB_OHCI_HCD_PPC_OF_LE=y
 CONFIG_USB_STORAGE=y
 CONFIG_MMC=y
 CONFIG_MMC_SDHCI=y
-CONFIG_MMC_SDHCI_OF=y
-CONFIG_MMC_SDHCI_OF_ESDHC=y
 CONFIG_EDAC=y
 CONFIG_EDAC_MM_EDAC=y
 CONFIG_EDAC_MPC85XX=y
@@ -146,7 +141,6 @@ CONFIG_RTC_DRV_DS3232=y
 CONFIG_RTC_DRV_CMOS=y
 CONFIG_UIO=y
 CONFIG_STAGING=y
-# CONFIG_STAGING_EXCLUDE_BUILD is not set
 CONFIG_VIRT_DRIVERS=y
 CONFIG_FSL_HV_MANAGER=y
 CONFIG_EXT2_FS=y
@@ -173,7 +167,6 @@ CONFIG_MAC_PARTITION=y
 CONFIG_NLS_ISO8859_1=y
 CONFIG_NLS_UTF8=m
 CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_KERNEL=y
 CONFIG_DEBUG_SHIRQ=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_DEBUG_INFO=y
index c92c204..782822c 100644 (file)
@@ -11,10 +11,8 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EXPERT=y
 CONFIG_KALLSYMS_ALL=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
@@ -25,7 +23,6 @@ CONFIG_P5020_DS=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_BINFMT_MISC=m
-# CONFIG_PCI is not set
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -93,10 +90,8 @@ CONFIG_CRC_T10DIF=y
 CONFIG_CRC_ITU_T=m
 CONFIG_FRAME_WARN=1024
 CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 CONFIG_SYSCTL_SYSCALL_CHECK=y
 CONFIG_VIRQ_DEBUG=y
 CONFIG_CRYPTO_PCBC=m
index 6cb588a..0d36b0e 100644 (file)
@@ -1,15 +1,22 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
 CONFIG_SPARSE_IRQ=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_EXPERT=y
+# CONFIG_RD_GZIP is not set
 CONFIG_KALLSYMS_ALL=y
+# CONFIG_PCSPKR_PLATFORM is not set
+CONFIG_EMBEDDED=y
 CONFIG_SLAB=y
 # CONFIG_IOSCHED_CFQ is not set
+# CONFIG_PPC_PMAC is not set
 CONFIG_PPC_82xx=y
 CONFIG_MGCOGE=y
+CONFIG_HIGH_RES_TIMERS=y
 CONFIG_BINFMT_MISC=y
 # CONFIG_SECCOMP is not set
 CONFIG_NET=y
@@ -24,11 +31,10 @@ CONFIG_SYN_COOKIES=y
 # CONFIG_INET_LRO is not set
 # CONFIG_IPV6 is not set
 CONFIG_NETFILTER=y
+CONFIG_TIPC=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_CONCAT=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLKDEVS=y
@@ -42,7 +48,6 @@ CONFIG_MTD_PHYSMAP_OF=y
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
-# CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
 CONFIG_FIXED_PHY=y
 CONFIG_NET_ETHERNET=y
@@ -50,6 +55,7 @@ CONFIG_FS_ENET=y
 CONFIG_FS_ENET_MDIO_FCC=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
@@ -57,24 +63,24 @@ CONFIG_SERIAL_CPM=y
 CONFIG_SERIAL_CPM_CONSOLE=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
-# CONFIG_I2C_POWERMAC is not set
 CONFIG_I2C_CPM=y
 # CONFIG_HWMON is not set
-# CONFIG_USB_SUPPORT is not set
+CONFIG_USB_GADGET=y
+CONFIG_USB_FSL_USB2=y
+CONFIG_USB_G_SERIAL=y
+CONFIG_UIO=y
+CONFIG_UIO_PDRV=y
 CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-# CONFIG_EXT3_FS_XATTR is not set
 CONFIG_AUTOFS4_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
 CONFIG_JFFS2_FS=y
 CONFIG_CRAMFS=y
+CONFIG_SQUASHFS=y
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 CONFIG_ROOT_NFS=y
 CONFIG_PARTITION_ADVANCED=y
-# CONFIG_MAC_PARTITION is not set
 CONFIG_NLS=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ASCII=y
@@ -82,7 +88,6 @@ CONFIG_NLS_ISO8859_1=y
 CONFIG_NLS_UTF8=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
 # CONFIG_SCHED_DEBUG is not set
 CONFIG_DEBUG_INFO=y
 CONFIG_SYSCTL_SYSCALL_CHECK=y
index c02bbb2..211fcc9 100644 (file)
@@ -1,9 +1,9 @@
 CONFIG_EXPERIMENTAL=y
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
+CONFIG_SPARSE_IRQ=y
 CONFIG_LOG_BUF_SHIFT=16
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 # CONFIG_COMPAT_BRK is not set
 CONFIG_SLAB=y
 CONFIG_MODULES=y
@@ -13,10 +13,11 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_PPC_CHRP is not set
 CONFIG_PPC_MPC512x=y
 CONFIG_MPC5121_ADS=y
+CONFIG_MPC5121_GENERIC=y
+CONFIG_PDM360NG=y
 # CONFIG_PPC_PMAC is not set
 CONFIG_NO_HZ=y
 CONFIG_HZ_1000=y
-CONFIG_SPARSE_IRQ=y
 # CONFIG_MIGRATION is not set
 # CONFIG_SECCOMP is not set
 # CONFIG_PCI is not set
@@ -35,18 +36,16 @@ CONFIG_CAN=y
 CONFIG_CAN_RAW=y
 CONFIG_CAN_BCM=y
 CONFIG_CAN_VCAN=y
-CONFIG_CAN_DEV=y
 CONFIG_CAN_MSCAN=y
 CONFIG_CAN_DEBUG_DEVICES=y
 # CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FIRMWARE_IN_KERNEL is not set
 CONFIG_MTD=y
-CONFIG_MTD_CONCAT=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_OF_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
@@ -63,6 +62,7 @@ CONFIG_BLK_DEV_RAM_SIZE=8192
 CONFIG_BLK_DEV_XIP=y
 CONFIG_MISC_DEVICES=y
 CONFIG_EEPROM_AT24=y
+CONFIG_EEPROM_AT25=y
 CONFIG_SCSI=y
 # CONFIG_SCSI_PROC_FS is not set
 CONFIG_BLK_DEV_SD=y
@@ -99,10 +99,14 @@ CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD=115200
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_MPC=y
+CONFIG_SPI=y
+CONFIG_SPI_MPC512x_PSC=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_MPC8XXX=y
 # CONFIG_HWMON is not set
 CONFIG_MEDIA_SUPPORT=y
 CONFIG_VIDEO_DEV=y
-# CONFIG_VIDEO_ALLOW_V4L1 is not set
 CONFIG_VIDEO_ADV_DEBUG=y
 # CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set
 CONFIG_VIDEO_SAA711X=y
@@ -132,6 +136,5 @@ CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
 # CONFIG_ENABLE_WARN_DEPRECATED is not set
 # CONFIG_ENABLE_MUST_CHECK is not set
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 # CONFIG_CRYPTO_HW is not set
index e63f537..2a1320f 100644 (file)
@@ -88,6 +88,18 @@ CONFIG_FB_RADEON=y
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_LOGO=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+# CONFIG_SND_SUPPORT_OLD_API is not set
+# CONFIG_SND_DRIVERS is not set
+# CONFIG_SND_PCI is not set
+# CONFIG_SND_PPC is not set
+# CONFIG_SND_SPI is not set
+# CONFIG_SND_USB is not set
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_MPC5200_I2S=y
+CONFIG_SND_MPC52xx_SOC_PCM030=y
+CONFIG_SND_MPC52xx_SOC_EFIKA=y
 CONFIG_HID_DRAGONRISE=y
 CONFIG_HID_GYRATION=y
 CONFIG_HID_TWINHAN=y
index a3467bf..a1e5a17 100644 (file)
@@ -10,10 +10,8 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EXPERT=y
 CONFIG_KALLSYMS_ALL=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
@@ -41,7 +39,6 @@ CONFIG_TQM8560=y
 CONFIG_SBC8548=y
 CONFIG_QUICC_ENGINE=y
 CONFIG_QE_GPIO=y
-CONFIG_MPC8xxx_GPIO=y
 CONFIG_HIGHMEM=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -123,6 +120,7 @@ CONFIG_NVRAM=y
 CONFIG_I2C=y
 CONFIG_I2C_CPM=m
 CONFIG_I2C_MPC=y
+CONFIG_GPIO_MPC8XXX=y
 # CONFIG_HWMON is not set
 CONFIG_VIDEO_OUTPUT_CONTROL=y
 CONFIG_FB=y
@@ -206,7 +204,6 @@ CONFIG_PARTITION_ADVANCED=y
 CONFIG_MAC_PARTITION=y
 CONFIG_CRC_T10DIF=y
 CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_DEBUG_INFO=y
 CONFIG_SYSCTL_SYSCALL_CHECK=y
index 9693f6e..dd1e413 100644 (file)
@@ -12,10 +12,8 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EXPERT=y
 CONFIG_KALLSYMS_ALL=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
@@ -42,7 +40,6 @@ CONFIG_TQM8560=y
 CONFIG_SBC8548=y
 CONFIG_QUICC_ENGINE=y
 CONFIG_QE_GPIO=y
-CONFIG_MPC8xxx_GPIO=y
 CONFIG_HIGHMEM=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -124,6 +121,7 @@ CONFIG_NVRAM=y
 CONFIG_I2C=y
 CONFIG_I2C_CPM=m
 CONFIG_I2C_MPC=y
+CONFIG_GPIO_MPC8XXX=y
 # CONFIG_HWMON is not set
 CONFIG_VIDEO_OUTPUT_CONTROL=y
 CONFIG_FB=y
@@ -207,10 +205,8 @@ CONFIG_PARTITION_ADVANCED=y
 CONFIG_MAC_PARTITION=y
 CONFIG_CRC_T10DIF=y
 CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 CONFIG_SYSCTL_SYSCALL_CHECK=y
 CONFIG_VIRQ_DEBUG=y
 CONFIG_CRYPTO_PCBC=m
index 7cb703b..1eb19ac 100644 (file)
@@ -14,7 +14,6 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_PPC4xx_GPIO=y
 CONFIG_ACADIA=y
 CONFIG_EP405=y
-CONFIG_HCU4=y
 CONFIG_HOTFOOT=y
 CONFIG_KILAUEA=y
 CONFIG_MAKALU=y
index 04360f9..c47f2be 100644 (file)
@@ -70,7 +70,7 @@ CONFIG_TAU_AVERAGE=y
 CONFIG_QUICC_ENGINE=y
 CONFIG_QE_GPIO=y
 CONFIG_PPC_BESTCOMM=y
-CONFIG_MPC8xxx_GPIO=y
+CONFIG_GPIO_MPC8XXX=y
 CONFIG_MCU_MPC8349EMITX=m
 CONFIG_HIGHMEM=y
 CONFIG_NO_HZ=y
index 16d25c0..d57c08a 100644 (file)
@@ -37,4 +37,6 @@ struct pdev_archdata {
        u64 dma_mask;
 };
 
+#define ARCH_HAS_DMA_GET_REQUIRED_MASK
+
 #endif /* _ASM_POWERPC_DEVICE_H */
index 3a6c586..14db29b 100644 (file)
@@ -48,6 +48,8 @@
 #define FW_FEATURE_CMO         ASM_CONST(0x0000000002000000)
 #define FW_FEATURE_VPHN                ASM_CONST(0x0000000004000000)
 #define FW_FEATURE_XCMO                ASM_CONST(0x0000000008000000)
+#define FW_FEATURE_OPAL                ASM_CONST(0x0000000010000000)
+#define FW_FEATURE_OPALv2      ASM_CONST(0x0000000020000000)
 
 #ifndef __ASSEMBLY__
 
@@ -65,6 +67,8 @@ enum {
        FW_FEATURE_PSERIES_ALWAYS = 0,
        FW_FEATURE_ISERIES_POSSIBLE = FW_FEATURE_ISERIES | FW_FEATURE_LPAR,
        FW_FEATURE_ISERIES_ALWAYS = FW_FEATURE_ISERIES | FW_FEATURE_LPAR,
+       FW_FEATURE_POWERNV_POSSIBLE = FW_FEATURE_OPAL | FW_FEATURE_OPALv2,
+       FW_FEATURE_POWERNV_ALWAYS = 0,
        FW_FEATURE_PS3_POSSIBLE = FW_FEATURE_LPAR | FW_FEATURE_PS3_LV1,
        FW_FEATURE_PS3_ALWAYS = FW_FEATURE_LPAR | FW_FEATURE_PS3_LV1,
        FW_FEATURE_CELLEB_POSSIBLE = FW_FEATURE_LPAR | FW_FEATURE_BEAT,
@@ -78,6 +82,9 @@ enum {
 #ifdef CONFIG_PPC_ISERIES
                FW_FEATURE_ISERIES_POSSIBLE |
 #endif
+#ifdef CONFIG_PPC_POWERNV
+               FW_FEATURE_POWERNV_POSSIBLE |
+#endif
 #ifdef CONFIG_PPC_PS3
                FW_FEATURE_PS3_POSSIBLE |
 #endif
@@ -95,6 +102,9 @@ enum {
 #ifdef CONFIG_PPC_ISERIES
                FW_FEATURE_ISERIES_ALWAYS &
 #endif
+#ifdef CONFIG_PPC_POWERNV
+               FW_FEATURE_POWERNV_ALWAYS &
+#endif
 #ifdef CONFIG_PPC_PS3
                FW_FEATURE_PS3_ALWAYS &
 #endif
index 5856a66..8600493 100644 (file)
@@ -1,15 +1,60 @@
 #ifndef _ASM_POWERPC_HUGETLB_H
 #define _ASM_POWERPC_HUGETLB_H
 
+#ifdef CONFIG_HUGETLB_PAGE
 #include <asm/page.h>
 
+extern struct kmem_cache *hugepte_cache;
+extern void __init reserve_hugetlb_gpages(void);
+
+static inline pte_t *hugepd_page(hugepd_t hpd)
+{
+       BUG_ON(!hugepd_ok(hpd));
+       return (pte_t *)((hpd.pd & ~HUGEPD_SHIFT_MASK) | PD_HUGE);
+}
+
+static inline unsigned int hugepd_shift(hugepd_t hpd)
+{
+       return hpd.pd & HUGEPD_SHIFT_MASK;
+}
+
+static inline pte_t *hugepte_offset(hugepd_t *hpdp, unsigned long addr,
+                                   unsigned pdshift)
+{
+       /*
+        * On 32-bit, we have multiple higher-level table entries that point to
+        * the same hugepte.  Just use the first one since they're all
+        * identical.  So for that case, idx=0.
+        */
+       unsigned long idx = 0;
+
+       pte_t *dir = hugepd_page(*hpdp);
+#ifdef CONFIG_PPC64
+       idx = (addr & ((1UL << pdshift) - 1)) >> hugepd_shift(*hpdp);
+#endif
+
+       return dir + idx;
+}
+
 pte_t *huge_pte_offset_and_shift(struct mm_struct *mm,
                                 unsigned long addr, unsigned *shift);
 
 void flush_dcache_icache_hugepage(struct page *page);
 
+#if defined(CONFIG_PPC_MM_SLICES) || defined(CONFIG_PPC_SUBPAGE_PROT)
 int is_hugepage_only_range(struct mm_struct *mm, unsigned long addr,
                           unsigned long len);
+#else
+static inline int is_hugepage_only_range(struct mm_struct *mm,
+                                        unsigned long addr,
+                                        unsigned long len)
+{
+       return 0;
+}
+#endif
+
+void book3e_hugetlb_preload(struct mm_struct *mm, unsigned long ea, pte_t pte);
+void flush_hugetlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
 
 void hugetlb_free_pgd_range(struct mmu_gather *tlb, unsigned long addr,
                            unsigned long end, unsigned long floor,
@@ -50,8 +95,11 @@ static inline void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
 static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
                                            unsigned long addr, pte_t *ptep)
 {
-       unsigned long old = pte_update(mm, addr, ptep, ~0UL, 1);
-       return __pte(old);
+#ifdef CONFIG_PPC64
+       return __pte(pte_update(mm, addr, ptep, ~0UL, 1));
+#else
+       return __pte(pte_update(ptep, ~0UL, 0));
+#endif
 }
 
 static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
@@ -93,4 +141,15 @@ static inline void arch_release_hugepage(struct page *page)
 {
 }
 
+#else /* ! CONFIG_HUGETLB_PAGE */
+static inline void reserve_hugetlb_gpages(void)
+{
+       pr_err("Cannot reserve gpages without hugetlb enabled\n");
+}
+static inline void flush_hugetlb_page(struct vm_area_struct *vma,
+                                     unsigned long vmaddr)
+{
+}
+#endif
+
 #endif /* _ASM_POWERPC_HUGETLB_H */
index 8a33698..f921eb1 100644 (file)
@@ -2,7 +2,7 @@
 #define _ASM_POWERPC_KEXEC_H
 #ifdef __KERNEL__
 
-#ifdef CONFIG_FSL_BOOKE
+#if defined(CONFIG_FSL_BOOKE) || defined(CONFIG_44x)
 
 /*
  * On FSL-BookE we setup a 1:1 mapping which covers the first 2GiB of memory
index 47cacdd..58fc216 100644 (file)
@@ -85,8 +85,9 @@ struct machdep_calls {
        void            (*pci_dma_dev_setup)(struct pci_dev *dev);
        void            (*pci_dma_bus_setup)(struct pci_bus *bus);
 
-       /* Platform set_dma_mask override */
+       /* Platform set_dma_mask and dma_get_required_mask overrides */
        int             (*dma_set_mask)(struct device *dev, u64 dma_mask);
+       u64             (*dma_get_required_mask)(struct device *dev);
 
        int             (*probe)(void);
        void            (*setup_arch)(void); /* Optional, may be NULL */
index 3ea0f9a..0260ea5 100644 (file)
@@ -66,6 +66,7 @@
 #define MAS2_M                 0x00000004
 #define MAS2_G                 0x00000002
 #define MAS2_E                 0x00000001
+#define MAS2_WIMGE_MASK                0x0000001f
 #define MAS2_EPN_MASK(size)            (~0 << (size + 10))
 #define MAS2_VAL(addr, size, flags)    ((addr) & MAS2_EPN_MASK(size) | (flags))
 
@@ -80,6 +81,7 @@
 #define MAS3_SW                        0x00000004
 #define MAS3_UR                        0x00000002
 #define MAS3_SR                        0x00000001
+#define MAS3_BAP_MASK          0x0000003f
 #define MAS3_SPSIZE            0x0000003e
 #define MAS3_SPSIZE_SHIFT      1
 
@@ -212,6 +214,11 @@ typedef struct {
        unsigned int    id;
        unsigned int    active;
        unsigned long   vdso_base;
+#ifdef CONFIG_PPC_MM_SLICES
+       u64 low_slices_psize;   /* SLB page size encodings */
+       u64 high_slices_psize;  /* 4 bits per slice for now */
+       u16 user_psize;         /* page size index */
+#endif
 } mm_context_t;
 
 /* Page size definitions, common between 32 and 64-bit
index b445e0a..db645ec 100644 (file)
@@ -262,8 +262,7 @@ extern void hash_failure_debug(unsigned long ea, unsigned long access,
 extern int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
                             unsigned long pstart, unsigned long prot,
                             int psize, int ssize);
-extern void add_gpage(unsigned long addr, unsigned long page_size,
-                         unsigned long number_of_pages);
+extern void add_gpage(u64 addr, u64 page_size, unsigned long number_of_pages);
 extern void demote_segment_4k(struct mm_struct *mm, unsigned long addr);
 
 extern void hpte_init_native(void);
index 698b306..f014552 100644 (file)
@@ -175,14 +175,16 @@ extern u64 ppc64_rma_size;
 #define MMU_PAGE_64K_AP        3       /* "Admixed pages" (hash64 only) */
 #define MMU_PAGE_256K  4
 #define MMU_PAGE_1M    5
-#define MMU_PAGE_8M    6
-#define MMU_PAGE_16M   7
-#define MMU_PAGE_256M  8
-#define MMU_PAGE_1G    9
-#define MMU_PAGE_16G   10
-#define MMU_PAGE_64G   11
-#define MMU_PAGE_COUNT 12
-
+#define MMU_PAGE_4M    6
+#define MMU_PAGE_8M    7
+#define MMU_PAGE_16M   8
+#define MMU_PAGE_64M   9
+#define MMU_PAGE_256M  10
+#define MMU_PAGE_1G    11
+#define MMU_PAGE_16G   12
+#define MMU_PAGE_64G   13
+
+#define MMU_PAGE_COUNT 14
 
 #if defined(CONFIG_PPC_STD_MMU_64)
 /* 64-bit classic hash table MMU */
index df18989..e6fae49 100644 (file)
@@ -273,8 +273,6 @@ struct mpic
        unsigned int            irq_count;
        /* Number of sources */
        unsigned int            num_sources;
-       /* Number of CPUs */
-       unsigned int            num_cpus;
        /* default senses array */
        unsigned char           *senses;
        unsigned int            senses_count;
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
new file mode 100644 (file)
index 0000000..2893e8f
--- /dev/null
@@ -0,0 +1,443 @@
+/*
+ * PowerNV OPAL definitions.
+ *
+ * Copyright 2011 IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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 __OPAL_H
+#define __OPAL_H
+
+/****** Takeover interface ********/
+
+/* PAPR H-Call used to querty the HAL existence and/or instanciate
+ * it from within pHyp (tech preview only).
+ *
+ * This is exclusively used in prom_init.c
+ */
+
+#ifndef __ASSEMBLY__
+
+struct opal_takeover_args {
+       u64     k_image;                /* r4 */
+       u64     k_size;                 /* r5 */
+       u64     k_entry;                /* r6 */
+       u64     k_entry2;               /* r7 */
+       u64     hal_addr;               /* r8 */
+       u64     rd_image;               /* r9 */
+       u64     rd_size;                /* r10 */
+       u64     rd_loc;                 /* r11 */
+};
+
+extern long opal_query_takeover(u64 *hal_size, u64 *hal_align);
+
+extern long opal_do_takeover(struct opal_takeover_args *args);
+
+struct rtas_args;
+extern int opal_enter_rtas(struct rtas_args *args,
+                          unsigned long data,
+                          unsigned long entry);
+
+#endif /* __ASSEMBLY__ */
+
+/****** OPAL APIs ******/
+
+/* Return codes */
+#define OPAL_SUCCESS           0
+#define OPAL_PARAMETER         -1
+#define OPAL_BUSY              -2
+#define OPAL_PARTIAL           -3
+#define OPAL_CONSTRAINED       -4
+#define OPAL_CLOSED            -5
+#define OPAL_HARDWARE          -6
+#define OPAL_UNSUPPORTED       -7
+#define OPAL_PERMISSION                -8
+#define OPAL_NO_MEM            -9
+#define OPAL_RESOURCE          -10
+#define OPAL_INTERNAL_ERROR    -11
+#define OPAL_BUSY_EVENT                -12
+#define OPAL_HARDWARE_FROZEN   -13
+
+/* API Tokens (in r0) */
+#define OPAL_CONSOLE_WRITE                     1
+#define OPAL_CONSOLE_READ                      2
+#define OPAL_RTC_READ                          3
+#define OPAL_RTC_WRITE                         4
+#define OPAL_CEC_POWER_DOWN                    5
+#define OPAL_CEC_REBOOT                                6
+#define OPAL_READ_NVRAM                                7
+#define OPAL_WRITE_NVRAM                       8
+#define OPAL_HANDLE_INTERRUPT                  9
+#define OPAL_POLL_EVENTS                       10
+#define OPAL_PCI_SET_HUB_TCE_MEMORY            11
+#define OPAL_PCI_SET_PHB_TCE_MEMORY            12
+#define OPAL_PCI_CONFIG_READ_BYTE              13
+#define OPAL_PCI_CONFIG_READ_HALF_WORD         14
+#define OPAL_PCI_CONFIG_READ_WORD              15
+#define OPAL_PCI_CONFIG_WRITE_BYTE             16
+#define OPAL_PCI_CONFIG_WRITE_HALF_WORD                17
+#define OPAL_PCI_CONFIG_WRITE_WORD             18
+#define OPAL_SET_XIVE                          19
+#define OPAL_GET_XIVE                          20
+#define OPAL_GET_COMPLETION_TOKEN_STATUS       21 /* obsolete */
+#define OPAL_REGISTER_OPAL_EXCEPTION_HANDLER   22
+#define OPAL_PCI_EEH_FREEZE_STATUS             23
+#define OPAL_PCI_SHPC                          24
+#define OPAL_CONSOLE_WRITE_BUFFER_SPACE                25
+#define OPAL_PCI_EEH_FREEZE_CLEAR              26
+#define OPAL_PCI_PHB_MMIO_ENABLE               27
+#define OPAL_PCI_SET_PHB_MEM_WINDOW            28
+#define OPAL_PCI_MAP_PE_MMIO_WINDOW            29
+#define OPAL_PCI_SET_PHB_TABLE_MEMORY          30
+#define OPAL_PCI_SET_PE                                31
+#define OPAL_PCI_SET_PELTV                     32
+#define OPAL_PCI_SET_MVE                       33
+#define OPAL_PCI_SET_MVE_ENABLE                        34
+#define OPAL_PCI_GET_XIVE_REISSUE              35
+#define OPAL_PCI_SET_XIVE_REISSUE              36
+#define OPAL_PCI_SET_XIVE_PE                   37
+#define OPAL_GET_XIVE_SOURCE                   38
+#define OPAL_GET_MSI_32                                39
+#define OPAL_GET_MSI_64                                40
+#define OPAL_START_CPU                         41
+#define OPAL_QUERY_CPU_STATUS                  42
+#define OPAL_WRITE_OPPANEL                     43
+#define OPAL_PCI_MAP_PE_DMA_WINDOW             44
+#define OPAL_PCI_MAP_PE_DMA_WINDOW_REAL                45
+#define OPAL_PCI_RESET                         49
+
+#ifndef __ASSEMBLY__
+
+/* Other enums */
+enum OpalVendorApiTokens {
+       OPAL_START_VENDOR_API_RANGE = 1000, OPAL_END_VENDOR_API_RANGE = 1999
+};
+enum OpalFreezeState {
+       OPAL_EEH_STOPPED_NOT_FROZEN = 0,
+       OPAL_EEH_STOPPED_MMIO_FREEZE = 1,
+       OPAL_EEH_STOPPED_DMA_FREEZE = 2,
+       OPAL_EEH_STOPPED_MMIO_DMA_FREEZE = 3,
+       OPAL_EEH_STOPPED_RESET = 4,
+       OPAL_EEH_STOPPED_TEMP_UNAVAIL = 5,
+       OPAL_EEH_STOPPED_PERM_UNAVAIL = 6
+};
+enum OpalEehFreezeActionToken {
+       OPAL_EEH_ACTION_CLEAR_FREEZE_MMIO = 1,
+       OPAL_EEH_ACTION_CLEAR_FREEZE_DMA = 2,
+       OPAL_EEH_ACTION_CLEAR_FREEZE_ALL = 3
+};
+enum OpalPciStatusToken {
+       OPAL_EEH_PHB_NO_ERROR = 0,
+       OPAL_EEH_PHB_FATAL = 1,
+       OPAL_EEH_PHB_RECOVERABLE = 2,
+       OPAL_EEH_PHB_BUS_ERROR = 3,
+       OPAL_EEH_PCI_NO_DEVSEL = 4,
+       OPAL_EEH_PCI_TA = 5,
+       OPAL_EEH_PCIEX_UR = 6,
+       OPAL_EEH_PCIEX_CA = 7,
+       OPAL_EEH_PCI_MMIO_ERROR = 8,
+       OPAL_EEH_PCI_DMA_ERROR = 9
+};
+enum OpalShpcAction {
+       OPAL_SHPC_GET_LINK_STATE = 0,
+       OPAL_SHPC_GET_SLOT_STATE = 1
+};
+enum OpalShpcLinkState {
+       OPAL_SHPC_LINK_DOWN = 0,
+       OPAL_SHPC_LINK_UP = 1
+};
+enum OpalMmioWindowType {
+       OPAL_M32_WINDOW_TYPE = 1,
+       OPAL_M64_WINDOW_TYPE = 2,
+       OPAL_IO_WINDOW_TYPE = 3
+};
+enum OpalShpcSlotState {
+       OPAL_SHPC_DEV_NOT_PRESENT = 0,
+       OPAL_SHPC_DEV_PRESENT = 1
+};
+enum OpalExceptionHandler {
+       OPAL_MACHINE_CHECK_HANDLER = 1,
+       OPAL_HYPERVISOR_MAINTENANCE_HANDLER = 2,
+       OPAL_SOFTPATCH_HANDLER = 3
+};
+enum OpalPendingState {
+       OPAL_EVENT_OPAL_INTERNAL = 0x1,
+       OPAL_EVENT_NVRAM = 0x2,
+       OPAL_EVENT_RTC = 0x4,
+       OPAL_EVENT_CONSOLE_OUTPUT = 0x8,
+       OPAL_EVENT_CONSOLE_INPUT = 0x10
+};
+
+/* Machine check related definitions */
+enum OpalMCE_Version {
+       OpalMCE_V1 = 1,
+};
+
+enum OpalMCE_Severity {
+       OpalMCE_SEV_NO_ERROR = 0,
+       OpalMCE_SEV_WARNING = 1,
+       OpalMCE_SEV_ERROR_SYNC = 2,
+       OpalMCE_SEV_FATAL = 3,
+};
+
+enum OpalMCE_Disposition {
+       OpalMCE_DISPOSITION_RECOVERED = 0,
+       OpalMCE_DISPOSITION_NOT_RECOVERED = 1,
+};
+
+enum OpalMCE_Initiator {
+       OpalMCE_INITIATOR_UNKNOWN = 0,
+       OpalMCE_INITIATOR_CPU = 1,
+};
+
+enum OpalMCE_ErrorType {
+       OpalMCE_ERROR_TYPE_UNKNOWN = 0,
+       OpalMCE_ERROR_TYPE_UE = 1,
+       OpalMCE_ERROR_TYPE_SLB = 2,
+       OpalMCE_ERROR_TYPE_ERAT = 3,
+       OpalMCE_ERROR_TYPE_TLB = 4,
+};
+
+enum OpalMCE_UeErrorType {
+       OpalMCE_UE_ERROR_INDETERMINATE = 0,
+       OpalMCE_UE_ERROR_IFETCH = 1,
+       OpalMCE_UE_ERROR_PAGE_TABLE_WALK_IFETCH = 2,
+       OpalMCE_UE_ERROR_LOAD_STORE = 3,
+       OpalMCE_UE_ERROR_PAGE_TABLE_WALK_LOAD_STORE = 4,
+};
+
+enum OpalMCE_SlbErrorType {
+       OpalMCE_SLB_ERROR_INDETERMINATE = 0,
+       OpalMCE_SLB_ERROR_PARITY = 1,
+       OpalMCE_SLB_ERROR_MULTIHIT = 2,
+};
+
+enum OpalMCE_EratErrorType {
+       OpalMCE_ERAT_ERROR_INDETERMINATE = 0,
+       OpalMCE_ERAT_ERROR_PARITY = 1,
+       OpalMCE_ERAT_ERROR_MULTIHIT = 2,
+};
+
+enum OpalMCE_TlbErrorType {
+       OpalMCE_TLB_ERROR_INDETERMINATE = 0,
+       OpalMCE_TLB_ERROR_PARITY = 1,
+       OpalMCE_TLB_ERROR_MULTIHIT = 2,
+};
+
+enum OpalThreadStatus {
+       OPAL_THREAD_INACTIVE = 0x0,
+       OPAL_THREAD_STARTED = 0x1
+};
+
+enum OpalPciBusCompare {
+       OpalPciBusAny   = 0,    /* Any bus number match */
+       OpalPciBus3Bits = 2,    /* Match top 3 bits of bus number */
+       OpalPciBus4Bits = 3,    /* Match top 4 bits of bus number */
+       OpalPciBus5Bits = 4,    /* Match top 5 bits of bus number */
+       OpalPciBus6Bits = 5,    /* Match top 6 bits of bus number */
+       OpalPciBus7Bits = 6,    /* Match top 7 bits of bus number */
+       OpalPciBusAll   = 7,    /* Match bus number exactly */
+};
+
+enum OpalDeviceCompare {
+       OPAL_IGNORE_RID_DEVICE_NUMBER = 0,
+       OPAL_COMPARE_RID_DEVICE_NUMBER = 1
+};
+
+enum OpalFuncCompare {
+       OPAL_IGNORE_RID_FUNCTION_NUMBER = 0,
+       OPAL_COMPARE_RID_FUNCTION_NUMBER = 1
+};
+
+enum OpalPeAction {
+       OPAL_UNMAP_PE = 0,
+       OPAL_MAP_PE = 1
+};
+
+enum OpalPciResetAndReinitScope {
+       OPAL_PHB_COMPLETE = 1, OPAL_PCI_LINK = 2, OPAL_PHB_ERROR = 3,
+       OPAL_PCI_HOT_RESET = 4, OPAL_PCI_FUNDAMENTAL_RESET = 5,
+       OPAL_PCI_IODA_RESET = 6,
+};
+
+enum OpalPciResetState { OPAL_DEASSERT_RESET = 0, OPAL_ASSERT_RESET = 1 };
+
+struct opal_machine_check_event {
+       enum OpalMCE_Version    version:8;      /* 0x00 */
+       uint8_t                 in_use;         /* 0x01 */
+       enum OpalMCE_Severity   severity:8;     /* 0x02 */
+       enum OpalMCE_Initiator  initiator:8;    /* 0x03 */
+       enum OpalMCE_ErrorType  error_type:8;   /* 0x04 */
+       enum OpalMCE_Disposition disposition:8; /* 0x05 */
+       uint8_t                 reserved_1[2];  /* 0x06 */
+       uint64_t                gpr3;           /* 0x08 */
+       uint64_t                srr0;           /* 0x10 */
+       uint64_t                srr1;           /* 0x18 */
+       union {                                 /* 0x20 */
+               struct {
+                       enum OpalMCE_UeErrorType ue_error_type:8;
+                       uint8_t         effective_address_provided;
+                       uint8_t         physical_address_provided;
+                       uint8_t         reserved_1[5];
+                       uint64_t        effective_address;
+                       uint64_t        physical_address;
+                       uint8_t         reserved_2[8];
+               } ue_error;
+
+               struct {
+                       enum OpalMCE_SlbErrorType slb_error_type:8;
+                       uint8_t         effective_address_provided;
+                       uint8_t         reserved_1[6];
+                       uint64_t        effective_address;
+                       uint8_t         reserved_2[16];
+               } slb_error;
+
+               struct {
+                       enum OpalMCE_EratErrorType erat_error_type:8;
+                       uint8_t         effective_address_provided;
+                       uint8_t         reserved_1[6];
+                       uint64_t        effective_address;
+                       uint8_t         reserved_2[16];
+               } erat_error;
+
+               struct {
+                       enum OpalMCE_TlbErrorType tlb_error_type:8;
+                       uint8_t         effective_address_provided;
+                       uint8_t         reserved_1[6];
+                       uint64_t        effective_address;
+                       uint8_t         reserved_2[16];
+               } tlb_error;
+       } u;
+};
+
+typedef struct oppanel_line {
+       /* XXX */
+} oppanel_line_t;
+
+/* API functions */
+int64_t opal_console_write(int64_t term_number, int64_t *length,
+                          const uint8_t *buffer);
+int64_t opal_console_read(int64_t term_number, int64_t *length,
+                         uint8_t *buffer);
+int64_t opal_console_write_buffer_space(int64_t term_number,
+                                       int64_t *length);
+int64_t opal_rtc_read(uint32_t *year_month_day,
+                     uint64_t *hour_minute_second_millisecond);
+int64_t opal_rtc_write(uint32_t year_month_day,
+                      uint64_t hour_minute_second_millisecond);
+int64_t opal_cec_power_down(uint64_t request);
+int64_t opal_cec_reboot(void);
+int64_t opal_read_nvram(uint64_t buffer, uint64_t size, uint64_t offset);
+int64_t opal_write_nvram(uint64_t buffer, uint64_t size, uint64_t offset);
+int64_t opal_handle_interrupt(uint64_t isn, uint64_t *outstanding_event_mask);
+int64_t opal_poll_events(uint64_t *outstanding_event_mask);
+int64_t opal_pci_set_hub_tce_memory(uint64_t hub_id, uint64_t tce_mem_addr,
+                                   uint64_t tce_mem_size);
+int64_t opal_pci_set_phb_tce_memory(uint64_t phb_id, uint64_t tce_mem_addr,
+                                   uint64_t tce_mem_size);
+int64_t opal_pci_config_read_byte(uint64_t phb_id, uint64_t bus_dev_func,
+                                 uint64_t offset, uint8_t *data);
+int64_t opal_pci_config_read_half_word(uint64_t phb_id, uint64_t bus_dev_func,
+                                      uint64_t offset, uint16_t *data);
+int64_t opal_pci_config_read_word(uint64_t phb_id, uint64_t bus_dev_func,
+                                 uint64_t offset, uint32_t *data);
+int64_t opal_pci_config_write_byte(uint64_t phb_id, uint64_t bus_dev_func,
+                                  uint64_t offset, uint8_t data);
+int64_t opal_pci_config_write_half_word(uint64_t phb_id, uint64_t bus_dev_func,
+                                       uint64_t offset, uint16_t data);
+int64_t opal_pci_config_write_word(uint64_t phb_id, uint64_t bus_dev_func,
+                                  uint64_t offset, uint32_t data);
+int64_t opal_set_xive(uint32_t isn, uint16_t server, uint8_t priority);
+int64_t opal_get_xive(uint32_t isn, uint16_t *server, uint8_t *priority);
+int64_t opal_register_exception_handler(uint64_t opal_exception,
+                                       uint64_t handler_address,
+                                       uint64_t glue_cache_line);
+int64_t opal_pci_eeh_freeze_status(uint64_t phb_id, uint64_t pe_number,
+                                  uint8_t *freeze_state,
+                                  uint16_t *pci_error_type,
+                                  uint64_t *phb_status);
+int64_t opal_pci_eeh_freeze_clear(uint64_t phb_id, uint64_t pe_number,
+                                 uint64_t eeh_action_token);
+int64_t opal_pci_shpc(uint64_t phb_id, uint64_t shpc_action, uint8_t *state);
+
+
+
+int64_t opal_pci_phb_mmio_enable(uint64_t phb_id, uint16_t window_type,
+                                uint16_t window_num, uint16_t enable);
+int64_t opal_pci_set_phb_mem_window(uint64_t phb_id, uint16_t window_type,
+                                   uint16_t window_num,
+                                   uint64_t starting_real_address,
+                                   uint64_t starting_pci_address,
+                                   uint16_t segment_size);
+int64_t opal_pci_map_pe_mmio_window(uint64_t phb_id, uint16_t pe_number,
+                                   uint16_t window_type, uint16_t window_num,
+                                   uint16_t segment_num);
+int64_t opal_pci_set_phb_table_memory(uint64_t phb_id, uint64_t rtt_addr,
+                                     uint64_t ivt_addr, uint64_t ivt_len,
+                                     uint64_t reject_array_addr,
+                                     uint64_t peltv_addr);
+int64_t opal_pci_set_pe(uint64_t phb_id, uint64_t pe_number, uint64_t bus_dev_func,
+                       uint8_t bus_compare, uint8_t dev_compare, uint8_t func_compare,
+                       uint8_t pe_action);
+int64_t opal_pci_set_peltv(uint64_t phb_id, uint32_t parent_pe, uint32_t child_pe,
+                          uint8_t state);
+int64_t opal_pci_set_mve(uint64_t phb_id, uint32_t mve_number, uint32_t pe_number);
+int64_t opal_pci_set_mve_enable(uint64_t phb_id, uint32_t mve_number,
+                               uint32_t state);
+int64_t opal_pci_get_xive_reissue(uint64_t phb_id, uint32_t xive_number,
+                                 uint8_t *p_bit, uint8_t *q_bit);
+int64_t opal_pci_set_xive_reissue(uint64_t phb_id, uint32_t xive_number,
+                                 uint8_t p_bit, uint8_t q_bit);
+int64_t opal_pci_set_xive_pe(uint64_t phb_id, uint32_t pe_number,
+                            uint32_t xive_num);
+int64_t opal_get_xive_source(uint64_t phb_id, uint32_t xive_num,
+                            int32_t *interrupt_source_number);
+int64_t opal_get_msi_32(uint64_t phb_id, uint32_t mve_number, uint32_t xive_num,
+                       uint8_t msi_range, uint32_t *msi_address,
+                       uint32_t *message_data);
+int64_t opal_get_msi_64(uint64_t phb_id, uint32_t mve_number,
+                       uint32_t xive_num, uint8_t msi_range,
+                       uint64_t *msi_address, uint32_t *message_data);
+int64_t opal_start_cpu(uint64_t thread_number, uint64_t start_address);
+int64_t opal_query_cpu_status(uint64_t thread_number, uint8_t *thread_status);
+int64_t opal_write_oppanel(oppanel_line_t *lines, uint64_t num_lines);
+int64_t opal_pci_map_pe_dma_window(uint64_t phb_id, uint16_t pe_number, uint16_t window_id,
+                                  uint16_t tce_levels, uint64_t tce_table_addr,
+                                  uint64_t tce_table_size, uint64_t tce_page_size);
+int64_t opal_pci_map_pe_dma_window_real(uint64_t phb_id, uint16_t pe_number,
+                                       uint16_t dma_window_number, uint64_t pci_start_addr,
+                                       uint64_t pci_mem_size);
+int64_t opal_pci_reset(uint64_t phb_id, uint8_t reset_scope, uint8_t assert_state);
+
+/* Internal functions */
+extern int early_init_dt_scan_opal(unsigned long node, const char *uname, int depth, void *data);
+
+extern int opal_get_chars(uint32_t vtermno, char *buf, int count);
+extern int opal_put_chars(uint32_t vtermno, const char *buf, int total_len);
+
+extern void hvc_opal_init_early(void);
+
+/* Internal functions */
+extern int early_init_dt_scan_opal(unsigned long node, const char *uname,
+                                  int depth, void *data);
+
+extern int opal_get_chars(uint32_t vtermno, char *buf, int count);
+extern int opal_put_chars(uint32_t vtermno, const char *buf, int total_len);
+
+extern void hvc_opal_init_early(void);
+
+struct rtc_time;
+extern int opal_set_rtc_time(struct rtc_time *tm);
+extern void opal_get_rtc_time(struct rtc_time *tm);
+extern unsigned long opal_get_boot_time(void);
+extern void opal_nvram_init(void);
+
+extern int opal_machine_check(struct pt_regs *regs);
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __OPAL_H */
index 516bfb3..17722c7 100644 (file)
@@ -43,6 +43,7 @@ extern unsigned int debug_smp_processor_id(void); /* from linux/smp.h */
 #define get_slb_shadow()       (get_paca()->slb_shadow_ptr)
 
 struct task_struct;
+struct opal_machine_check_event;
 
 /*
  * Defines the layout of the paca.
@@ -135,6 +136,13 @@ struct paca_struct {
        u8 io_sync;                     /* writel() needs spin_unlock sync */
        u8 irq_work_pending;            /* IRQ_WORK interrupt while soft-disable */
 
+#ifdef CONFIG_PPC_POWERNV
+       /* Pointer to OPAL machine check event structure set by the
+        * early exception handler for use by high level C handler
+        */
+       struct opal_machine_check_event *opal_mc_evt;
+#endif
+
        /* Stuff for accurate time accounting */
        u64 user_time;                  /* accumulated usermode TB ticks */
        u64 system_time;                /* accumulated system TB ticks */
index 2cd664e..dd9c4fd 100644 (file)
 
 #define PAGE_SIZE              (ASM_CONST(1) << PAGE_SHIFT)
 
+#ifndef __ASSEMBLY__
+#ifdef CONFIG_HUGETLB_PAGE
+extern unsigned int HPAGE_SHIFT;
+#else
+#define HPAGE_SHIFT PAGE_SHIFT
+#endif
+#define HPAGE_SIZE             ((1UL) << HPAGE_SHIFT)
+#define HPAGE_MASK             (~(HPAGE_SIZE - 1))
+#define HUGETLB_PAGE_ORDER     (HPAGE_SHIFT - PAGE_SHIFT)
+#define HUGE_MAX_HSTATE                (MMU_PAGE_COUNT-1)
+#endif
+
 /* We do define AT_SYSINFO_EHDR but don't use the gate mechanism */
 #define __HAVE_ARCH_GATE_AREA          1
 
@@ -158,6 +170,24 @@ extern phys_addr_t kernstart_addr;
 #define is_kernel_addr(x)      ((x) >= PAGE_OFFSET)
 #endif
 
+/*
+ * Use the top bit of the higher-level page table entries to indicate whether
+ * the entries we point to contain hugepages.  This works because we know that
+ * the page tables live in kernel space.  If we ever decide to support having
+ * page tables at arbitrary addresses, this breaks and will have to change.
+ */
+#ifdef CONFIG_PPC64
+#define PD_HUGE 0x8000000000000000
+#else
+#define PD_HUGE 0x80000000
+#endif
+
+/*
+ * Some number of bits at the level of the page table that points to
+ * a hugepte are used to encode the size.  This masks those bits.
+ */
+#define HUGEPD_SHIFT_MASK     0x3f
+
 #ifndef __ASSEMBLY__
 
 #undef STRICT_MM_TYPECHECKS
@@ -243,7 +273,6 @@ typedef unsigned long pgprot_t;
 #endif
 
 typedef struct { signed long pd; } hugepd_t;
-#define HUGEPD_SHIFT_MASK     0x3f
 
 #ifdef CONFIG_HUGETLB_PAGE
 static inline int hugepd_ok(hugepd_t hpd)
index 9356262..fb40ede 100644 (file)
@@ -64,17 +64,6 @@ extern void copy_page(void *to, void *from);
 /* Log 2 of page table size */
 extern u64 ppc64_pft_size;
 
-/* Large pages size */
-#ifdef CONFIG_HUGETLB_PAGE
-extern unsigned int HPAGE_SHIFT;
-#else
-#define HPAGE_SHIFT PAGE_SHIFT
-#endif
-#define HPAGE_SIZE             ((1UL) << HPAGE_SHIFT)
-#define HPAGE_MASK             (~(HPAGE_SIZE - 1))
-#define HUGETLB_PAGE_ORDER     (HPAGE_SHIFT - PAGE_SHIFT)
-#define HUGE_MAX_HSTATE                (MMU_PAGE_COUNT-1)
-
 #endif /* __ASSEMBLY__ */
 
 #ifdef CONFIG_PPC_MM_SLICES
index 082d515..0156702 100644 (file)
@@ -72,6 +72,9 @@
 #define        PTE_RPN_SHIFT   (24)
 #endif
 
+#define PTE_WIMGE_SHIFT (19)
+#define PTE_BAP_SHIFT  (2)
+
 /* On 32-bit, we never clear the top part of the PTE */
 #ifdef CONFIG_PPC32
 #define _PTE_NONE_MASK 0xffffffff00000000ULL
index 9ec0b39..28cdbd9 100644 (file)
 #define L1CSR1_ICFI    0x00000002      /* Instr Cache Flash Invalidate */
 #define L1CSR1_ICE     0x00000001      /* Instr Cache Enable */
 
+/* Bit definitions for L1CSR2. */
+#define L1CSR2_DCWS    0x40000000      /* Data Cache write shadow */
+
 /* Bit definitions for L2CSR0. */
 #define L2CSR0_L2E     0x80000000      /* L2 Cache Enable */
 #define L2CSR0_L2PE    0x40000000      /* L2 Cache Parity/ECC Enable */
index 58625d1..41f69ae 100644 (file)
@@ -249,10 +249,12 @@ extern void pSeries_log_error(char *buf, unsigned int err_type, int fatal);
 #define ERR_FLAG_ALREADY_LOGGED        0x0
 #define ERR_FLAG_BOOT          0x1     /* log was pulled from NVRAM on boot */
 #define ERR_TYPE_RTAS_LOG      0x2     /* from rtas event-scan */
-#define ERR_TYPE_KERNEL_PANIC  0x4     /* from panic() */
+#define ERR_TYPE_KERNEL_PANIC  0x4     /* from die()/panic() */
+#define ERR_TYPE_KERNEL_PANIC_GZ 0x8   /* ditto, compressed */
 
 /* All the types and not flags */
-#define ERR_TYPE_MASK  (ERR_TYPE_RTAS_LOG | ERR_TYPE_KERNEL_PANIC)
+#define ERR_TYPE_MASK \
+       (ERR_TYPE_RTAS_LOG | ERR_TYPE_KERNEL_PANIC | ERR_TYPE_KERNEL_PANIC_GZ)
 
 #define RTAS_DEBUG KERN_DEBUG "RTAS: "
  
index 15a70b7..adba970 100644 (file)
@@ -65,6 +65,7 @@ int generic_cpu_disable(void);
 void generic_cpu_die(unsigned int cpu);
 void generic_mach_cpu_die(void);
 void generic_set_cpu_dead(unsigned int cpu);
+int generic_check_cpu_restart(unsigned int cpu);
 #endif
 
 #ifdef CONFIG_PPC64
index 54a47ea..0c5fa31 100644 (file)
@@ -16,7 +16,7 @@
 #endif /* CONFIG_SPARSEMEM */
 
 #ifdef CONFIG_MEMORY_HOTPLUG
-extern void create_section_mapping(unsigned long start, unsigned long end);
+extern int create_section_mapping(unsigned long start, unsigned long end);
 extern int remove_section_mapping(unsigned long start, unsigned long end);
 #ifdef CONFIG_NUMA
 extern int hot_add_scn_to_nid(unsigned long scn_addr);
index 7ef0d90..1e104af 100644 (file)
@@ -19,14 +19,10 @@ struct device_node;
 #define RECLAIM_DISTANCE 10
 
 /*
- * Before going off node we want the VM to try and reclaim from the local
- * node. It does this if the remote distance is larger than RECLAIM_DISTANCE.
- * With the default REMOTE_DISTANCE of 20 and the default RECLAIM_DISTANCE of
- * 20, we never reclaim and go off node straight away.
- *
- * To fix this we choose a smaller value of RECLAIM_DISTANCE.
+ * Avoid creating an extra level of balancing (SD_ALLNODES) on the largest
+ * POWER7 boxes which have a maximum of 32 nodes.
  */
-#define RECLAIM_DISTANCE 10
+#define SD_NODES_PER_DOMAIN 32
 
 #include <asm/mmzone.h>
 
@@ -69,11 +65,11 @@ static inline int pcibus_to_node(struct pci_bus *bus)
        .forkexec_idx           = 0,                                    \
                                                                        \
        .flags                  = 1*SD_LOAD_BALANCE                     \
-                               | 1*SD_BALANCE_NEWIDLE                  \
+                               | 0*SD_BALANCE_NEWIDLE                  \
                                | 1*SD_BALANCE_EXEC                     \
                                | 1*SD_BALANCE_FORK                     \
                                | 0*SD_BALANCE_WAKE                     \
-                               | 0*SD_WAKE_AFFINE                      \
+                               | 1*SD_WAKE_AFFINE                      \
                                | 0*SD_PREFER_LOCAL                     \
                                | 0*SD_SHARE_CPUPOWER                   \
                                | 0*SD_POWERSAVINGS_BALANCE             \
index 5354ae9..8338aef 100644 (file)
@@ -55,6 +55,9 @@ extern void __init udbg_init_cpm(void);
 extern void __init udbg_init_usbgecko(void);
 extern void __init udbg_init_wsp(void);
 extern void __init udbg_init_ehv_bc(void);
+extern void __init udbg_init_ps3gelic(void);
+extern void __init udbg_init_debug_opal_raw(void);
+extern void __init udbg_init_debug_opal_hvsi(void);
 
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_UDBG_H */
index b183a40..bd6c401 100644 (file)
 #define MAX_NUM_PRIORITIES     3
 
 /* Native ICP */
+#ifdef CONFIG_PPC_ICP_NATIVE
 extern int icp_native_init(void);
+#else
+static inline int icp_native_init(void) { return -ENODEV; }
+#endif
 
 /* PAPR ICP */
+#ifdef CONFIG_PPC_ICP_HV
 extern int icp_hv_init(void);
+#else
+static inline int icp_hv_init(void) { return -ENODEV; }
+#endif
 
 /* ICP ops */
 struct icp_ops {
@@ -51,7 +59,18 @@ extern const struct icp_ops *icp_ops;
 extern int ics_native_init(void);
 
 /* RTAS ICS */
+#ifdef CONFIG_PPC_ICS_RTAS
 extern int ics_rtas_init(void);
+#else
+static inline int ics_rtas_init(void) { return -ENODEV; }
+#endif
+
+/* HAL ICS */
+#ifdef CONFIG_PPC_POWERNV
+extern int ics_opal_init(void);
+#else
+static inline int ics_opal_init(void) { return -ENODEV; }
+#endif
 
 /* ICS instance, hooked up to chip_data of an irq */
 struct ics {
index 69f7ffe..7c5324f 100644 (file)
@@ -49,6 +49,9 @@
 #ifdef CONFIG_PPC_ISERIES
 #include <asm/iseries/alpaca.h>
 #endif
+#ifdef CONFIG_PPC_POWERNV
+#include <asm/opal.h>
+#endif
 #if defined(CONFIG_KVM) || defined(CONFIG_KVM_GUEST)
 #include <linux/kvm_host.h>
 #endif
@@ -610,5 +613,12 @@ int main(void)
                                        arch.timing_last_enter.tv32.tbl));
 #endif
 
+#ifdef CONFIG_PPC_POWERNV
+       DEFINE(OPAL_MC_GPR3, offsetof(struct opal_machine_check_event, gpr3));
+       DEFINE(OPAL_MC_SRR0, offsetof(struct opal_machine_check_event, srr0));
+       DEFINE(OPAL_MC_SRR1, offsetof(struct opal_machine_check_event, srr1));
+       DEFINE(PACA_OPAL_MC_EVT, offsetof(struct paca_struct, opal_mc_evt));
+#endif
+
        return 0;
 }
index e755415..6f04b9c 100644 (file)
@@ -90,13 +90,27 @@ static int dma_iommu_dma_supported(struct device *dev, u64 mask)
                return 1;
 }
 
+static u64 dma_iommu_get_required_mask(struct device *dev)
+{
+       struct iommu_table *tbl = get_iommu_table_base(dev);
+       u64 mask;
+       if (!tbl)
+               return 0;
+
+       mask = 1ULL < (fls_long(tbl->it_offset + tbl->it_size) - 1);
+       mask += mask - 1;
+
+       return mask;
+}
+
 struct dma_map_ops dma_iommu_ops = {
-       .alloc_coherent = dma_iommu_alloc_coherent,
-       .free_coherent  = dma_iommu_free_coherent,
-       .map_sg         = dma_iommu_map_sg,
-       .unmap_sg       = dma_iommu_unmap_sg,
-       .dma_supported  = dma_iommu_dma_supported,
-       .map_page       = dma_iommu_map_page,
-       .unmap_page     = dma_iommu_unmap_page,
+       .alloc_coherent         = dma_iommu_alloc_coherent,
+       .free_coherent          = dma_iommu_free_coherent,
+       .map_sg                 = dma_iommu_map_sg,
+       .unmap_sg               = dma_iommu_unmap_sg,
+       .dma_supported          = dma_iommu_dma_supported,
+       .map_page               = dma_iommu_map_page,
+       .unmap_page             = dma_iommu_unmap_page,
+       .get_required_mask      = dma_iommu_get_required_mask,
 };
 EXPORT_SYMBOL(dma_iommu_ops);
index 4295e0b..1ebc918 100644 (file)
 
 unsigned int ppc_swiotlb_enable;
 
+static u64 swiotlb_powerpc_get_required(struct device *dev)
+{
+       u64 end, mask, max_direct_dma_addr = dev->archdata.max_direct_dma_addr;
+
+       end = memblock_end_of_DRAM();
+       if (max_direct_dma_addr && end > max_direct_dma_addr)
+               end = max_direct_dma_addr;
+       end += get_dma_offset(dev);
+
+       mask = 1ULL << (fls64(end) - 1);
+       mask += mask - 1;
+
+       return mask;
+}
+
 /*
  * At the moment, all platforms that use this code only require
  * swiotlb to be used if we're operating on HIGHMEM.  Since
@@ -44,6 +59,7 @@ struct dma_map_ops swiotlb_dma_ops = {
        .sync_sg_for_cpu = swiotlb_sync_sg_for_cpu,
        .sync_sg_for_device = swiotlb_sync_sg_for_device,
        .mapping_error = swiotlb_dma_mapping_error,
+       .get_required_mask = swiotlb_powerpc_get_required,
 };
 
 void pci_dma_dev_setup_swiotlb(struct pci_dev *pdev)
index 4f0959f..8593f53 100644 (file)
@@ -96,6 +96,18 @@ static int dma_direct_dma_supported(struct device *dev, u64 mask)
 #endif
 }
 
+static u64 dma_direct_get_required_mask(struct device *dev)
+{
+       u64 end, mask;
+
+       end = memblock_end_of_DRAM() + get_dma_offset(dev);
+
+       mask = 1ULL << (fls64(end) - 1);
+       mask += mask - 1;
+
+       return mask;
+}
+
 static inline dma_addr_t dma_direct_map_page(struct device *dev,
                                             struct page *page,
                                             unsigned long offset,
@@ -137,13 +149,14 @@ static inline void dma_direct_sync_single(struct device *dev,
 #endif
 
 struct dma_map_ops dma_direct_ops = {
-       .alloc_coherent = dma_direct_alloc_coherent,
-       .free_coherent  = dma_direct_free_coherent,
-       .map_sg         = dma_direct_map_sg,
-       .unmap_sg       = dma_direct_unmap_sg,
-       .dma_supported  = dma_direct_dma_supported,
-       .map_page       = dma_direct_map_page,
-       .unmap_page     = dma_direct_unmap_page,
+       .alloc_coherent                 = dma_direct_alloc_coherent,
+       .free_coherent                  = dma_direct_free_coherent,
+       .map_sg                         = dma_direct_map_sg,
+       .unmap_sg                       = dma_direct_unmap_sg,
+       .dma_supported                  = dma_direct_dma_supported,
+       .map_page                       = dma_direct_map_page,
+       .unmap_page                     = dma_direct_unmap_page,
+       .get_required_mask              = dma_direct_get_required_mask,
 #ifdef CONFIG_NOT_COHERENT_CACHE
        .sync_single_for_cpu            = dma_direct_sync_single,
        .sync_single_for_device         = dma_direct_sync_single,
@@ -170,6 +183,23 @@ int dma_set_mask(struct device *dev, u64 dma_mask)
 }
 EXPORT_SYMBOL(dma_set_mask);
 
+u64 dma_get_required_mask(struct device *dev)
+{
+       struct dma_map_ops *dma_ops = get_dma_ops(dev);
+
+       if (ppc_md.dma_get_required_mask)
+               return ppc_md.dma_get_required_mask(dev);
+
+       if (unlikely(dma_ops == NULL))
+               return 0;
+
+       if (dma_ops->get_required_mask)
+               return dma_ops->get_required_mask(dev);
+
+       return DMA_BIT_MASK(8 * sizeof(dma_addr_t));
+}
+EXPORT_SYMBOL_GPL(dma_get_required_mask);
+
 static int __init dma_init(void)
 {
        dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES);
index 29ddd8b..a54d92f 100644 (file)
@@ -1133,7 +1133,7 @@ _GLOBAL(do_stab_bolted)
        rfid
        b       .       /* prevent speculative execution */
 
-#ifdef CONFIG_PPC_PSERIES
+#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV)
 /*
  * Data area reserved for FWNMI option.
  * This address (0x7000) is fixed by the RPA.
@@ -1141,7 +1141,7 @@ _GLOBAL(do_stab_bolted)
        .= 0x7000
        .globl fwnmi_data_area
 fwnmi_data_area:
-#endif /* CONFIG_PPC_PSERIES */
+#endif /* defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) */
 
        /* iSeries does not use the FWNMI stuff, so it is safe to put
         * this here, even if we later allow kernels that will boot on
@@ -1166,9 +1166,12 @@ xLparMap:
 
 #endif /* CONFIG_PPC_ISERIES */
 
-#ifdef CONFIG_PPC_PSERIES
+#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV)
+       /* pseries and powernv need to keep the whole page from
+        * 0x7000 to 0x8000 free for use by the firmware
+        */
         . = 0x8000
-#endif /* CONFIG_PPC_PSERIES */
+#endif /* defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) */
 
 /*
  * Space for CPU0's segment table.
@@ -1183,3 +1186,19 @@ xLparMap:
        .globl initial_stab
 initial_stab:
        .space  4096
+#ifdef CONFIG_PPC_POWERNV
+_GLOBAL(opal_mc_secondary_handler)
+       HMT_MEDIUM
+       SET_SCRATCH0(r13)
+       GET_PACA(r13)
+       clrldi  r3,r3,2
+       tovirt(r3,r3)
+       std     r3,PACA_OPAL_MC_EVT(r13)
+       ld      r13,OPAL_MC_SRR0(r3)
+       mtspr   SPRN_SRR0,r13
+       ld      r13,OPAL_MC_SRR1(r3)
+       mtspr   SPRN_SRR1,r13
+       ld      r3,OPAL_MC_GPR3(r3)
+       GET_SCRATCH0(r13)
+       b       machine_check_pSeries
+#endif /* CONFIG_PPC_POWERNV */
index ba250d5..0654dba 100644 (file)
@@ -139,8 +139,7 @@ __start:
        trap
 #endif /* CONFIG_PPC_PMAC */
 
-1:     mr      r31,r3                  /* save parameters */
-       mr      r30,r4
+1:     mr      r31,r3                  /* save device tree ptr */
        li      r24,0                   /* cpu # */
 
 /*
@@ -964,8 +963,8 @@ start_here:
  * Do early platform-specific initialization,
  * and set up the MMU.
  */
-       mr      r3,r31
-       mr      r4,r30
+       li      r3,0
+       mr      r4,r31
        bl      machine_init
        bl      __save_cpu_setup
        bl      MMU_init
index a91626d..872a6af 100644 (file)
 _ENTRY(_stext);
 _ENTRY(_start);
 
-       /* Save parameters we are passed.
-       */
-       mr      r31,r3
-       mr      r30,r4
-       mr      r29,r5
-       mr      r28,r6
-       mr      r27,r7
+       mr      r31,r3                  /* save device tree ptr */
 
        /* We have to turn on the MMU right away so we get cache modes
         * set correctly.
@@ -849,11 +843,8 @@ start_here:
 /*
  * Decide what sort of machine this is and initialize the MMU.
  */
-       mr      r3,r31
-       mr      r4,r30
-       mr      r5,r29
-       mr      r6,r28
-       mr      r7,r27
+       li      r3,0
+       mr      r4,r31
        bl      machine_init
        bl      MMU_init
 
index f8e971b..b725dab 100644 (file)
@@ -61,14 +61,7 @@ _ENTRY(_start);
         * of abatron_pteptrs
         */
        nop
-/*
- * Save parameters we are passed
- */
-       mr      r31,r3
-       mr      r30,r4
-       mr      r29,r5
-       mr      r28,r6
-       mr      r27,r7
+       mr      r31,r3          /* save device tree ptr */
        li      r24,0           /* CPU number */
 
        bl      init_cpu_state
@@ -120,11 +113,8 @@ _ENTRY(_start);
 /*
  * Decide what sort of machine this is and initialize the MMU.
  */
-       mr      r3,r31
-       mr      r4,r30
-       mr      r5,r29
-       mr      r6,r28
-       mr      r7,r27
+       li      r3,0
+       mr      r4,r31
        bl      machine_init
        bl      MMU_init
 
index 3564c49..06c7251 100644 (file)
  *  For pSeries or server processors:
  *   1. The MMU is off & open firmware is running in real mode.
  *   2. The kernel is entered at __start
+ * -or- For OPAL entry:
+ *   1. The MMU is off, processor in HV mode, primary CPU enters at 0
+ *      with device-tree in gpr3. We also get OPAL base in r8 and
+ *     entry in r9 for debugging purposes
+ *   2. Secondary processors enter at 0x60 with PIR in gpr3
  *
  *  For iSeries:
  *   1. The MMU is on (as it always is for iSeries)
@@ -331,6 +336,11 @@ _GLOBAL(__start_initialization_multiplatform)
        /* Save parameters */
        mr      r31,r3
        mr      r30,r4
+#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL
+       /* Save OPAL entry */
+       mr      r28,r8
+       mr      r29,r9
+#endif
 
 #ifdef CONFIG_PPC_BOOK3E
        bl      .start_initialization_book3e
@@ -674,9 +684,9 @@ _GLOBAL(enable_64b_mode)
 _GLOBAL(relative_toc)
        mflr    r0
        bcl     20,31,$+4
-0:     mflr    r9
-       ld      r2,(p_toc - 0b)(r9)
-       add     r2,r2,r9
+0:     mflr    r11
+       ld      r2,(p_toc - 0b)(r11)
+       add     r2,r2,r11
        mtlr    r0
        blr
 
@@ -707,6 +717,12 @@ _INIT_STATIC(start_here_multiplatform)
        bdnz    3b
 4:
 
+#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL
+       /* Setup OPAL entry */
+       std     r28,0(r11);
+       std     r29,8(r11);
+#endif
+
 #ifndef CONFIG_PPC_BOOK3E
        mfmsr   r6
        ori     r6,r6,MSR_RI
index 1cbf64e..b68cb17 100644 (file)
@@ -76,11 +76,7 @@ _ENTRY(_start);
  */
        .globl  __start
 __start:
-       mr      r31,r3                  /* save parameters */
-       mr      r30,r4
-       mr      r29,r5
-       mr      r28,r6
-       mr      r27,r7
+       mr      r31,r3                  /* save device tree ptr */
 
        /* We have to turn on the MMU right away so we get cache modes
         * set correctly.
@@ -723,11 +719,8 @@ start_here:
 /*
  * Decide what sort of machine this is and initialize the MMU.
  */
-       mr      r3,r31
-       mr      r4,r30
-       mr      r5,r29
-       mr      r6,r28
-       mr      r7,r27
+       li      r3,0
+       mr      r4,r31
        bl      machine_init
        bl      MMU_init
 
index 5084592..9f5d210 100644 (file)
@@ -63,17 +63,30 @@ _ENTRY(_start);
         * of abatron_pteptrs
         */
        nop
-/*
- * Save parameters we are passed
- */
-       mr      r31,r3
-       mr      r30,r4
-       mr      r29,r5
-       mr      r28,r6
-       mr      r27,r7
-       li      r25,0           /* phys kernel start (low) */
-       li      r24,0           /* CPU number */
-       li      r23,0           /* phys kernel start (high) */
+
+       /* Translate device tree address to physical, save in r30/r31 */
+       mfmsr   r16
+       mfspr   r17,SPRN_PID
+       rlwinm  r17,r17,16,0x3fff0000   /* turn PID into MAS6[SPID] */
+       rlwimi  r17,r16,28,0x00000001   /* turn MSR[DS] into MAS6[SAS] */
+       mtspr   SPRN_MAS6,r17
+
+       tlbsx   0,r3                    /* must succeed */
+
+       mfspr   r16,SPRN_MAS1
+       mfspr   r20,SPRN_MAS3
+       rlwinm  r17,r16,25,0x1f         /* r17 = log2(page size) */
+       li      r18,1024
+       slw     r18,r18,r17             /* r18 = page size */
+       addi    r18,r18,-1
+       and     r19,r3,r18              /* r19 = page offset */
+       andc    r31,r20,r18             /* r31 = page base */
+       or      r31,r31,r19             /* r31 = devtree phys addr */
+       mfspr   r30,SPRN_MAS7
+
+       li      r25,0                   /* phys kernel start (low) */
+       li      r24,0                   /* CPU number */
+       li      r23,0                   /* phys kernel start (high) */
 
 /* We try to not make any assumptions about how the boot loader
  * setup or used the TLBs.  We invalidate all mappings from the
@@ -198,11 +211,8 @@ _ENTRY(__early_start)
 /*
  * Decide what sort of machine this is and initialize the MMU.
  */
-       mr      r3,r31
-       mr      r4,r30
-       mr      r5,r29
-       mr      r6,r28
-       mr      r7,r27
+       mr      r3,r30
+       mr      r4,r31
        bl      machine_init
        bl      MMU_init
 
@@ -236,8 +246,24 @@ _ENTRY(__early_start)
  * if we find the pte (fall through):
  *   r11 is low pte word
  *   r12 is pointer to the pte
+ *   r10 is the pshift from the PGD, if we're a hugepage
  */
 #ifdef CONFIG_PTE_64BIT
+#ifdef CONFIG_HUGETLB_PAGE
+#define FIND_PTE       \
+       rlwinm  r12, r10, 13, 19, 29;   /* Compute pgdir/pmd offset */  \
+       lwzx    r11, r12, r11;          /* Get pgd/pmd entry */         \
+       rlwinm. r12, r11, 0, 0, 20;     /* Extract pt base address */   \
+       blt     1000f;                  /* Normal non-huge page */      \
+       beq     2f;                     /* Bail if no table */          \
+       oris    r11, r11, PD_HUGE@h;    /* Put back address bit */      \
+       andi.   r10, r11, HUGEPD_SHIFT_MASK@l; /* extract size field */ \
+       xor     r12, r10, r11;          /* drop size bits from pointer */ \
+       b       1001f;                                                  \
+1000:  rlwimi  r12, r10, 23, 20, 28;   /* Compute pte address */       \
+       li      r10, 0;                 /* clear r10 */                 \
+1001:  lwz     r11, 4(r12);            /* Get pte entry */
+#else
 #define FIND_PTE       \
        rlwinm  r12, r10, 13, 19, 29;   /* Compute pgdir/pmd offset */  \
        lwzx    r11, r12, r11;          /* Get pgd/pmd entry */         \
@@ -245,7 +271,8 @@ _ENTRY(__early_start)
        beq     2f;                     /* Bail if no table */          \
        rlwimi  r12, r10, 23, 20, 28;   /* Compute pte address */       \
        lwz     r11, 4(r12);            /* Get pte entry */
-#else
+#endif /* HUGEPAGE */
+#else /* !PTE_64BIT */
 #define FIND_PTE       \
        rlwimi  r11, r10, 12, 20, 29;   /* Create L1 (pgdir/pmd) address */     \
        lwz     r11, 0(r11);            /* Get L1 entry */                      \
@@ -402,8 +429,8 @@ interrupt_base:
 
 #ifdef CONFIG_PTE_64BIT
 #ifdef CONFIG_SMP
-       subf    r10,r11,r12             /* create false data dep */
-       lwzx    r13,r11,r10             /* Get upper pte bits */
+       subf    r13,r11,r12             /* create false data dep */
+       lwzx    r13,r11,r13             /* Get upper pte bits */
 #else
        lwz     r13,0(r12)              /* Get upper pte bits */
 #endif
@@ -483,8 +510,8 @@ interrupt_base:
 
 #ifdef CONFIG_PTE_64BIT
 #ifdef CONFIG_SMP
-       subf    r10,r11,r12             /* create false data dep */
-       lwzx    r13,r11,r10             /* Get upper pte bits */
+       subf    r13,r11,r12             /* create false data dep */
+       lwzx    r13,r11,r13             /* Get upper pte bits */
 #else
        lwz     r13,0(r12)              /* Get upper pte bits */
 #endif
@@ -548,7 +575,7 @@ interrupt_base:
 /*
  * Both the instruction and data TLB miss get to this
  * point to load the TLB.
- *     r10 - available to use
+ *     r10 - tsize encoding (if HUGETLB_PAGE) or available to use
  *     r11 - TLB (info from Linux PTE)
  *     r12 - available to use
  *     r13 - upper bits of PTE (if PTE_64BIT) or available to use
@@ -558,21 +585,73 @@ interrupt_base:
  *     Upon exit, we reload everything and RFI.
  */
 finish_tlb_load:
+#ifdef CONFIG_HUGETLB_PAGE
+       cmpwi   6, r10, 0                       /* check for huge page */
+       beq     6, finish_tlb_load_cont         /* !huge */
+
+       /* Alas, we need more scratch registers for hugepages */
+       mfspr   r12, SPRN_SPRG_THREAD
+       stw     r14, THREAD_NORMSAVE(4)(r12)
+       stw     r15, THREAD_NORMSAVE(5)(r12)
+       stw     r16, THREAD_NORMSAVE(6)(r12)
+       stw     r17, THREAD_NORMSAVE(7)(r12)
+
+       /* Get the next_tlbcam_idx percpu var */
+#ifdef CONFIG_SMP
+       lwz     r12, THREAD_INFO-THREAD(r12)
+       lwz     r15, TI_CPU(r12)
+       lis     r14, __per_cpu_offset@h
+       ori     r14, r14, __per_cpu_offset@l
+       rlwinm  r15, r15, 2, 0, 29
+       lwzx    r16, r14, r15
+#else
+       li      r16, 0
+#endif
+       lis     r17, next_tlbcam_idx@h
+       ori     r17, r17, next_tlbcam_idx@l
+       add     r17, r17, r16                   /* r17 = *next_tlbcam_idx */
+       lwz     r15, 0(r17)                     /* r15 = next_tlbcam_idx */
+
+       lis     r14, MAS0_TLBSEL(1)@h           /* select TLB1 (TLBCAM) */
+       rlwimi  r14, r15, 16, 4, 15             /* next_tlbcam_idx entry */
+       mtspr   SPRN_MAS0, r14
+
+       /* Extract TLB1CFG(NENTRY) */
+       mfspr   r16, SPRN_TLB1CFG
+       andi.   r16, r16, 0xfff
+
+       /* Update next_tlbcam_idx, wrapping when necessary */
+       addi    r15, r15, 1
+       cmpw    r15, r16
+       blt     100f
+       lis     r14, tlbcam_index@h
+       ori     r14, r14, tlbcam_index@l
+       lwz     r15, 0(r14)
+100:   stw     r15, 0(r17)
+
+       /*
+        * Calc MAS1_TSIZE from r10 (which has pshift encoded)
+        * tlb_enc = (pshift - 10).
+        */
+       subi    r15, r10, 10
+       mfspr   r16, SPRN_MAS1
+       rlwimi  r16, r15, 7, 20, 24
+       mtspr   SPRN_MAS1, r16
+
+       /* copy the pshift for use later */
+       mr      r14, r10
+
+       /* fall through */
+
+#endif /* CONFIG_HUGETLB_PAGE */
+
        /*
         * We set execute, because we don't have the granularity to
         * properly set this at the page level (Linux problem).
         * Many of these bits are software only.  Bits we don't set
         * here we (properly should) assume have the appropriate value.
         */
-
-       mfspr   r12, SPRN_MAS2
-#ifdef CONFIG_PTE_64BIT
-       rlwimi  r12, r11, 32-19, 27, 31 /* extract WIMGE from pte */
-#else
-       rlwimi  r12, r11, 26, 27, 31    /* extract WIMGE from pte */
-#endif
-       mtspr   SPRN_MAS2, r12
-
+finish_tlb_load_cont:
 #ifdef CONFIG_PTE_64BIT
        rlwinm  r12, r11, 32-2, 26, 31  /* Move in perm bits */
        andi.   r10, r11, _PAGE_DIRTY
@@ -581,22 +660,40 @@ finish_tlb_load:
        andc    r12, r12, r10
 1:     rlwimi  r12, r13, 20, 0, 11     /* grab RPN[32:43] */
        rlwimi  r12, r11, 20, 12, 19    /* grab RPN[44:51] */
-       mtspr   SPRN_MAS3, r12
+2:     mtspr   SPRN_MAS3, r12
 BEGIN_MMU_FTR_SECTION
        srwi    r10, r13, 12            /* grab RPN[12:31] */
        mtspr   SPRN_MAS7, r10
 END_MMU_FTR_SECTION_IFSET(MMU_FTR_BIG_PHYS)
 #else
        li      r10, (_PAGE_EXEC | _PAGE_PRESENT)
+       mr      r13, r11
        rlwimi  r10, r11, 31, 29, 29    /* extract _PAGE_DIRTY into SW */
        and     r12, r11, r10
        andi.   r10, r11, _PAGE_USER    /* Test for _PAGE_USER */
        slwi    r10, r12, 1
        or      r10, r10, r12
        iseleq  r12, r12, r10
-       rlwimi  r11, r12, 0, 20, 31     /* Extract RPN from PTE and merge with perms */
-       mtspr   SPRN_MAS3, r11
+       rlwimi  r13, r12, 0, 20, 31     /* Get RPN from PTE, merge w/ perms */
+       mtspr   SPRN_MAS3, r13
 #endif
+
+       mfspr   r12, SPRN_MAS2
+#ifdef CONFIG_PTE_64BIT
+       rlwimi  r12, r11, 32-19, 27, 31 /* extract WIMGE from pte */
+#else
+       rlwimi  r12, r11, 26, 27, 31    /* extract WIMGE from pte */
+#endif
+#ifdef CONFIG_HUGETLB_PAGE
+       beq     6, 3f                   /* don't mask if page isn't huge */
+       li      r13, 1
+       slw     r13, r13, r14
+       subi    r13, r13, 1
+       rlwinm  r13, r13, 0, 0, 19      /* bottom bits used for WIMGE/etc */
+       andc    r12, r12, r13           /* mask off ea bits within the page */
+#endif
+3:     mtspr   SPRN_MAS2, r12
+
 #ifdef CONFIG_E200
        /* Round robin TLB1 entries assignment */
        mfspr   r12, SPRN_MAS0
@@ -622,11 +719,19 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_BIG_PHYS)
        mtspr   SPRN_MAS0,r12
 #endif /* CONFIG_E200 */
 
+tlb_write_entry:
        tlbwe
 
        /* Done...restore registers and get out of here.  */
        mfspr   r10, SPRN_SPRG_THREAD
-       lwz     r11, THREAD_NORMSAVE(3)(r10)
+#ifdef CONFIG_HUGETLB_PAGE
+       beq     6, 8f /* skip restore for 4k page faults */
+       lwz     r14, THREAD_NORMSAVE(4)(r10)
+       lwz     r15, THREAD_NORMSAVE(5)(r10)
+       lwz     r16, THREAD_NORMSAVE(6)(r10)
+       lwz     r17, THREAD_NORMSAVE(7)(r10)
+#endif
+8:     lwz     r11, THREAD_NORMSAVE(3)(r10)
        mtcr    r11
        lwz     r13, THREAD_NORMSAVE(2)(r10)
        lwz     r12, THREAD_NORMSAVE(1)(r10)
index 28581f1..73110fb 100644 (file)
@@ -125,17 +125,23 @@ static void ibmebus_unmap_sg(struct device *dev,
 
 static int ibmebus_dma_supported(struct device *dev, u64 mask)
 {
-       return 1;
+       return mask == DMA_BIT_MASK(64);
+}
+
+static u64 ibmebus_dma_get_required_mask(struct device *dev)
+{
+       return DMA_BIT_MASK(64);
 }
 
 static struct dma_map_ops ibmebus_dma_ops = {
-       .alloc_coherent = ibmebus_alloc_coherent,
-       .free_coherent  = ibmebus_free_coherent,
-       .map_sg         = ibmebus_map_sg,
-       .unmap_sg       = ibmebus_unmap_sg,
-       .dma_supported  = ibmebus_dma_supported,
-       .map_page       = ibmebus_map_page,
-       .unmap_page     = ibmebus_unmap_page,
+       .alloc_coherent     = ibmebus_alloc_coherent,
+       .free_coherent      = ibmebus_free_coherent,
+       .map_sg             = ibmebus_map_sg,
+       .unmap_sg           = ibmebus_unmap_sg,
+       .dma_supported      = ibmebus_dma_supported,
+       .get_required_mask  = ibmebus_dma_get_required_mask,
+       .map_page           = ibmebus_map_page,
+       .unmap_page         = ibmebus_unmap_page,
 };
 
 static int ibmebus_match_path(struct device *dev, void *data)
index 3e2b95c..4f0ab85 100644 (file)
@@ -26,7 +26,7 @@ _GLOBAL(e500_idle)
        ori     r4,r4,_TLF_NAPPING      /* so when we take an exception */
        stw     r4,TI_LOCAL_FLAGS(r3)   /* it will return to our caller */
 
-#ifdef CONFIG_E500MC
+#ifdef CONFIG_PPC_E500MC
        wrteei  1
 1:     wait
 
index 961bb03..0cfcf98 100644 (file)
@@ -501,6 +501,14 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid)
        tbl->it_map = page_address(page);
        memset(tbl->it_map, 0, sz);
 
+       /*
+        * Reserve page 0 so it will not be used for any mappings.
+        * This avoids buggy drivers that consider page 0 to be invalid
+        * to crash the machine or even lose data.
+        */
+       if (tbl->it_offset == 0)
+               set_bit(0, tbl->it_map);
+
        tbl->it_hint = 0;
        tbl->it_largehint = tbl->it_halfpoint;
        spin_lock_init(&tbl->it_lock);
index 2b97b80..c7b5afe 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/pci.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
+#include <linux/serial_reg.h>
 #include <asm/io.h>
 #include <asm/mmu.h>
 #include <asm/prom.h>
@@ -47,6 +48,24 @@ static struct __initdata of_device_id legacy_serial_parents[] = {
 static unsigned int legacy_serial_count;
 static int legacy_serial_console = -1;
 
+static unsigned int tsi_serial_in(struct uart_port *p, int offset)
+{
+       unsigned int tmp;
+       offset = offset << p->regshift;
+       if (offset == UART_IIR) {
+               tmp = readl(p->membase + (UART_IIR & ~3));
+               return (tmp >> 16) & 0xff; /* UART_IIR % 4 == 2 */
+       } else
+               return readb(p->membase + offset);
+}
+
+static void tsi_serial_out(struct uart_port *p, int offset, int value)
+{
+       offset = offset << p->regshift;
+       if (!((offset == UART_IER) && (value & UART_IER_UUE)))
+               writeb(value, p->membase + offset);
+}
+
 static int __init add_legacy_port(struct device_node *np, int want_index,
                                  int iotype, phys_addr_t base,
                                  phys_addr_t taddr, unsigned long irq,
@@ -102,6 +121,7 @@ static int __init add_legacy_port(struct device_node *np, int want_index,
                legacy_serial_ports[index].iobase = base;
        else
                legacy_serial_ports[index].mapbase = base;
+
        legacy_serial_ports[index].iotype = iotype;
        legacy_serial_ports[index].uartclk = clock;
        legacy_serial_ports[index].irq = irq;
@@ -112,6 +132,11 @@ static int __init add_legacy_port(struct device_node *np, int want_index,
        legacy_serial_infos[index].speed = spd ? be32_to_cpup(spd) : 0;
        legacy_serial_infos[index].irq_check_parent = irq_check_parent;
 
+       if (iotype == UPIO_TSI) {
+               legacy_serial_ports[index].serial_in = tsi_serial_in;
+               legacy_serial_ports[index].serial_out = tsi_serial_out;
+       }
+
        printk(KERN_DEBUG "Found legacy serial port %d for %s\n",
               index, np->full_name);
        printk(KERN_DEBUG "  %s=%llx, taddr=%llx, irq=%lx, clk=%d, speed=%d\n",
index 583af70..26ccbf7 100644 (file)
@@ -74,8 +74,7 @@ int default_machine_kexec_prepare(struct kimage *image)
        }
 
        /* We also should not overwrite the tce tables */
-       for (node = of_find_node_by_type(NULL, "pci"); node != NULL;
-                       node = of_find_node_by_type(node, "pci")) {
+       for_each_node_by_type(node, "pci") {
                basep = of_get_property(node, "linux,tce-base", NULL);
                sizep = of_get_property(node, "linux,tce-size", NULL);
                if (basep == NULL || sizep == NULL)
index 998a100..f7d760a 100644 (file)
@@ -8,6 +8,8 @@
  * kexec bits:
  * Copyright (C) 2002-2003 Eric Biederman  <ebiederm@xmission.com>
  * GameCube/ppc32 port Copyright (C) 2004 Albert Herranz
+ * PPC44x port. Copyright (C) 2011,  IBM Corporation
+ *             Author: Suzuki Poulose <suzuki@in.ibm.com>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -736,6 +738,175 @@ relocate_new_kernel:
        mr      r5, r31
 
        li      r0, 0
+#elif defined(CONFIG_44x)  && !defined(CONFIG_47x)
+
+/*
+ * Code for setting up 1:1 mapping for PPC440x for KEXEC
+ *
+ * We cannot switch off the MMU on PPC44x.
+ * So we:
+ * 1) Invalidate all the mappings except the one we are running from.
+ * 2) Create a tmp mapping for our code in the other address space(TS) and
+ *    jump to it. Invalidate the entry we started in.
+ * 3) Create a 1:1 mapping for 0-2GiB in chunks of 256M in original TS.
+ * 4) Jump to the 1:1 mapping in original TS.
+ * 5) Invalidate the tmp mapping.
+ *
+ * - Based on the kexec support code for FSL BookE
+ * - Doesn't support 47x yet.
+ *
+ */
+       /* Save our parameters */
+       mr      r29, r3
+       mr      r30, r4
+       mr      r31, r5
+
+       /* Load our MSR_IS and TID to MMUCR for TLB search */
+       mfspr   r3,SPRN_PID
+       mfmsr   r4
+       andi.   r4,r4,MSR_IS@l
+       beq     wmmucr
+       oris    r3,r3,PPC44x_MMUCR_STS@h
+wmmucr:
+       mtspr   SPRN_MMUCR,r3
+       sync
+
+       /*
+        * Invalidate all the TLB entries except the current entry
+        * where we are running from
+        */
+       bl      0f                              /* Find our address */
+0:     mflr    r5                              /* Make it accessible */
+       tlbsx   r23,0,r5                        /* Find entry we are in */
+       li      r4,0                            /* Start at TLB entry 0 */
+       li      r3,0                            /* Set PAGEID inval value */
+1:     cmpw    r23,r4                          /* Is this our entry? */
+       beq     skip                            /* If so, skip the inval */
+       tlbwe   r3,r4,PPC44x_TLB_PAGEID         /* If not, inval the entry */
+skip:
+       addi    r4,r4,1                         /* Increment */
+       cmpwi   r4,64                           /* Are we done? */
+       bne     1b                              /* If not, repeat */
+       isync
+
+       /* Create a temp mapping and jump to it */
+       andi.   r6, r23, 1              /* Find the index to use */
+       addi    r24, r6, 1              /* r24 will contain 1 or 2 */
+
+       mfmsr   r9                      /* get the MSR */
+       rlwinm  r5, r9, 27, 31, 31      /* Extract the MSR[IS] */
+       xori    r7, r5, 1               /* Use the other address space */
+
+       /* Read the current mapping entries */
+       tlbre   r3, r23, PPC44x_TLB_PAGEID
+       tlbre   r4, r23, PPC44x_TLB_XLAT
+       tlbre   r5, r23, PPC44x_TLB_ATTRIB
+
+       /* Save our current XLAT entry */
+       mr      r25, r4
+
+       /* Extract the TLB PageSize */
+       li      r10, 1                  /* r10 will hold PageSize */
+       rlwinm  r11, r3, 0, 24, 27      /* bits 24-27 */
+
+       /* XXX: As of now we use 256M, 4K pages */
+       cmpwi   r11, PPC44x_TLB_256M
+       bne     tlb_4k
+       rotlwi  r10, r10, 28            /* r10 = 256M */
+       b       write_out
+tlb_4k:
+       cmpwi   r11, PPC44x_TLB_4K
+       bne     default
+       rotlwi  r10, r10, 12            /* r10 = 4K */
+       b       write_out
+default:
+       rotlwi  r10, r10, 10            /* r10 = 1K */
+
+write_out:
+       /*
+        * Write out the tmp 1:1 mapping for this code in other address space
+        * Fixup  EPN = RPN , TS=other address space
+        */
+       insrwi  r3, r7, 1, 23           /* Bit 23 is TS for PAGEID field */
+
+       /* Write out the tmp mapping entries */
+       tlbwe   r3, r24, PPC44x_TLB_PAGEID
+       tlbwe   r4, r24, PPC44x_TLB_XLAT
+       tlbwe   r5, r24, PPC44x_TLB_ATTRIB
+
+       subi    r11, r10, 1             /* PageOffset Mask = PageSize - 1 */
+       not     r10, r11                /* Mask for PageNum */
+
+       /* Switch to other address space in MSR */
+       insrwi  r9, r7, 1, 26           /* Set MSR[IS] = r7 */
+
+       bl      1f
+1:     mflr    r8
+       addi    r8, r8, (2f-1b)         /* Find the target offset */
+
+       /* Jump to the tmp mapping */
+       mtspr   SPRN_SRR0, r8
+       mtspr   SPRN_SRR1, r9
+       rfi
+
+2:
+       /* Invalidate the entry we were executing from */
+       li      r3, 0
+       tlbwe   r3, r23, PPC44x_TLB_PAGEID
+
+       /* attribute fields. rwx for SUPERVISOR mode */
+       li      r5, 0
+       ori     r5, r5, (PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_SX | PPC44x_TLB_G)
+
+       /* Create 1:1 mapping in 256M pages */
+       xori    r7, r7, 1                       /* Revert back to Original TS */
+
+       li      r8, 0                           /* PageNumber */
+       li      r6, 3                           /* TLB Index, start at 3  */
+
+next_tlb:
+       rotlwi  r3, r8, 28                      /* Create EPN (bits 0-3) */
+       mr      r4, r3                          /* RPN = EPN  */
+       ori     r3, r3, (PPC44x_TLB_VALID | PPC44x_TLB_256M) /* SIZE = 256M, Valid */
+       insrwi  r3, r7, 1, 23                   /* Set TS from r7 */
+
+       tlbwe   r3, r6, PPC44x_TLB_PAGEID       /* PageID field : EPN, V, SIZE */
+       tlbwe   r4, r6, PPC44x_TLB_XLAT         /* Address translation : RPN   */
+       tlbwe   r5, r6, PPC44x_TLB_ATTRIB       /* Attributes */
+
+       addi    r8, r8, 1                       /* Increment PN */
+       addi    r6, r6, 1                       /* Increment TLB Index */
+       cmpwi   r8, 8                           /* Are we done ? */
+       bne     next_tlb
+       isync
+
+       /* Jump to the new mapping 1:1 */
+       li      r9,0
+       insrwi  r9, r7, 1, 26                   /* Set MSR[IS] = r7 */
+
+       bl      1f
+1:     mflr    r8
+       and     r8, r8, r11                     /* Get our offset within page */
+       addi    r8, r8, (2f-1b)
+
+       and     r5, r25, r10                    /* Get our target PageNum */
+       or      r8, r8, r5                      /* Target jump address */
+
+       mtspr   SPRN_SRR0, r8
+       mtspr   SPRN_SRR1, r9
+       rfi
+2:
+       /* Invalidate the tmp entry we used */
+       li      r3, 0
+       tlbwe   r3, r24, PPC44x_TLB_PAGEID
+       sync
+
+       /* Restore the parameters */
+       mr      r3, r29
+       mr      r4, r30
+       mr      r5, r31
+
+       li      r0, 0
 #else
        li      r0, 0
 
index 32656f1..677eccc 100644 (file)
@@ -1730,6 +1730,17 @@ void __devinit pcibios_scan_phb(struct pci_controller *hose)
 
        if (mode == PCI_PROBE_NORMAL)
                hose->last_busno = bus->subordinate = pci_scan_child_bus(bus);
+
+       /* Configure PCI Express settings */
+       if (bus && !pci_has_flag(PCI_PROBE_ONLY)) {
+               struct pci_bus *child;
+               list_for_each_entry(child, &bus->children, node) {
+                       struct pci_dev *self = child->self;
+                       if (!self)
+                               continue;
+                       pcie_bus_configure_settings(child, self->pcie_mpss);
+               }
+       }
 }
 
 static void fixup_hide_host_resource_fsl(struct pci_dev *dev)
index 03b95e2..0bbc901 100644 (file)
@@ -487,8 +487,8 @@ static int power6_generic_events[] = {
  */
 static int power6_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
        [C(L1D)] = {            /*      RESULT_ACCESS   RESULT_MISS */
-               [C(OP_READ)] = {        0x80082,        0x80080         },
-               [C(OP_WRITE)] = {       0x80086,        0x80088         },
+               [C(OP_READ)] = {        0x280030,       0x80080         },
+               [C(OP_WRITE)] = {       0x180032,       0x80088         },
                [C(OP_PREFETCH)] = {    0x810a4,        0               },
        },
        [C(L1I)] = {            /*      RESULT_ACCESS   RESULT_MISS */
index de83d60..1251e4d 100644 (file)
@@ -297,6 +297,8 @@ static void power7_disable_pmc(unsigned int pmc, unsigned long mmcr[])
 
 static int power7_generic_events[] = {
        [PERF_COUNT_HW_CPU_CYCLES] = 0x1e,
+       [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = 0x100f8, /* GCT_NOSLOT_CYC */
+       [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = 0x4000a,  /* CMPLU_STALL */
        [PERF_COUNT_HW_INSTRUCTIONS] = 2,
        [PERF_COUNT_HW_CACHE_REFERENCES] = 0xc880,      /* LD_REF_L1_LSU*/
        [PERF_COUNT_HW_CACHE_MISSES] = 0x400f0,         /* LD_MISS_L1   */
index 174e1e9..8ad825c 100644 (file)
@@ -54,6 +54,8 @@
 #include <asm/pci-bridge.h>
 #include <asm/phyp_dump.h>
 #include <asm/kexec.h>
+#include <asm/opal.h>
+
 #include <mm/mmu_decl.h>
 
 #ifdef DEBUG
@@ -707,11 +709,23 @@ void __init early_init_devtree(void *params)
        of_scan_flat_dt(early_init_dt_scan_rtas, NULL);
 #endif
 
+#ifdef CONFIG_PPC_POWERNV
+       /* Some machines might need OPAL info for debugging, grab it now. */
+       of_scan_flat_dt(early_init_dt_scan_opal, NULL);
+#endif
+
 #ifdef CONFIG_PHYP_DUMP
        /* scan tree to see if dump occurred during last boot */
        of_scan_flat_dt(early_init_dt_scan_phyp_dump, NULL);
 #endif
 
+       /* Pre-initialize the cmd_line with the content of boot_commmand_line,
+        * which will be empty except when the content of the variable has
+        * been overriden by a bootloading mechanism. This happens typically
+        * with HAL takeover
+        */
+       strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE);
+
        /* Retrieve various informations from the /chosen node of the
         * device-tree, including the platform type, initrd location and
         * size, TCE reserve, and more ...
@@ -723,12 +737,15 @@ void __init early_init_devtree(void *params)
 
        of_scan_flat_dt(early_init_dt_scan_root, NULL);
        of_scan_flat_dt(early_init_dt_scan_memory_ppc, NULL);
-       setup_initial_memory_limit(memstart_addr, first_memblock_size);
 
        /* Save command line for /proc/cmdline and then parse parameters */
        strlcpy(boot_command_line, cmd_line, COMMAND_LINE_SIZE);
        parse_early_param();
 
+       /* make sure we've parsed cmdline for mem= before this */
+       if (memory_limit)
+               first_memblock_size = min(first_memblock_size, memory_limit);
+       setup_initial_memory_limit(memstart_addr, first_memblock_size);
        /* Reserve MEMBLOCK regions used by kernel, initrd, dt, etc... */
        memblock_reserve(PHYSICAL_START, __pa(klimit) - PHYSICAL_START);
        /* If relocatable, reserve first 32k for interrupt vectors etc. */
index a909f4e..b4fa661 100644 (file)
@@ -43,6 +43,7 @@
 #include <asm/btext.h>
 #include <asm/sections.h>
 #include <asm/machdep.h>
+#include <asm/opal.h>
 
 #include <linux/linux_logo.h>
 
@@ -139,7 +140,9 @@ struct mem_map_entry {
 
 typedef u32 cell_t;
 
-extern void __start(unsigned long r3, unsigned long r4, unsigned long r5);
+extern void __start(unsigned long r3, unsigned long r4, unsigned long r5,
+                   unsigned long r6, unsigned long r7, unsigned long r8,
+                   unsigned long r9);
 
 #ifdef CONFIG_PPC64
 extern int enter_prom(struct prom_args *args, unsigned long entry);
@@ -185,6 +188,7 @@ static unsigned long __initdata prom_tce_alloc_end;
 #define PLATFORM_LPAR          0x0001
 #define PLATFORM_POWERMAC      0x0400
 #define PLATFORM_GENERIC       0x0500
+#define PLATFORM_OPAL          0x0600
 
 static int __initdata of_platform;
 
@@ -644,7 +648,7 @@ static void __init early_cmdline_parse(void)
        }
 }
 
-#ifdef CONFIG_PPC_PSERIES
+#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV)
 /*
  * There are two methods for telling firmware what our capabilities are.
  * Newer machines have an "ibm,client-architecture-support" method on the
@@ -1274,6 +1278,284 @@ static void __init prom_init_mem(void)
        prom_printf("  ram_top      : %x\n", RELOC(ram_top));
 }
 
+static void __init prom_close_stdin(void)
+{
+       struct prom_t *_prom = &RELOC(prom);
+       ihandle val;
+
+       if (prom_getprop(_prom->chosen, "stdin", &val, sizeof(val)) > 0)
+               call_prom("close", 1, 0, val);
+}
+
+#ifdef CONFIG_PPC_POWERNV
+
+static u64 __initdata prom_opal_size;
+static u64 __initdata prom_opal_align;
+static int __initdata prom_rtas_start_cpu;
+static u64 __initdata prom_rtas_data;
+static u64 __initdata prom_rtas_entry;
+
+#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL
+static u64 __initdata prom_opal_base;
+static u64 __initdata prom_opal_entry;
+#endif
+
+/* XXX Don't change this structure without updating opal-takeover.S */
+static struct opal_secondary_data {
+       s64                             ack;    /*  0 */
+       u64                             go;     /*  8 */
+       struct opal_takeover_args       args;   /* 16 */
+} opal_secondary_data;
+
+extern char opal_secondary_entry;
+
+static void prom_query_opal(void)
+{
+       long rc;
+
+       /* We must not query for OPAL presence on a machine that
+        * supports TNK takeover (970 blades), as this uses the same
+        * h-call with different arguments and will crash
+        */
+       if (PHANDLE_VALID(call_prom("finddevice", 1, 1,
+                                   ADDR("/tnk-memory-map")))) {
+               prom_printf("TNK takeover detected, skipping OPAL check\n");
+               return;
+       }
+
+       prom_printf("Querying for OPAL presence... ");
+       rc = opal_query_takeover(&RELOC(prom_opal_size),
+                                &RELOC(prom_opal_align));
+       prom_debug("(rc = %ld) ", rc);
+       if (rc != 0) {
+               prom_printf("not there.\n");
+               return;
+       }
+       RELOC(of_platform) = PLATFORM_OPAL;
+       prom_printf(" there !\n");
+       prom_debug("  opal_size  = 0x%lx\n", RELOC(prom_opal_size));
+       prom_debug("  opal_align = 0x%lx\n", RELOC(prom_opal_align));
+       if (RELOC(prom_opal_align) < 0x10000)
+               RELOC(prom_opal_align) = 0x10000;
+}
+
+static int prom_rtas_call(int token, int nargs, int nret, int *outputs, ...)
+{
+       struct rtas_args rtas_args;
+       va_list list;
+       int i;
+
+       rtas_args.token = token;
+       rtas_args.nargs = nargs;
+       rtas_args.nret  = nret;
+       rtas_args.rets  = (rtas_arg_t *)&(rtas_args.args[nargs]);
+       va_start(list, outputs);
+       for (i = 0; i < nargs; ++i)
+               rtas_args.args[i] = va_arg(list, rtas_arg_t);
+       va_end(list);
+
+       for (i = 0; i < nret; ++i)
+               rtas_args.rets[i] = 0;
+
+       opal_enter_rtas(&rtas_args, RELOC(prom_rtas_data),
+                       RELOC(prom_rtas_entry));
+
+       if (nret > 1 && outputs != NULL)
+               for (i = 0; i < nret-1; ++i)
+                       outputs[i] = rtas_args.rets[i+1];
+       return (nret > 0)? rtas_args.rets[0]: 0;
+}
+
+static void __init prom_opal_hold_cpus(void)
+{
+       int i, cnt, cpu, rc;
+       long j;
+       phandle node;
+       char type[64];
+       u32 servers[8];
+       struct prom_t *_prom = &RELOC(prom);
+       void *entry = (unsigned long *)&RELOC(opal_secondary_entry);
+       struct opal_secondary_data *data = &RELOC(opal_secondary_data);
+
+       prom_debug("prom_opal_hold_cpus: start...\n");
+       prom_debug("    - entry       = 0x%x\n", entry);
+       prom_debug("    - data        = 0x%x\n", data);
+
+       data->ack = -1;
+       data->go = 0;
+
+       /* look for cpus */
+       for (node = 0; prom_next_node(&node); ) {
+               type[0] = 0;
+               prom_getprop(node, "device_type", type, sizeof(type));
+               if (strcmp(type, RELOC("cpu")) != 0)
+                       continue;
+
+               /* Skip non-configured cpus. */
+               if (prom_getprop(node, "status", type, sizeof(type)) > 0)
+                       if (strcmp(type, RELOC("okay")) != 0)
+                               continue;
+
+               cnt = prom_getprop(node, "ibm,ppc-interrupt-server#s", servers,
+                            sizeof(servers));
+               if (cnt == PROM_ERROR)
+                       break;
+               cnt >>= 2;
+               for (i = 0; i < cnt; i++) {
+                       cpu = servers[i];
+                       prom_debug("CPU %d ... ", cpu);
+                       if (cpu == _prom->cpu) {
+                               prom_debug("booted !\n");
+                               continue;
+                       }
+                       prom_debug("starting ... ");
+
+                       /* Init the acknowledge var which will be reset by
+                        * the secondary cpu when it awakens from its OF
+                        * spinloop.
+                        */
+                       data->ack = -1;
+                       rc = prom_rtas_call(RELOC(prom_rtas_start_cpu), 3, 1,
+                                           NULL, cpu, entry, data);
+                       prom_debug("rtas rc=%d ...", rc);
+
+                       for (j = 0; j < 100000000 && data->ack == -1; j++) {
+                               HMT_low();
+                               mb();
+                       }
+                       HMT_medium();
+                       if (data->ack != -1)
+                               prom_debug("done, PIR=0x%x\n", data->ack);
+                       else
+                               prom_debug("timeout !\n");
+               }
+       }
+       prom_debug("prom_opal_hold_cpus: end...\n");
+}
+
+static void prom_opal_takeover(void)
+{
+       struct opal_secondary_data *data = &RELOC(opal_secondary_data);
+       struct opal_takeover_args *args = &data->args;
+       u64 align = RELOC(prom_opal_align);
+       u64 top_addr, opal_addr;
+
+       args->k_image   = (u64)RELOC(_stext);
+       args->k_size    = _end - _stext;
+       args->k_entry   = 0;
+       args->k_entry2  = 0x60;
+
+       top_addr = _ALIGN_UP(args->k_size, align);
+
+       if (RELOC(prom_initrd_start) != 0) {
+               args->rd_image = RELOC(prom_initrd_start);
+               args->rd_size = RELOC(prom_initrd_end) - args->rd_image;
+               args->rd_loc = top_addr;
+               top_addr = _ALIGN_UP(args->rd_loc + args->rd_size, align);
+       }
+
+       /* Pickup an address for the HAL. We want to go really high
+        * up to avoid problem with future kexecs. On the other hand
+        * we don't want to be all over the TCEs on P5IOC2 machines
+        * which are going to be up there too. We assume the machine
+        * has plenty of memory, and we ask for the HAL for now to
+        * be just below the 1G point, or above the initrd
+        */
+       opal_addr = _ALIGN_DOWN(0x40000000 - RELOC(prom_opal_size), align);
+       if (opal_addr < top_addr)
+               opal_addr = top_addr;
+       args->hal_addr = opal_addr;
+
+       /* Copy the command line to the kernel image */
+       strlcpy(RELOC(boot_command_line), RELOC(prom_cmd_line),
+               COMMAND_LINE_SIZE);
+
+       prom_debug("  k_image    = 0x%lx\n", args->k_image);
+       prom_debug("  k_size     = 0x%lx\n", args->k_size);
+       prom_debug("  k_entry    = 0x%lx\n", args->k_entry);
+       prom_debug("  k_entry2   = 0x%lx\n", args->k_entry2);
+       prom_debug("  hal_addr   = 0x%lx\n", args->hal_addr);
+       prom_debug("  rd_image   = 0x%lx\n", args->rd_image);
+       prom_debug("  rd_size    = 0x%lx\n", args->rd_size);
+       prom_debug("  rd_loc     = 0x%lx\n", args->rd_loc);
+       prom_printf("Performing OPAL takeover,this can take a few minutes..\n");
+       prom_close_stdin();
+       mb();
+       data->go = 1;
+       for (;;)
+               opal_do_takeover(args);
+}
+
+/*
+ * Allocate room for and instantiate OPAL
+ */
+static void __init prom_instantiate_opal(void)
+{
+       phandle opal_node;
+       ihandle opal_inst;
+       u64 base, entry;
+       u64 size = 0, align = 0x10000;
+       u32 rets[2];
+
+       prom_debug("prom_instantiate_opal: start...\n");
+
+       opal_node = call_prom("finddevice", 1, 1, ADDR("/ibm,opal"));
+       prom_debug("opal_node: %x\n", opal_node);
+       if (!PHANDLE_VALID(opal_node))
+               return;
+
+       prom_getprop(opal_node, "opal-runtime-size", &size, sizeof(size));
+       if (size == 0)
+               return;
+       prom_getprop(opal_node, "opal-runtime-alignment", &align,
+                    sizeof(align));
+
+       base = alloc_down(size, align, 0);
+       if (base == 0) {
+               prom_printf("OPAL allocation failed !\n");
+               return;
+       }
+
+       opal_inst = call_prom("open", 1, 1, ADDR("/ibm,opal"));
+       if (!IHANDLE_VALID(opal_inst)) {
+               prom_printf("opening opal package failed (%x)\n", opal_inst);
+               return;
+       }
+
+       prom_printf("instantiating opal at 0x%x...", base);
+
+       if (call_prom_ret("call-method", 4, 3, rets,
+                         ADDR("load-opal-runtime"),
+                         opal_inst,
+                         base >> 32, base & 0xffffffff) != 0
+           || (rets[0] == 0 && rets[1] == 0)) {
+               prom_printf(" failed\n");
+               return;
+       }
+       entry = (((u64)rets[0]) << 32) | rets[1];
+
+       prom_printf(" done\n");
+
+       reserve_mem(base, size);
+
+       prom_debug("opal base     = 0x%x\n", base);
+       prom_debug("opal align    = 0x%x\n", align);
+       prom_debug("opal entry    = 0x%x\n", entry);
+       prom_debug("opal size     = 0x%x\n", (long)size);
+
+       prom_setprop(opal_node, "/ibm,opal", "opal-base-address",
+                    &base, sizeof(base));
+       prom_setprop(opal_node, "/ibm,opal", "opal-entry-address",
+                    &entry, sizeof(entry));
+
+#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL
+       RELOC(prom_opal_base) = base;
+       RELOC(prom_opal_entry) = entry;
+#endif
+       prom_debug("prom_instantiate_opal: end...\n");
+}
+
+#endif /* CONFIG_PPC_POWERNV */
 
 /*
  * Allocate room for and instantiate RTAS
@@ -1326,6 +1608,12 @@ static void __init prom_instantiate_rtas(void)
        prom_setprop(rtas_node, "/rtas", "linux,rtas-entry",
                     &entry, sizeof(entry));
 
+#ifdef CONFIG_PPC_POWERNV
+       /* PowerVN takeover hack */
+       RELOC(prom_rtas_data) = base;
+       RELOC(prom_rtas_entry) = entry;
+       prom_getprop(rtas_node, "start-cpu", &RELOC(prom_rtas_start_cpu), 4);
+#endif
        prom_debug("rtas base     = 0x%x\n", base);
        prom_debug("rtas entry    = 0x%x\n", entry);
        prom_debug("rtas size     = 0x%x\n", (long)size);
@@ -1543,7 +1831,7 @@ static void __init prom_hold_cpus(void)
                *acknowledge = (unsigned long)-1;
 
                if (reg != _prom->cpu) {
-                       /* Primary Thread of non-boot cpu */
+                       /* Primary Thread of non-boot cpu or any thread */
                        prom_printf("starting cpu hw idx %lu... ", reg);
                        call_prom("start-cpu", 3, 0, node,
                                  secondary_hold, reg);
@@ -1652,15 +1940,6 @@ static void __init prom_init_stdout(void)
                prom_setprop(val, path, "linux,boot-display", NULL, 0);
 }
 
-static void __init prom_close_stdin(void)
-{
-       struct prom_t *_prom = &RELOC(prom);
-       ihandle val;
-
-       if (prom_getprop(_prom->chosen, "stdin", &val, sizeof(val)) > 0)
-               call_prom("close", 1, 0, val);
-}
-
 static int __init prom_find_machine_type(void)
 {
        struct prom_t *_prom = &RELOC(prom);
@@ -1671,7 +1950,7 @@ static int __init prom_find_machine_type(void)
        int x;
 #endif
 
-       /* Look for a PowerMac */
+       /* Look for a PowerMac or a Cell */
        len = prom_getprop(_prom->root, "compatible",
                           compat, sizeof(compat)-1);
        if (len > 0) {
@@ -1697,7 +1976,11 @@ static int __init prom_find_machine_type(void)
                }
        }
 #ifdef CONFIG_PPC64
-       /* If not a mac, try to figure out if it's an IBM pSeries or any other
+       /* Try to detect OPAL */
+       if (PHANDLE_VALID(call_prom("finddevice", 1, 1, ADDR("/ibm,opal"))))
+               return PLATFORM_OPAL;
+
+       /* Try to figure out if it's an IBM pSeries or any other
         * PAPR compliant platform. We assume it is if :
         *  - /device_type is "chrp" (please, do NOT use that for future
         *    non-IBM designs !
@@ -1924,7 +2207,7 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
        unsigned long soff;
        unsigned char *valp;
        static char pname[MAX_PROPERTY_NAME];
-       int l, room;
+       int l, room, has_phandle = 0;
 
        dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end);
 
@@ -2008,19 +2291,26 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
                valp = make_room(mem_start, mem_end, l, 4);
                call_prom("getprop", 4, 1, node, RELOC(pname), valp, l);
                *mem_start = _ALIGN(*mem_start, 4);
+
+               if (!strcmp(RELOC(pname), RELOC("phandle")))
+                       has_phandle = 1;
        }
 
-       /* Add a "linux,phandle" property. */
-       soff = dt_find_string(RELOC("linux,phandle"));
-       if (soff == 0)
-               prom_printf("WARNING: Can't find string index for"
-                           " <linux-phandle> node %s\n", path);
-       else {
-               dt_push_token(OF_DT_PROP, mem_start, mem_end);
-               dt_push_token(4, mem_start, mem_end);
-               dt_push_token(soff, mem_start, mem_end);
-               valp = make_room(mem_start, mem_end, 4, 4);
-               *(u32 *)valp = node;
+       /* Add a "linux,phandle" property if no "phandle" property already
+        * existed (can happen with OPAL)
+        */
+       if (!has_phandle) {
+               soff = dt_find_string(RELOC("linux,phandle"));
+               if (soff == 0)
+                       prom_printf("WARNING: Can't find string index for"
+                                   " <linux-phandle> node %s\n", path);
+               else {
+                       dt_push_token(OF_DT_PROP, mem_start, mem_end);
+                       dt_push_token(4, mem_start, mem_end);
+                       dt_push_token(soff, mem_start, mem_end);
+                       valp = make_room(mem_start, mem_end, 4, 4);
+                       *(u32 *)valp = node;
+               }
        }
 
        /* do all our children */
@@ -2504,6 +2794,7 @@ static void __init prom_check_initrd(unsigned long r3, unsigned long r4)
 #endif /* CONFIG_BLK_DEV_INITRD */
 }
 
+
 /*
  * We enter here early on, when the Open Firmware prom is still
  * handling exceptions and the MMU hash table for us.
@@ -2553,6 +2844,7 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
         * between pSeries SMP and pSeries LPAR
         */
        RELOC(of_platform) = prom_find_machine_type();
+       prom_printf("Detected machine type: %x\n", RELOC(of_platform));
 
 #ifndef CONFIG_RELOCATABLE
        /* Bail if this is a kdump kernel. */
@@ -2565,7 +2857,7 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
         */
        prom_check_initrd(r3, r4);
 
-#ifdef CONFIG_PPC_PSERIES
+#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV)
        /*
         * On pSeries, inform the firmware about our capabilities
         */
@@ -2611,14 +2903,33 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
 #endif
 
        /*
-        * On non-powermacs, try to instantiate RTAS and puts all CPUs
-        * in spin-loops. PowerMacs don't have a working RTAS and use
-        * a different way to spin CPUs
+        * On non-powermacs, try to instantiate RTAS. PowerMacs don't
+        * have a usable RTAS implementation.
         */
-       if (RELOC(of_platform) != PLATFORM_POWERMAC) {
+       if (RELOC(of_platform) != PLATFORM_POWERMAC &&
+           RELOC(of_platform) != PLATFORM_OPAL)
                prom_instantiate_rtas();
+
+#ifdef CONFIG_PPC_POWERNV
+       /* Detect HAL and try instanciating it & doing takeover */
+       if (RELOC(of_platform) == PLATFORM_PSERIES_LPAR) {
+               prom_query_opal();
+               if (RELOC(of_platform) == PLATFORM_OPAL) {
+                       prom_opal_hold_cpus();
+                       prom_opal_takeover();
+               }
+       } else if (RELOC(of_platform) == PLATFORM_OPAL)
+               prom_instantiate_opal();
+#endif
+
+       /*
+        * On non-powermacs, put all CPUs in spin-loops.
+        *
+        * PowerMacs use a different mechanism to spin CPUs
+        */
+       if (RELOC(of_platform) != PLATFORM_POWERMAC &&
+           RELOC(of_platform) != PLATFORM_OPAL)
                prom_hold_cpus();
-       }
 
        /*
         * Fill in some infos for use by the kernel later on
@@ -2685,7 +2996,13 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
        reloc_got2(-offset);
 #endif
 
-       __start(hdr, kbase, 0);
+#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL
+       /* OPAL early debug gets the OPAL base & entry in r8 and r9 */
+       __start(hdr, kbase, 0, 0, 0,
+               RELOC(prom_opal_base), RELOC(prom_opal_entry));
+#else
+       __start(hdr, kbase, 0, 0, 0, 0, 0);
+#endif
 
        return 0;
 }
index 9f82f49..70f4286 100644 (file)
@@ -20,7 +20,9 @@ WHITELIST="add_reloc_offset __bss_start __bss_stop copy_and_flush
 _end enter_prom memcpy memset reloc_offset __secondary_hold
 __secondary_hold_acknowledge __secondary_hold_spinloop __start
 strcmp strcpy strlcpy strlen strncmp strstr logo_linux_clut224
-reloc_got2 kernstart_addr memstart_addr linux_banner"
+reloc_got2 kernstart_addr memstart_addr linux_banner _stext
+opal_query_takeover opal_do_takeover opal_enter_rtas opal_secondary_entry
+boot_command_line"
 
 NM="$1"
 OBJ="$2"
index 05b7dd2..18447c4 100644 (file)
@@ -1497,9 +1497,14 @@ long arch_ptrace(struct task_struct *child, long request,
                if (index < PT_FPR0) {
                        tmp = ptrace_get_reg(child, (int) index);
                } else {
+                       unsigned int fpidx = index - PT_FPR0;
+
                        flush_fp_to_thread(child);
-                       tmp = ((unsigned long *)child->thread.fpr)
-                               [TS_FPRWIDTH * (index - PT_FPR0)];
+                       if (fpidx < (PT_FPSCR - PT_FPR0))
+                               tmp = ((unsigned long *)child->thread.fpr)
+                                       [fpidx * TS_FPRWIDTH];
+                       else
+                               tmp = child->thread.fpscr.val;
                }
                ret = put_user(tmp, datalp);
                break;
@@ -1525,9 +1530,14 @@ long arch_ptrace(struct task_struct *child, long request,
                if (index < PT_FPR0) {
                        ret = ptrace_put_reg(child, index, data);
                } else {
+                       unsigned int fpidx = index - PT_FPR0;
+
                        flush_fp_to_thread(child);
-                       ((unsigned long *)child->thread.fpr)
-                               [TS_FPRWIDTH * (index - PT_FPR0)] = data;
+                       if (fpidx < (PT_FPSCR - PT_FPR0))
+                               ((unsigned long *)child->thread.fpr)
+                                       [fpidx * TS_FPRWIDTH] = data;
+                       else
+                               child->thread.fpscr.val = data;
                        ret = 0;
                }
                break;
index 209135a..c1ce863 100644 (file)
@@ -117,7 +117,7 @@ notrace unsigned long __init early_init(unsigned long dt_ptr)
  * This is called very early on the boot process, after a minimal
  * MMU environment has been set up but before MMU_init is called.
  */
-notrace void __init machine_init(unsigned long dt_ptr)
+notrace void __init machine_init(u64 dt_ptr)
 {
        lockdep_init();
 
index aebef13..d4168c9 100644 (file)
@@ -278,14 +278,14 @@ static void __init initialize_cache_info(void)
 
        DBG(" -> initialize_cache_info()\n");
 
-       for (np = NULL; (np = of_find_node_by_type(np, "cpu"));) {
+       for_each_node_by_type(np, "cpu") {
                num_cpus += 1;
 
-               /* We're assuming *all* of the CPUs have the same
+               /*
+                * We're assuming *all* of the CPUs have the same
                 * d-cache and i-cache sizes... -Peter
                 */
-
-               if ( num_cpus == 1 ) {
+               if (num_cpus == 1) {
                        const u32 *sizep, *lsizep;
                        u32 size, lsize;
 
@@ -294,10 +294,13 @@ static void __init initialize_cache_info(void)
                        sizep = of_get_property(np, "d-cache-size", NULL);
                        if (sizep != NULL)
                                size = *sizep;
-                       lsizep = of_get_property(np, "d-cache-block-size", NULL);
+                       lsizep = of_get_property(np, "d-cache-block-size",
+                                                NULL);
                        /* fallback if block size missing */
                        if (lsizep == NULL)
-                               lsizep = of_get_property(np, "d-cache-line-size", NULL);
+                               lsizep = of_get_property(np,
+                                                        "d-cache-line-size",
+                                                        NULL);
                        if (lsizep != NULL)
                                lsize = *lsizep;
                        if (sizep == 0 || lsizep == 0)
@@ -314,9 +317,12 @@ static void __init initialize_cache_info(void)
                        sizep = of_get_property(np, "i-cache-size", NULL);
                        if (sizep != NULL)
                                size = *sizep;
-                       lsizep = of_get_property(np, "i-cache-block-size", NULL);
+                       lsizep = of_get_property(np, "i-cache-block-size",
+                                                NULL);
                        if (lsizep == NULL)
-                               lsizep = of_get_property(np, "i-cache-line-size", NULL);
+                               lsizep = of_get_property(np,
+                                                        "i-cache-line-size",
+                                                        NULL);
                        if (lsizep != NULL)
                                lsize = *lsizep;
                        if (sizep == 0 || lsizep == 0)
index 7bf2187..af7e772 100644 (file)
 static DEFINE_PER_CPU(struct task_struct *, idle_thread_array);
 #define get_idle_for_cpu(x)      (per_cpu(idle_thread_array, x))
 #define set_idle_for_cpu(x, p)   (per_cpu(idle_thread_array, x) = (p))
+
+/* State of each CPU during hotplug phases */
+static DEFINE_PER_CPU(int, cpu_state) = { 0 };
+
 #else
 static struct task_struct *idle_thread_array[NR_CPUS] __cpuinitdata ;
 #define get_idle_for_cpu(x)      (idle_thread_array[(x)])
@@ -104,12 +108,25 @@ int __devinit smp_generic_kick_cpu(int nr)
         * cpu_start field to become non-zero After we set cpu_start,
         * the processor will continue on to secondary_start
         */
-       paca[nr].cpu_start = 1;
-       smp_mb();
+       if (!paca[nr].cpu_start) {
+               paca[nr].cpu_start = 1;
+               smp_mb();
+               return 0;
+       }
+
+#ifdef CONFIG_HOTPLUG_CPU
+       /*
+        * Ok it's not there, so it might be soft-unplugged, let's
+        * try to bring it back
+        */
+       per_cpu(cpu_state, nr) = CPU_UP_PREPARE;
+       smp_wmb();
+       smp_send_reschedule(nr);
+#endif /* CONFIG_HOTPLUG_CPU */
 
        return 0;
 }
-#endif
+#endif /* CONFIG_PPC64 */
 
 static irqreturn_t call_function_action(int irq, void *data)
 {
@@ -357,8 +374,6 @@ void __devinit smp_prepare_boot_cpu(void)
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
-/* State of each CPU during hotplug phases */
-static DEFINE_PER_CPU(int, cpu_state) = { 0 };
 
 int generic_cpu_disable(void)
 {
@@ -406,6 +421,11 @@ void generic_set_cpu_dead(unsigned int cpu)
 {
        per_cpu(cpu_state, cpu) = CPU_DEAD;
 }
+
+int generic_check_cpu_restart(unsigned int cpu)
+{
+       return per_cpu(cpu_state, cpu) == CPU_UP_PREPARE;
+}
 #endif
 
 struct create_idle {
index aa17b76..641f9ad 100644 (file)
@@ -33,6 +33,6 @@ void save_processor_state(void)
 void restore_processor_state(void)
 {
 #ifdef CONFIG_PPC32
-       switch_mmu_context(NULL, current->active_mm);
+       switch_mmu_context(current->active_mm, current->active_mm);
 #endif
 }
index f19d977..4e59082 100644 (file)
@@ -457,7 +457,14 @@ int machine_check_e500mc(struct pt_regs *regs)
 
        if (reason & MCSR_DCPERR_MC) {
                printk("Data Cache Parity Error\n");
-               recoverable = 0;
+
+               /*
+                * In write shadow mode we auto-recover from the error, but it
+                * may still get logged and cause a machine check.  We should
+                * only treat the non-write shadow case as non-recoverable.
+                */
+               if (!(mfspr(SPRN_L1CSR2) & L1CSR2_DCWS))
+                       recoverable = 0;
        }
 
        if (reason & MCSR_L2MMU_MHIT) {
index b4607a9..57fa2c0 100644 (file)
@@ -69,6 +69,12 @@ void __init udbg_early_init(void)
        udbg_init_wsp();
 #elif defined(CONFIG_PPC_EARLY_DEBUG_EHV_BC)
        udbg_init_ehv_bc();
+#elif defined(CONFIG_PPC_EARLY_DEBUG_PS3GELIC)
+       udbg_init_ps3gelic();
+#elif defined(CONFIG_PPC_EARLY_DEBUG_OPAL_RAW)
+       udbg_init_debug_opal_raw();
+#elif defined(CONFIG_PPC_EARLY_DEBUG_OPAL_HVSI)
+       udbg_init_debug_opal_hvsi();
 #endif
 
 #ifdef CONFIG_PPC_EARLY_DEBUG
index 1b695fd..34d291d 100644 (file)
@@ -605,15 +605,20 @@ static int vio_dma_iommu_dma_supported(struct device *dev, u64 mask)
         return dma_iommu_ops.dma_supported(dev, mask);
 }
 
-struct dma_map_ops vio_dma_mapping_ops = {
-       .alloc_coherent = vio_dma_iommu_alloc_coherent,
-       .free_coherent  = vio_dma_iommu_free_coherent,
-       .map_sg         = vio_dma_iommu_map_sg,
-       .unmap_sg       = vio_dma_iommu_unmap_sg,
-       .map_page       = vio_dma_iommu_map_page,
-       .unmap_page     = vio_dma_iommu_unmap_page,
-       .dma_supported  = vio_dma_iommu_dma_supported,
+static u64 vio_dma_get_required_mask(struct device *dev)
+{
+        return dma_iommu_ops.get_required_mask(dev);
+}
 
+struct dma_map_ops vio_dma_mapping_ops = {
+       .alloc_coherent    = vio_dma_iommu_alloc_coherent,
+       .free_coherent     = vio_dma_iommu_free_coherent,
+       .map_sg            = vio_dma_iommu_map_sg,
+       .unmap_sg          = vio_dma_iommu_unmap_sg,
+       .map_page          = vio_dma_iommu_map_page,
+       .unmap_page        = vio_dma_iommu_unmap_page,
+       .dma_supported     = vio_dma_iommu_dma_supported,
+       .get_required_mask = vio_dma_get_required_mask,
 };
 
 /**
index 6227920..a73f088 100644 (file)
@@ -171,10 +171,6 @@ static unsigned long insn_type(unsigned long speinsn)
        case EFDNABS:   ret = XA;       break;
        case EFDNEG:    ret = XA;       break;
        case EFDSUB:    ret = AB;       break;
-
-       default:
-               printk(KERN_ERR "\nOoops! SPE instruction no type found.");
-               printk(KERN_ERR "\ninst code: %08lx\n", speinsn);
        }
 
        return ret;
@@ -195,7 +191,7 @@ int do_spe_mathemu(struct pt_regs *regs)
 
        type = insn_type(speinsn);
        if (type == NOTYPE)
-               return -ENOSYS;
+               goto illegal;
 
        func = speinsn & 0x7ff;
        fc = (speinsn >> 21) & 0x1f;
@@ -212,12 +208,10 @@ int do_spe_mathemu(struct pt_regs *regs)
 
        __FPU_FPSCR = mfspr(SPRN_SPEFSCR);
 
-#ifdef DEBUG
-       printk("speinsn:%08lx spefscr:%08lx\n", speinsn, __FPU_FPSCR);
-       printk("vc: %08x  %08x\n", vc.wp[0], vc.wp[1]);
-       printk("va: %08x  %08x\n", va.wp[0], va.wp[1]);
-       printk("vb: %08x  %08x\n", vb.wp[0], vb.wp[1]);
-#endif
+       pr_debug("speinsn:%08lx spefscr:%08lx\n", speinsn, __FPU_FPSCR);
+       pr_debug("vc: %08x  %08x\n", vc.wp[0], vc.wp[1]);
+       pr_debug("va: %08x  %08x\n", va.wp[0], va.wp[1]);
+       pr_debug("vb: %08x  %08x\n", vb.wp[0], vb.wp[1]);
 
        switch (src) {
        case SPFP: {
@@ -235,10 +229,8 @@ int do_spe_mathemu(struct pt_regs *regs)
                        break;
                }
 
-#ifdef DEBUG
-               printk("SA: %ld %08lx %ld (%ld)\n", SA_s, SA_f, SA_e, SA_c);
-               printk("SB: %ld %08lx %ld (%ld)\n", SB_s, SB_f, SB_e, SB_c);
-#endif
+               pr_debug("SA: %ld %08lx %ld (%ld)\n", SA_s, SA_f, SA_e, SA_c);
+               pr_debug("SB: %ld %08lx %ld (%ld)\n", SB_s, SB_f, SB_e, SB_c);
 
                switch (func) {
                case EFSABS:
@@ -305,10 +297,10 @@ int do_spe_mathemu(struct pt_regs *regs)
                        FP_DECL_D(DB);
                        FP_CLEAR_EXCEPTIONS;
                        FP_UNPACK_DP(DB, vb.dp);
-#ifdef DEBUG
-                       printk("DB: %ld %08lx %08lx %ld (%ld)\n",
+
+                       pr_debug("DB: %ld %08lx %08lx %ld (%ld)\n",
                                        DB_s, DB_f1, DB_f0, DB_e, DB_c);
-#endif
+
                        FP_CONV(S, D, 1, 2, SR, DB);
                        goto pack_s;
                }
@@ -332,9 +324,8 @@ int do_spe_mathemu(struct pt_regs *regs)
                break;
 
 pack_s:
-#ifdef DEBUG
-               printk("SR: %ld %08lx %ld (%ld)\n", SR_s, SR_f, SR_e, SR_c);
-#endif
+               pr_debug("SR: %ld %08lx %ld (%ld)\n", SR_s, SR_f, SR_e, SR_c);
+
                FP_PACK_SP(vc.wp + 1, SR);
                goto update_regs;
 
@@ -365,12 +356,10 @@ cmp_s:
                        break;
                }
 
-#ifdef DEBUG
-               printk("DA: %ld %08lx %08lx %ld (%ld)\n",
+               pr_debug("DA: %ld %08lx %08lx %ld (%ld)\n",
                                DA_s, DA_f1, DA_f0, DA_e, DA_c);
-               printk("DB: %ld %08lx %08lx %ld (%ld)\n",
+               pr_debug("DB: %ld %08lx %08lx %ld (%ld)\n",
                                DB_s, DB_f1, DB_f0, DB_e, DB_c);
-#endif
 
                switch (func) {
                case EFDABS:
@@ -438,10 +427,10 @@ cmp_s:
                        FP_DECL_S(SB);
                        FP_CLEAR_EXCEPTIONS;
                        FP_UNPACK_SP(SB, vb.wp + 1);
-#ifdef DEBUG
-                       printk("SB: %ld %08lx %ld (%ld)\n",
+
+                       pr_debug("SB: %ld %08lx %ld (%ld)\n",
                                        SB_s, SB_f, SB_e, SB_c);
-#endif
+
                        FP_CONV(D, S, 2, 1, DR, SB);
                        goto pack_d;
                }
@@ -471,10 +460,9 @@ cmp_s:
                break;
 
 pack_d:
-#ifdef DEBUG
-               printk("DR: %ld %08lx %08lx %ld (%ld)\n",
+               pr_debug("DR: %ld %08lx %08lx %ld (%ld)\n",
                                DR_s, DR_f1, DR_f0, DR_e, DR_c);
-#endif
+
                FP_PACK_DP(vc.dp, DR);
                goto update_regs;
 
@@ -511,12 +499,14 @@ cmp_d:
                        break;
                }
 
-#ifdef DEBUG
-               printk("SA0: %ld %08lx %ld (%ld)\n", SA0_s, SA0_f, SA0_e, SA0_c);
-               printk("SA1: %ld %08lx %ld (%ld)\n", SA1_s, SA1_f, SA1_e, SA1_c);
-               printk("SB0: %ld %08lx %ld (%ld)\n", SB0_s, SB0_f, SB0_e, SB0_c);
-               printk("SB1: %ld %08lx %ld (%ld)\n", SB1_s, SB1_f, SB1_e, SB1_c);
-#endif
+               pr_debug("SA0: %ld %08lx %ld (%ld)\n",
+                               SA0_s, SA0_f, SA0_e, SA0_c);
+               pr_debug("SA1: %ld %08lx %ld (%ld)\n",
+                               SA1_s, SA1_f, SA1_e, SA1_c);
+               pr_debug("SB0: %ld %08lx %ld (%ld)\n",
+                               SB0_s, SB0_f, SB0_e, SB0_c);
+               pr_debug("SB1: %ld %08lx %ld (%ld)\n",
+                               SB1_s, SB1_f, SB1_e, SB1_c);
 
                switch (func) {
                case EVFSABS:
@@ -605,10 +595,11 @@ cmp_d:
                break;
 
 pack_vs:
-#ifdef DEBUG
-               printk("SR0: %ld %08lx %ld (%ld)\n", SR0_s, SR0_f, SR0_e, SR0_c);
-               printk("SR1: %ld %08lx %ld (%ld)\n", SR1_s, SR1_f, SR1_e, SR1_c);
-#endif
+               pr_debug("SR0: %ld %08lx %ld (%ld)\n",
+                               SR0_s, SR0_f, SR0_e, SR0_c);
+               pr_debug("SR1: %ld %08lx %ld (%ld)\n",
+                               SR1_s, SR1_f, SR1_e, SR1_c);
+
                FP_PACK_SP(vc.wp, SR0);
                FP_PACK_SP(vc.wp + 1, SR1);
                goto update_regs;
@@ -646,14 +637,12 @@ update_regs:
        current->thread.evr[fc] = vc.wp[0];
        regs->gpr[fc] = vc.wp[1];
 
-#ifdef DEBUG
-       printk("ccr = %08lx\n", regs->ccr);
-       printk("cur exceptions = %08x spefscr = %08lx\n",
+       pr_debug("ccr = %08lx\n", regs->ccr);
+       pr_debug("cur exceptions = %08x spefscr = %08lx\n",
                        FP_CUR_EXCEPTIONS, __FPU_FPSCR);
-       printk("vc: %08x  %08x\n", vc.wp[0], vc.wp[1]);
-       printk("va: %08x  %08x\n", va.wp[0], va.wp[1]);
-       printk("vb: %08x  %08x\n", vb.wp[0], vb.wp[1]);
-#endif
+       pr_debug("vc: %08x  %08x\n", vc.wp[0], vc.wp[1]);
+       pr_debug("va: %08x  %08x\n", va.wp[0], va.wp[1]);
+       pr_debug("vb: %08x  %08x\n", vb.wp[0], vb.wp[1]);
 
        return 0;
 
@@ -661,9 +650,7 @@ illegal:
        if (have_e500_cpu_a005_erratum) {
                /* according to e500 cpu a005 erratum, reissue efp inst */
                regs->nip -= 4;
-#ifdef DEBUG
-               printk(KERN_DEBUG "re-issue efp inst: %08lx\n", speinsn);
-#endif
+               pr_debug("re-issue efp inst: %08lx\n", speinsn);
                return 0;
        }
 
@@ -685,13 +672,20 @@ int speround_handler(struct pt_regs *regs)
        type = insn_type(speinsn & 0x7ff);
        if (type == XCR) return -ENOSYS;
 
+       __FPU_FPSCR = mfspr(SPRN_SPEFSCR);
+       pr_debug("speinsn:%08lx spefscr:%08lx\n", speinsn, __FPU_FPSCR);
+
+       /* No need to round if the result is exact */
+       if (!(__FPU_FPSCR & FP_EX_INEXACT))
+               return 0;
+
        fc = (speinsn >> 21) & 0x1f;
        s_lo = regs->gpr[fc] & SIGN_BIT_S;
        s_hi = current->thread.evr[fc] & SIGN_BIT_S;
        fgpr.wp[0] = current->thread.evr[fc];
        fgpr.wp[1] = regs->gpr[fc];
 
-       __FPU_FPSCR = mfspr(SPRN_SPEFSCR);
+       pr_debug("round fgpr: %08x  %08x\n", fgpr.wp[0], fgpr.wp[1]);
 
        switch ((speinsn >> 5) & 0x7) {
        /* Since SPE instructions on E500 core can handle round to nearest
@@ -731,6 +725,8 @@ int speround_handler(struct pt_regs *regs)
        current->thread.evr[fc] = fgpr.wp[0];
        regs->gpr[fc] = fgpr.wp[1];
 
+       pr_debug("  to fgpr: %08x  %08x\n", fgpr.wp[0], fgpr.wp[1]);
+
        return 0;
 }
 
index bdca46e..991ee81 100644 (file)
@@ -29,6 +29,7 @@ obj-$(CONFIG_PPC_MM_SLICES)   += slice.o
 ifeq ($(CONFIG_HUGETLB_PAGE),y)
 obj-y                          += hugetlbpage.o
 obj-$(CONFIG_PPC_STD_MMU_64)   += hugetlbpage-hash64.o
+obj-$(CONFIG_PPC_BOOK3E_MMU)   += hugetlbpage-book3e.o
 endif
 obj-$(CONFIG_PPC_SUBPAGE_PROT) += subpage-prot.o
 obj-$(CONFIG_NOT_COHERENT_CACHE) += dma-noncoherent.o
index f7802c8..66a6fd3 100644 (file)
@@ -101,17 +101,17 @@ unsigned long p_mapped_by_tlbcam(phys_addr_t pa)
 
 /*
  * Set up a variable-size TLB entry (tlbcam). The parameters are not checked;
- * in particular size must be a power of 4 between 4k and 256M (or 1G, for cpus
- * that support extended page sizes).  Note that while some cpus support a
- * page size of 4G, we don't allow its use here.
+ * in particular size must be a power of 4 between 4k and the max supported by
+ * an implementation; max may further be limited by what can be represented in
+ * an unsigned long (for example, 32-bit implementations cannot support a 4GB
+ * size).
  */
 static void settlbcam(int index, unsigned long virt, phys_addr_t phys,
                unsigned long size, unsigned long flags, unsigned int pid)
 {
-       unsigned int tsize, lz;
+       unsigned int tsize;
 
-       asm (PPC_CNTLZL "%0,%1" : "=r" (lz) : "r" (size));
-       tsize = 21 - lz;
+       tsize = __ilog2(size) - 10;
 
 #ifdef CONFIG_SMP
        if ((flags & _PAGE_NO_CACHE) == 0)
@@ -146,29 +146,36 @@ static void settlbcam(int index, unsigned long virt, phys_addr_t phys,
        loadcam_entry(index);
 }
 
+unsigned long calc_cam_sz(unsigned long ram, unsigned long virt,
+                         phys_addr_t phys)
+{
+       unsigned int camsize = __ilog2(ram) & ~1U;
+       unsigned int align = __ffs(virt | phys) & ~1U;
+       unsigned long max_cam = (mfspr(SPRN_TLB1CFG) >> 16) & 0xf;
+
+       /* Convert (4^max) kB to (2^max) bytes */
+       max_cam = max_cam * 2 + 10;
+
+       if (camsize > align)
+               camsize = align;
+       if (camsize > max_cam)
+               camsize = max_cam;
+
+       return 1UL << camsize;
+}
+
 unsigned long map_mem_in_cams(unsigned long ram, int max_cam_idx)
 {
        int i;
        unsigned long virt = PAGE_OFFSET;
        phys_addr_t phys = memstart_addr;
        unsigned long amount_mapped = 0;
-       unsigned long max_cam = (mfspr(SPRN_TLB1CFG) >> 16) & 0xf;
-
-       /* Convert (4^max) kB to (2^max) bytes */
-       max_cam = max_cam * 2 + 10;
 
        /* Calculate CAM values */
        for (i = 0; ram && i < max_cam_idx; i++) {
-               unsigned int camsize = __ilog2(ram) & ~1U;
-               unsigned int align = __ffs(virt | phys) & ~1U;
                unsigned long cam_sz;
 
-               if (camsize > align)
-                       camsize = align;
-               if (camsize > max_cam)
-                       camsize = max_cam;
-
-               cam_sz = 1UL << camsize;
+               cam_sz = calc_cam_sz(ram, virt, phys);
                settlbcam(i, virt, phys, cam_sz, PAGE_KERNEL_X, 0);
 
                ram -= cam_sz;
index 26b2872..1628201 100644 (file)
@@ -105,9 +105,6 @@ int mmu_kernel_ssize = MMU_SEGSIZE_256M;
 int mmu_highuser_ssize = MMU_SEGSIZE_256M;
 u16 mmu_slb_size = 64;
 EXPORT_SYMBOL_GPL(mmu_slb_size);
-#ifdef CONFIG_HUGETLB_PAGE
-unsigned int HPAGE_SHIFT;
-#endif
 #ifdef CONFIG_PPC_64K_PAGES
 int mmu_ci_restrictions;
 #endif
@@ -534,11 +531,11 @@ static unsigned long __init htab_get_table_size(void)
 }
 
 #ifdef CONFIG_MEMORY_HOTPLUG
-void create_section_mapping(unsigned long start, unsigned long end)
+int create_section_mapping(unsigned long start, unsigned long end)
 {
-       BUG_ON(htab_bolt_mapping(start, end, __pa(start),
+       return htab_bolt_mapping(start, end, __pa(start),
                                 pgprot_val(PAGE_KERNEL), mmu_linear_psize,
-                                mmu_kernel_ssize));
+                                mmu_kernel_ssize);
 }
 
 int remove_section_mapping(unsigned long start, unsigned long end)
diff --git a/arch/powerpc/mm/hugetlbpage-book3e.c b/arch/powerpc/mm/hugetlbpage-book3e.c
new file mode 100644 (file)
index 0000000..343ad0b
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * PPC Huge TLB Page Support for Book3E MMU
+ *
+ * Copyright (C) 2009 David Gibson, IBM Corporation.
+ * Copyright (C) 2011 Becky Bruce, Freescale Semiconductor
+ *
+ */
+#include <linux/mm.h>
+#include <linux/hugetlb.h>
+
+static inline int mmu_get_tsize(int psize)
+{
+       return mmu_psize_defs[psize].enc;
+}
+
+static inline int book3e_tlb_exists(unsigned long ea, unsigned long pid)
+{
+       int found = 0;
+
+       mtspr(SPRN_MAS6, pid << 16);
+       if (mmu_has_feature(MMU_FTR_USE_TLBRSRV)) {
+               asm volatile(
+                       "li     %0,0\n"
+                       "tlbsx. 0,%1\n"
+                       "bne    1f\n"
+                       "li     %0,1\n"
+                       "1:\n"
+                       : "=&r"(found) : "r"(ea));
+       } else {
+               asm volatile(
+                       "tlbsx  0,%1\n"
+                       "mfspr  %0,0x271\n"
+                       "srwi   %0,%0,31\n"
+                       : "=&r"(found) : "r"(ea));
+       }
+
+       return found;
+}
+
+void book3e_hugetlb_preload(struct mm_struct *mm, unsigned long ea, pte_t pte)
+{
+       unsigned long mas1, mas2;
+       u64 mas7_3;
+       unsigned long psize, tsize, shift;
+       unsigned long flags;
+
+#ifdef CONFIG_PPC_FSL_BOOK3E
+       int index, lz, ncams;
+       struct vm_area_struct *vma;
+#endif
+
+       if (unlikely(is_kernel_addr(ea)))
+               return;
+
+#ifdef CONFIG_PPC_MM_SLICES
+       psize = mmu_get_tsize(get_slice_psize(mm, ea));
+       tsize = mmu_get_psize(psize);
+       shift = mmu_psize_defs[psize].shift;
+#else
+       vma = find_vma(mm, ea);
+       psize = vma_mmu_pagesize(vma);  /* returns actual size in bytes */
+       asm (PPC_CNTLZL "%0,%1" : "=r" (lz) : "r" (psize));
+       shift = 31 - lz;
+       tsize = 21 - lz;
+#endif
+
+       /*
+        * We can't be interrupted while we're setting up the MAS
+        * regusters or after we've confirmed that no tlb exists.
+        */
+       local_irq_save(flags);
+
+       if (unlikely(book3e_tlb_exists(ea, mm->context.id))) {
+               local_irq_restore(flags);
+               return;
+       }
+
+#ifdef CONFIG_PPC_FSL_BOOK3E
+       ncams = mfspr(SPRN_TLB1CFG) & TLBnCFG_N_ENTRY;
+
+       /* We have to use the CAM(TLB1) on FSL parts for hugepages */
+       index = __get_cpu_var(next_tlbcam_idx);
+       mtspr(SPRN_MAS0, MAS0_ESEL(index) | MAS0_TLBSEL(1));
+
+       /* Just round-robin the entries and wrap when we hit the end */
+       if (unlikely(index == ncams - 1))
+               __get_cpu_var(next_tlbcam_idx) = tlbcam_index;
+       else
+               __get_cpu_var(next_tlbcam_idx)++;
+#endif
+       mas1 = MAS1_VALID | MAS1_TID(mm->context.id) | MAS1_TSIZE(tsize);
+       mas2 = ea & ~((1UL << shift) - 1);
+       mas2 |= (pte_val(pte) >> PTE_WIMGE_SHIFT) & MAS2_WIMGE_MASK;
+       mas7_3 = (u64)pte_pfn(pte) << PAGE_SHIFT;
+       mas7_3 |= (pte_val(pte) >> PTE_BAP_SHIFT) & MAS3_BAP_MASK;
+       if (!pte_dirty(pte))
+               mas7_3 &= ~(MAS3_SW|MAS3_UW);
+
+       mtspr(SPRN_MAS1, mas1);
+       mtspr(SPRN_MAS2, mas2);
+
+       if (mmu_has_feature(MMU_FTR_USE_PAIRED_MAS)) {
+               mtspr(SPRN_MAS7_MAS3, mas7_3);
+       } else {
+               mtspr(SPRN_MAS7, upper_32_bits(mas7_3));
+               mtspr(SPRN_MAS3, lower_32_bits(mas7_3));
+       }
+
+       asm volatile ("tlbwe");
+
+       local_irq_restore(flags);
+}
+
+void flush_hugetlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
+{
+       struct hstate *hstate = hstate_file(vma->vm_file);
+       unsigned long tsize = huge_page_shift(hstate) - 10;
+
+       __flush_tlb_page(vma ? vma->vm_mm : NULL, vmaddr, tsize, 0);
+
+}
index da5eb38..5964371 100644 (file)
@@ -1,7 +1,8 @@
 /*
- * PPC64 (POWER4) Huge TLB Page Support for Kernel.
+ * PPC Huge TLB Page Support for Kernel.
  *
  * Copyright (C) 2003 David Gibson, IBM Corporation.
+ * Copyright (C) 2011 Becky Bruce, Freescale Semiconductor
  *
  * Based on the IA-32 version:
  * Copyright (C) 2002, Rohit Seth <rohit.seth@intel.com>
 #include <linux/io.h>
 #include <linux/slab.h>
 #include <linux/hugetlb.h>
+#include <linux/of_fdt.h>
+#include <linux/memblock.h>
+#include <linux/bootmem.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
 #include <asm/tlb.h>
+#include <asm/setup.h>
 
 #define PAGE_SHIFT_64K 16
 #define PAGE_SHIFT_16M 24
 #define PAGE_SHIFT_16G 34
 
-#define MAX_NUMBER_GPAGES      1024
+unsigned int HPAGE_SHIFT;
 
-/* Tracks the 16G pages after the device tree is scanned and before the
- * huge_boot_pages list is ready.  */
-static unsigned long gpage_freearray[MAX_NUMBER_GPAGES];
+/*
+ * Tracks gpages after the device tree is scanned and before the
+ * huge_boot_pages list is ready.  On 64-bit implementations, this is
+ * just used to track 16G pages and so is a single array.  32-bit
+ * implementations may have more than one gpage size due to limitations
+ * of the memory allocators, so we need multiple arrays
+ */
+#ifdef CONFIG_PPC64
+#define MAX_NUMBER_GPAGES      1024
+static u64 gpage_freearray[MAX_NUMBER_GPAGES];
 static unsigned nr_gpages;
-
-/* Flag to mark huge PD pointers.  This means pmd_bad() and pud_bad()
- * will choke on pointers to hugepte tables, which is handy for
- * catching screwups early. */
+#else
+#define MAX_NUMBER_GPAGES      128
+struct psize_gpages {
+       u64 gpage_list[MAX_NUMBER_GPAGES];
+       unsigned int nr_gpages;
+};
+static struct psize_gpages gpage_freearray[MMU_PAGE_COUNT];
+#endif
 
 static inline int shift_to_mmu_psize(unsigned int shift)
 {
@@ -49,25 +65,6 @@ static inline unsigned int mmu_psize_to_shift(unsigned int mmu_psize)
 
 #define hugepd_none(hpd)       ((hpd).pd == 0)
 
-static inline pte_t *hugepd_page(hugepd_t hpd)
-{
-       BUG_ON(!hugepd_ok(hpd));
-       return (pte_t *)((hpd.pd & ~HUGEPD_SHIFT_MASK) | 0xc000000000000000);
-}
-
-static inline unsigned int hugepd_shift(hugepd_t hpd)
-{
-       return hpd.pd & HUGEPD_SHIFT_MASK;
-}
-
-static inline pte_t *hugepte_offset(hugepd_t *hpdp, unsigned long addr, unsigned pdshift)
-{
-       unsigned long idx = (addr & ((1UL << pdshift) - 1)) >> hugepd_shift(*hpdp);
-       pte_t *dir = hugepd_page(*hpdp);
-
-       return dir + idx;
-}
-
 pte_t *find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea, unsigned *shift)
 {
        pgd_t *pg;
@@ -93,7 +90,7 @@ pte_t *find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea, unsigned *shift
                        if (is_hugepd(pm))
                                hpdp = (hugepd_t *)pm;
                        else if (!pmd_none(*pm)) {
-                               return pte_offset_map(pm, ea);
+                               return pte_offset_kernel(pm, ea);
                        }
                }
        }
@@ -114,8 +111,18 @@ pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
 static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp,
                           unsigned long address, unsigned pdshift, unsigned pshift)
 {
-       pte_t *new = kmem_cache_zalloc(PGT_CACHE(pdshift - pshift),
-                                      GFP_KERNEL|__GFP_REPEAT);
+       struct kmem_cache *cachep;
+       pte_t *new;
+
+#ifdef CONFIG_PPC64
+       cachep = PGT_CACHE(pdshift - pshift);
+#else
+       int i;
+       int num_hugepd = 1 << (pshift - pdshift);
+       cachep = hugepte_cache;
+#endif
+
+       new = kmem_cache_zalloc(cachep, GFP_KERNEL|__GFP_REPEAT);
 
        BUG_ON(pshift > HUGEPD_SHIFT_MASK);
        BUG_ON((unsigned long)new & HUGEPD_SHIFT_MASK);
@@ -124,10 +131,31 @@ static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp,
                return -ENOMEM;
 
        spin_lock(&mm->page_table_lock);
+#ifdef CONFIG_PPC64
        if (!hugepd_none(*hpdp))
-               kmem_cache_free(PGT_CACHE(pdshift - pshift), new);
+               kmem_cache_free(cachep, new);
        else
-               hpdp->pd = ((unsigned long)new & ~0x8000000000000000) | pshift;
+               hpdp->pd = ((unsigned long)new & ~PD_HUGE) | pshift;
+#else
+       /*
+        * We have multiple higher-level entries that point to the same
+        * actual pte location.  Fill in each as we go and backtrack on error.
+        * We need all of these so the DTLB pgtable walk code can find the
+        * right higher-level entry without knowing if it's a hugepage or not.
+        */
+       for (i = 0; i < num_hugepd; i++, hpdp++) {
+               if (unlikely(!hugepd_none(*hpdp)))
+                       break;
+               else
+                       hpdp->pd = ((unsigned long)new & ~PD_HUGE) | pshift;
+       }
+       /* If we bailed from the for loop early, an error occurred, clean up */
+       if (i < num_hugepd) {
+               for (i = i - 1 ; i >= 0; i--, hpdp--)
+                       hpdp->pd = 0;
+               kmem_cache_free(cachep, new);
+       }
+#endif
        spin_unlock(&mm->page_table_lock);
        return 0;
 }
@@ -169,11 +197,132 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr, unsigned long sz
        return hugepte_offset(hpdp, addr, pdshift);
 }
 
+#ifdef CONFIG_PPC32
 /* Build list of addresses of gigantic pages.  This function is used in early
  * boot before the buddy or bootmem allocator is setup.
  */
-void add_gpage(unsigned long addr, unsigned long page_size,
-       unsigned long number_of_pages)
+void add_gpage(u64 addr, u64 page_size, unsigned long number_of_pages)
+{
+       unsigned int idx = shift_to_mmu_psize(__ffs(page_size));
+       int i;
+
+       if (addr == 0)
+               return;
+
+       gpage_freearray[idx].nr_gpages = number_of_pages;
+
+       for (i = 0; i < number_of_pages; i++) {
+               gpage_freearray[idx].gpage_list[i] = addr;
+               addr += page_size;
+       }
+}
+
+/*
+ * Moves the gigantic page addresses from the temporary list to the
+ * huge_boot_pages list.
+ */
+int alloc_bootmem_huge_page(struct hstate *hstate)
+{
+       struct huge_bootmem_page *m;
+       int idx = shift_to_mmu_psize(hstate->order + PAGE_SHIFT);
+       int nr_gpages = gpage_freearray[idx].nr_gpages;
+
+       if (nr_gpages == 0)
+               return 0;
+
+#ifdef CONFIG_HIGHMEM
+       /*
+        * If gpages can be in highmem we can't use the trick of storing the
+        * data structure in the page; allocate space for this
+        */
+       m = alloc_bootmem(sizeof(struct huge_bootmem_page));
+       m->phys = gpage_freearray[idx].gpage_list[--nr_gpages];
+#else
+       m = phys_to_virt(gpage_freearray[idx].gpage_list[--nr_gpages]);
+#endif
+
+       list_add(&m->list, &huge_boot_pages);
+       gpage_freearray[idx].nr_gpages = nr_gpages;
+       gpage_freearray[idx].gpage_list[nr_gpages] = 0;
+       m->hstate = hstate;
+
+       return 1;
+}
+/*
+ * Scan the command line hugepagesz= options for gigantic pages; store those in
+ * a list that we use to allocate the memory once all options are parsed.
+ */
+
+unsigned long gpage_npages[MMU_PAGE_COUNT];
+
+static int __init do_gpage_early_setup(char *param, char *val)
+{
+       static phys_addr_t size;
+       unsigned long npages;
+
+       /*
+        * The hugepagesz and hugepages cmdline options are interleaved.  We
+        * use the size variable to keep track of whether or not this was done
+        * properly and skip over instances where it is incorrect.  Other
+        * command-line parsing code will issue warnings, so we don't need to.
+        *
+        */
+       if ((strcmp(param, "default_hugepagesz") == 0) ||
+           (strcmp(param, "hugepagesz") == 0)) {
+               size = memparse(val, NULL);
+       } else if (strcmp(param, "hugepages") == 0) {
+               if (size != 0) {
+                       if (sscanf(val, "%lu", &npages) <= 0)
+                               npages = 0;
+                       gpage_npages[shift_to_mmu_psize(__ffs(size))] = npages;
+                       size = 0;
+               }
+       }
+       return 0;
+}
+
+
+/*
+ * This function allocates physical space for pages that are larger than the
+ * buddy allocator can handle.  We want to allocate these in highmem because
+ * the amount of lowmem is limited.  This means that this function MUST be
+ * called before lowmem_end_addr is set up in MMU_init() in order for the lmb
+ * allocate to grab highmem.
+ */
+void __init reserve_hugetlb_gpages(void)
+{
+       static __initdata char cmdline[COMMAND_LINE_SIZE];
+       phys_addr_t size, base;
+       int i;
+
+       strlcpy(cmdline, boot_command_line, COMMAND_LINE_SIZE);
+       parse_args("hugetlb gpages", cmdline, NULL, 0, &do_gpage_early_setup);
+
+       /*
+        * Walk gpage list in reverse, allocating larger page sizes first.
+        * Skip over unsupported sizes, or sizes that have 0 gpages allocated.
+        * When we reach the point in the list where pages are no longer
+        * considered gpages, we're done.
+        */
+       for (i = MMU_PAGE_COUNT-1; i >= 0; i--) {
+               if (mmu_psize_defs[i].shift == 0 || gpage_npages[i] == 0)
+                       continue;
+               else if (mmu_psize_to_shift(i) < (MAX_ORDER + PAGE_SHIFT))
+                       break;
+
+               size = (phys_addr_t)(1ULL << mmu_psize_to_shift(i));
+               base = memblock_alloc_base(size * gpage_npages[i], size,
+                                          MEMBLOCK_ALLOC_ANYWHERE);
+               add_gpage(base, size, gpage_npages[i]);
+       }
+}
+
+#else /* PPC64 */
+
+/* Build list of addresses of gigantic pages.  This function is used in early
+ * boot before the buddy or bootmem allocator is setup.
+ */
+void add_gpage(u64 addr, u64 page_size, unsigned long number_of_pages)
 {
        if (!addr)
                return;
@@ -199,19 +348,79 @@ int alloc_bootmem_huge_page(struct hstate *hstate)
        m->hstate = hstate;
        return 1;
 }
+#endif
 
 int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep)
 {
        return 0;
 }
 
+#ifdef CONFIG_PPC32
+#define HUGEPD_FREELIST_SIZE \
+       ((PAGE_SIZE - sizeof(struct hugepd_freelist)) / sizeof(pte_t))
+
+struct hugepd_freelist {
+       struct rcu_head rcu;
+       unsigned int index;
+       void *ptes[0];
+};
+
+static DEFINE_PER_CPU(struct hugepd_freelist *, hugepd_freelist_cur);
+
+static void hugepd_free_rcu_callback(struct rcu_head *head)
+{
+       struct hugepd_freelist *batch =
+               container_of(head, struct hugepd_freelist, rcu);
+       unsigned int i;
+
+       for (i = 0; i < batch->index; i++)
+               kmem_cache_free(hugepte_cache, batch->ptes[i]);
+
+       free_page((unsigned long)batch);
+}
+
+static void hugepd_free(struct mmu_gather *tlb, void *hugepte)
+{
+       struct hugepd_freelist **batchp;
+
+       batchp = &__get_cpu_var(hugepd_freelist_cur);
+
+       if (atomic_read(&tlb->mm->mm_users) < 2 ||
+           cpumask_equal(mm_cpumask(tlb->mm),
+                         cpumask_of(smp_processor_id()))) {
+               kmem_cache_free(hugepte_cache, hugepte);
+               return;
+       }
+
+       if (*batchp == NULL) {
+               *batchp = (struct hugepd_freelist *)__get_free_page(GFP_ATOMIC);
+               (*batchp)->index = 0;
+       }
+
+       (*batchp)->ptes[(*batchp)->index++] = hugepte;
+       if ((*batchp)->index == HUGEPD_FREELIST_SIZE) {
+               call_rcu_sched(&(*batchp)->rcu, hugepd_free_rcu_callback);
+               *batchp = NULL;
+       }
+}
+#endif
+
 static void free_hugepd_range(struct mmu_gather *tlb, hugepd_t *hpdp, int pdshift,
                              unsigned long start, unsigned long end,
                              unsigned long floor, unsigned long ceiling)
 {
        pte_t *hugepte = hugepd_page(*hpdp);
-       unsigned shift = hugepd_shift(*hpdp);
+       int i;
+
        unsigned long pdmask = ~((1UL << pdshift) - 1);
+       unsigned int num_hugepd = 1;
+
+#ifdef CONFIG_PPC64
+       unsigned int shift = hugepd_shift(*hpdp);
+#else
+       /* Note: On 32-bit the hpdp may be the first of several */
+       num_hugepd = (1 << (hugepd_shift(*hpdp) - pdshift));
+#endif
 
        start &= pdmask;
        if (start < floor)
@@ -224,9 +433,15 @@ static void free_hugepd_range(struct mmu_gather *tlb, hugepd_t *hpdp, int pdshif
        if (end - 1 > ceiling - 1)
                return;
 
-       hpdp->pd = 0;
+       for (i = 0; i < num_hugepd; i++, hpdp++)
+               hpdp->pd = 0;
+
        tlb->need_flush = 1;
+#ifdef CONFIG_PPC64
        pgtable_free_tlb(tlb, hugepte, pdshift - shift);
+#else
+       hugepd_free(tlb, hugepte);
+#endif
 }
 
 static void hugetlb_free_pmd_range(struct mmu_gather *tlb, pud_t *pud,
@@ -331,18 +546,27 @@ void hugetlb_free_pgd_range(struct mmu_gather *tlb,
         * too.
         */
 
-       pgd = pgd_offset(tlb->mm, addr);
        do {
                next = pgd_addr_end(addr, end);
+               pgd = pgd_offset(tlb->mm, addr);
                if (!is_hugepd(pgd)) {
                        if (pgd_none_or_clear_bad(pgd))
                                continue;
                        hugetlb_free_pud_range(tlb, pgd, addr, next, floor, ceiling);
                } else {
+#ifdef CONFIG_PPC32
+                       /*
+                        * Increment next by the size of the huge mapping since
+                        * on 32-bit there may be more than one entry at the pgd
+                        * level for a single hugepage, but all of them point to
+                        * the same kmem cache that holds the hugepte.
+                        */
+                       next = addr + (1 << hugepd_shift(*(hugepd_t *)pgd));
+#endif
                        free_hugepd_range(tlb, (hugepd_t *)pgd, PGDIR_SHIFT,
                                          addr, next, floor, ceiling);
                }
-       } while (pgd++, addr = next, addr != end);
+       } while (addr = next, addr != end);
 }
 
 struct page *
@@ -477,17 +701,35 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
                                        unsigned long len, unsigned long pgoff,
                                        unsigned long flags)
 {
+#ifdef CONFIG_PPC_MM_SLICES
        struct hstate *hstate = hstate_file(file);
        int mmu_psize = shift_to_mmu_psize(huge_page_shift(hstate));
 
        return slice_get_unmapped_area(addr, len, flags, mmu_psize, 1, 0);
+#else
+       return get_unmapped_area(file, addr, len, pgoff, flags);
+#endif
 }
 
 unsigned long vma_mmu_pagesize(struct vm_area_struct *vma)
 {
+#ifdef CONFIG_PPC_MM_SLICES
        unsigned int psize = get_slice_psize(vma->vm_mm, vma->vm_start);
 
        return 1UL << mmu_psize_to_shift(psize);
+#else
+       if (!is_vm_hugetlb_page(vma))
+               return PAGE_SIZE;
+
+       return huge_page_size(hstate_vma(vma));
+#endif
+}
+
+static inline bool is_power_of_4(unsigned long x)
+{
+       if (is_power_of_2(x))
+               return (__ilog2(x) % 2) ? false : true;
+       return false;
 }
 
 static int __init add_huge_page_size(unsigned long long size)
@@ -497,9 +739,14 @@ static int __init add_huge_page_size(unsigned long long size)
 
        /* Check that it is a page size supported by the hardware and
         * that it fits within pagetable and slice limits. */
+#ifdef CONFIG_PPC_FSL_BOOK3E
+       if ((size < PAGE_SIZE) || !is_power_of_4(size))
+               return -EINVAL;
+#else
        if (!is_power_of_2(size)
            || (shift > SLICE_HIGH_SHIFT) || (shift <= PAGE_SHIFT))
                return -EINVAL;
+#endif
 
        if ((mmu_psize = shift_to_mmu_psize(shift)) < 0)
                return -EINVAL;
@@ -536,6 +783,46 @@ static int __init hugepage_setup_sz(char *str)
 }
 __setup("hugepagesz=", hugepage_setup_sz);
 
+#ifdef CONFIG_FSL_BOOKE
+struct kmem_cache *hugepte_cache;
+static int __init hugetlbpage_init(void)
+{
+       int psize;
+
+       for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) {
+               unsigned shift;
+
+               if (!mmu_psize_defs[psize].shift)
+                       continue;
+
+               shift = mmu_psize_to_shift(psize);
+
+               /* Don't treat normal page sizes as huge... */
+               if (shift != PAGE_SHIFT)
+                       if (add_huge_page_size(1ULL << shift) < 0)
+                               continue;
+       }
+
+       /*
+        * Create a kmem cache for hugeptes.  The bottom bits in the pte have
+        * size information encoded in them, so align them to allow this
+        */
+       hugepte_cache =  kmem_cache_create("hugepte-cache", sizeof(pte_t),
+                                          HUGEPD_SHIFT_MASK + 1, 0, NULL);
+       if (hugepte_cache == NULL)
+               panic("%s: Unable to create kmem cache for hugeptes\n",
+                     __func__);
+
+       /* Default hpage size = 4M */
+       if (mmu_psize_defs[MMU_PAGE_4M].shift)
+               HPAGE_SHIFT = mmu_psize_defs[MMU_PAGE_4M].shift;
+       else
+               panic("%s: Unable to set default huge page size\n", __func__);
+
+
+       return 0;
+}
+#else
 static int __init hugetlbpage_init(void)
 {
        int psize;
@@ -578,15 +865,23 @@ static int __init hugetlbpage_init(void)
 
        return 0;
 }
-
+#endif
 module_init(hugetlbpage_init);
 
 void flush_dcache_icache_hugepage(struct page *page)
 {
        int i;
+       void *start;
 
        BUG_ON(!PageCompound(page));
 
-       for (i = 0; i < (1UL << compound_order(page)); i++)
-               __flush_dcache_icache(page_address(page+i));
+       for (i = 0; i < (1UL << compound_order(page)); i++) {
+               if (!PageHighMem(page)) {
+                       __flush_dcache_icache(page_address(page+i));
+               } else {
+                       start = kmap_atomic(page+i, KM_PPC_SYNC_ICACHE);
+                       __flush_dcache_icache(start);
+                       kunmap_atomic(start, KM_PPC_SYNC_ICACHE);
+               }
+       }
 }
index c77fef5..161cefd 100644 (file)
@@ -32,6 +32,8 @@
 #include <linux/pagemap.h>
 #include <linux/memblock.h>
 #include <linux/gfp.h>
+#include <linux/slab.h>
+#include <linux/hugetlb.h>
 
 #include <asm/pgalloc.h>
 #include <asm/prom.h>
@@ -44,6 +46,7 @@
 #include <asm/tlb.h>
 #include <asm/sections.h>
 #include <asm/system.h>
+#include <asm/hugetlb.h>
 
 #include "mmu_decl.h"
 
@@ -123,6 +126,12 @@ void __init MMU_init(void)
        /* parse args from command line */
        MMU_setup();
 
+       /*
+        * Reserve gigantic pages for hugetlb.  This MUST occur before
+        * lowmem_end_addr is initialized below.
+        */
+       reserve_hugetlb_gpages();
+
        if (memblock.memory.cnt > 1) {
 #ifndef CONFIG_WII
                memblock.memory.cnt = 1;
index c781bbc..5db316c 100644 (file)
@@ -123,7 +123,8 @@ int arch_add_memory(int nid, u64 start, u64 size)
        pgdata = NODE_DATA(nid);
 
        start = (unsigned long)__va(start);
-       create_section_mapping(start, start + size);
+       if (create_section_mapping(start, start + size))
+               return -EINVAL;
 
        /* this should work for most non-highmem platforms */
        zone = pgdata->node_zones;
@@ -548,4 +549,9 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address,
                return;
        hash_preload(vma->vm_mm, address, access, trap);
 #endif /* CONFIG_PPC_STD_MMU */
+#if (defined(CONFIG_PPC_BOOK3E_64) || defined(CONFIG_PPC_FSL_BOOK3E)) \
+       && defined(CONFIG_HUGETLB_PAGE)
+       if (is_vm_hugetlb_page(vma))
+               book3e_hugetlb_preload(vma->vm_mm, address, *ptep);
+#endif
 }
index 3bafc3d..4ff587e 100644 (file)
@@ -136,8 +136,8 @@ int use_cop(unsigned long acop, struct mm_struct *mm)
        if (!mm || !acop)
                return -EINVAL;
 
-       /* We need to make sure mm_users doesn't change */
-       down_read(&mm->mmap_sem);
+       /* The page_table_lock ensures mm_users won't change under us */
+       spin_lock(&mm->page_table_lock);
        spin_lock(mm->context.cop_lockp);
 
        if (mm->context.cop_pid == COP_PID_NONE) {
@@ -164,7 +164,7 @@ int use_cop(unsigned long acop, struct mm_struct *mm)
 
 out:
        spin_unlock(mm->context.cop_lockp);
-       up_read(&mm->mmap_sem);
+       spin_unlock(&mm->page_table_lock);
 
        return ret;
 }
@@ -185,8 +185,8 @@ void drop_cop(unsigned long acop, struct mm_struct *mm)
        if (WARN_ON_ONCE(!mm))
                return;
 
-       /* We need to make sure mm_users doesn't change */
-       down_read(&mm->mmap_sem);
+       /* The page_table_lock ensures mm_users won't change under us */
+       spin_lock(&mm->page_table_lock);
        spin_lock(mm->context.cop_lockp);
 
        mm->context.acop &= ~acop;
@@ -213,7 +213,7 @@ void drop_cop(unsigned long acop, struct mm_struct *mm)
        }
 
        spin_unlock(mm->context.cop_lockp);
-       up_read(&mm->mmap_sem);
+       spin_unlock(&mm->page_table_lock);
 }
 EXPORT_SYMBOL_GPL(drop_cop);
 
index 336807d..5b63bd3 100644 (file)
@@ -292,6 +292,11 @@ int init_new_context(struct task_struct *t, struct mm_struct *mm)
        mm->context.id = MMU_NO_CONTEXT;
        mm->context.active = 0;
 
+#ifdef CONFIG_PPC_MM_SLICES
+       if (slice_mm_new_context(mm))
+               slice_set_user_psize(mm, mmu_virtual_psize);
+#endif
+
        return 0;
 }
 
index dd0a258..83eb5d5 100644 (file)
@@ -142,6 +142,8 @@ extern unsigned long mmu_mapin_ram(unsigned long top);
 
 #elif defined(CONFIG_PPC_FSL_BOOK3E)
 extern unsigned long map_mem_in_cams(unsigned long ram, int max_cam_idx);
+extern unsigned long calc_cam_sz(unsigned long ram, unsigned long virt,
+                                phys_addr_t phys);
 #ifdef CONFIG_PPC32
 extern void MMU_init_hw(void);
 extern unsigned long mmu_mapin_ram(unsigned long top);
index 2164006..0bfb90c 100644 (file)
@@ -709,8 +709,7 @@ static void __init parse_drconf_memory(struct device_node *memory)
 
 static int __init parse_numa_properties(void)
 {
-       struct device_node *cpu = NULL;
-       struct device_node *memory = NULL;
+       struct device_node *memory;
        int default_nid = 0;
        unsigned long i;
 
@@ -732,6 +731,7 @@ static int __init parse_numa_properties(void)
         * each node to be onlined must have NODE_DATA etc backing it.
         */
        for_each_present_cpu(i) {
+               struct device_node *cpu;
                int nid;
 
                cpu = of_get_cpu_node(i, NULL);
@@ -750,8 +750,8 @@ static int __init parse_numa_properties(void)
        }
 
        get_n_mem_cells(&n_mem_addr_cells, &n_mem_size_cells);
-       memory = NULL;
-       while ((memory = of_find_node_by_type(memory, "memory")) != NULL) {
+
+       for_each_node_by_type(memory, "memory") {
                unsigned long start;
                unsigned long size;
                int nid;
@@ -800,8 +800,9 @@ new_range:
        }
 
        /*
-        * Now do the same thing for each MEMBLOCK listed in the ibm,dynamic-memory
-        * property in the ibm,dynamic-reconfiguration-memory node.
+        * Now do the same thing for each MEMBLOCK listed in the
+        * ibm,dynamic-memory property in the
+        * ibm,dynamic-reconfiguration-memory node.
         */
        memory = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
        if (memory)
@@ -1187,10 +1188,10 @@ static int hot_add_drconf_scn_to_nid(struct device_node *memory,
  */
 int hot_add_node_scn_to_nid(unsigned long scn_addr)
 {
-       struct device_node *memory = NULL;
+       struct device_node *memory;
        int nid = -1;
 
-       while ((memory = of_find_node_by_type(memory, "memory")) != NULL) {
+       for_each_node_by_type(memory, "memory") {
                unsigned long start, size;
                int ranges;
                const unsigned int *memcell_buf;
@@ -1214,11 +1215,12 @@ int hot_add_node_scn_to_nid(unsigned long scn_addr)
                        break;
                }
 
-               of_node_put(memory);
                if (nid >= 0)
                        break;
        }
 
+       of_node_put(memory);
+
        return nid;
 }
 
index af40c87..214130a 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/init.h>
 #include <linux/percpu.h>
 #include <linux/hardirq.h>
+#include <linux/hugetlb.h>
 #include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
 #include <asm/tlb.h>
@@ -212,7 +213,7 @@ int ptep_set_access_flags(struct vm_area_struct *vma, unsigned long address,
        entry = set_access_flags_filter(entry, vma, dirty);
        changed = !pte_same(*(ptep), entry);
        if (changed) {
-               if (!(vma->vm_flags & VM_HUGETLB))
+               if (!is_vm_hugetlb_page(vma))
                        assert_pte_locked(vma->vm_mm, address);
                __ptep_set_access_flags(ptep, entry);
                flush_tlb_page_nohash(vma, address);
index 4ebb34b..dc4a5f3 100644 (file)
@@ -553,24 +553,24 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_TLBRSRV)
        rldicl  r11,r16,64-VPTE_PGD_SHIFT,64-PGD_INDEX_SIZE-3
        clrrdi  r10,r11,3
        ldx     r15,r10,r15
-       cmpldi  cr0,r15,0
-       beq     virt_page_table_tlb_miss_fault
+       cmpdi   cr0,r15,0
+       bge     virt_page_table_tlb_miss_fault
 
 #ifndef CONFIG_PPC_64K_PAGES
        /* Get to PUD entry */
        rldicl  r11,r16,64-VPTE_PUD_SHIFT,64-PUD_INDEX_SIZE-3
        clrrdi  r10,r11,3
        ldx     r15,r10,r15
-       cmpldi  cr0,r15,0
-       beq     virt_page_table_tlb_miss_fault
+       cmpdi   cr0,r15,0
+       bge     virt_page_table_tlb_miss_fault
 #endif /* CONFIG_PPC_64K_PAGES */
 
        /* Get to PMD entry */
        rldicl  r11,r16,64-VPTE_PMD_SHIFT,64-PMD_INDEX_SIZE-3
        clrrdi  r10,r11,3
        ldx     r15,r10,r15
-       cmpldi  cr0,r15,0
-       beq     virt_page_table_tlb_miss_fault
+       cmpdi   cr0,r15,0
+       bge     virt_page_table_tlb_miss_fault
 
        /* Ok, we're all right, we can now create a kernel translation for
         * a 4K or 64K page from r16 -> r15.
@@ -802,24 +802,24 @@ htw_tlb_miss:
        rldicl  r11,r16,64-(PGDIR_SHIFT-3),64-PGD_INDEX_SIZE-3
        clrrdi  r10,r11,3
        ldx     r15,r10,r15
-       cmpldi  cr0,r15,0
-       beq     htw_tlb_miss_fault
+       cmpdi   cr0,r15,0
+       bge     htw_tlb_miss_fault
 
 #ifndef CONFIG_PPC_64K_PAGES
        /* Get to PUD entry */
        rldicl  r11,r16,64-(PUD_SHIFT-3),64-PUD_INDEX_SIZE-3
        clrrdi  r10,r11,3
        ldx     r15,r10,r15
-       cmpldi  cr0,r15,0
-       beq     htw_tlb_miss_fault
+       cmpdi   cr0,r15,0
+       bge     htw_tlb_miss_fault
 #endif /* CONFIG_PPC_64K_PAGES */
 
        /* Get to PMD entry */
        rldicl  r11,r16,64-(PMD_SHIFT-3),64-PMD_INDEX_SIZE-3
        clrrdi  r10,r11,3
        ldx     r15,r10,r15
-       cmpldi  cr0,r15,0
-       beq     htw_tlb_miss_fault
+       cmpdi   cr0,r15,0
+       bge     htw_tlb_miss_fault
 
        /* Ok, we're all right, we can now create an indirect entry for
         * a 1M or 256M page.
index d32ec64..6c2eabf 100644 (file)
 #include <linux/spinlock.h>
 #include <linux/memblock.h>
 #include <linux/of_fdt.h>
+#include <linux/hugetlb.h>
 
 #include <asm/tlbflush.h>
 #include <asm/tlb.h>
 #include <asm/code-patching.h>
+#include <asm/hugetlb.h>
 
 #include "mmu_decl.h"
 
-#ifdef CONFIG_PPC_BOOK3E
+/*
+ * This struct lists the sw-supported page sizes.  The hardawre MMU may support
+ * other sizes not listed here.   The .ind field is only used on MMUs that have
+ * indirect page table entries.
+ */
+#ifdef CONFIG_PPC_BOOK3E_MMU
+#ifdef CONFIG_FSL_BOOKE
+struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT] = {
+       [MMU_PAGE_4K] = {
+               .shift  = 12,
+               .enc    = BOOK3E_PAGESZ_4K,
+       },
+       [MMU_PAGE_4M] = {
+               .shift  = 22,
+               .enc    = BOOK3E_PAGESZ_4M,
+       },
+       [MMU_PAGE_16M] = {
+               .shift  = 24,
+               .enc    = BOOK3E_PAGESZ_16M,
+       },
+       [MMU_PAGE_64M] = {
+               .shift  = 26,
+               .enc    = BOOK3E_PAGESZ_64M,
+       },
+       [MMU_PAGE_256M] = {
+               .shift  = 28,
+               .enc    = BOOK3E_PAGESZ_256M,
+       },
+       [MMU_PAGE_1G] = {
+               .shift  = 30,
+               .enc    = BOOK3E_PAGESZ_1GB,
+       },
+};
+#else
 struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT] = {
        [MMU_PAGE_4K] = {
                .shift  = 12,
@@ -77,6 +112,8 @@ struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT] = {
                .enc    = BOOK3E_PAGESZ_1GB,
        },
 };
+#endif /* CONFIG_FSL_BOOKE */
+
 static inline int mmu_get_tsize(int psize)
 {
        return mmu_psize_defs[psize].enc;
@@ -87,7 +124,7 @@ static inline int mmu_get_tsize(int psize)
        /* This isn't used on !Book3E for now */
        return 0;
 }
-#endif
+#endif /* CONFIG_PPC_BOOK3E_MMU */
 
 /* The variables below are currently only used on 64-bit Book3E
  * though this will probably be made common with other nohash
@@ -266,6 +303,11 @@ void __flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr,
 
 void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
 {
+#ifdef CONFIG_HUGETLB_PAGE
+       if (is_vm_hugetlb_page(vma))
+               flush_hugetlb_page(vma, vmaddr);
+#endif
+
        __flush_tlb_page(vma ? vma->vm_mm : NULL, vmaddr,
                         mmu_get_tsize(mmu_virtual_psize), 0);
 }
@@ -600,13 +642,28 @@ void __cpuinit early_init_mmu_secondary(void)
 void setup_initial_memory_limit(phys_addr_t first_memblock_base,
                                phys_addr_t first_memblock_size)
 {
-       /* On Embedded 64-bit, we adjust the RMA size to match
+       /* On non-FSL Embedded 64-bit, we adjust the RMA size to match
         * the bolted TLB entry. We know for now that only 1G
         * entries are supported though that may eventually
-        * change. We crop it to the size of the first MEMBLOCK to
+        * change.
+        *
+        * on FSL Embedded 64-bit, we adjust the RMA size to match the
+        * first bolted TLB entry size.  We still limit max to 1G even if
+        * the TLB could cover more.  This is due to what the early init
+        * code is setup to do.
+        *
+        * We crop it to the size of the first MEMBLOCK to
         * avoid going over total available memory just in case...
         */
-       ppc64_rma_size = min_t(u64, first_memblock_size, 0x40000000);
+#ifdef CONFIG_PPC_FSL_BOOK3E
+       if (mmu_has_feature(MMU_FTR_TYPE_FSL_E)) {
+               unsigned long linear_sz;
+               linear_sz = calc_cam_sz(first_memblock_size, PAGE_OFFSET,
+                                       first_memblock_base);
+               ppc64_rma_size = min_t(u64, linear_sz, 0x40000000);
+       } else
+#endif
+               ppc64_rma_size = min_t(u64, first_memblock_size, 0x40000000);
 
        /* Finally limit subsequent allocations */
        memblock_set_current_limit(first_memblock_base + ppc64_rma_size);
index b5d8706..8f9c3e2 100644 (file)
@@ -32,14 +32,6 @@ config EP405
        help
          This option enables support for the EP405/EP405PC boards.
 
-config HCU4
-       bool "Hcu4"
-       depends on 40x
-       default n
-       select 405GPR
-       help
-         This option enables support for the Nestal Maschinen HCU4 board.
-
 config HOTFOOT
         bool "Hotfoot"
        depends on 40x
index 56e8900..88c22de 100644 (file)
@@ -1,4 +1,3 @@
-obj-$(CONFIG_HCU4)                             += hcu4.o
 obj-$(CONFIG_WALNUT)                           += walnut.o
 obj-$(CONFIG_XILINX_VIRTEX_GENERIC_BOARD)      += virtex.o
 obj-$(CONFIG_EP405)                            += ep405.o
diff --git a/arch/powerpc/platforms/40x/hcu4.c b/arch/powerpc/platforms/40x/hcu4.c
deleted file mode 100644 (file)
index 60b2afe..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Architecture- / platform-specific boot-time initialization code for
- * IBM PowerPC 4xx based boards. Adapted from original
- * code by Gary Thomas, Cort Dougan <cort@fsmlabs.com>, and Dan Malek
- * <dan@net4x.com>.
- *
- * Copyright(c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
- *
- * Rewritten and ported to the merged powerpc tree:
- * Copyright 2007 IBM Corporation
- * Josh Boyer <jwboyer@linux.vnet.ibm.com>
- *
- * 2002 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.  This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#include <linux/init.h>
-#include <linux/of_platform.h>
-
-#include <asm/machdep.h>
-#include <asm/prom.h>
-#include <asm/udbg.h>
-#include <asm/time.h>
-#include <asm/uic.h>
-#include <asm/ppc4xx.h>
-
-static __initdata struct of_device_id hcu4_of_bus[] = {
-       { .compatible = "ibm,plb3", },
-       { .compatible = "ibm,opb", },
-       { .compatible = "ibm,ebc", },
-       {},
-};
-
-static int __init hcu4_device_probe(void)
-{
-       of_platform_bus_probe(NULL, hcu4_of_bus, NULL);
-       return 0;
-}
-machine_device_initcall(hcu4, hcu4_device_probe);
-
-static int __init hcu4_probe(void)
-{
-       unsigned long root = of_get_flat_dt_root();
-
-       if (!of_flat_dt_is_compatible(root, "netstal,hcu4"))
-               return 0;
-
-       return 1;
-}
-
-define_machine(hcu4) {
-       .name                   = "HCU4",
-       .probe                  = hcu4_probe,
-       .progress               = udbg_progress,
-       .init_IRQ               = uic_init_tree,
-       .get_irq                = uic_get_irq,
-       .restart                = ppc4xx_reset_system,
-       .calibrate_decr         = generic_calibrate_decr,
-};
index 27b0651..b3ebce1 100644 (file)
@@ -6,6 +6,7 @@ config PPC_MPC512x
        select PPC_CLOCK
        select PPC_PCI_CHOICE
        select FSL_PCI if PCI
+       select ARCH_WANT_OPTIONAL_GPIOLIB
 
 config MPC5121_ADS
        bool "Freescale MPC5121E ADS"
index 428c5e0..3661bcd 100644 (file)
@@ -49,6 +49,9 @@ struct cpm_pin {
 };
 
 static __initdata struct cpm_pin km82xx_pins[] = {
+       /* SMC1 */
+       {2, 4, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+       {2, 5, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
 
        /* SMC2 */
        {0, 8, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
@@ -137,6 +140,7 @@ static void __init init_ioports(void)
        }
 
        cpm2_smc_clk_setup(CPM_CLK_SMC2, CPM_BRG8);
+       cpm2_smc_clk_setup(CPM_CLK_SMC1, CPM_BRG7);
        cpm2_clk_setup(CPM_CLK_SCC1, CPM_CLK11, CPM_CLK_RX);
        cpm2_clk_setup(CPM_CLK_SCC1, CPM_CLK11, CPM_CLK_TX);
        cpm2_clk_setup(CPM_CLK_SCC3, CPM_CLK5, CPM_CLK_RTX);
index 73f4135..670a033 100644 (file)
@@ -114,18 +114,21 @@ config KMETER1
 
 endif
 
-# used for usb
+# used for usb & gpio
 config PPC_MPC831x
        bool
+       select ARCH_WANT_OPTIONAL_GPIOLIB
 
 # used for math-emu
 config PPC_MPC832x
        bool
 
-# used for usb
+# used for usb & gpio
 config PPC_MPC834x
        bool
+       select ARCH_WANT_OPTIONAL_GPIOLIB
 
-# used for usb
+# used for usb & gpio
 config PPC_MPC837x
        bool
+       select ARCH_WANT_OPTIONAL_GPIOLIB
index 70798ac..ef6537b 100644 (file)
@@ -21,6 +21,8 @@
 #include <linux/of.h>
 #include <linux/of_gpio.h>
 #include <linux/slab.h>
+#include <linux/kthread.h>
+#include <linux/reboot.h>
 #include <asm/prom.h>
 #include <asm/machdep.h>
 
@@ -30,6 +32,7 @@
  */
 #define MCU_REG_CTRL   0x20
 #define MCU_CTRL_POFF  0x40
+#define MCU_CTRL_BTN   0x80
 
 #define MCU_NUM_GPIO   2
 
@@ -42,13 +45,55 @@ struct mcu {
 
 static struct mcu *glob_mcu;
 
+struct task_struct *shutdown_thread;
+static int shutdown_thread_fn(void *data)
+{
+       int ret;
+       struct mcu *mcu = glob_mcu;
+
+       while (!kthread_should_stop()) {
+               ret = i2c_smbus_read_byte_data(mcu->client, MCU_REG_CTRL);
+               if (ret < 0)
+                       pr_err("MCU status reg read failed.\n");
+               mcu->reg_ctrl = ret;
+
+
+               if (mcu->reg_ctrl & MCU_CTRL_BTN) {
+                       i2c_smbus_write_byte_data(mcu->client, MCU_REG_CTRL,
+                                                 mcu->reg_ctrl & ~MCU_CTRL_BTN);
+
+                       ctrl_alt_del();
+               }
+
+               set_current_state(TASK_INTERRUPTIBLE);
+               schedule_timeout(HZ);
+       }
+
+       return 0;
+}
+
+static ssize_t show_status(struct device *d,
+                          struct device_attribute *attr, char *buf)
+{
+       int ret;
+       struct mcu *mcu = glob_mcu;
+
+       ret = i2c_smbus_read_byte_data(mcu->client, MCU_REG_CTRL);
+       if (ret < 0)
+               return -ENODEV;
+       mcu->reg_ctrl = ret;
+
+       return sprintf(buf, "%02x\n", ret);
+}
+static DEVICE_ATTR(status, S_IRUGO, show_status, NULL);
+
 static void mcu_power_off(void)
 {
        struct mcu *mcu = glob_mcu;
 
        pr_info("Sending power-off request to the MCU...\n");
        mutex_lock(&mcu->lock);
-       i2c_smbus_write_byte_data(glob_mcu->client, MCU_REG_CTRL,
+       i2c_smbus_write_byte_data(mcu->client, MCU_REG_CTRL,
                                  mcu->reg_ctrl | MCU_CTRL_POFF);
        mutex_unlock(&mcu->lock);
 }
@@ -130,6 +175,13 @@ static int __devinit mcu_probe(struct i2c_client *client,
                dev_info(&client->dev, "will provide power-off service\n");
        }
 
+       if (device_create_file(&client->dev, &dev_attr_status))
+               dev_err(&client->dev,
+                       "couldn't create device file for status\n");
+
+       shutdown_thread = kthread_run(shutdown_thread_fn, NULL,
+                                     "mcu-i2c-shdn");
+
        return 0;
 err:
        kfree(mcu);
@@ -141,6 +193,10 @@ static int __devexit mcu_remove(struct i2c_client *client)
        struct mcu *mcu = i2c_get_clientdata(client);
        int ret;
 
+       kthread_stop(shutdown_thread);
+
+       device_remove_file(&client->dev, &dev_attr_status);
+
        if (glob_mcu == mcu) {
                ppc_md.power_off = NULL;
                glob_mcu = NULL;
index 12f5932..45023e2 100644 (file)
@@ -171,17 +171,18 @@ config SBC8560
        help
          This option enables support for the Wind River SBC8560 board
 
-config P2040_RDB
-       bool "Freescale P2040 RDB"
+config P2041_RDB
+       bool "Freescale P2041 RDB"
        select DEFAULT_UIMAGE
        select PPC_E500MC
        select PHYS_64BIT
        select SWIOTLB
-       select MPC8xxx_GPIO
+       select ARCH_REQUIRE_GPIOLIB
+       select GPIO_MPC8XXX
        select HAS_RAPIDIO
        select PPC_EPAPR_HV_PIC
        help
-         This option enables support for the P2040 RDB board
+         This option enables support for the P2041 RDB board
 
 config P3041_DS
        bool "Freescale P3041 DS"
@@ -189,19 +190,33 @@ config P3041_DS
        select PPC_E500MC
        select PHYS_64BIT
        select SWIOTLB
-       select MPC8xxx_GPIO
+       select ARCH_REQUIRE_GPIOLIB
+       select GPIO_MPC8XXX
        select HAS_RAPIDIO
        select PPC_EPAPR_HV_PIC
        help
          This option enables support for the P3041 DS board
 
+config P3060_QDS
+       bool "Freescale P3060 QDS"
+       select DEFAULT_UIMAGE
+       select PPC_E500MC
+       select PHYS_64BIT
+       select SWIOTLB
+       select MPC8xxx_GPIO
+       select HAS_RAPIDIO
+       select PPC_EPAPR_HV_PIC
+       help
+         This option enables support for the P3060 QDS board
+
 config P4080_DS
        bool "Freescale P4080 DS"
        select DEFAULT_UIMAGE
        select PPC_E500MC
        select PHYS_64BIT
        select SWIOTLB
-       select MPC8xxx_GPIO
+       select ARCH_REQUIRE_GPIOLIB
+       select GPIO_MPC8XXX
        select HAS_RAPIDIO
        select PPC_EPAPR_HV_PIC
        help
@@ -216,7 +231,8 @@ config P5020_DS
        select PPC_E500MC
        select PHYS_64BIT
        select SWIOTLB
-       select MPC8xxx_GPIO
+       select ARCH_REQUIRE_GPIOLIB
+       select GPIO_MPC8XXX
        select HAS_RAPIDIO
        select PPC_EPAPR_HV_PIC
        help
index a971b32..bc5acb9 100644 (file)
@@ -13,8 +13,9 @@ obj-$(CONFIG_MPC85xx_RDB) += mpc85xx_rdb.o
 obj-$(CONFIG_P1010_RDB)   += p1010rdb.o
 obj-$(CONFIG_P1022_DS)    += p1022_ds.o
 obj-$(CONFIG_P1023_RDS)   += p1023_rds.o
-obj-$(CONFIG_P2040_RDB)   += p2040_rdb.o corenet_ds.o
+obj-$(CONFIG_P2041_RDB)   += p2041_rdb.o corenet_ds.o
 obj-$(CONFIG_P3041_DS)    += p3041_ds.o corenet_ds.o
+obj-$(CONFIG_P3060_QDS)   += p3060_qds.o corenet_ds.o
 obj-$(CONFIG_P4080_DS)    += p4080_ds.o corenet_ds.o
 obj-$(CONFIG_P5020_DS)    += p5020_ds.o corenet_ds.o
 obj-$(CONFIG_STX_GP3)    += stx_gp3.o
index c01c727..fda1571 100644 (file)
@@ -129,17 +129,20 @@ static void p1022ds_set_gamma_table(enum fsl_diu_monitor_port port,
  */
 static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port)
 {
-       struct device_node *pixis_node;
+       struct device_node *np;
        void __iomem *pixis;
        u8 __iomem *brdcfg1;
 
-       pixis_node = of_find_compatible_node(NULL, NULL, "fsl,p1022ds-pixis");
-       if (!pixis_node) {
+       np = of_find_compatible_node(NULL, NULL, "fsl,p1022ds-fpga");
+       if (!np)
+               /* older device trees used "fsl,p1022ds-pixis" */
+               np = of_find_compatible_node(NULL, NULL, "fsl,p1022ds-pixis");
+       if (!np) {
                pr_err("p1022ds: missing ngPIXIS node\n");
                return;
        }
 
-       pixis = of_iomap(pixis_node, 0);
+       pixis = of_iomap(np, 0);
        if (!pixis) {
                pr_err("p1022ds: could not map ngPIXIS registers\n");
                return;
similarity index 82%
rename from arch/powerpc/platforms/85xx/p2040_rdb.c
rename to arch/powerpc/platforms/85xx/p2041_rdb.c
index 32b56ac..eda6ed5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * P2040 RDB Setup
+ * P2041 RDB Setup
  *
  * Copyright 2011 Freescale Semiconductor Inc.
  *
 /*
  * Called very early, device-tree isn't unflattened
  */
-static int __init p2040_rdb_probe(void)
+static int __init p2041_rdb_probe(void)
 {
        unsigned long root = of_get_flat_dt_root();
 #ifdef CONFIG_SMP
        extern struct smp_ops_t smp_85xx_ops;
 #endif
 
-       if (of_flat_dt_is_compatible(root, "fsl,P2040RDB"))
+       if (of_flat_dt_is_compatible(root, "fsl,P2041RDB"))
                return 1;
 
        /* Check if we're running under the Freescale hypervisor */
-       if (of_flat_dt_is_compatible(root, "fsl,P2040RDB-hv")) {
+       if (of_flat_dt_is_compatible(root, "fsl,P2041RDB-hv")) {
                ppc_md.init_IRQ = ehv_pic_init;
                ppc_md.get_irq = ehv_pic_get_irq;
                ppc_md.restart = fsl_hv_restart;
@@ -66,9 +66,9 @@ static int __init p2040_rdb_probe(void)
        return 0;
 }
 
-define_machine(p2040_rdb) {
-       .name                   = "P2040 RDB",
-       .probe                  = p2040_rdb_probe,
+define_machine(p2041_rdb) {
+       .name                   = "P2041 RDB",
+       .probe                  = p2041_rdb_probe,
        .setup_arch             = corenet_ds_setup_arch,
        .init_IRQ               = corenet_ds_pic_init,
 #ifdef CONFIG_PCI
@@ -81,8 +81,8 @@ define_machine(p2040_rdb) {
        .power_save             = e500_idle,
 };
 
-machine_device_initcall(p2040_rdb, corenet_ds_publish_devices);
+machine_device_initcall(p2041_rdb, corenet_ds_publish_devices);
 
 #ifdef CONFIG_SWIOTLB
-machine_arch_initcall(p2040_rdb, swiotlb_setup_bus_notifier);
+machine_arch_initcall(p2041_rdb, swiotlb_setup_bus_notifier);
 #endif
diff --git a/arch/powerpc/platforms/85xx/p3060_qds.c b/arch/powerpc/platforms/85xx/p3060_qds.c
new file mode 100644 (file)
index 0000000..01dcf44
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * P3060 QDS Setup
+ *
+ * Copyright 2011 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/phy.h>
+#include <asm/machdep.h>
+#include <asm/udbg.h>
+#include <asm/mpic.h>
+#include <linux/of_platform.h>
+#include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pci.h>
+#include <asm/ehv_pic.h>
+#include "corenet_ds.h"
+
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+static int __init p3060_qds_probe(void)
+{
+       unsigned long root = of_get_flat_dt_root();
+#ifdef CONFIG_SMP
+       extern struct smp_ops_t smp_85xx_ops;
+#endif
+
+       if (of_flat_dt_is_compatible(root, "fsl,P3060QDS"))
+               return 1;
+
+       /* Check if we're running under the Freescale hypervisor */
+       if (of_flat_dt_is_compatible(root, "fsl,P3060QDS-hv")) {
+               ppc_md.init_IRQ = ehv_pic_init;
+               ppc_md.get_irq = ehv_pic_get_irq;
+               ppc_md.restart = fsl_hv_restart;
+               ppc_md.power_off = fsl_hv_halt;
+               ppc_md.halt = fsl_hv_halt;
+#ifdef CONFIG_SMP
+               /*
+                * Disable the timebase sync operations because we can't write
+                * to the timebase registers under the hypervisor.
+                */
+               smp_85xx_ops.give_timebase = NULL;
+               smp_85xx_ops.take_timebase = NULL;
+#endif
+               return 1;
+       }
+
+       return 0;
+}
+
+define_machine(p3060_qds) {
+       .name                   = "P3060 QDS",
+       .probe                  = p3060_qds_probe,
+       .setup_arch             = corenet_ds_setup_arch,
+       .init_IRQ               = corenet_ds_pic_init,
+#ifdef CONFIG_PCI
+       .pcibios_fixup_bus      = fsl_pcibios_fixup_bus,
+#endif
+       .get_irq                = mpic_get_coreint_irq,
+       .restart                = fsl_rstcr_restart,
+       .calibrate_decr         = generic_calibrate_decr,
+       .progress               = udbg_progress,
+       .power_save             = e500_idle,
+};
+
+machine_device_initcall(p3060_qds, declare_of_platform_devices);
+
+#ifdef CONFIG_SWIOTLB
+machine_arch_initcall(p3060_qds, swiotlb_setup_bus_notifier);
+#endif
index 09ced72..cebd786 100644 (file)
@@ -283,7 +283,7 @@ static int __init sbc8560_bdrstcr_init(void)
 
        of_address_to_resource(np, 0, &res);
 
-       printk(KERN_INFO "sbc8560: Found BRSTCR at i/o 0x%x\n", res.start);
+       printk(KERN_INFO "sbc8560: Found BRSTCR at %pR\n", &res);
 
        brstcr = ioremap(res.start, resource_size(&res));
        if(!brstcr)
index 5b9b901..2df4785 100644 (file)
@@ -48,10 +48,11 @@ smp_85xx_kick_cpu(int nr)
        const u64 *cpu_rel_addr;
        __iomem u32 *bptr_vaddr;
        struct device_node *np;
-       int n = 0;
+       int n = 0, hw_cpu = get_hard_smp_processor_id(nr);
        int ioremappable;
 
-       WARN_ON (nr < 0 || nr >= NR_CPUS);
+       WARN_ON(nr < 0 || nr >= NR_CPUS);
+       WARN_ON(hw_cpu < 0 || hw_cpu >= NR_CPUS);
 
        pr_debug("smp_85xx_kick_cpu: kick CPU #%d\n", nr);
 
@@ -79,7 +80,7 @@ smp_85xx_kick_cpu(int nr)
 
        local_irq_save(flags);
 
-       out_be32(bptr_vaddr + BOOT_ENTRY_PIR, nr);
+       out_be32(bptr_vaddr + BOOT_ENTRY_PIR, hw_cpu);
 #ifdef CONFIG_PPC32
        out_be32(bptr_vaddr + BOOT_ENTRY_ADDR_LOWER, __pa(__early_start));
 
@@ -88,7 +89,7 @@ smp_85xx_kick_cpu(int nr)
                                (ulong)(bptr_vaddr + SIZE_BOOT_ENTRY));
 
        /* Wait a bit for the CPU to ack. */
-       while ((__secondary_hold_acknowledge != nr) && (++n < 1000))
+       while ((__secondary_hold_acknowledge != hw_cpu) && (++n < 1000))
                mdelay(1);
 #else
        smp_generic_kick_cpu(nr);
@@ -206,7 +207,7 @@ static void mpc85xx_smp_machine_kexec(struct kimage *image)
        if ( !timeout )
                printk(KERN_ERR "Unable to bring down secondary cpu(s)");
 
-       for (i = 0; i < num_cpus; i++)
+       for_each_online_cpu(i)
        {
                if ( i == smp_processor_id() ) continue;
                mpic_reset_core(i);
@@ -243,6 +244,7 @@ void __init mpc85xx_smp_init(void)
                 * If left NULL, .message_pass defaults to
                 * smp_muxed_ipi_message_pass
                 */
+               smp_85xx_ops.message_pass = NULL;
                smp_85xx_ops.cause_ipi = doorbell_cause_ipi;
        }
 
index a0b5638..8d6599d 100644 (file)
@@ -4,6 +4,7 @@ menuconfig PPC_86xx
        depends on 6xx
        select FSL_SOC
        select ALTIVEC
+       select ARCH_WANT_OPTIONAL_GPIOLIB
        help
          The Freescale E600 SoCs have 74xx cores.
 
index b9ba861..e458872 100644 (file)
@@ -1,5 +1,6 @@
 menu "Platform support"
 
+source "arch/powerpc/platforms/powernv/Kconfig"
 source "arch/powerpc/platforms/pseries/Kconfig"
 source "arch/powerpc/platforms/iseries/Kconfig"
 source "arch/powerpc/platforms/chrp/Kconfig"
@@ -333,16 +334,6 @@ config OF_RTC
 
 source "arch/powerpc/sysdev/bestcomm/Kconfig"
 
-config MPC8xxx_GPIO
-       bool "MPC512x/MPC8xxx GPIO support"
-       depends on PPC_MPC512x || PPC_MPC831x || PPC_MPC834x || PPC_MPC837x || \
-                  FSL_SOC_BOOKE || PPC_86xx
-       select GENERIC_GPIO
-       select ARCH_REQUIRE_GPIOLIB
-       help
-         Say Y here if you're going to use hardware that connects to the
-         MPC512x/831x/834x/837x/8572/8610 GPIOs.
-
 config SIMPLE_GPIO
        bool "Support for simple, memory-mapped GPIO controllers"
        depends on PPC
@@ -355,7 +346,7 @@ config SIMPLE_GPIO
          on-board peripherals.
 
 config MCU_MPC8349EMITX
-       tristate "MPC8349E-mITX MCU driver"
+       bool "MPC8349E-mITX MCU driver"
        depends on I2C && PPC_83xx
        select GENERIC_GPIO
        select ARCH_REQUIRE_GPIOLIB
index e06e395..a85990c 100644 (file)
@@ -69,6 +69,7 @@ config PPC_BOOK3S_64
        bool "Server processors"
        select PPC_FPU
        select PPC_HAVE_PMU_SUPPORT
+       select SYS_SUPPORTS_HUGETLBFS
 
 config PPC_BOOK3E_64
        bool "Embedded processors"
@@ -173,6 +174,7 @@ config BOOKE
 config FSL_BOOKE
        bool
        depends on (E200 || E500) && PPC32
+       select SYS_SUPPORTS_HUGETLBFS if PHYS_64BIT
        default y
 
 # this is for common code between PPC32 & PPC64 FSL BOOKE
@@ -296,7 +298,7 @@ config PPC_BOOK3E_MMU
 
 config PPC_MM_SLICES
        bool
-       default y if HUGETLB_PAGE || (PPC_STD_MMU_64 && PPC_64K_PAGES)
+       default y if (PPC64 && HUGETLB_PAGE) || (PPC_STD_MMU_64 && PPC_64K_PAGES)
        default n
 
 config VIRT_CPU_ACCOUNTING
index 73e2116..2635a22 100644 (file)
@@ -14,6 +14,7 @@ obj-$(CONFIG_PPC_82xx)                += 82xx/
 obj-$(CONFIG_PPC_83xx)         += 83xx/
 obj-$(CONFIG_FSL_SOC_BOOKE)    += 85xx/
 obj-$(CONFIG_PPC_86xx)         += 86xx/
+obj-$(CONFIG_PPC_POWERNV)      += powernv/
 obj-$(CONFIG_PPC_PSERIES)      += pseries/
 obj-$(CONFIG_PPC_ISERIES)      += iseries/
 obj-$(CONFIG_PPC_MAPLE)                += maple/
index 26a0671..fc46fca 100644 (file)
@@ -1159,6 +1159,26 @@ static int __init setup_iommu_fixed(char *str)
 }
 __setup("iommu_fixed=", setup_iommu_fixed);
 
+static u64 cell_dma_get_required_mask(struct device *dev)
+{
+       struct dma_map_ops *dma_ops;
+
+       if (!dev->dma_mask)
+               return 0;
+
+       if (!iommu_fixed_disabled &&
+                       cell_iommu_get_fixed_address(dev) != OF_BAD_ADDR)
+               return DMA_BIT_MASK(64);
+
+       dma_ops = get_dma_ops(dev);
+       if (dma_ops->get_required_mask)
+               return dma_ops->get_required_mask(dev);
+
+       WARN_ONCE(1, "no get_required_mask in %p ops", dma_ops);
+
+       return DMA_BIT_MASK(64);
+}
+
 static int __init cell_iommu_init(void)
 {
        struct device_node *np;
@@ -1175,6 +1195,7 @@ static int __init cell_iommu_init(void)
 
        /* Setup various ppc_md. callbacks */
        ppc_md.pci_dma_dev_setup = cell_pci_dma_dev_setup;
+       ppc_md.dma_get_required_mask = cell_dma_get_required_mask;
        ppc_md.tce_build = tce_build_cell;
        ppc_md.tce_free = tce_free_cell;
 
diff --git a/arch/powerpc/platforms/powernv/Kconfig b/arch/powerpc/platforms/powernv/Kconfig
new file mode 100644 (file)
index 0000000..74fea5c
--- /dev/null
@@ -0,0 +1,16 @@
+config PPC_POWERNV
+       depends on PPC64 && PPC_BOOK3S
+       bool "IBM PowerNV (Non-Virtualized) platform support"
+       select PPC_NATIVE
+       select PPC_XICS
+       select PPC_ICP_NATIVE
+       select PPC_P7_NAP
+       select PPC_PCI_CHOICE if EMBEDDED
+       default y
+
+config PPC_POWERNV_RTAS
+       depends on PPC_POWERNV
+       bool "Support for RTAS based PowerNV platforms such as BML"
+       default y
+       select PPC_ICS_RTAS
+       select PPC_RTAS
diff --git a/arch/powerpc/platforms/powernv/Makefile b/arch/powerpc/platforms/powernv/Makefile
new file mode 100644 (file)
index 0000000..3185300
--- /dev/null
@@ -0,0 +1,5 @@
+obj-y                  += setup.o opal-takeover.o opal-wrappers.o opal.o
+obj-y                  += opal-rtc.o opal-nvram.o
+
+obj-$(CONFIG_SMP)      += smp.o
+obj-$(CONFIG_PCI)      += pci.o pci-p5ioc2.o
diff --git a/arch/powerpc/platforms/powernv/opal-nvram.c b/arch/powerpc/platforms/powernv/opal-nvram.c
new file mode 100644 (file)
index 0000000..3f83e1a
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * PowerNV nvram code.
+ *
+ * Copyright 2011 IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#define DEBUG
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/of.h>
+
+#include <asm/opal.h>
+#include <asm/machdep.h>
+
+static unsigned int nvram_size;
+
+static ssize_t opal_nvram_size(void)
+{
+       return nvram_size;
+}
+
+static ssize_t opal_nvram_read(char *buf, size_t count, loff_t *index)
+{
+       s64 rc;
+       int off;
+
+       if (*index >= nvram_size)
+               return 0;
+       off = *index;
+       if ((off + count) > nvram_size)
+               count = nvram_size - off;
+       rc = opal_read_nvram(__pa(buf), count, off);
+       if (rc != OPAL_SUCCESS)
+               return -EIO;
+       *index += count;
+       return count;
+}
+
+static ssize_t opal_nvram_write(char *buf, size_t count, loff_t *index)
+{
+       s64 rc = OPAL_BUSY;
+       int off;
+
+       if (*index >= nvram_size)
+               return 0;
+       off = *index;
+       if ((off + count) > nvram_size)
+               count = nvram_size - off;
+
+       while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) {
+               rc = opal_write_nvram(__pa(buf), count, off);
+               if (rc == OPAL_BUSY_EVENT)
+                       opal_poll_events(NULL);
+       }
+       *index += count;
+       return count;
+}
+
+void __init opal_nvram_init(void)
+{
+       struct device_node *np;
+       const u32 *nbytes_p;
+
+       np = of_find_compatible_node(NULL, NULL, "ibm,opal-nvram");
+       if (np == NULL)
+               return;
+
+       nbytes_p = of_get_property(np, "#bytes", NULL);
+       if (!nbytes_p) {
+               of_node_put(np);
+               return;
+       }
+       nvram_size = *nbytes_p;
+
+       printk(KERN_INFO "OPAL nvram setup, %u bytes\n", nvram_size);
+       of_node_put(np);
+
+       ppc_md.nvram_read = opal_nvram_read;
+       ppc_md.nvram_write = opal_nvram_write;
+       ppc_md.nvram_size = opal_nvram_size;
+}
+
diff --git a/arch/powerpc/platforms/powernv/opal-rtc.c b/arch/powerpc/platforms/powernv/opal-rtc.c
new file mode 100644 (file)
index 0000000..2aa7641
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * PowerNV Real Time Clock.
+ *
+ * Copyright 2011 IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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/time.h>
+#include <linux/bcd.h>
+#include <linux/rtc.h>
+#include <linux/delay.h>
+
+#include <asm/opal.h>
+#include <asm/firmware.h>
+
+static void opal_to_tm(u32 y_m_d, u64 h_m_s_ms, struct rtc_time *tm)
+{
+       tm->tm_year     = ((bcd2bin(y_m_d >> 24) * 100) +
+                          bcd2bin((y_m_d >> 16) & 0xff)) - 1900;
+       tm->tm_mon      = bcd2bin((y_m_d >> 8) & 0xff) - 1;
+       tm->tm_mday     = bcd2bin(y_m_d & 0xff);
+       tm->tm_hour     = bcd2bin((h_m_s_ms >> 56) & 0xff);
+       tm->tm_min      = bcd2bin((h_m_s_ms >> 48) & 0xff);
+       tm->tm_sec      = bcd2bin((h_m_s_ms >> 40) & 0xff);
+
+        GregorianDay(tm);
+}
+
+unsigned long __init opal_get_boot_time(void)
+{
+       struct rtc_time tm;
+       u32 y_m_d;
+       u64 h_m_s_ms;
+       long rc = OPAL_BUSY;
+
+       while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) {
+               rc = opal_rtc_read(&y_m_d, &h_m_s_ms);
+               if (rc == OPAL_BUSY_EVENT)
+                       opal_poll_events(NULL);
+               else
+                       mdelay(10);
+       }
+       if (rc != OPAL_SUCCESS)
+               return 0;
+       opal_to_tm(y_m_d, h_m_s_ms, &tm);
+       return mktime(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
+                     tm.tm_hour, tm.tm_min, tm.tm_sec);
+}
+
+void opal_get_rtc_time(struct rtc_time *tm)
+{
+       long rc = OPAL_BUSY;
+       u32 y_m_d;
+       u64 h_m_s_ms;
+
+       while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) {
+               rc = opal_rtc_read(&y_m_d, &h_m_s_ms);
+               if (rc == OPAL_BUSY_EVENT)
+                       opal_poll_events(NULL);
+               else
+                       mdelay(10);
+       }
+       if (rc != OPAL_SUCCESS)
+               return;
+       opal_to_tm(y_m_d, h_m_s_ms, tm);
+}
+
+int opal_set_rtc_time(struct rtc_time *tm)
+{
+       long rc = OPAL_BUSY;
+       u32 y_m_d = 0;
+       u64 h_m_s_ms = 0;
+
+       y_m_d |= ((u32)bin2bcd((tm->tm_year + 1900) / 100)) << 24;
+       y_m_d |= ((u32)bin2bcd((tm->tm_year + 1900) % 100)) << 16;
+       y_m_d |= ((u32)bin2bcd((tm->tm_mon + 1))) << 8;
+       y_m_d |= ((u32)bin2bcd(tm->tm_mday));
+
+       h_m_s_ms |= ((u64)bin2bcd(tm->tm_hour)) << 56;
+       h_m_s_ms |= ((u64)bin2bcd(tm->tm_min)) << 48;
+       h_m_s_ms |= ((u64)bin2bcd(tm->tm_sec)) << 40;
+
+       while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) {
+               rc = opal_rtc_write(y_m_d, h_m_s_ms);
+               if (rc == OPAL_BUSY_EVENT)
+                       opal_poll_events(NULL);
+               else
+                       mdelay(10);
+       }
+       return rc == OPAL_SUCCESS ? 0 : -EIO;
+}
diff --git a/arch/powerpc/platforms/powernv/opal-takeover.S b/arch/powerpc/platforms/powernv/opal-takeover.S
new file mode 100644 (file)
index 0000000..77b48b2
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * PowerNV OPAL takeover assembly code, for use by prom_init.c
+ *
+ * Copyright 2011 IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <asm/ppc_asm.h>
+#include <asm/hvcall.h>
+#include <asm/asm-offsets.h>
+#include <asm/opal.h>
+
+#define STK_PARAM(i)   (48 + ((i)-3)*8)
+
+#define H_HAL_TAKEOVER                 0x5124
+#define H_HAL_TAKEOVER_QUERY_MAGIC     -1
+
+       .text
+_GLOBAL(opal_query_takeover)
+       mfcr    r0
+       stw     r0,8(r1)
+       std     r3,STK_PARAM(r3)(r1)
+       std     r4,STK_PARAM(r4)(r1)
+       li      r3,H_HAL_TAKEOVER
+       li      r4,H_HAL_TAKEOVER_QUERY_MAGIC
+       HVSC
+       ld      r10,STK_PARAM(r3)(r1)
+       std     r4,0(r10)
+       ld      r10,STK_PARAM(r4)(r1)
+       std     r5,0(r10)
+       lwz     r0,8(r1)
+       mtcrf   0xff,r0
+       blr
+
+_GLOBAL(opal_do_takeover)
+       mfcr    r0
+       stw     r0,8(r1)
+       mflr    r0
+       std     r0,16(r1)
+       bl      __opal_do_takeover
+       ld      r0,16(r1)
+       mtlr    r0
+       lwz     r0,8(r1)
+       mtcrf   0xff,r0
+       blr
+
+__opal_do_takeover:
+       ld      r4,0(r3)
+       ld      r5,0x8(r3)
+       ld      r6,0x10(r3)
+       ld      r7,0x18(r3)
+       ld      r8,0x20(r3)
+       ld      r9,0x28(r3)
+       ld      r10,0x30(r3)
+       ld      r11,0x38(r3)
+       li      r3,H_HAL_TAKEOVER
+       HVSC
+       blr
+
+       .globl opal_secondary_entry
+opal_secondary_entry:
+       mr      r31,r3
+       mfmsr   r11
+       li      r12,(MSR_SF | MSR_ISF)@highest
+       sldi    r12,r12,48
+       or      r11,r11,r12
+       mtmsrd  r11
+       isync
+       mfspr   r4,SPRN_PIR
+       std     r4,0(r3)
+1:     HMT_LOW
+       ld      r4,8(r3)
+       cmpli   cr0,r4,0
+       beq     1b
+       HMT_MEDIUM
+1:     addi    r3,r31,16
+       bl      __opal_do_takeover
+       b       1b
+
+_GLOBAL(opal_enter_rtas)
+       mflr    r0
+       std     r0,16(r1)
+        stdu   r1,-PROM_FRAME_SIZE(r1) /* Save SP and create stack space */
+
+       /* Because PROM is running in 32b mode, it clobbers the high order half
+        * of all registers that it saves.  We therefore save those registers
+        * PROM might touch to the stack.  (r0, r3-r13 are caller saved)
+       */
+       SAVE_GPR(2, r1)
+       SAVE_GPR(13, r1)
+       SAVE_8GPRS(14, r1)
+       SAVE_10GPRS(22, r1)
+       mfcr    r10
+       mfmsr   r11
+       std     r10,_CCR(r1)
+       std     r11,_MSR(r1)
+
+       /* Get the PROM entrypoint */
+       mtlr    r5
+
+       /* Switch MSR to 32 bits mode
+        */
+        li      r12,1
+        rldicr  r12,r12,MSR_SF_LG,(63-MSR_SF_LG)
+        andc    r11,r11,r12
+        li      r12,1
+        rldicr  r12,r12,MSR_ISF_LG,(63-MSR_ISF_LG)
+        andc    r11,r11,r12
+        mtmsrd  r11
+        isync
+
+       /* Enter RTAS here... */
+       blrl
+
+       /* Just make sure that r1 top 32 bits didn't get
+        * corrupt by OF
+        */
+       rldicl  r1,r1,0,32
+
+       /* Restore the MSR (back to 64 bits) */
+       ld      r0,_MSR(r1)
+       MTMSRD(r0)
+        isync
+
+       /* Restore other registers */
+       REST_GPR(2, r1)
+       REST_GPR(13, r1)
+       REST_8GPRS(14, r1)
+       REST_10GPRS(22, r1)
+       ld      r4,_CCR(r1)
+       mtcr    r4
+
+        addi   r1,r1,PROM_FRAME_SIZE
+       ld      r0,16(r1)
+       mtlr    r0
+       blr
diff --git a/arch/powerpc/platforms/powernv/opal-wrappers.S b/arch/powerpc/platforms/powernv/opal-wrappers.S
new file mode 100644 (file)
index 0000000..4a3f46d
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * PowerNV OPAL API wrappers
+ *
+ * Copyright 2011 IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <asm/ppc_asm.h>
+#include <asm/hvcall.h>
+#include <asm/asm-offsets.h>
+#include <asm/opal.h>
+
+/* TODO:
+ *
+ * - Trace irqs in/off (needs saving/restoring all args, argh...)
+ * - Get r11 feed up by Dave so I can have better register usage
+ */
+#define OPAL_CALL(name, token)         \
+ _GLOBAL(name);                                \
+       mflr    r0;                     \
+       mfcr    r12;                    \
+       std     r0,16(r1);              \
+       std     r12,8(r1);              \
+       std     r1,PACAR1(r13);         \
+       li      r0,0;                   \
+       mfmsr   r12;                    \
+       ori     r0,r0,MSR_EE;           \
+       std     r12,PACASAVEDMSR(r13);  \
+       andc    r12,r12,r0;             \
+       mtmsrd  r12,1;                  \
+       LOAD_REG_ADDR(r0,.opal_return); \
+       mtlr    r0;                     \
+       li      r0,MSR_DR|MSR_IR;       \
+       andc    r12,r12,r0;             \
+       li      r0,token;               \
+       mtspr   SPRN_HSRR1,r12;         \
+       LOAD_REG_ADDR(r11,opal);        \
+       ld      r12,8(r11);             \
+       ld      r2,0(r11);              \
+       mtspr   SPRN_HSRR0,r12;         \
+       hrfid
+
+_STATIC(opal_return)
+       ld      r2,PACATOC(r13);
+       ld      r4,8(r1);
+       ld      r5,16(r1);
+       ld      r6,PACASAVEDMSR(r13);
+       mtspr   SPRN_SRR0,r5;
+       mtspr   SPRN_SRR1,r6;
+       mtcr    r4;
+       rfid
+
+OPAL_CALL(opal_console_write,                  OPAL_CONSOLE_WRITE);
+OPAL_CALL(opal_console_read,                   OPAL_CONSOLE_READ);
+OPAL_CALL(opal_console_write_buffer_space,     OPAL_CONSOLE_WRITE_BUFFER_SPACE);
+OPAL_CALL(opal_rtc_read,                       OPAL_RTC_READ);
+OPAL_CALL(opal_rtc_write,                      OPAL_RTC_WRITE);
+OPAL_CALL(opal_cec_power_down,                 OPAL_CEC_POWER_DOWN);
+OPAL_CALL(opal_cec_reboot,                     OPAL_CEC_REBOOT);
+OPAL_CALL(opal_read_nvram,                     OPAL_READ_NVRAM);
+OPAL_CALL(opal_write_nvram,                    OPAL_WRITE_NVRAM);
+OPAL_CALL(opal_handle_interrupt,               OPAL_HANDLE_INTERRUPT);
+OPAL_CALL(opal_poll_events,                    OPAL_POLL_EVENTS);
+OPAL_CALL(opal_pci_set_hub_tce_memory,         OPAL_PCI_SET_HUB_TCE_MEMORY);
+OPAL_CALL(opal_pci_set_phb_tce_memory,         OPAL_PCI_SET_PHB_TCE_MEMORY);
+OPAL_CALL(opal_pci_config_read_byte,           OPAL_PCI_CONFIG_READ_BYTE);
+OPAL_CALL(opal_pci_config_read_half_word,      OPAL_PCI_CONFIG_READ_HALF_WORD);
+OPAL_CALL(opal_pci_config_read_word,           OPAL_PCI_CONFIG_READ_WORD);
+OPAL_CALL(opal_pci_config_write_byte,          OPAL_PCI_CONFIG_WRITE_BYTE);
+OPAL_CALL(opal_pci_config_write_half_word,     OPAL_PCI_CONFIG_WRITE_HALF_WORD);
+OPAL_CALL(opal_pci_config_write_word,          OPAL_PCI_CONFIG_WRITE_WORD);
+OPAL_CALL(opal_set_xive,                       OPAL_SET_XIVE);
+OPAL_CALL(opal_get_xive,                       OPAL_GET_XIVE);
+OPAL_CALL(opal_register_exception_handler,     OPAL_REGISTER_OPAL_EXCEPTION_HANDLER);
+OPAL_CALL(opal_pci_eeh_freeze_status,          OPAL_PCI_EEH_FREEZE_STATUS);
+OPAL_CALL(opal_pci_eeh_freeze_clear,           OPAL_PCI_EEH_FREEZE_CLEAR);
+OPAL_CALL(opal_pci_shpc,                       OPAL_PCI_SHPC);
+OPAL_CALL(opal_pci_phb_mmio_enable,            OPAL_PCI_PHB_MMIO_ENABLE);
+OPAL_CALL(opal_pci_set_phb_mem_window,         OPAL_PCI_SET_PHB_MEM_WINDOW);
+OPAL_CALL(opal_pci_map_pe_mmio_window,         OPAL_PCI_MAP_PE_MMIO_WINDOW);
+OPAL_CALL(opal_pci_set_phb_table_memory,       OPAL_PCI_SET_PHB_TABLE_MEMORY);
+OPAL_CALL(opal_pci_set_pe,                     OPAL_PCI_SET_PE);
+OPAL_CALL(opal_pci_set_peltv,                  OPAL_PCI_SET_PELTV);
+OPAL_CALL(opal_pci_set_mve,                    OPAL_PCI_SET_MVE);
+OPAL_CALL(opal_pci_set_mve_enable,             OPAL_PCI_SET_MVE_ENABLE);
+OPAL_CALL(opal_pci_get_xive_reissue,           OPAL_PCI_GET_XIVE_REISSUE);
+OPAL_CALL(opal_pci_set_xive_reissue,           OPAL_PCI_SET_XIVE_REISSUE);
+OPAL_CALL(opal_pci_set_xive_pe,                        OPAL_PCI_SET_XIVE_PE);
+OPAL_CALL(opal_get_xive_source,                        OPAL_GET_XIVE_SOURCE);
+OPAL_CALL(opal_get_msi_32,                     OPAL_GET_MSI_32);
+OPAL_CALL(opal_get_msi_64,                     OPAL_GET_MSI_64);
+OPAL_CALL(opal_start_cpu,                      OPAL_START_CPU);
+OPAL_CALL(opal_query_cpu_status,               OPAL_QUERY_CPU_STATUS);
+OPAL_CALL(opal_write_oppanel,                  OPAL_WRITE_OPPANEL);
+OPAL_CALL(opal_pci_map_pe_dma_window,          OPAL_PCI_MAP_PE_DMA_WINDOW);
+OPAL_CALL(opal_pci_map_pe_dma_window_real,     OPAL_PCI_MAP_PE_DMA_WINDOW_REAL);
+OPAL_CALL(opal_pci_reset,                      OPAL_PCI_RESET);
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
new file mode 100644 (file)
index 0000000..aaa0dba
--- /dev/null
@@ -0,0 +1,322 @@
+/*
+ * PowerNV OPAL high level interfaces
+ *
+ * Copyright 2011 IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#undef DEBUG
+
+#include <linux/types.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/interrupt.h>
+#include <asm/opal.h>
+#include <asm/firmware.h>
+
+#include "powernv.h"
+
+struct opal {
+       u64 base;
+       u64 entry;
+} opal;
+
+static struct device_node *opal_node;
+static DEFINE_SPINLOCK(opal_write_lock);
+extern u64 opal_mc_secondary_handler[];
+
+int __init early_init_dt_scan_opal(unsigned long node,
+                                  const char *uname, int depth, void *data)
+{
+       const void *basep, *entryp;
+       unsigned long basesz, entrysz;
+       u64 glue;
+
+       if (depth != 1 || strcmp(uname, "ibm,opal") != 0)
+               return 0;
+
+       basep  = of_get_flat_dt_prop(node, "opal-base-address", &basesz);
+       entryp = of_get_flat_dt_prop(node, "opal-entry-address", &entrysz);
+
+       if (!basep || !entryp)
+               return 1;
+
+       opal.base = of_read_number(basep, basesz/4);
+       opal.entry = of_read_number(entryp, entrysz/4);
+
+       pr_debug("OPAL Base  = 0x%llx (basep=%p basesz=%ld)\n",
+                opal.base, basep, basesz);
+       pr_debug("OPAL Entry = 0x%llx (entryp=%p basesz=%ld)\n",
+                opal.entry, entryp, entrysz);
+
+       powerpc_firmware_features |= FW_FEATURE_OPAL;
+       if (of_flat_dt_is_compatible(node, "ibm,opal-v2")) {
+               powerpc_firmware_features |= FW_FEATURE_OPALv2;
+               printk("OPAL V2 detected !\n");
+       } else {
+               printk("OPAL V1 detected !\n");
+       }
+
+       /* Hookup some exception handlers. We use the fwnmi area at 0x7000
+        * to provide the glue space to OPAL
+        */
+       glue = 0x7000;
+       opal_register_exception_handler(OPAL_MACHINE_CHECK_HANDLER,
+                                       __pa(opal_mc_secondary_handler[0]),
+                                       glue);
+       glue += 128;
+       opal_register_exception_handler(OPAL_HYPERVISOR_MAINTENANCE_HANDLER,
+                                       0, glue);
+       glue += 128;
+       opal_register_exception_handler(OPAL_SOFTPATCH_HANDLER, 0, glue);
+
+       return 1;
+}
+
+int opal_get_chars(uint32_t vtermno, char *buf, int count)
+{
+       s64 len, rc;
+       u64 evt;
+
+       if (!opal.entry)
+               return -ENODEV;
+       opal_poll_events(&evt);
+       if ((evt & OPAL_EVENT_CONSOLE_INPUT) == 0)
+               return 0;
+       len = count;
+       rc = opal_console_read(vtermno, &len, buf);
+       if (rc == OPAL_SUCCESS)
+               return len;
+       return 0;
+}
+
+int opal_put_chars(uint32_t vtermno, const char *data, int total_len)
+{
+       int written = 0;
+       s64 len, rc;
+       unsigned long flags;
+       u64 evt;
+
+       if (!opal.entry)
+               return -ENODEV;
+
+       /* We want put_chars to be atomic to avoid mangling of hvsi
+        * packets. To do that, we first test for room and return
+        * -EAGAIN if there isn't enough.
+        *
+        * Unfortunately, opal_console_write_buffer_space() doesn't
+        * appear to work on opal v1, so we just assume there is
+        * enough room and be done with it
+        */
+       spin_lock_irqsave(&opal_write_lock, flags);
+       if (firmware_has_feature(FW_FEATURE_OPALv2)) {
+               rc = opal_console_write_buffer_space(vtermno, &len);
+               if (rc || len < total_len) {
+                       spin_unlock_irqrestore(&opal_write_lock, flags);
+                       /* Closed -> drop characters */
+                       if (rc)
+                               return total_len;
+                       opal_poll_events(&evt);
+                       return -EAGAIN;
+               }
+       }
+
+       /* We still try to handle partial completions, though they
+        * should no longer happen.
+        */
+       rc = OPAL_BUSY;
+       while(total_len > 0 && (rc == OPAL_BUSY ||
+                               rc == OPAL_BUSY_EVENT || rc == OPAL_SUCCESS)) {
+               len = total_len;
+               rc = opal_console_write(vtermno, &len, data);
+               if (rc == OPAL_SUCCESS) {
+                       total_len -= len;
+                       data += len;
+                       written += len;
+               }
+               /* This is a bit nasty but we need that for the console to
+                * flush when there aren't any interrupts. We will clean
+                * things a bit later to limit that to synchronous path
+                * such as the kernel console and xmon/udbg
+                */
+               do
+                       opal_poll_events(&evt);
+               while(rc == OPAL_SUCCESS && (evt & OPAL_EVENT_CONSOLE_OUTPUT));
+       }
+       spin_unlock_irqrestore(&opal_write_lock, flags);
+       return written;
+}
+
+int opal_machine_check(struct pt_regs *regs)
+{
+       struct opal_machine_check_event *opal_evt = get_paca()->opal_mc_evt;
+       struct opal_machine_check_event evt;
+       const char *level, *sevstr, *subtype;
+       static const char *opal_mc_ue_types[] = {
+               "Indeterminate",
+               "Instruction fetch",
+               "Page table walk ifetch",
+               "Load/Store",
+               "Page table walk Load/Store",
+       };
+       static const char *opal_mc_slb_types[] = {
+               "Indeterminate",
+               "Parity",
+               "Multihit",
+       };
+       static const char *opal_mc_erat_types[] = {
+               "Indeterminate",
+               "Parity",
+               "Multihit",
+       };
+       static const char *opal_mc_tlb_types[] = {
+               "Indeterminate",
+               "Parity",
+               "Multihit",
+       };
+
+       /* Copy the event structure and release the original */
+       evt = *opal_evt;
+       opal_evt->in_use = 0;
+
+       /* Print things out */
+       if (evt.version != OpalMCE_V1) {
+               pr_err("Machine Check Exception, Unknown event version %d !\n",
+                      evt.version);
+               return 0;
+       }
+       switch(evt.severity) {
+       case OpalMCE_SEV_NO_ERROR:
+               level = KERN_INFO;
+               sevstr = "Harmless";
+               break;
+       case OpalMCE_SEV_WARNING:
+               level = KERN_WARNING;
+               sevstr = "";
+               break;
+       case OpalMCE_SEV_ERROR_SYNC:
+               level = KERN_ERR;
+               sevstr = "Severe";
+               break;
+       case OpalMCE_SEV_FATAL:
+       default:
+               level = KERN_ERR;
+               sevstr = "Fatal";
+               break;
+       }
+
+       printk("%s%s Machine check interrupt [%s]\n", level, sevstr,
+              evt.disposition == OpalMCE_DISPOSITION_RECOVERED ?
+              "Recovered" : "[Not recovered");
+       printk("%s  Initiator: %s\n", level,
+              evt.initiator == OpalMCE_INITIATOR_CPU ? "CPU" : "Unknown");
+       switch(evt.error_type) {
+       case OpalMCE_ERROR_TYPE_UE:
+               subtype = evt.u.ue_error.ue_error_type <
+                       ARRAY_SIZE(opal_mc_ue_types) ?
+                       opal_mc_ue_types[evt.u.ue_error.ue_error_type]
+                       : "Unknown";
+               printk("%s  Error type: UE [%s]\n", level, subtype);
+               if (evt.u.ue_error.effective_address_provided)
+                       printk("%s    Effective address: %016llx\n",
+                              level, evt.u.ue_error.effective_address);
+               if (evt.u.ue_error.physical_address_provided)
+                       printk("%s      Physial address: %016llx\n",
+                              level, evt.u.ue_error.physical_address);
+               break;
+       case OpalMCE_ERROR_TYPE_SLB:
+               subtype = evt.u.slb_error.slb_error_type <
+                       ARRAY_SIZE(opal_mc_slb_types) ?
+                       opal_mc_slb_types[evt.u.slb_error.slb_error_type]
+                       : "Unknown";
+               printk("%s  Error type: SLB [%s]\n", level, subtype);
+               if (evt.u.slb_error.effective_address_provided)
+                       printk("%s    Effective address: %016llx\n",
+                              level, evt.u.slb_error.effective_address);
+               break;
+       case OpalMCE_ERROR_TYPE_ERAT:
+               subtype = evt.u.erat_error.erat_error_type <
+                       ARRAY_SIZE(opal_mc_erat_types) ?
+                       opal_mc_erat_types[evt.u.erat_error.erat_error_type]
+                       : "Unknown";
+               printk("%s  Error type: ERAT [%s]\n", level, subtype);
+               if (evt.u.erat_error.effective_address_provided)
+                       printk("%s    Effective address: %016llx\n",
+                              level, evt.u.erat_error.effective_address);
+               break;
+       case OpalMCE_ERROR_TYPE_TLB:
+               subtype = evt.u.tlb_error.tlb_error_type <
+                       ARRAY_SIZE(opal_mc_tlb_types) ?
+                       opal_mc_tlb_types[evt.u.tlb_error.tlb_error_type]
+                       : "Unknown";
+               printk("%s  Error type: TLB [%s]\n", level, subtype);
+               if (evt.u.tlb_error.effective_address_provided)
+                       printk("%s    Effective address: %016llx\n",
+                              level, evt.u.tlb_error.effective_address);
+               break;
+       default:
+       case OpalMCE_ERROR_TYPE_UNKNOWN:
+               printk("%s  Error type: Unknown\n", level);
+               break;
+       }
+       return evt.severity == OpalMCE_SEV_FATAL ? 0 : 1;
+}
+
+static irqreturn_t opal_interrupt(int irq, void *data)
+{
+       uint64_t events;
+
+       opal_handle_interrupt(virq_to_hw(irq), &events);
+
+       /* XXX TODO: Do something with the events */
+
+       return IRQ_HANDLED;
+}
+
+static int __init opal_init(void)
+{
+       struct device_node *np, *consoles;
+       const u32 *irqs;
+       int rc, i, irqlen;
+
+       opal_node = of_find_node_by_path("/ibm,opal");
+       if (!opal_node) {
+               pr_warn("opal: Node not found\n");
+               return -ENODEV;
+       }
+       if (firmware_has_feature(FW_FEATURE_OPALv2))
+               consoles = of_find_node_by_path("/ibm,opal/consoles");
+       else
+               consoles = of_node_get(opal_node);
+
+       /* Register serial ports */
+       for_each_child_of_node(consoles, np) {
+               if (strcmp(np->name, "serial"))
+                       continue;
+               of_platform_device_create(np, NULL, NULL);
+       }
+       of_node_put(consoles);
+
+       /* Find all OPAL interrupts and request them */
+       irqs = of_get_property(opal_node, "opal-interrupts", &irqlen);
+       pr_debug("opal: Found %d interrupts reserved for OPAL\n",
+                irqs ? (irqlen / 4) : 0);
+       for (i = 0; irqs && i < (irqlen / 4); i++, irqs++) {
+               unsigned int hwirq = be32_to_cpup(irqs);
+               unsigned int irq = irq_create_mapping(NULL, hwirq);
+               if (irq == NO_IRQ) {
+                       pr_warning("opal: Failed to map irq 0x%x\n", hwirq);
+                       continue;
+               }
+               rc = request_irq(irq, opal_interrupt, 0, "opal", NULL);
+               if (rc)
+                       pr_warning("opal: Error %d requesting irq %d"
+                                  " (0x%x)\n", rc, irq, hwirq);
+       }
+       return 0;
+}
+subsys_initcall(opal_init);
diff --git a/arch/powerpc/platforms/powernv/pci-p5ioc2.c b/arch/powerpc/platforms/powernv/pci-p5ioc2.c
new file mode 100644 (file)
index 0000000..4c80f7c
--- /dev/null
@@ -0,0 +1,234 @@
+/*
+ * Support PCI/PCIe on PowerNV platforms
+ *
+ * Currently supports only P5IOC2
+ *
+ * Copyright 2011 Benjamin Herrenschmidt, IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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/pci.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/msi.h>
+
+#include <asm/sections.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+#include <asm/ppc-pci.h>
+#include <asm/opal.h>
+#include <asm/iommu.h>
+#include <asm/tce.h>
+#include <asm/abs_addr.h>
+
+#include "powernv.h"
+#include "pci.h"
+
+/* For now, use a fixed amount of TCE memory for each p5ioc2
+ * hub, 16M will do
+ */
+#define P5IOC2_TCE_MEMORY      0x01000000
+
+#ifdef CONFIG_PCI_MSI
+static int pnv_pci_p5ioc2_msi_setup(struct pnv_phb *phb, struct pci_dev *dev,
+                                   unsigned int hwirq, unsigned int is_64,
+                                   struct msi_msg *msg)
+{
+       if (WARN_ON(!is_64))
+               return -ENXIO;
+       msg->data = hwirq - phb->msi_base;
+       msg->address_hi = 0x10000000;
+       msg->address_lo = 0;
+
+       return 0;
+}
+
+static void pnv_pci_init_p5ioc2_msis(struct pnv_phb *phb)
+{
+       unsigned int bmap_size;
+       const __be32 *prop = of_get_property(phb->hose->dn,
+                                            "ibm,opal-msi-ranges", NULL);
+       if (!prop)
+               return;
+
+       /* Don't do MSI's on p5ioc2 PCI-X are they are not properly
+        * verified in HW
+        */
+       if (of_device_is_compatible(phb->hose->dn, "ibm,p5ioc2-pcix"))
+               return;
+       phb->msi_base = be32_to_cpup(prop);
+       phb->msi_count = be32_to_cpup(prop + 1);
+       bmap_size = BITS_TO_LONGS(phb->msi_count) * sizeof(unsigned long);
+       phb->msi_map = zalloc_maybe_bootmem(bmap_size, GFP_KERNEL);
+       if (!phb->msi_map) {
+               pr_err("PCI %d: Failed to allocate MSI bitmap !\n",
+                      phb->hose->global_number);
+               return;
+       }
+       phb->msi_setup = pnv_pci_p5ioc2_msi_setup;
+       phb->msi32_support = 0;
+       pr_info(" Allocated bitmap for %d MSIs (base IRQ 0x%x)\n",
+               phb->msi_count, phb->msi_base);
+}
+#else
+static void pnv_pci_init_p5ioc2_msis(struct pnv_phb *phb) { }
+#endif /* CONFIG_PCI_MSI */
+
+static void __devinit pnv_pci_p5ioc2_dma_dev_setup(struct pnv_phb *phb,
+                                                  struct pci_dev *pdev)
+{
+       if (phb->p5ioc2.iommu_table.it_map == NULL)
+               iommu_init_table(&phb->p5ioc2.iommu_table, phb->hose->node);
+
+       set_iommu_table_base(&pdev->dev, &phb->p5ioc2.iommu_table);
+}
+
+static void __init pnv_pci_init_p5ioc2_phb(struct device_node *np,
+                                          void *tce_mem, u64 tce_size)
+{
+       struct pnv_phb *phb;
+       const u64 *prop64;
+       u64 phb_id;
+       int64_t rc;
+       static int primary = 1;
+
+       pr_info(" Initializing p5ioc2 PHB %s\n", np->full_name);
+
+       prop64 = of_get_property(np, "ibm,opal-phbid", NULL);
+       if (!prop64) {
+               pr_err("  Missing \"ibm,opal-phbid\" property !\n");
+               return;
+       }
+       phb_id = be64_to_cpup(prop64);
+       pr_devel("  PHB-ID  : 0x%016llx\n", phb_id);
+       pr_devel("  TCE AT  : 0x%016lx\n", __pa(tce_mem));
+       pr_devel("  TCE SZ  : 0x%016llx\n", tce_size);
+
+       rc = opal_pci_set_phb_tce_memory(phb_id, __pa(tce_mem), tce_size);
+       if (rc != OPAL_SUCCESS) {
+               pr_err("  Failed to set TCE memory, OPAL error %lld\n", rc);
+               return;
+       }
+
+       phb = alloc_bootmem(sizeof(struct pnv_phb));
+       if (phb) {
+               memset(phb, 0, sizeof(struct pnv_phb));
+               phb->hose = pcibios_alloc_controller(np);
+       }
+       if (!phb || !phb->hose) {
+               pr_err("  Failed to allocate PCI controller\n");
+               return;
+       }
+
+       spin_lock_init(&phb->lock);
+       phb->hose->first_busno = 0;
+       phb->hose->last_busno = 0xff;
+       phb->hose->private_data = phb;
+       phb->opal_id = phb_id;
+       phb->type = PNV_PHB_P5IOC2;
+
+       phb->regs = of_iomap(np, 0);
+
+       if (phb->regs == NULL)
+               pr_err("  Failed to map registers !\n");
+       else {
+               pr_devel("  P_BUID     = 0x%08x\n", in_be32(phb->regs + 0x100));
+               pr_devel("  P_IOSZ     = 0x%08x\n", in_be32(phb->regs + 0x1b0));
+               pr_devel("  P_IO_ST    = 0x%08x\n", in_be32(phb->regs + 0x1e0));
+               pr_devel("  P_MEM1_H   = 0x%08x\n", in_be32(phb->regs + 0x1a0));
+               pr_devel("  P_MEM1_L   = 0x%08x\n", in_be32(phb->regs + 0x190));
+               pr_devel("  P_MSZ1_L   = 0x%08x\n", in_be32(phb->regs + 0x1c0));
+               pr_devel("  P_MEM_ST   = 0x%08x\n", in_be32(phb->regs + 0x1d0));
+               pr_devel("  P_MEM2_H   = 0x%08x\n", in_be32(phb->regs + 0x2c0));
+               pr_devel("  P_MEM2_L   = 0x%08x\n", in_be32(phb->regs + 0x2b0));
+               pr_devel("  P_MSZ2_H   = 0x%08x\n", in_be32(phb->regs + 0x2d0));
+               pr_devel("  P_MSZ2_L   = 0x%08x\n", in_be32(phb->regs + 0x2e0));
+       }
+
+       /* Interpret the "ranges" property */
+       /* This also maps the I/O region and sets isa_io/mem_base */
+       pci_process_bridge_OF_ranges(phb->hose, np, primary);
+       primary = 0;
+
+       phb->hose->ops = &pnv_pci_ops;
+
+       /* Setup MSI support */
+       pnv_pci_init_p5ioc2_msis(phb);
+
+       /* Setup TCEs */
+       phb->dma_dev_setup = pnv_pci_p5ioc2_dma_dev_setup;
+       pnv_pci_setup_iommu_table(&phb->p5ioc2.iommu_table,
+                                 tce_mem, tce_size, 0);
+}
+
+void __init pnv_pci_init_p5ioc2_hub(struct device_node *np)
+{
+       struct device_node *phbn;
+       const u64 *prop64;
+       u64 hub_id;
+       void *tce_mem;
+       uint64_t tce_per_phb;
+       int64_t rc;
+       int phb_count = 0;
+
+       pr_info("Probing p5ioc2 IO-Hub %s\n", np->full_name);
+
+       prop64 = of_get_property(np, "ibm,opal-hubid", NULL);
+       if (!prop64) {
+               pr_err(" Missing \"ibm,opal-hubid\" property !\n");
+               return;
+       }
+       hub_id = be64_to_cpup(prop64);
+       pr_info(" HUB-ID : 0x%016llx\n", hub_id);
+
+       /* Currently allocate 16M of TCE memory for every Hub
+        *
+        * XXX TODO: Make it chip local if possible
+        */
+       tce_mem = __alloc_bootmem(P5IOC2_TCE_MEMORY, P5IOC2_TCE_MEMORY,
+                                 __pa(MAX_DMA_ADDRESS));
+       if (!tce_mem) {
+               pr_err(" Failed to allocate TCE Memory !\n");
+               return;
+       }
+       pr_debug(" TCE    : 0x%016lx..0x%016lx\n",
+               __pa(tce_mem), __pa(tce_mem) + P5IOC2_TCE_MEMORY - 1);
+       rc = opal_pci_set_hub_tce_memory(hub_id, __pa(tce_mem),
+                                       P5IOC2_TCE_MEMORY);
+       if (rc != OPAL_SUCCESS) {
+               pr_err(" Failed to allocate TCE memory, OPAL error %lld\n", rc);
+               return;
+       }
+
+       /* Count child PHBs */
+       for_each_child_of_node(np, phbn) {
+               if (of_device_is_compatible(phbn, "ibm,p5ioc2-pcix") ||
+                   of_device_is_compatible(phbn, "ibm,p5ioc2-pciex"))
+                       phb_count++;
+       }
+
+       /* Calculate how much TCE space we can give per PHB */
+       tce_per_phb = __rounddown_pow_of_two(P5IOC2_TCE_MEMORY / phb_count);
+       pr_info(" Allocating %lld MB of TCE memory per PHB\n",
+               tce_per_phb >> 20);
+
+       /* Initialize PHBs */
+       for_each_child_of_node(np, phbn) {
+               if (of_device_is_compatible(phbn, "ibm,p5ioc2-pcix") ||
+                   of_device_is_compatible(phbn, "ibm,p5ioc2-pciex")) {
+                       pnv_pci_init_p5ioc2_phb(phbn, tce_mem, tce_per_phb);
+                       tce_mem += tce_per_phb;
+               }
+       }
+}
diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c
new file mode 100644 (file)
index 0000000..85bb66d
--- /dev/null
@@ -0,0 +1,427 @@
+/*
+ * Support PCI/PCIe on PowerNV platforms
+ *
+ * Currently supports only P5IOC2
+ *
+ * Copyright 2011 Benjamin Herrenschmidt, IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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/pci.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/msi.h>
+
+#include <asm/sections.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+#include <asm/ppc-pci.h>
+#include <asm/opal.h>
+#include <asm/iommu.h>
+#include <asm/tce.h>
+#include <asm/abs_addr.h>
+
+#include "powernv.h"
+#include "pci.h"
+
+/* Delay in usec */
+#define PCI_RESET_DELAY_US     3000000
+
+#define cfg_dbg(fmt...)        do { } while(0)
+//#define cfg_dbg(fmt...)      printk(fmt)
+
+#ifdef CONFIG_PCI_MSI
+static int pnv_msi_check_device(struct pci_dev* pdev, int nvec, int type)
+{
+       struct pci_controller *hose = pci_bus_to_host(pdev->bus);
+       struct pnv_phb *phb = hose->private_data;
+
+       return (phb && phb->msi_map) ? 0 : -ENODEV;
+}
+
+static unsigned int pnv_get_one_msi(struct pnv_phb *phb)
+{
+       unsigned int id;
+
+       spin_lock(&phb->lock);
+       id = find_next_zero_bit(phb->msi_map, phb->msi_count, phb->msi_next);
+       if (id >= phb->msi_count && phb->msi_next)
+               id = find_next_zero_bit(phb->msi_map, phb->msi_count, 0);
+       if (id >= phb->msi_count) {
+               spin_unlock(&phb->lock);
+               return 0;
+       }
+       __set_bit(id, phb->msi_map);
+       spin_unlock(&phb->lock);
+       return id + phb->msi_base;
+}
+
+static void pnv_put_msi(struct pnv_phb *phb, unsigned int hwirq)
+{
+       unsigned int id;
+
+       if (WARN_ON(hwirq < phb->msi_base ||
+                   hwirq >= (phb->msi_base + phb->msi_count)))
+               return;
+       id = hwirq - phb->msi_base;
+       spin_lock(&phb->lock);
+       __clear_bit(id, phb->msi_map);
+       spin_unlock(&phb->lock);
+}
+
+static int pnv_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
+{
+       struct pci_controller *hose = pci_bus_to_host(pdev->bus);
+       struct pnv_phb *phb = hose->private_data;
+       struct msi_desc *entry;
+       struct msi_msg msg;
+       unsigned int hwirq, virq;
+       int rc;
+
+       if (WARN_ON(!phb))
+               return -ENODEV;
+
+       list_for_each_entry(entry, &pdev->msi_list, list) {
+               if (!entry->msi_attrib.is_64 && !phb->msi32_support) {
+                       pr_warn("%s: Supports only 64-bit MSIs\n",
+                               pci_name(pdev));
+                       return -ENXIO;
+               }
+               hwirq = pnv_get_one_msi(phb);
+               if (!hwirq) {
+                       pr_warn("%s: Failed to find a free MSI\n",
+                               pci_name(pdev));
+                       return -ENOSPC;
+               }
+               virq = irq_create_mapping(NULL, hwirq);
+               if (virq == NO_IRQ) {
+                       pr_warn("%s: Failed to map MSI to linux irq\n",
+                               pci_name(pdev));
+                       pnv_put_msi(phb, hwirq);
+                       return -ENOMEM;
+               }
+               rc = phb->msi_setup(phb, pdev, hwirq, entry->msi_attrib.is_64,
+                                   &msg);
+               if (rc) {
+                       pr_warn("%s: Failed to setup MSI\n", pci_name(pdev));
+                       irq_dispose_mapping(virq);
+                       pnv_put_msi(phb, hwirq);
+                       return rc;
+               }
+               irq_set_msi_desc(virq, entry);
+               write_msi_msg(virq, &msg);
+       }
+       return 0;
+}
+
+static void pnv_teardown_msi_irqs(struct pci_dev *pdev)
+{
+       struct pci_controller *hose = pci_bus_to_host(pdev->bus);
+       struct pnv_phb *phb = hose->private_data;
+       struct msi_desc *entry;
+
+       if (WARN_ON(!phb))
+               return;
+
+       list_for_each_entry(entry, &pdev->msi_list, list) {
+               if (entry->irq == NO_IRQ)
+                       continue;
+               irq_set_msi_desc(entry->irq, NULL);
+               pnv_put_msi(phb, virq_to_hw(entry->irq));
+               irq_dispose_mapping(entry->irq);
+       }
+}
+#endif /* CONFIG_PCI_MSI */
+
+static void pnv_pci_config_check_eeh(struct pnv_phb *phb, struct pci_bus *bus,
+                                    u32 bdfn)
+{
+       s64     rc;
+       u8      fstate;
+       u16     pcierr;
+       u32     pe_no;
+
+       /* Get PE# if we support IODA */
+       pe_no = phb->bdfn_to_pe ? phb->bdfn_to_pe(phb, bus, bdfn & 0xff) : 0;
+
+       /* Read freeze status */
+       rc = opal_pci_eeh_freeze_status(phb->opal_id, pe_no, &fstate, &pcierr,
+                                       NULL);
+       if (rc) {
+               pr_warning("PCI %d: Failed to read EEH status for PE#%d,"
+                          " err %lld\n", phb->hose->global_number, pe_no, rc);
+               return;
+       }
+       cfg_dbg(" -> EEH check, bdfn=%04x PE%d fstate=%x\n",
+               bdfn, pe_no, fstate);
+       if (fstate != 0) {
+               rc = opal_pci_eeh_freeze_clear(phb->opal_id, pe_no,
+                                             OPAL_EEH_ACTION_CLEAR_FREEZE_ALL);
+               if (rc) {
+                       pr_warning("PCI %d: Failed to clear EEH freeze state"
+                                  " for PE#%d, err %lld\n",
+                                  phb->hose->global_number, pe_no, rc);
+               }
+       }
+}
+
+static int pnv_pci_read_config(struct pci_bus *bus,
+                              unsigned int devfn,
+                              int where, int size, u32 *val)
+{
+       struct pci_controller *hose = pci_bus_to_host(bus);
+       struct pnv_phb *phb = hose->private_data;
+       u32 bdfn = (((uint64_t)bus->number) << 8) | devfn;
+       s64 rc;
+
+       if (hose == NULL)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       switch (size) {
+       case 1: {
+               u8 v8;
+               rc = opal_pci_config_read_byte(phb->opal_id, bdfn, where, &v8);
+               *val = (rc == OPAL_SUCCESS) ? v8 : 0xff;
+               break;
+       }
+       case 2: {
+               u16 v16;
+               rc = opal_pci_config_read_half_word(phb->opal_id, bdfn, where,
+                                                  &v16);
+               *val = (rc == OPAL_SUCCESS) ? v16 : 0xffff;
+               break;
+       }
+       case 4: {
+               u32 v32;
+               rc = opal_pci_config_read_word(phb->opal_id, bdfn, where, &v32);
+               *val = (rc == OPAL_SUCCESS) ? v32 : 0xffffffff;
+               break;
+       }
+       default:
+               return PCIBIOS_FUNC_NOT_SUPPORTED;
+       }
+       cfg_dbg("pnv_pci_read_config bus: %x devfn: %x +%x/%x -> %08x\n",
+               bus->number, devfn, where, size, *val);
+
+       /* Check if the PHB got frozen due to an error (no response) */
+       pnv_pci_config_check_eeh(phb, bus, bdfn);
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int pnv_pci_write_config(struct pci_bus *bus,
+                               unsigned int devfn,
+                               int where, int size, u32 val)
+{
+       struct pci_controller *hose = pci_bus_to_host(bus);
+       struct pnv_phb *phb = hose->private_data;
+       u32 bdfn = (((uint64_t)bus->number) << 8) | devfn;
+
+       if (hose == NULL)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       cfg_dbg("pnv_pci_write_config bus: %x devfn: %x +%x/%x -> %08x\n",
+               bus->number, devfn, where, size, val);
+       switch (size) {
+       case 1:
+               opal_pci_config_write_byte(phb->opal_id, bdfn, where, val);
+               break;
+       case 2:
+               opal_pci_config_write_half_word(phb->opal_id, bdfn, where, val);
+               break;
+       case 4:
+               opal_pci_config_write_word(phb->opal_id, bdfn, where, val);
+               break;
+       default:
+               return PCIBIOS_FUNC_NOT_SUPPORTED;
+       }
+       /* Check if the PHB got frozen due to an error (no response) */
+       pnv_pci_config_check_eeh(phb, bus, bdfn);
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops pnv_pci_ops = {
+       .read = pnv_pci_read_config,
+       .write = pnv_pci_write_config,
+};
+
+static int pnv_tce_build(struct iommu_table *tbl, long index, long npages,
+                        unsigned long uaddr, enum dma_data_direction direction,
+                        struct dma_attrs *attrs)
+{
+       u64 proto_tce;
+       u64 *tcep;
+       u64 rpn;
+
+       proto_tce = TCE_PCI_READ; // Read allowed
+
+       if (direction != DMA_TO_DEVICE)
+               proto_tce |= TCE_PCI_WRITE;
+
+       tcep = ((u64 *)tbl->it_base) + index;
+
+       while (npages--) {
+               /* can't move this out since we might cross LMB boundary */
+               rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
+               *tcep = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT;
+
+               uaddr += TCE_PAGE_SIZE;
+               tcep++;
+       }
+       return 0;
+}
+
+static void pnv_tce_free(struct iommu_table *tbl, long index, long npages)
+{
+       u64 *tcep = ((u64 *)tbl->it_base) + index;
+
+       while (npages--)
+               *(tcep++) = 0;
+}
+
+void pnv_pci_setup_iommu_table(struct iommu_table *tbl,
+                              void *tce_mem, u64 tce_size,
+                              u64 dma_offset)
+{
+       tbl->it_blocksize = 16;
+       tbl->it_base = (unsigned long)tce_mem;
+       tbl->it_offset = dma_offset >> IOMMU_PAGE_SHIFT;
+       tbl->it_index = 0;
+       tbl->it_size = tce_size >> 3;
+       tbl->it_busno = 0;
+       tbl->it_type = TCE_PCI;
+}
+
+static struct iommu_table * __devinit
+pnv_pci_setup_bml_iommu(struct pci_controller *hose)
+{
+       struct iommu_table *tbl;
+       const __be64 *basep;
+       const __be32 *sizep;
+
+       basep = of_get_property(hose->dn, "linux,tce-base", NULL);
+       sizep = of_get_property(hose->dn, "linux,tce-size", NULL);
+       if (basep == NULL || sizep == NULL) {
+               pr_err("PCI: %s has missing tce entries !\n", hose->dn->full_name);
+               return NULL;
+       }
+       tbl = kzalloc_node(sizeof(struct iommu_table), GFP_KERNEL, hose->node);
+       if (WARN_ON(!tbl))
+               return NULL;
+       pnv_pci_setup_iommu_table(tbl, __va(be64_to_cpup(basep)),
+                                 be32_to_cpup(sizep), 0);
+       iommu_init_table(tbl, hose->node);
+       return tbl;
+}
+
+static void __devinit pnv_pci_dma_fallback_setup(struct pci_controller *hose,
+                                                struct pci_dev *pdev)
+{
+       struct device_node *np = pci_bus_to_OF_node(hose->bus);
+       struct pci_dn *pdn;
+
+       if (np == NULL)
+               return;
+       pdn = PCI_DN(np);
+       if (!pdn->iommu_table)
+               pdn->iommu_table = pnv_pci_setup_bml_iommu(hose);
+       if (!pdn->iommu_table)
+               return;
+       set_iommu_table_base(&pdev->dev, pdn->iommu_table);
+}
+
+static void __devinit pnv_pci_dma_dev_setup(struct pci_dev *pdev)
+{
+       struct pci_controller *hose = pci_bus_to_host(pdev->bus);
+       struct pnv_phb *phb = hose->private_data;
+
+       /* If we have no phb structure, try to setup a fallback based on
+        * the device-tree (RTAS PCI for example)
+        */
+       if (phb && phb->dma_dev_setup)
+               phb->dma_dev_setup(phb, pdev);
+       else
+               pnv_pci_dma_fallback_setup(hose, pdev);
+}
+
+static int pnv_pci_probe_mode(struct pci_bus *bus)
+{
+       struct pci_controller *hose = pci_bus_to_host(bus);
+       const __be64 *tstamp;
+       u64 now, target;
+
+
+       /* We hijack this as a way to ensure we have waited long
+        * enough since the reset was lifted on the PCI bus
+        */
+       if (bus != hose->bus)
+               return PCI_PROBE_NORMAL;
+       tstamp = of_get_property(hose->dn, "reset-clear-timestamp", NULL);
+       if (!tstamp || !*tstamp)
+               return PCI_PROBE_NORMAL;
+
+       now = mftb() / tb_ticks_per_usec;
+       target = (be64_to_cpup(tstamp) / tb_ticks_per_usec)
+               + PCI_RESET_DELAY_US;
+
+       pr_devel("pci %04d: Reset target: 0x%llx now: 0x%llx\n",
+                hose->global_number, target, now);
+
+       if (now < target)
+               msleep((target - now + 999) / 1000);
+
+       return PCI_PROBE_NORMAL;
+}
+
+void __init pnv_pci_init(void)
+{
+       struct device_node *np;
+
+       pci_set_flags(PCI_CAN_SKIP_ISA_ALIGN);
+
+       /* We do not want to just probe */
+       pci_probe_only = 0;
+
+       /* OPAL absent, try POPAL first then RTAS detection of PHBs */
+       if (!firmware_has_feature(FW_FEATURE_OPAL)) {
+#ifdef CONFIG_PPC_POWERNV_RTAS
+               init_pci_config_tokens();
+               find_and_init_phbs();
+#endif /* CONFIG_PPC_POWERNV_RTAS */
+       } else {
+               /* OPAL is here, do our normal stuff */
+
+               /* Look for p5ioc2 IO-Hubs */
+               for_each_compatible_node(np, NULL, "ibm,p5ioc2")
+                       pnv_pci_init_p5ioc2_hub(np);
+       }
+
+       /* Setup the linkage between OF nodes and PHBs */
+       pci_devs_phb_init();
+
+       /* Configure IOMMU DMA hooks */
+       ppc_md.pci_dma_dev_setup = pnv_pci_dma_dev_setup;
+       ppc_md.tce_build = pnv_tce_build;
+       ppc_md.tce_free = pnv_tce_free;
+       ppc_md.pci_probe_mode = pnv_pci_probe_mode;
+       set_pci_dma_ops(&dma_iommu_ops);
+
+       /* Configure MSIs */
+#ifdef CONFIG_PCI_MSI
+       ppc_md.msi_check_device = pnv_msi_check_device;
+       ppc_md.setup_msi_irqs = pnv_setup_msi_irqs;
+       ppc_md.teardown_msi_irqs = pnv_teardown_msi_irqs;
+#endif
+}
diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h
new file mode 100644 (file)
index 0000000..d4dbc49
--- /dev/null
@@ -0,0 +1,48 @@
+#ifndef __POWERNV_PCI_H
+#define __POWERNV_PCI_H
+
+struct pci_dn;
+
+enum pnv_phb_type {
+       PNV_PHB_P5IOC2,
+       PNV_PHB_IODA1,
+       PNV_PHB_IODA2,
+};
+
+struct pnv_phb {
+       struct pci_controller   *hose;
+       enum pnv_phb_type       type;
+       u64                     opal_id;
+       void __iomem            *regs;
+       spinlock_t              lock;
+
+#ifdef CONFIG_PCI_MSI
+       unsigned long           *msi_map;
+       unsigned int            msi_base;
+       unsigned int            msi_count;
+       unsigned int            msi_next;
+       unsigned int            msi32_support;
+#endif
+       int (*msi_setup)(struct pnv_phb *phb, struct pci_dev *dev,
+                        unsigned int hwirq, unsigned int is_64,
+                        struct msi_msg *msg);
+       void (*dma_dev_setup)(struct pnv_phb *phb, struct pci_dev *pdev);
+       void (*fixup_phb)(struct pci_controller *hose);
+       u32 (*bdfn_to_pe)(struct pnv_phb *phb, struct pci_bus *bus, u32 devfn);
+
+       union {
+               struct {
+                       struct iommu_table iommu_table;
+               } p5ioc2;
+       };
+};
+
+extern struct pci_ops pnv_pci_ops;
+
+extern void pnv_pci_setup_iommu_table(struct iommu_table *tbl,
+                                     void *tce_mem, u64 tce_size,
+                                     u64 dma_offset);
+extern void pnv_pci_init_p5ioc2_hub(struct device_node *np);
+
+
+#endif /* __POWERNV_PCI_H */
diff --git a/arch/powerpc/platforms/powernv/powernv.h b/arch/powerpc/platforms/powernv/powernv.h
new file mode 100644 (file)
index 0000000..8a9df7f
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef _POWERNV_H
+#define _POWERNV_H
+
+#ifdef CONFIG_SMP
+extern void pnv_smp_init(void);
+#else
+static inline void pnv_smp_init(void) { }
+#endif
+
+#ifdef CONFIG_PCI
+extern void pnv_pci_init(void);
+#else
+static inline void pnv_pci_init(void) { }
+#endif
+
+#endif /* _POWERNV_H */
diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c
new file mode 100644 (file)
index 0000000..467bd4a
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ * PowerNV setup code.
+ *
+ * Copyright 2011 IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#undef DEBUG
+
+#include <linux/cpu.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/tty.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/of.h>
+#include <linux/interrupt.h>
+#include <linux/bug.h>
+
+#include <asm/machdep.h>
+#include <asm/firmware.h>
+#include <asm/xics.h>
+#include <asm/rtas.h>
+#include <asm/opal.h>
+#include <asm/xics.h>
+
+#include "powernv.h"
+
+static void __init pnv_setup_arch(void)
+{
+       /* Initialize SMP */
+       pnv_smp_init();
+
+       /* Setup PCI */
+       pnv_pci_init();
+
+       /* Setup RTC and NVRAM callbacks */
+       if (firmware_has_feature(FW_FEATURE_OPAL))
+               opal_nvram_init();
+
+       /* Enable NAP mode */
+       powersave_nap = 1;
+
+       /* XXX PMCS */
+}
+
+static void __init pnv_init_early(void)
+{
+#ifdef CONFIG_HVC_OPAL
+       if (firmware_has_feature(FW_FEATURE_OPAL))
+               hvc_opal_init_early();
+       else
+#endif
+               add_preferred_console("hvc", 0, NULL);
+}
+
+static void __init pnv_init_IRQ(void)
+{
+       xics_init();
+
+       WARN_ON(!ppc_md.get_irq);
+}
+
+static void pnv_show_cpuinfo(struct seq_file *m)
+{
+       struct device_node *root;
+       const char *model = "";
+
+       root = of_find_node_by_path("/");
+       if (root)
+               model = of_get_property(root, "model", NULL);
+       seq_printf(m, "machine\t\t: PowerNV %s\n", model);
+       if (firmware_has_feature(FW_FEATURE_OPALv2))
+               seq_printf(m, "firmware\t: OPAL v2\n");
+       else if (firmware_has_feature(FW_FEATURE_OPAL))
+               seq_printf(m, "firmware\t: OPAL v1\n");
+       else
+               seq_printf(m, "firmware\t: BML\n");
+       of_node_put(root);
+}
+
+static void  __noreturn pnv_restart(char *cmd)
+{
+       long rc = OPAL_BUSY;
+
+       while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) {
+               rc = opal_cec_reboot();
+               if (rc == OPAL_BUSY_EVENT)
+                       opal_poll_events(NULL);
+               else
+                       mdelay(10);
+       }
+       for (;;)
+               opal_poll_events(NULL);
+}
+
+static void __noreturn pnv_power_off(void)
+{
+       long rc = OPAL_BUSY;
+
+       while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) {
+               rc = opal_cec_power_down(0);
+               if (rc == OPAL_BUSY_EVENT)
+                       opal_poll_events(NULL);
+               else
+                       mdelay(10);
+       }
+       for (;;)
+               opal_poll_events(NULL);
+}
+
+static void __noreturn pnv_halt(void)
+{
+       pnv_power_off();
+}
+
+static void pnv_progress(char *s, unsigned short hex)
+{
+}
+
+#ifdef CONFIG_KEXEC
+static void pnv_kexec_cpu_down(int crash_shutdown, int secondary)
+{
+       xics_kexec_teardown_cpu(secondary);
+}
+#endif /* CONFIG_KEXEC */
+
+static void __init pnv_setup_machdep_opal(void)
+{
+       ppc_md.get_boot_time = opal_get_boot_time;
+       ppc_md.get_rtc_time = opal_get_rtc_time;
+       ppc_md.set_rtc_time = opal_set_rtc_time;
+       ppc_md.restart = pnv_restart;
+       ppc_md.power_off = pnv_power_off;
+       ppc_md.halt = pnv_halt;
+       ppc_md.machine_check_exception = opal_machine_check;
+}
+
+#ifdef CONFIG_PPC_POWERNV_RTAS
+static void __init pnv_setup_machdep_rtas(void)
+{
+       if (rtas_token("get-time-of-day") != RTAS_UNKNOWN_SERVICE) {
+               ppc_md.get_boot_time = rtas_get_boot_time;
+               ppc_md.get_rtc_time = rtas_get_rtc_time;
+               ppc_md.set_rtc_time = rtas_set_rtc_time;
+       }
+       ppc_md.restart = rtas_restart;
+       ppc_md.power_off = rtas_power_off;
+       ppc_md.halt = rtas_halt;
+}
+#endif /* CONFIG_PPC_POWERNV_RTAS */
+
+static int __init pnv_probe(void)
+{
+       unsigned long root = of_get_flat_dt_root();
+
+       if (!of_flat_dt_is_compatible(root, "ibm,powernv"))
+               return 0;
+
+       hpte_init_native();
+
+       if (firmware_has_feature(FW_FEATURE_OPAL))
+               pnv_setup_machdep_opal();
+#ifdef CONFIG_PPC_POWERNV_RTAS
+       else if (rtas.base)
+               pnv_setup_machdep_rtas();
+#endif /* CONFIG_PPC_POWERNV_RTAS */
+
+       pr_debug("PowerNV detected !\n");
+
+       return 1;
+}
+
+define_machine(powernv) {
+       .name                   = "PowerNV",
+       .probe                  = pnv_probe,
+       .init_early             = pnv_init_early,
+       .setup_arch             = pnv_setup_arch,
+       .init_IRQ               = pnv_init_IRQ,
+       .show_cpuinfo           = pnv_show_cpuinfo,
+       .progress               = pnv_progress,
+       .power_save             = power7_idle,
+       .calibrate_decr         = generic_calibrate_decr,
+#ifdef CONFIG_KEXEC
+       .kexec_cpu_down         = pnv_kexec_cpu_down,
+#endif
+};
diff --git a/arch/powerpc/platforms/powernv/smp.c b/arch/powerpc/platforms/powernv/smp.c
new file mode 100644 (file)
index 0000000..e877366
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * SMP support for PowerNV machines.
+ *
+ * Copyright 2011 IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/cpu.h>
+
+#include <asm/irq.h>
+#include <asm/smp.h>
+#include <asm/paca.h>
+#include <asm/machdep.h>
+#include <asm/cputable.h>
+#include <asm/firmware.h>
+#include <asm/system.h>
+#include <asm/rtas.h>
+#include <asm/vdso_datapage.h>
+#include <asm/cputhreads.h>
+#include <asm/xics.h>
+#include <asm/opal.h>
+
+#include "powernv.h"
+
+#ifdef DEBUG
+#include <asm/udbg.h>
+#define DBG(fmt...) udbg_printf(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+static void __cpuinit pnv_smp_setup_cpu(int cpu)
+{
+       if (cpu != boot_cpuid)
+               xics_setup_cpu();
+}
+
+static int pnv_smp_cpu_bootable(unsigned int nr)
+{
+       /* Special case - we inhibit secondary thread startup
+        * during boot if the user requests it.
+        */
+       if (system_state < SYSTEM_RUNNING && cpu_has_feature(CPU_FTR_SMT)) {
+               if (!smt_enabled_at_boot && cpu_thread_in_core(nr) != 0)
+                       return 0;
+               if (smt_enabled_at_boot
+                   && cpu_thread_in_core(nr) >= smt_enabled_at_boot)
+                       return 0;
+       }
+
+       return 1;
+}
+
+int __devinit pnv_smp_kick_cpu(int nr)
+{
+       unsigned int pcpu = get_hard_smp_processor_id(nr);
+       unsigned long start_here = __pa(*((unsigned long *)
+                                         generic_secondary_smp_init));
+       long rc;
+
+       BUG_ON(nr < 0 || nr >= NR_CPUS);
+
+       /* On OPAL v2 the CPU are still spinning inside OPAL itself,
+        * get them back now
+        */
+       if (firmware_has_feature(FW_FEATURE_OPALv2)) {
+               pr_devel("OPAL: Starting CPU %d (HW 0x%x)...\n", nr, pcpu);
+               rc = opal_start_cpu(pcpu, start_here);
+               if (rc != OPAL_SUCCESS)
+                       pr_warn("OPAL Error %ld starting CPU %d\n",
+                               rc, nr);
+       }
+       return smp_generic_kick_cpu(nr);
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+
+static int pnv_smp_cpu_disable(void)
+{
+       int cpu = smp_processor_id();
+
+       /* This is identical to pSeries... might consolidate by
+        * moving migrate_irqs_away to a ppc_md with default to
+        * the generic fixup_irqs. --BenH.
+        */
+       set_cpu_online(cpu, false);
+       vdso_data->processorCount--;
+       if (cpu == boot_cpuid)
+               boot_cpuid = cpumask_any(cpu_online_mask);
+       xics_migrate_irqs_away();
+       return 0;
+}
+
+static void pnv_smp_cpu_kill_self(void)
+{
+       unsigned int cpu;
+
+       /* If powersave_nap is enabled, use NAP mode, else just
+        * spin aimlessly
+        */
+       if (!powersave_nap) {
+               generic_mach_cpu_die();
+               return;
+       }
+
+       /* Standard hot unplug procedure */
+       local_irq_disable();
+       idle_task_exit();
+       current->active_mm = NULL; /* for sanity */
+       cpu = smp_processor_id();
+       DBG("CPU%d offline\n", cpu);
+       generic_set_cpu_dead(cpu);
+       smp_wmb();
+
+       /* We don't want to take decrementer interrupts while we are offline,
+        * so clear LPCR:PECE1. We keep PECE2 enabled.
+        */
+       mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) & ~(u64)LPCR_PECE1);
+       while (!generic_check_cpu_restart(cpu)) {
+               power7_idle();
+               if (!generic_check_cpu_restart(cpu)) {
+                       DBG("CPU%d Unexpected exit while offline !\n", cpu);
+                       /* We may be getting an IPI, so we re-enable
+                        * interrupts to process it, it will be ignored
+                        * since we aren't online (hopefully)
+                        */
+                       local_irq_enable();
+                       local_irq_disable();
+               }
+       }
+       mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) | LPCR_PECE1);
+       DBG("CPU%d coming online...\n", cpu);
+}
+
+#endif /* CONFIG_HOTPLUG_CPU */
+
+static struct smp_ops_t pnv_smp_ops = {
+       .message_pass   = smp_muxed_ipi_message_pass,
+       .cause_ipi      = NULL, /* Filled at runtime by xics_smp_probe() */
+       .probe          = xics_smp_probe,
+       .kick_cpu       = pnv_smp_kick_cpu,
+       .setup_cpu      = pnv_smp_setup_cpu,
+       .cpu_bootable   = pnv_smp_cpu_bootable,
+#ifdef CONFIG_HOTPLUG_CPU
+       .cpu_disable    = pnv_smp_cpu_disable,
+       .cpu_die        = generic_cpu_die,
+#endif /* CONFIG_HOTPLUG_CPU */
+};
+
+/* This is called very early during platform setup_arch */
+void __init pnv_smp_init(void)
+{
+       smp_ops = &pnv_smp_ops;
+
+       /* XXX We don't yet have a proper entry point from HAL, for
+        * now we rely on kexec-style entry from BML
+        */
+
+#ifdef CONFIG_PPC_RTAS
+       /* Non-lpar has additional take/give timebase */
+       if (rtas_token("freeze-time-base") != RTAS_UNKNOWN_SERVICE) {
+               smp_ops->give_timebase = rtas_give_timebase;
+               smp_ops->take_timebase = rtas_take_timebase;
+       }
+#endif /* CONFIG_PPC_RTAS */
+
+#ifdef CONFIG_HOTPLUG_CPU
+       ppc_md.cpu_die  = pnv_smp_cpu_kill_self;
+#endif
+}
index dfe316b..476d9d9 100644 (file)
@@ -148,4 +148,16 @@ config PS3_LPM
          profiling support of the Cell processor with programs like
          oprofile and perfmon2, then say Y or M, otherwise say N.
 
+config PS3GELIC_UDBG
+       bool "PS3 udbg output via UDP broadcasts on Ethernet"
+       depends on PPC_PS3
+       help
+         Enables udbg early debugging output by sending broadcast UDP
+         via the Ethernet port (UDP port number 18194).
+
+         This driver uses a trivial implementation and is independent
+         from the main network driver.
+
+         If in doubt, say N here.
+
 endmenu
index ac1bdf8..02b9e63 100644 (file)
@@ -2,6 +2,7 @@ obj-y += setup.o mm.o time.o hvcall.o htab.o repository.o
 obj-y += interrupt.o exports.o os-area.o
 obj-y += system-bus.o
 
+obj-$(CONFIG_PS3GELIC_UDBG) += gelic_udbg.o
 obj-$(CONFIG_SMP) += smp.o
 obj-$(CONFIG_SPU_BASE) += spu.o
 obj-y += device-init.o
diff --git a/arch/powerpc/platforms/ps3/gelic_udbg.c b/arch/powerpc/platforms/ps3/gelic_udbg.c
new file mode 100644 (file)
index 0000000..20b46a1
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+ * udbg debug output routine via GELIC UDP broadcasts
+ *
+ * Copyright (C) 2007 Sony Computer Entertainment Inc.
+ * Copyright 2006, 2007 Sony Corporation
+ * Copyright (C) 2010 Hector Martin <hector@marcansoft.com>
+ * Copyright (C) 2011 Andre Heider <a.heider@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ */
+
+#include <asm/io.h>
+#include <asm/udbg.h>
+#include <asm/lv1call.h>
+
+#define GELIC_BUS_ID 1
+#define GELIC_DEVICE_ID 0
+#define GELIC_DEBUG_PORT 18194
+#define GELIC_MAX_MESSAGE_SIZE 1000
+
+#define GELIC_LV1_GET_MAC_ADDRESS 1
+#define GELIC_LV1_GET_VLAN_ID 4
+#define GELIC_LV1_VLAN_TX_ETHERNET_0 2
+
+#define GELIC_DESCR_DMA_STAT_MASK 0xf0000000
+#define GELIC_DESCR_DMA_CARDOWNED 0xa0000000
+
+#define GELIC_DESCR_TX_DMA_IKE 0x00080000
+#define GELIC_DESCR_TX_DMA_NO_CHKSUM 0x00000000
+#define GELIC_DESCR_TX_DMA_FRAME_TAIL 0x00040000
+
+#define GELIC_DESCR_DMA_CMD_NO_CHKSUM (GELIC_DESCR_DMA_CARDOWNED | \
+                                      GELIC_DESCR_TX_DMA_IKE | \
+                                      GELIC_DESCR_TX_DMA_NO_CHKSUM)
+
+static u64 bus_addr;
+
+struct gelic_descr {
+       /* as defined by the hardware */
+       __be32 buf_addr;
+       __be32 buf_size;
+       __be32 next_descr_addr;
+       __be32 dmac_cmd_status;
+       __be32 result_size;
+       __be32 valid_size;      /* all zeroes for tx */
+       __be32 data_status;
+       __be32 data_error;      /* all zeroes for tx */
+} __attribute__((aligned(32)));
+
+struct debug_block {
+       struct gelic_descr descr;
+       u8 pkt[1520];
+} __packed;
+
+struct ethhdr {
+       u8 dest[6];
+       u8 src[6];
+       u16 type;
+} __packed;
+
+struct vlantag {
+       u16 vlan;
+       u16 subtype;
+} __packed;
+
+struct iphdr {
+       u8 ver_len;
+       u8 dscp_ecn;
+       u16 total_length;
+       u16 ident;
+       u16 frag_off_flags;
+       u8 ttl;
+       u8 proto;
+       u16 checksum;
+       u32 src;
+       u32 dest;
+} __packed;
+
+struct udphdr {
+       u16 src;
+       u16 dest;
+       u16 len;
+       u16 checksum;
+} __packed;
+
+static __iomem struct ethhdr *h_eth;
+static __iomem struct vlantag *h_vlan;
+static __iomem struct iphdr *h_ip;
+static __iomem struct udphdr *h_udp;
+
+static __iomem char *pmsg;
+static __iomem char *pmsgc;
+
+static __iomem struct debug_block dbg __attribute__((aligned(32)));
+
+static int header_size;
+
+static void map_dma_mem(int bus_id, int dev_id, void *start, size_t len,
+                       u64 *real_bus_addr)
+{
+       s64 result;
+       u64 real_addr = ((u64)start) & 0x0fffffffffffffffUL;
+       u64 real_end = real_addr + len;
+       u64 map_start = real_addr & ~0xfff;
+       u64 map_end = (real_end + 0xfff) & ~0xfff;
+       u64 bus_addr = 0;
+
+       u64 flags = 0xf800000000000000UL;
+
+       result = lv1_allocate_device_dma_region(bus_id, dev_id,
+                                               map_end - map_start, 12, 0,
+                                               &bus_addr);
+       if (result)
+               lv1_panic(0);
+
+       result = lv1_map_device_dma_region(bus_id, dev_id, map_start,
+                                          bus_addr, map_end - map_start,
+                                          flags);
+       if (result)
+               lv1_panic(0);
+
+       *real_bus_addr = bus_addr + real_addr - map_start;
+}
+
+static int unmap_dma_mem(int bus_id, int dev_id, u64 bus_addr, size_t len)
+{
+       s64 result;
+       u64 real_bus_addr;
+
+       real_bus_addr = bus_addr & ~0xfff;
+       len += bus_addr - real_bus_addr;
+       len = (len + 0xfff) & ~0xfff;
+
+       result = lv1_unmap_device_dma_region(bus_id, dev_id, real_bus_addr,
+                                            len);
+       if (result)
+               return result;
+
+       return lv1_free_device_dma_region(bus_id, dev_id, real_bus_addr);
+}
+
+static void gelic_debug_init(void)
+{
+       s64 result;
+       u64 v2;
+       u64 mac;
+       u64 vlan_id;
+
+       result = lv1_open_device(GELIC_BUS_ID, GELIC_DEVICE_ID, 0);
+       if (result)
+               lv1_panic(0);
+
+       map_dma_mem(GELIC_BUS_ID, GELIC_DEVICE_ID, &dbg, sizeof(dbg),
+                   &bus_addr);
+
+       memset(&dbg, 0, sizeof(dbg));
+
+       dbg.descr.buf_addr = bus_addr + offsetof(struct debug_block, pkt);
+
+       wmb();
+
+       result = lv1_net_control(GELIC_BUS_ID, GELIC_DEVICE_ID,
+                                GELIC_LV1_GET_MAC_ADDRESS, 0, 0, 0,
+                                &mac, &v2);
+       if (result)
+               lv1_panic(0);
+
+       mac <<= 16;
+
+       h_eth = (struct ethhdr *)dbg.pkt;
+
+       memset(&h_eth->dest, 0xff, 6);
+       memcpy(&h_eth->src, &mac, 6);
+
+       header_size = sizeof(struct ethhdr);
+
+       result = lv1_net_control(GELIC_BUS_ID, GELIC_DEVICE_ID,
+                                GELIC_LV1_GET_VLAN_ID,
+                                GELIC_LV1_VLAN_TX_ETHERNET_0, 0, 0,
+                                &vlan_id, &v2);
+       if (!result) {
+               h_eth->type = 0x8100;
+
+               header_size += sizeof(struct vlantag);
+               h_vlan = (struct vlantag *)(h_eth + 1);
+               h_vlan->vlan = vlan_id;
+               h_vlan->subtype = 0x0800;
+               h_ip = (struct iphdr *)(h_vlan + 1);
+       } else {
+               h_eth->type = 0x0800;
+               h_ip = (struct iphdr *)(h_eth + 1);
+       }
+
+       header_size += sizeof(struct iphdr);
+       h_ip->ver_len = 0x45;
+       h_ip->ttl = 10;
+       h_ip->proto = 0x11;
+       h_ip->src = 0x00000000;
+       h_ip->dest = 0xffffffff;
+
+       header_size += sizeof(struct udphdr);
+       h_udp = (struct udphdr *)(h_ip + 1);
+       h_udp->src = GELIC_DEBUG_PORT;
+       h_udp->dest = GELIC_DEBUG_PORT;
+
+       pmsgc = pmsg = (char *)(h_udp + 1);
+}
+
+static void gelic_debug_shutdown(void)
+{
+       if (bus_addr)
+               unmap_dma_mem(GELIC_BUS_ID, GELIC_DEVICE_ID,
+                             bus_addr, sizeof(dbg));
+       lv1_close_device(GELIC_BUS_ID, GELIC_DEVICE_ID);
+}
+
+static void gelic_sendbuf(int msgsize)
+{
+       u16 *p;
+       u32 sum;
+       int i;
+
+       dbg.descr.buf_size = header_size + msgsize;
+       h_ip->total_length = msgsize + sizeof(struct udphdr) +
+                            sizeof(struct iphdr);
+       h_udp->len = msgsize + sizeof(struct udphdr);
+
+       h_ip->checksum = 0;
+       sum = 0;
+       p = (u16 *)h_ip;
+       for (i = 0; i < 5; i++)
+               sum += *p++;
+       h_ip->checksum = ~(sum + (sum >> 16));
+
+       dbg.descr.dmac_cmd_status = GELIC_DESCR_DMA_CMD_NO_CHKSUM |
+                                   GELIC_DESCR_TX_DMA_FRAME_TAIL;
+       dbg.descr.result_size = 0;
+       dbg.descr.data_status = 0;
+
+       wmb();
+
+       lv1_net_start_tx_dma(GELIC_BUS_ID, GELIC_DEVICE_ID, bus_addr, 0);
+
+       while ((dbg.descr.dmac_cmd_status & GELIC_DESCR_DMA_STAT_MASK) ==
+              GELIC_DESCR_DMA_CARDOWNED)
+               cpu_relax();
+}
+
+static void ps3gelic_udbg_putc(char ch)
+{
+       *pmsgc++ = ch;
+       if (ch == '\n' || (pmsgc-pmsg) >= GELIC_MAX_MESSAGE_SIZE) {
+               gelic_sendbuf(pmsgc-pmsg);
+               pmsgc = pmsg;
+       }
+}
+
+void __init udbg_init_ps3gelic(void)
+{
+       gelic_debug_init();
+       udbg_putc = ps3gelic_udbg_putc;
+}
+
+void udbg_shutdown_ps3gelic(void)
+{
+       udbg_putc = NULL;
+       gelic_debug_shutdown();
+}
+EXPORT_SYMBOL(udbg_shutdown_ps3gelic);
index 23083c3..688141c 100644 (file)
@@ -695,12 +695,18 @@ static int ps3_dma_supported(struct device *_dev, u64 mask)
        return mask >= DMA_BIT_MASK(32);
 }
 
+static u64 ps3_dma_get_required_mask(struct device *_dev)
+{
+       return DMA_BIT_MASK(32);
+}
+
 static struct dma_map_ops ps3_sb_dma_ops = {
        .alloc_coherent = ps3_alloc_coherent,
        .free_coherent = ps3_free_coherent,
        .map_sg = ps3_sb_map_sg,
        .unmap_sg = ps3_sb_unmap_sg,
        .dma_supported = ps3_dma_supported,
+       .get_required_mask = ps3_dma_get_required_mask,
        .map_page = ps3_sb_map_page,
        .unmap_page = ps3_unmap_page,
 };
@@ -711,6 +717,7 @@ static struct dma_map_ops ps3_ioc0_dma_ops = {
        .map_sg = ps3_ioc0_map_sg,
        .unmap_sg = ps3_ioc0_unmap_sg,
        .dma_supported = ps3_dma_supported,
+       .get_required_mask = ps3_dma_get_required_mask,
        .map_page = ps3_ioc0_map_page,
        .unmap_page = ps3_unmap_page,
 };
index 05cf476..c81f6bb 100644 (file)
@@ -15,6 +15,7 @@ config PPC_PSERIES
        select PPC_UDBG_16550
        select PPC_NATIVE
        select PPC_PCI_CHOICE if EXPERT
+       select ZLIB_DEFLATE
        default y
 
 config PPC_SPLPAR
index e9be25b..0f1b706 100644 (file)
@@ -112,6 +112,7 @@ void dlpar_free_cc_nodes(struct device_node *dn)
        dlpar_free_one_cc_node(dn);
 }
 
+#define COMPLETE       0
 #define NEXT_SIBLING    1
 #define NEXT_CHILD      2
 #define NEXT_PROPERTY   3
@@ -158,6 +159,9 @@ struct device_node *dlpar_configure_connector(u32 drc_index)
                spin_unlock(&rtas_data_buf_lock);
 
                switch (rc) {
+               case COMPLETE:
+                       break;
+
                case NEXT_SIBLING:
                        dn = dlpar_parse_cc_node(ccwa);
                        if (!dn)
index ada6e07..d42f37d 100644 (file)
@@ -1338,7 +1338,7 @@ static const struct file_operations proc_eeh_operations = {
 static int __init eeh_init_proc(void)
 {
        if (machine_is(pseries))
-               proc_create("ppc64/eeh", 0, NULL, &proc_eeh_operations);
+               proc_create("powerpc/eeh", 0, NULL, &proc_eeh_operations);
        return 0;
 }
 __initcall(eeh_init_proc);
index 01faab9..5905a3b 100644 (file)
@@ -939,14 +939,14 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn)
        if (ret) {
                dev_info(&dev->dev, "failed to map direct window for %s: %d\n",
                         dn->full_name, ret);
-               goto out_clear_window;
+               goto out_free_window;
        }
 
        ret = prom_add_property(pdn, win64);
        if (ret) {
                dev_err(&dev->dev, "unable to add dma window property for %s: %d",
                         pdn->full_name, ret);
-               goto out_clear_window;
+               goto out_free_window;
        }
 
        window->device = pdn;
@@ -958,6 +958,9 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn)
        dma_addr = of_read_number(&create.addr_hi, 2);
        goto out_unlock;
 
+out_free_window:
+       kfree(window);
+
 out_clear_window:
        remove_ddw(pdn);
 
@@ -1077,12 +1080,38 @@ check_mask:
        return 0;
 }
 
+static u64 dma_get_required_mask_pSeriesLP(struct device *dev)
+{
+       if (!dev->dma_mask)
+               return 0;
+
+       if (!disable_ddw && dev_is_pci(dev)) {
+               struct pci_dev *pdev = to_pci_dev(dev);
+               struct device_node *dn;
+
+               dn = pci_device_to_OF_node(pdev);
+
+               /* search upwards for ibm,dma-window */
+               for (; dn && PCI_DN(dn) && !PCI_DN(dn)->iommu_table;
+                               dn = dn->parent)
+                       if (of_get_property(dn, "ibm,dma-window", NULL))
+                               break;
+               /* if there is a ibm,ddw-applicable property require 64 bits */
+               if (dn && PCI_DN(dn) &&
+                               of_get_property(dn, "ibm,ddw-applicable", NULL))
+                       return DMA_BIT_MASK(64);
+       }
+
+       return dma_iommu_ops.get_required_mask(dev);
+}
+
 #else  /* CONFIG_PCI */
 #define pci_dma_bus_setup_pSeries      NULL
 #define pci_dma_dev_setup_pSeries      NULL
 #define pci_dma_bus_setup_pSeriesLP    NULL
 #define pci_dma_dev_setup_pSeriesLP    NULL
 #define dma_set_mask_pSeriesLP         NULL
+#define dma_get_required_mask_pSeriesLP        NULL
 #endif /* !CONFIG_PCI */
 
 static int iommu_mem_notifier(struct notifier_block *nb, unsigned long action,
@@ -1186,6 +1215,7 @@ void iommu_init_early_pSeries(void)
                ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_pSeriesLP;
                ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_pSeriesLP;
                ppc_md.dma_set_mask = dma_set_mask_pSeriesLP;
+               ppc_md.dma_get_required_mask = dma_get_required_mask_pSeriesLP;
        } else {
                ppc_md.tce_build = tce_build_pSeries;
                ppc_md.tce_free  = tce_free_pSeries;
index 00cc3a0..a76b228 100644 (file)
@@ -18,6 +18,8 @@
 #include <linux/spinlock.h>
 #include <linux/slab.h>
 #include <linux/kmsg_dump.h>
+#include <linux/ctype.h>
+#include <linux/zlib.h>
 #include <asm/uaccess.h>
 #include <asm/nvram.h>
 #include <asm/rtas.h>
@@ -78,8 +80,41 @@ static struct kmsg_dumper nvram_kmsg_dumper = {
 #define NVRAM_RTAS_READ_TIMEOUT 5              /* seconds */
 static unsigned long last_unread_rtas_event;   /* timestamp */
 
-/* We preallocate oops_buf during init to avoid kmalloc during oops/panic. */
-static char *oops_buf;
+/*
+ * For capturing and compressing an oops or panic report...
+
+ * big_oops_buf[] holds the uncompressed text we're capturing.
+ *
+ * oops_buf[] holds the compressed text, preceded by a prefix.
+ * The prefix is just a u16 holding the length of the compressed* text.
+ * (*Or uncompressed, if compression fails.)  oops_buf[] gets written
+ * to NVRAM.
+ *
+ * oops_len points to the prefix.  oops_data points to the compressed text.
+ *
+ * +- oops_buf
+ * |           +- oops_data
+ * v           v
+ * +------------+-----------------------------------------------+
+ * | length    | text                                          |
+ * | (2 bytes) | (oops_data_sz bytes)                          |
+ * +------------+-----------------------------------------------+
+ * ^
+ * +- oops_len
+ *
+ * We preallocate these buffers during init to avoid kmalloc during oops/panic.
+ */
+static size_t big_oops_buf_sz;
+static char *big_oops_buf, *oops_buf;
+static u16 *oops_len;
+static char *oops_data;
+static size_t oops_data_sz;
+
+/* Compression parameters */
+#define COMPR_LEVEL 6
+#define WINDOW_BITS 12
+#define MEM_LEVEL 4
+static struct z_stream_s stream;
 
 static ssize_t pSeries_nvram_read(char *buf, size_t count, loff_t *index)
 {
@@ -387,11 +422,44 @@ static void __init nvram_init_oops_partition(int rtas_partition_exists)
                                                sizeof(rtas_log_partition));
        }
        oops_buf = kmalloc(oops_log_partition.size, GFP_KERNEL);
+       if (!oops_buf) {
+               pr_err("nvram: No memory for %s partition\n",
+                                               oops_log_partition.name);
+               return;
+       }
+       oops_len = (u16*) oops_buf;
+       oops_data = oops_buf + sizeof(u16);
+       oops_data_sz = oops_log_partition.size - sizeof(u16);
+
+       /*
+        * Figure compression (preceded by elimination of each line's <n>
+        * severity prefix) will reduce the oops/panic report to at most
+        * 45% of its original size.
+        */
+       big_oops_buf_sz = (oops_data_sz * 100) / 45;
+       big_oops_buf = kmalloc(big_oops_buf_sz, GFP_KERNEL);
+       if (big_oops_buf) {
+               stream.workspace = kmalloc(zlib_deflate_workspacesize(
+                               WINDOW_BITS, MEM_LEVEL), GFP_KERNEL);
+               if (!stream.workspace) {
+                       pr_err("nvram: No memory for compression workspace; "
+                               "skipping compression of %s partition data\n",
+                               oops_log_partition.name);
+                       kfree(big_oops_buf);
+                       big_oops_buf = NULL;
+               }
+       } else {
+               pr_err("No memory for uncompressed %s data; "
+                       "skipping compression\n", oops_log_partition.name);
+               stream.workspace = NULL;
+       }
+
        rc = kmsg_dump_register(&nvram_kmsg_dumper);
        if (rc != 0) {
                pr_err("nvram: kmsg_dump_register() failed; returned %d\n", rc);
                kfree(oops_buf);
-               return;
+               kfree(big_oops_buf);
+               kfree(stream.workspace);
        }
 }
 
@@ -473,7 +541,83 @@ static int clobbering_unread_rtas_event(void)
                                                NVRAM_RTAS_READ_TIMEOUT);
 }
 
-/* our kmsg_dump callback */
+/* Squeeze out each line's <n> severity prefix. */
+static size_t elide_severities(char *buf, size_t len)
+{
+       char *in, *out, *buf_end = buf + len;
+       /* Assume a <n> at the very beginning marks the start of a line. */
+       int newline = 1;
+
+       in = out = buf;
+       while (in < buf_end) {
+               if (newline && in+3 <= buf_end &&
+                               *in == '<' && isdigit(in[1]) && in[2] == '>') {
+                       in += 3;
+                       newline = 0;
+               } else {
+                       newline = (*in == '\n');
+                       *out++ = *in++;
+               }
+       }
+       return out - buf;
+}
+
+/* Derived from logfs_compress() */
+static int nvram_compress(const void *in, void *out, size_t inlen,
+                                                       size_t outlen)
+{
+       int err, ret;
+
+       ret = -EIO;
+       err = zlib_deflateInit2(&stream, COMPR_LEVEL, Z_DEFLATED, WINDOW_BITS,
+                                               MEM_LEVEL, Z_DEFAULT_STRATEGY);
+       if (err != Z_OK)
+               goto error;
+
+       stream.next_in = in;
+       stream.avail_in = inlen;
+       stream.total_in = 0;
+       stream.next_out = out;
+       stream.avail_out = outlen;
+       stream.total_out = 0;
+
+       err = zlib_deflate(&stream, Z_FINISH);
+       if (err != Z_STREAM_END)
+               goto error;
+
+       err = zlib_deflateEnd(&stream);
+       if (err != Z_OK)
+               goto error;
+
+       if (stream.total_out >= stream.total_in)
+               goto error;
+
+       ret = stream.total_out;
+error:
+       return ret;
+}
+
+/* Compress the text from big_oops_buf into oops_buf. */
+static int zip_oops(size_t text_len)
+{
+       int zipped_len = nvram_compress(big_oops_buf, oops_data, text_len,
+                                                               oops_data_sz);
+       if (zipped_len < 0) {
+               pr_err("nvram: compression failed; returned %d\n", zipped_len);
+               pr_err("nvram: logging uncompressed oops/panic report\n");
+               return -1;
+       }
+       *oops_len = (u16) zipped_len;
+       return 0;
+}
+
+/*
+ * This is our kmsg_dump callback, called after an oops or panic report
+ * has been written to the printk buffer.  We want to capture as much
+ * of the printk buffer as possible.  First, capture as much as we can
+ * that we think will compress sufficiently to fit in the lnx,oops-log
+ * partition.  If that's too much, go back and capture uncompressed text.
+ */
 static void oops_to_nvram(struct kmsg_dumper *dumper,
                enum kmsg_dump_reason reason,
                const char *old_msgs, unsigned long old_len,
@@ -482,6 +626,8 @@ static void oops_to_nvram(struct kmsg_dumper *dumper,
        static unsigned int oops_count = 0;
        static bool panicking = false;
        size_t text_len;
+       unsigned int err_type = ERR_TYPE_KERNEL_PANIC_GZ;
+       int rc = -1;
 
        switch (reason) {
        case KMSG_DUMP_RESTART:
@@ -509,8 +655,19 @@ static void oops_to_nvram(struct kmsg_dumper *dumper,
        if (clobbering_unread_rtas_event())
                return;
 
-       text_len = capture_last_msgs(old_msgs, old_len, new_msgs, new_len,
-                                       oops_buf, oops_log_partition.size);
+       if (big_oops_buf) {
+               text_len = capture_last_msgs(old_msgs, old_len,
+                       new_msgs, new_len, big_oops_buf, big_oops_buf_sz);
+               text_len = elide_severities(big_oops_buf, text_len);
+               rc = zip_oops(text_len);
+       }
+       if (rc != 0) {
+               text_len = capture_last_msgs(old_msgs, old_len,
+                               new_msgs, new_len, oops_data, oops_data_sz);
+               err_type = ERR_TYPE_KERNEL_PANIC;
+               *oops_len = (u16) text_len;
+       }
+
        (void) nvram_write_os_partition(&oops_log_partition, oops_buf,
-               (int) text_len, ERR_TYPE_KERNEL_PANIC, ++oops_count);
+               (int) (sizeof(*oops_len) + *oops_len), err_type, ++oops_count);
 }
index c3c48eb..f4fb837 100644 (file)
@@ -1,5 +1,12 @@
 config PPC_WSP
        bool
+       select PPC_A2
+       select PPC_SCOM
+       select PPC_XICS
+       select PPC_ICP_NATIVE
+       select PCI
+       select PPC_IO_WORKAROUNDS if PCI
+       select PPC_INDIRECT_PIO if PCI
        default n
 
 menu "WSP platform selection"
@@ -7,13 +14,9 @@ menu "WSP platform selection"
 
 config PPC_PSR2
        bool "PSR-2 platform"
-       select PPC_A2
        select GENERIC_TBSYNC
-       select PPC_SCOM
        select EPAPR_BOOT
        select PPC_WSP
-       select PPC_XICS
-       select PPC_ICP_NATIVE
        default y
 
 endmenu
index 095be73..a1486b4 100644 (file)
@@ -4,3 +4,5 @@ obj-y                           += setup.o ics.o
 obj-$(CONFIG_PPC_PSR2)         += psr2.o opb_pic.o
 obj-$(CONFIG_PPC_WSP)          += scom_wsp.o
 obj-$(CONFIG_SMP)              += smp.o scom_smp.o
+obj-$(CONFIG_PCI)              += wsp_pci.o
+obj-$(CONFIG_PCI_MSI)          += msi.o
\ No newline at end of file
index e53bd9e..5768743 100644 (file)
@@ -710,3 +710,51 @@ void __init wsp_init_irq(void)
        /* We need to patch our irq chip's EOI to point to the right ICP */
        wsp_irq_chip.irq_eoi = icp_ops->eoi;
 }
+
+#ifdef CONFIG_PCI_MSI
+static void wsp_ics_msi_unmask_irq(struct irq_data *d)
+{
+       wsp_chip_unmask_irq(d);
+       unmask_msi_irq(d);
+}
+
+static unsigned int wsp_ics_msi_startup(struct irq_data *d)
+{
+       wsp_ics_msi_unmask_irq(d);
+       return 0;
+}
+
+static void wsp_ics_msi_mask_irq(struct irq_data *d)
+{
+       mask_msi_irq(d);
+       wsp_chip_mask_irq(d);
+}
+
+/*
+ * we do it this way because we reassinge default EOI handling in
+ * irq_init() above
+ */
+static void wsp_ics_eoi(struct irq_data *data)
+{
+       wsp_irq_chip.irq_eoi(data);
+}
+
+static struct irq_chip wsp_ics_msi = {
+       .name = "WSP ICS MSI",
+       .irq_startup = wsp_ics_msi_startup,
+       .irq_mask = wsp_ics_msi_mask_irq,
+       .irq_unmask = wsp_ics_msi_unmask_irq,
+       .irq_eoi = wsp_ics_eoi,
+       .irq_set_affinity = wsp_chip_set_affinity
+};
+
+void wsp_ics_set_msi_chip(unsigned int irq)
+{
+       irq_set_chip(irq, &wsp_ics_msi);
+}
+
+void wsp_ics_set_std_chip(unsigned int irq)
+{
+       irq_set_chip(irq, &wsp_irq_chip);
+}
+#endif /* CONFIG_PCI_MSI */
index e34d531..07b644e 100644 (file)
@@ -17,4 +17,9 @@ extern void wsp_init_irq(void);
 extern int wsp_ics_alloc_irq(struct device_node *dn, int num);
 extern void wsp_ics_free_irq(struct device_node *dn, unsigned int irq);
 
+#ifdef CONFIG_PCI_MSI
+extern void wsp_ics_set_msi_chip(unsigned int irq);
+extern void wsp_ics_set_std_chip(unsigned int irq);
+#endif /* CONFIG_PCI_MSI */
+
 #endif /* __ICS_H */
diff --git a/arch/powerpc/platforms/wsp/msi.c b/arch/powerpc/platforms/wsp/msi.c
new file mode 100644 (file)
index 0000000..380882f
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2011 Michael Ellerman, IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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/pci.h>
+#include <linux/msi.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+
+#include "msi.h"
+#include "ics.h"
+#include "wsp_pci.h"
+
+/* Magic addresses for 32 & 64-bit MSIs with hardcoded MVE 0 */
+#define MSI_ADDR_32            0xFFFF0000ul
+#define MSI_ADDR_64            0x1000000000000000ul
+
+int wsp_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+{
+       struct pci_controller *phb;
+       struct msi_desc *entry;
+       struct msi_msg msg;
+       unsigned int virq;
+       int hwirq;
+
+       phb = pci_bus_to_host(dev->bus);
+       if (!phb)
+               return -ENOENT;
+
+       entry = list_first_entry(&dev->msi_list, struct msi_desc, list);
+       if (entry->msi_attrib.is_64) {
+               msg.address_lo = 0;
+               msg.address_hi = MSI_ADDR_64 >> 32;
+       } else {
+               msg.address_lo = MSI_ADDR_32;
+               msg.address_hi = 0;
+       }
+
+       list_for_each_entry(entry, &dev->msi_list, list) {
+               hwirq = wsp_ics_alloc_irq(phb->dn, 1);
+               if (hwirq < 0) {
+                       dev_warn(&dev->dev, "wsp_msi: hwirq alloc failed!\n");
+                       return hwirq;
+               }
+
+               virq = irq_create_mapping(NULL, hwirq);
+               if (virq == NO_IRQ) {
+                       dev_warn(&dev->dev, "wsp_msi: virq alloc failed!\n");
+                       return -1;
+               }
+
+               dev_dbg(&dev->dev, "wsp_msi: allocated irq %#x/%#x\n",
+                       hwirq, virq);
+
+               wsp_ics_set_msi_chip(virq);
+               irq_set_msi_desc(virq, entry);
+               msg.data = hwirq & XIVE_ADDR_MASK;
+               write_msi_msg(virq, &msg);
+       }
+
+       return 0;
+}
+
+void wsp_teardown_msi_irqs(struct pci_dev *dev)
+{
+       struct pci_controller *phb;
+       struct msi_desc *entry;
+       int hwirq;
+
+       phb = pci_bus_to_host(dev->bus);
+
+       dev_dbg(&dev->dev, "wsp_msi: tearing down msi irqs\n");
+
+       list_for_each_entry(entry, &dev->msi_list, list) {
+               if (entry->irq == NO_IRQ)
+                       continue;
+
+               irq_set_msi_desc(entry->irq, NULL);
+               wsp_ics_set_std_chip(entry->irq);
+
+               hwirq = virq_to_hw(entry->irq);
+               /* In this order to avoid racing with irq_create_mapping() */
+               irq_dispose_mapping(entry->irq);
+               wsp_ics_free_irq(phb->dn, hwirq);
+       }
+}
+
+void wsp_setup_phb_msi(struct pci_controller *phb)
+{
+       /* Create a single MVE at offset 0 that matches everything */
+       out_be64(phb->cfg_data + PCIE_REG_IODA_ADDR, PCIE_REG_IODA_AD_TBL_MVT);
+       out_be64(phb->cfg_data + PCIE_REG_IODA_DATA0, 1ull << 63);
+
+       ppc_md.setup_msi_irqs = wsp_setup_msi_irqs;
+       ppc_md.teardown_msi_irqs = wsp_teardown_msi_irqs;
+}
diff --git a/arch/powerpc/platforms/wsp/msi.h b/arch/powerpc/platforms/wsp/msi.h
new file mode 100644 (file)
index 0000000..0ab27b7
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2011 Michael Ellerman, IBM Corp.
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the 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 __WSP_MSI_H
+#define __WSP_MSI_H
+
+#ifdef CONFIG_PCI_MSI
+extern void wsp_setup_phb_msi(struct pci_controller *phb);
+#else
+static inline void wsp_setup_phb_msi(struct pci_controller *phb) { }
+#endif
+
+#endif /* __WSP_MSI_H */
index 40f2891..166f2e4 100644 (file)
@@ -63,6 +63,10 @@ static void __init psr2_setup_arch(void)
 #ifdef CONFIG_SMP
        a2_setup_smp();
 #endif
+#ifdef CONFIG_PCI
+       wsp_setup_pci();
+#endif
+
 }
 
 static int __init psr2_probe(void)
index 7c3e087..3347981 100644 (file)
@@ -3,6 +3,9 @@
 
 #include <asm/wsp.h>
 
+/* Devtree compatible strings for major devices */
+#define PCIE_COMPATIBLE     "ibm,wsp-pciex"
+
 extern void wsp_setup_pci(void);
 extern void scom_init_wsp(void);
 
diff --git a/arch/powerpc/platforms/wsp/wsp_pci.c b/arch/powerpc/platforms/wsp/wsp_pci.c
new file mode 100644 (file)
index 0000000..e0262cd
--- /dev/null
@@ -0,0 +1,1133 @@
+/*
+ * Copyright 2010 Ben Herrenschmidt, IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#define DEBUG
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/debugfs.h>
+
+#include <asm/sections.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+#include <asm/ppc-pci.h>
+#include <asm/iommu.h>
+#include <asm/io-workarounds.h>
+
+#include "wsp.h"
+#include "wsp_pci.h"
+#include "msi.h"
+
+
+/* Max number of TVTs for one table. Only 32-bit tables can use
+ * multiple TVTs and so the max currently supported is thus 8
+ * since only 2G of DMA space is supported
+ */
+#define MAX_TABLE_TVT_COUNT            8
+
+struct wsp_dma_table {
+       struct list_head        link;
+       struct iommu_table      table;
+       struct wsp_phb  *phb;
+       struct page             *tces[MAX_TABLE_TVT_COUNT];
+};
+
+/* We support DMA regions from 0...2G in 32bit space (no support for
+ * 64-bit DMA just yet). Each device gets a separate TCE table (TVT
+ * entry) with validation enabled (though not supported by SimiCS
+ * just yet).
+ *
+ * To simplify things, we divide this 2G space into N regions based
+ * on the constant below which could be turned into a tunable eventually
+ *
+ * We then assign dynamically those regions to devices as they show up.
+ *
+ * We use a bitmap as an allocator for these.
+ *
+ * Tables are allocated/created dynamically as devices are discovered,
+ * multiple TVT entries are used if needed
+ *
+ * When 64-bit DMA support is added we should simply use a separate set
+ * of larger regions (the HW supports 64 TVT entries). We can
+ * additionally create a bypass region in 64-bit space for performances
+ * though that would have a cost in term of security.
+ *
+ * If you set NUM_DMA32_REGIONS to 1, then a single table is shared
+ * for all devices and bus/dev/fn validation is disabled
+ *
+ * Note that a DMA32 region cannot be smaller than 256M so the max
+ * supported here for now is 8. We don't yet support sharing regions
+ * between multiple devices so the max number of devices supported
+ * is MAX_TABLE_TVT_COUNT.
+ */
+#define NUM_DMA32_REGIONS      1
+
+struct wsp_phb {
+       struct pci_controller   *hose;
+
+       /* Lock controlling access to the list of dma tables.
+        * It does -not- protect against dma_* operations on
+        * those tables, those should be stopped before an entry
+        * is removed from the list.
+        *
+        * The lock is also used for error handling operations
+        */
+       spinlock_t              lock;
+       struct list_head        dma_tables;
+       unsigned long           dma32_map;
+       unsigned long           dma32_base;
+       unsigned int            dma32_num_regions;
+       unsigned long           dma32_region_size;
+
+       /* Debugfs stuff */
+       struct dentry           *ddir;
+
+       struct list_head        all;
+};
+static LIST_HEAD(wsp_phbs);
+
+//#define cfg_debug(fmt...)    pr_debug(fmt)
+#define cfg_debug(fmt...)
+
+
+static int wsp_pcie_read_config(struct pci_bus *bus, unsigned int devfn,
+                                 int offset, int len, u32 *val)
+{
+       struct pci_controller *hose;
+       int suboff;
+       u64 addr;
+
+       hose = pci_bus_to_host(bus);
+       if (hose == NULL)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+       if (offset >= 0x1000)
+               return  PCIBIOS_BAD_REGISTER_NUMBER;
+       addr = PCIE_REG_CA_ENABLE |
+               ((u64)bus->number) << PCIE_REG_CA_BUS_SHIFT |
+               ((u64)devfn) << PCIE_REG_CA_FUNC_SHIFT |
+               ((u64)offset & ~3) << PCIE_REG_CA_REG_SHIFT;
+       suboff = offset & 3;
+
+       /*
+        * Note: the caller has already checked that offset is
+        * suitably aligned and that len is 1, 2 or 4.
+        */
+
+       switch (len) {
+       case 1:
+               addr |= (0x8ul >> suboff) << PCIE_REG_CA_BE_SHIFT;
+               out_be64(hose->cfg_data + PCIE_REG_CONFIG_ADDRESS, addr);
+               *val = (in_le32(hose->cfg_data + PCIE_REG_CONFIG_DATA)
+                       >> (suboff << 3)) & 0xff;
+               cfg_debug("read 1 %02x:%02x:%02x + %02x/%x addr=0x%llx val=%02x\n",
+                         bus->number, devfn >> 3, devfn & 7,
+                         offset, suboff, addr, *val);
+               break;
+       case 2:
+               addr |= (0xcul >> suboff) << PCIE_REG_CA_BE_SHIFT;
+               out_be64(hose->cfg_data + PCIE_REG_CONFIG_ADDRESS, addr);
+               *val = (in_le32(hose->cfg_data + PCIE_REG_CONFIG_DATA)
+                       >> (suboff << 3)) & 0xffff;
+               cfg_debug("read 2 %02x:%02x:%02x + %02x/%x addr=0x%llx val=%04x\n",
+                         bus->number, devfn >> 3, devfn & 7,
+                         offset, suboff, addr, *val);
+               break;
+       default:
+               addr |= 0xful << PCIE_REG_CA_BE_SHIFT;
+               out_be64(hose->cfg_data + PCIE_REG_CONFIG_ADDRESS, addr);
+               *val = in_le32(hose->cfg_data + PCIE_REG_CONFIG_DATA);
+               cfg_debug("read 4 %02x:%02x:%02x + %02x/%x addr=0x%llx val=%08x\n",
+                         bus->number, devfn >> 3, devfn & 7,
+                         offset, suboff, addr, *val);
+               break;
+       }
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int wsp_pcie_write_config(struct pci_bus *bus, unsigned int devfn,
+                                  int offset, int len, u32 val)
+{
+       struct pci_controller *hose;
+       int suboff;
+       u64 addr;
+
+       hose = pci_bus_to_host(bus);
+       if (hose == NULL)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+       if (offset >= 0x1000)
+               return  PCIBIOS_BAD_REGISTER_NUMBER;
+       addr = PCIE_REG_CA_ENABLE |
+               ((u64)bus->number) << PCIE_REG_CA_BUS_SHIFT |
+               ((u64)devfn) << PCIE_REG_CA_FUNC_SHIFT |
+               ((u64)offset & ~3) << PCIE_REG_CA_REG_SHIFT;
+       suboff = offset & 3;
+
+       /*
+        * Note: the caller has already checked that offset is
+        * suitably aligned and that len is 1, 2 or 4.
+        */
+       switch (len) {
+       case 1:
+               addr |= (0x8ul >> suboff) << PCIE_REG_CA_BE_SHIFT;
+               val <<= suboff << 3;
+               out_be64(hose->cfg_data + PCIE_REG_CONFIG_ADDRESS, addr);
+               out_le32(hose->cfg_data + PCIE_REG_CONFIG_DATA, val);
+               cfg_debug("write 1 %02x:%02x:%02x + %02x/%x addr=0x%llx val=%02x\n",
+                         bus->number, devfn >> 3, devfn & 7,
+                         offset, suboff, addr, val);
+               break;
+       case 2:
+               addr |= (0xcul >> suboff) << PCIE_REG_CA_BE_SHIFT;
+               val <<= suboff << 3;
+               out_be64(hose->cfg_data + PCIE_REG_CONFIG_ADDRESS, addr);
+               out_le32(hose->cfg_data + PCIE_REG_CONFIG_DATA, val);
+               cfg_debug("write 2 %02x:%02x:%02x + %02x/%x addr=0x%llx val=%04x\n",
+                         bus->number, devfn >> 3, devfn & 7,
+                         offset, suboff, addr, val);
+               break;
+       default:
+               addr |= 0xful << PCIE_REG_CA_BE_SHIFT;
+               out_be64(hose->cfg_data + PCIE_REG_CONFIG_ADDRESS, addr);
+               out_le32(hose->cfg_data + PCIE_REG_CONFIG_DATA, val);
+               cfg_debug("write 4 %02x:%02x:%02x + %02x/%x addr=0x%llx val=%08x\n",
+                         bus->number, devfn >> 3, devfn & 7,
+                         offset, suboff, addr, val);
+               break;
+       }
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops wsp_pcie_pci_ops =
+{
+       .read = wsp_pcie_read_config,
+       .write = wsp_pcie_write_config,
+};
+
+#define TCE_SHIFT              12
+#define TCE_PAGE_SIZE          (1 << TCE_SHIFT)
+#define TCE_PCI_WRITE          0x2              /* write from PCI allowed */
+#define TCE_PCI_READ           0x1              /* read from PCI allowed */
+#define TCE_RPN_MASK           0x3fffffffffful  /* 42-bit RPN (4K pages) */
+#define TCE_RPN_SHIFT          12
+
+//#define dma_debug(fmt...)    pr_debug(fmt)
+#define dma_debug(fmt...)
+
+static int tce_build_wsp(struct iommu_table *tbl, long index, long npages,
+                          unsigned long uaddr, enum dma_data_direction direction,
+                          struct dma_attrs *attrs)
+{
+       struct wsp_dma_table *ptbl = container_of(tbl,
+                                                   struct wsp_dma_table,
+                                                   table);
+       u64 proto_tce;
+       u64 *tcep;
+       u64 rpn;
+
+       proto_tce = TCE_PCI_READ;
+#ifdef CONFIG_WSP_DD1_WORKAROUND_DD1_TCE_BUGS
+       proto_tce |= TCE_PCI_WRITE;
+#else
+       if (direction != DMA_TO_DEVICE)
+               proto_tce |= TCE_PCI_WRITE;
+#endif
+
+       /* XXX Make this faster by factoring out the page address for
+        * within a TCE table
+        */
+       while (npages--) {
+               /* We don't use it->base as the table can be scattered */
+               tcep = (u64 *)page_address(ptbl->tces[index >> 16]);
+               tcep += (index & 0xffff);
+
+               /* can't move this out since we might cross LMB boundary */
+               rpn = __pa(uaddr) >> TCE_SHIFT;
+               *tcep = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT;
+
+               dma_debug("[DMA] TCE %p set to 0x%016llx (dma addr: 0x%lx)\n",
+                         tcep, *tcep, (tbl->it_offset + index) << IOMMU_PAGE_SHIFT);
+
+               uaddr += TCE_PAGE_SIZE;
+               index++;
+       }
+       return 0;
+}
+
+static void tce_free_wsp(struct iommu_table *tbl, long index, long npages)
+{
+       struct wsp_dma_table *ptbl = container_of(tbl,
+                                                   struct wsp_dma_table,
+                                                   table);
+#ifndef CONFIG_WSP_DD1_WORKAROUND_DD1_TCE_BUGS
+       struct pci_controller *hose = ptbl->phb->hose;
+#endif
+       u64 *tcep;
+
+       /* XXX Make this faster by factoring out the page address for
+        * within a TCE table. Also use line-kill option to kill multiple
+        * TCEs at once
+        */
+       while (npages--) {
+               /* We don't use it->base as the table can be scattered */
+               tcep = (u64 *)page_address(ptbl->tces[index >> 16]);
+               tcep += (index & 0xffff);
+               dma_debug("[DMA] TCE %p cleared\n", tcep);
+               *tcep = 0;
+#ifndef CONFIG_WSP_DD1_WORKAROUND_DD1_TCE_BUGS
+               /* Don't write there since it would pollute other MMIO accesses */
+               out_be64(hose->cfg_data + PCIE_REG_TCE_KILL,
+                        PCIE_REG_TCEKILL_SINGLE | PCIE_REG_TCEKILL_PS_4K |
+                        (__pa(tcep) & PCIE_REG_TCEKILL_ADDR_MASK));
+#endif
+               index++;
+       }
+}
+
+static struct wsp_dma_table *wsp_pci_create_dma32_table(struct wsp_phb *phb,
+                                                           unsigned int region,
+                                                           struct pci_dev *validate)
+{
+       struct pci_controller *hose = phb->hose;
+       unsigned long size = phb->dma32_region_size;
+       unsigned long addr = phb->dma32_region_size * region + phb->dma32_base;
+       struct wsp_dma_table *tbl;
+       int tvts_per_table, i, tvt, nid;
+       unsigned long flags;
+
+       nid = of_node_to_nid(phb->hose->dn);
+
+       /* Calculate how many TVTs are needed */
+       tvts_per_table = size / 0x10000000;
+       if (tvts_per_table == 0)
+               tvts_per_table = 1;
+
+       /* Calculate the base TVT index. We know all tables have the same
+        * size so we just do a simple multiply here
+        */
+       tvt = region * tvts_per_table;
+
+       pr_debug("         Region : %d\n", region);
+       pr_debug("      DMA range : 0x%08lx..0x%08lx\n", addr, addr + size - 1);
+       pr_debug(" Number of TVTs : %d\n", tvts_per_table);
+       pr_debug("       Base TVT : %d\n", tvt);
+       pr_debug("         Node   : %d\n", nid);
+
+       tbl = kzalloc_node(sizeof(struct wsp_dma_table), GFP_KERNEL, nid);
+       if (!tbl)
+               return ERR_PTR(-ENOMEM);
+       tbl->phb = phb;
+
+       /* Create as many TVTs as needed, each represents 256M at most */
+       for (i = 0; i < tvts_per_table; i++) {
+               u64 tvt_data1, tvt_data0;
+
+               /* Allocate table. We use a 4K TCE size for now always so
+                * one table is always 8 * (258M / 4K) == 512K
+                */
+               tbl->tces[i] = alloc_pages_node(nid, GFP_KERNEL, get_order(0x80000));
+               if (tbl->tces[i] == NULL)
+                       goto fail;
+               memset(page_address(tbl->tces[i]), 0, 0x80000);
+
+               pr_debug(" TCE table %d at : %p\n", i, page_address(tbl->tces[i]));
+
+               /* Table size. We currently set it to be the whole 256M region */
+               tvt_data0 = 2ull << IODA_TVT0_TCE_TABLE_SIZE_SHIFT;
+               /* IO page size set to 4K */
+               tvt_data1 = 1ull << IODA_TVT1_IO_PAGE_SIZE_SHIFT;
+               /* Shift in the address */
+               tvt_data0 |= __pa(page_address(tbl->tces[i])) << IODA_TVT0_TTA_SHIFT;
+
+               /* Validation stuff. We only validate fully bus/dev/fn for now
+                * one day maybe we can group devices but that isn't the case
+                * at the moment
+                */
+               if (validate) {
+                       tvt_data0 |= IODA_TVT0_BUSNUM_VALID_MASK;
+                       tvt_data0 |= validate->bus->number;
+                       tvt_data1 |= IODA_TVT1_DEVNUM_VALID;
+                       tvt_data1 |= ((u64)PCI_SLOT(validate->devfn))
+                               << IODA_TVT1_DEVNUM_VALUE_SHIFT;
+                       tvt_data1 |= IODA_TVT1_FUNCNUM_VALID;
+                       tvt_data1 |= ((u64)PCI_FUNC(validate->devfn))
+                               << IODA_TVT1_FUNCNUM_VALUE_SHIFT;
+               }
+
+               /* XX PE number is always 0 for now */
+
+               /* Program the values using the PHB lock */
+               spin_lock_irqsave(&phb->lock, flags);
+               out_be64(hose->cfg_data + PCIE_REG_IODA_ADDR,
+                        (tvt + i) | PCIE_REG_IODA_AD_TBL_TVT);
+               out_be64(hose->cfg_data + PCIE_REG_IODA_DATA1, tvt_data1);
+               out_be64(hose->cfg_data + PCIE_REG_IODA_DATA0, tvt_data0);
+               spin_unlock_irqrestore(&phb->lock, flags);
+       }
+
+       /* Init bits and pieces */
+       tbl->table.it_blocksize = 16;
+       tbl->table.it_offset = addr >> IOMMU_PAGE_SHIFT;
+       tbl->table.it_size = size >> IOMMU_PAGE_SHIFT;
+
+       /*
+        * It's already blank but we clear it anyway.
+        * Consider an aditiona interface that makes cleaing optional
+        */
+       iommu_init_table(&tbl->table, nid);
+
+       list_add(&tbl->link, &phb->dma_tables);
+       return tbl;
+
+ fail:
+       pr_debug("  Failed to allocate a 256M TCE table !\n");
+       for (i = 0; i < tvts_per_table; i++)
+               if (tbl->tces[i])
+                       __free_pages(tbl->tces[i], get_order(0x80000));
+       kfree(tbl);
+       return ERR_PTR(-ENOMEM);
+}
+
+static void __devinit wsp_pci_dma_dev_setup(struct pci_dev *pdev)
+{
+       struct dev_archdata *archdata = &pdev->dev.archdata;
+       struct pci_controller *hose = pci_bus_to_host(pdev->bus);
+       struct wsp_phb *phb = hose->private_data;
+       struct wsp_dma_table *table = NULL;
+       unsigned long flags;
+       int i;
+
+       /* Don't assign an iommu table to a bridge */
+       if (pdev->hdr_type == PCI_HEADER_TYPE_BRIDGE)
+               return;
+
+       pr_debug("%s: Setting up DMA...\n", pci_name(pdev));
+
+       spin_lock_irqsave(&phb->lock, flags);
+
+       /* If only one region, check if it already exist */
+       if (phb->dma32_num_regions == 1) {
+               spin_unlock_irqrestore(&phb->lock, flags);
+               if (list_empty(&phb->dma_tables))
+                       table = wsp_pci_create_dma32_table(phb, 0, NULL);
+               else
+                       table = list_first_entry(&phb->dma_tables,
+                                                struct wsp_dma_table,
+                                                link);
+       } else {
+               /* else find a free region */
+               for (i = 0; i < phb->dma32_num_regions && !table; i++) {
+                       if (__test_and_set_bit(i, &phb->dma32_map))
+                               continue;
+                       spin_unlock_irqrestore(&phb->lock, flags);
+                       table = wsp_pci_create_dma32_table(phb, i, pdev);
+               }
+       }
+
+       /* Check if we got an error */
+       if (IS_ERR(table)) {
+               pr_err("%s: Failed to create DMA table, err %ld !\n",
+                      pci_name(pdev), PTR_ERR(table));
+               return;
+       }
+
+       /* Or a valid table */
+       if (table) {
+               pr_info("%s: Setup iommu: 32-bit DMA region 0x%08lx..0x%08lx\n",
+                       pci_name(pdev),
+                       table->table.it_offset << IOMMU_PAGE_SHIFT,
+                       (table->table.it_offset << IOMMU_PAGE_SHIFT)
+                       + phb->dma32_region_size - 1);
+               archdata->dma_data.iommu_table_base = &table->table;
+               return;
+       }
+
+       /* Or no room */
+       spin_unlock_irqrestore(&phb->lock, flags);
+       pr_err("%s: Out of DMA space !\n", pci_name(pdev));
+}
+
+static void __init wsp_pcie_configure_hw(struct pci_controller *hose)
+{
+       u64 val;
+       int i;
+
+#define DUMP_REG(x) \
+       pr_debug("%-30s : 0x%016llx\n", #x, in_be64(hose->cfg_data + x))
+
+#ifdef CONFIG_WSP_DD1_WORKAROUND_BAD_PCIE_CLASS
+       /* WSP DD1 has a bogus class code by default in the PCI-E
+        * root complex's built-in P2P bridge */
+       val = in_be64(hose->cfg_data + PCIE_REG_SYS_CFG1);
+       pr_debug("PCI-E SYS_CFG1 : 0x%llx\n", val);
+       out_be64(hose->cfg_data + PCIE_REG_SYS_CFG1,
+                (val & ~PCIE_REG_SYS_CFG1_CLASS_CODE) | (PCI_CLASS_BRIDGE_PCI << 8));
+       pr_debug("PCI-E SYS_CFG1 : 0x%llx\n", in_be64(hose->cfg_data + PCIE_REG_SYS_CFG1));
+#endif /* CONFIG_WSP_DD1_WORKAROUND_BAD_PCIE_CLASS */
+
+#ifdef CONFIG_WSP_DD1_WORKAROUND_DD1_TCE_BUGS
+       /* XXX Disable TCE caching, it doesn't work on DD1 */
+       out_be64(hose->cfg_data + 0xe50,
+                in_be64(hose->cfg_data + 0xe50) | (3ull << 62));
+       printk("PCI-E DEBUG CONTROL 5 = 0x%llx\n", in_be64(hose->cfg_data + 0xe50));
+#endif
+
+       /* Configure M32A and IO. IO is hard wired to be 1M for now */
+       out_be64(hose->cfg_data + PCIE_REG_IO_BASE_ADDR, hose->io_base_phys);
+       out_be64(hose->cfg_data + PCIE_REG_IO_BASE_MASK,
+                (~(hose->io_resource.end - hose->io_resource.start)) &
+                0x3fffffff000ul);
+       out_be64(hose->cfg_data + PCIE_REG_IO_START_ADDR, 0 | 1);
+
+       out_be64(hose->cfg_data + PCIE_REG_M32A_BASE_ADDR,
+                hose->mem_resources[0].start);
+       printk("Want to write to M32A_BASE_MASK : 0x%llx\n",
+                (~(hose->mem_resources[0].end -
+                   hose->mem_resources[0].start)) & 0x3ffffff0000ul);
+       out_be64(hose->cfg_data + PCIE_REG_M32A_BASE_MASK,
+                (~(hose->mem_resources[0].end -
+                   hose->mem_resources[0].start)) & 0x3ffffff0000ul);
+       out_be64(hose->cfg_data + PCIE_REG_M32A_START_ADDR,
+                (hose->mem_resources[0].start - hose->pci_mem_offset) | 1);
+
+       /* Clear all TVT entries
+        *
+        * XX Might get TVT count from device-tree
+        */
+       for (i = 0; i < IODA_TVT_COUNT; i++) {
+               out_be64(hose->cfg_data + PCIE_REG_IODA_ADDR,
+                        PCIE_REG_IODA_AD_TBL_TVT | i);
+               out_be64(hose->cfg_data + PCIE_REG_IODA_DATA1, 0);
+               out_be64(hose->cfg_data + PCIE_REG_IODA_DATA0, 0);
+       }
+
+       /* Kill the TCE cache */
+       out_be64(hose->cfg_data + PCIE_REG_PHB_CONFIG,
+                in_be64(hose->cfg_data + PCIE_REG_PHB_CONFIG) |
+                PCIE_REG_PHBC_64B_TCE_EN);
+
+       /* Enable 32 & 64-bit MSIs, IO space and M32A */
+       val = PCIE_REG_PHBC_32BIT_MSI_EN |
+             PCIE_REG_PHBC_IO_EN |
+             PCIE_REG_PHBC_64BIT_MSI_EN |
+             PCIE_REG_PHBC_M32A_EN;
+       if (iommu_is_off)
+               val |= PCIE_REG_PHBC_DMA_XLATE_BYPASS;
+       pr_debug("Will write config: 0x%llx\n", val);
+       out_be64(hose->cfg_data + PCIE_REG_PHB_CONFIG, val);
+
+       /* Enable error reporting */
+       out_be64(hose->cfg_data + 0xe00,
+                in_be64(hose->cfg_data + 0xe00) | 0x0008000000000000ull);
+
+       /* Mask an error that's generated when doing config space probe
+        *
+        * XXX Maybe we should only mask it around config space cycles... that or
+        * ignore it when we know we had a config space cycle recently ?
+        */
+       out_be64(hose->cfg_data + PCIE_REG_DMA_ERR_STATUS_MASK, 0x8000000000000000ull);
+       out_be64(hose->cfg_data + PCIE_REG_DMA_ERR1_STATUS_MASK, 0x8000000000000000ull);
+
+       /* Enable UTL errors, for now, all of them got to UTL irq 1
+        *
+        * We similarily mask one UTL error caused apparently during normal
+        * probing. We also mask the link up error
+        */
+       out_be64(hose->cfg_data + PCIE_UTL_SYS_BUS_AGENT_ERR_SEV, 0);
+       out_be64(hose->cfg_data + PCIE_UTL_RC_ERR_SEVERITY, 0);
+       out_be64(hose->cfg_data + PCIE_UTL_PCIE_PORT_ERROR_SEV, 0);
+       out_be64(hose->cfg_data + PCIE_UTL_SYS_BUS_AGENT_IRQ_EN, 0xffffffff00000000ull);
+       out_be64(hose->cfg_data + PCIE_UTL_PCIE_PORT_IRQ_EN, 0xff5fffff00000000ull);
+       out_be64(hose->cfg_data + PCIE_UTL_EP_ERR_IRQ_EN, 0xffffffff00000000ull);
+
+       DUMP_REG(PCIE_REG_IO_BASE_ADDR);
+       DUMP_REG(PCIE_REG_IO_BASE_MASK);
+       DUMP_REG(PCIE_REG_IO_START_ADDR);
+       DUMP_REG(PCIE_REG_M32A_BASE_ADDR);
+       DUMP_REG(PCIE_REG_M32A_BASE_MASK);
+       DUMP_REG(PCIE_REG_M32A_START_ADDR);
+       DUMP_REG(PCIE_REG_M32B_BASE_ADDR);
+       DUMP_REG(PCIE_REG_M32B_BASE_MASK);
+       DUMP_REG(PCIE_REG_M32B_START_ADDR);
+       DUMP_REG(PCIE_REG_M64_BASE_ADDR);
+       DUMP_REG(PCIE_REG_M64_BASE_MASK);
+       DUMP_REG(PCIE_REG_M64_START_ADDR);
+       DUMP_REG(PCIE_REG_PHB_CONFIG);
+}
+
+static void wsp_pci_wait_io_idle(struct wsp_phb *phb, unsigned long port)
+{
+       u64 val;
+       int i;
+
+       for (i = 0; i < 10000; i++) {
+               val = in_be64(phb->hose->cfg_data + 0xe08);
+               if ((val & 0x1900000000000000ull) == 0x0100000000000000ull)
+                       return;
+               udelay(1);
+       }
+       pr_warning("PCI IO timeout on domain %d port 0x%lx\n",
+                  phb->hose->global_number, port);
+}
+
+#define DEF_PCI_AC_RET_pio(name, ret, at, al, aa)              \
+static ret wsp_pci_##name at                                   \
+{                                                              \
+       struct iowa_bus *bus;                                   \
+       struct wsp_phb *phb;                                    \
+       unsigned long flags;                                    \
+       ret rval;                                               \
+       bus = iowa_pio_find_bus(aa);                            \
+       WARN_ON(!bus);                                          \
+       phb = bus->private;                                     \
+       spin_lock_irqsave(&phb->lock, flags);                   \
+       wsp_pci_wait_io_idle(phb, aa);                          \
+       rval = __do_##name al;                                  \
+       spin_unlock_irqrestore(&phb->lock, flags);              \
+       return rval;                                            \
+}
+
+#define DEF_PCI_AC_NORET_pio(name, at, al, aa)                 \
+static void wsp_pci_##name at                                  \
+{                                                              \
+       struct iowa_bus *bus;                                   \
+       struct wsp_phb *phb;                                    \
+       unsigned long flags;                                    \
+       bus = iowa_pio_find_bus(aa);                            \
+       WARN_ON(!bus);                                          \
+       phb = bus->private;                                     \
+       spin_lock_irqsave(&phb->lock, flags);                   \
+       wsp_pci_wait_io_idle(phb, aa);                          \
+       __do_##name al;                                         \
+       spin_unlock_irqrestore(&phb->lock, flags);              \
+}
+
+#define DEF_PCI_AC_RET_mem(name, ret, at, al, aa)
+#define DEF_PCI_AC_NORET_mem(name, at, al, aa)
+
+#define DEF_PCI_AC_RET(name, ret, at, al, space, aa)           \
+       DEF_PCI_AC_RET_##space(name, ret, at, al, aa)
+
+#define DEF_PCI_AC_NORET(name, at, al, space, aa)              \
+       DEF_PCI_AC_NORET_##space(name, at, al, aa)              \
+
+
+#include <asm/io-defs.h>
+
+#undef DEF_PCI_AC_RET
+#undef DEF_PCI_AC_NORET
+
+static struct ppc_pci_io wsp_pci_iops = {
+       .inb = wsp_pci_inb,
+       .inw = wsp_pci_inw,
+       .inl = wsp_pci_inl,
+       .outb = wsp_pci_outb,
+       .outw = wsp_pci_outw,
+       .outl = wsp_pci_outl,
+       .insb = wsp_pci_insb,
+       .insw = wsp_pci_insw,
+       .insl = wsp_pci_insl,
+       .outsb = wsp_pci_outsb,
+       .outsw = wsp_pci_outsw,
+       .outsl = wsp_pci_outsl,
+};
+
+static int __init wsp_setup_one_phb(struct device_node *np)
+{
+       struct pci_controller *hose;
+       struct wsp_phb *phb;
+
+       pr_info("PCI: Setting up PCIe host bridge 0x%s\n", np->full_name);
+
+       phb = zalloc_maybe_bootmem(sizeof(struct wsp_phb), GFP_KERNEL);
+       if (!phb)
+               return -ENOMEM;
+       hose = pcibios_alloc_controller(np);
+       if (!hose) {
+               /* Can't really free the phb */
+               return -ENOMEM;
+       }
+       hose->private_data = phb;
+       phb->hose = hose;
+
+       INIT_LIST_HEAD(&phb->dma_tables);
+       spin_lock_init(&phb->lock);
+
+       /* XXX Use bus-range property ? */
+       hose->first_busno = 0;
+       hose->last_busno = 0xff;
+
+       /* We use cfg_data as the address for the whole bridge MMIO space
+        */
+       hose->cfg_data = of_iomap(hose->dn, 0);
+
+       pr_debug("PCIe registers mapped at 0x%p\n", hose->cfg_data);
+
+       /* Get the ranges of the device-tree */
+       pci_process_bridge_OF_ranges(hose, np, 0);
+
+       /* XXX Force re-assigning of everything for now */
+       pci_add_flags(PCI_REASSIGN_ALL_BUS | PCI_REASSIGN_ALL_RSRC |
+                     PCI_ENABLE_PROC_DOMAINS);
+       pci_probe_only = 0;
+
+       /* Calculate how the TCE space is divided */
+       phb->dma32_base         = 0;
+       phb->dma32_num_regions  = NUM_DMA32_REGIONS;
+       if (phb->dma32_num_regions > MAX_TABLE_TVT_COUNT) {
+               pr_warning("IOMMU: Clamped to %d DMA32 regions\n",
+                          MAX_TABLE_TVT_COUNT);
+               phb->dma32_num_regions = MAX_TABLE_TVT_COUNT;
+       }
+       phb->dma32_region_size  = 0x80000000 / phb->dma32_num_regions;
+
+       BUG_ON(!is_power_of_2(phb->dma32_region_size));
+
+       /* Setup config ops */
+       hose->ops = &wsp_pcie_pci_ops;
+
+       /* Configure the HW */
+       wsp_pcie_configure_hw(hose);
+
+       /* Instanciate IO workarounds */
+       iowa_register_bus(hose, &wsp_pci_iops, NULL, phb);
+#ifdef CONFIG_PCI_MSI
+       wsp_setup_phb_msi(hose);
+#endif
+
+       /* Add to global list */
+       list_add(&phb->all, &wsp_phbs);
+
+       return 0;
+}
+
+void __init wsp_setup_pci(void)
+{
+       struct device_node *np;
+       int rc;
+
+       /* Find host bridges */
+       for_each_compatible_node(np, "pciex", PCIE_COMPATIBLE) {
+               rc = wsp_setup_one_phb(np);
+               if (rc)
+                       pr_err("Failed to setup PCIe bridge %s, rc=%d\n",
+                              np->full_name, rc);
+       }
+
+       /* Establish device-tree linkage */
+       pci_devs_phb_init();
+
+       /* Set DMA ops to use TCEs */
+       if (iommu_is_off) {
+               pr_info("PCI-E: Disabled TCEs, using direct DMA\n");
+               set_pci_dma_ops(&dma_direct_ops);
+       } else {
+               ppc_md.pci_dma_dev_setup = wsp_pci_dma_dev_setup;
+               ppc_md.tce_build = tce_build_wsp;
+               ppc_md.tce_free = tce_free_wsp;
+               set_pci_dma_ops(&dma_iommu_ops);
+       }
+}
+
+#define err_debug(fmt...)      pr_debug(fmt)
+//#define err_debug(fmt...)
+
+static int __init wsp_pci_get_err_irq_no_dt(struct device_node *np)
+{
+       const u32 *prop;
+       int hw_irq;
+
+       /* Ok, no interrupts property, let's try to find our child P2P */
+       np = of_get_next_child(np, NULL);
+       if (np == NULL)
+               return 0;
+
+       /* Grab it's interrupt map */
+       prop = of_get_property(np, "interrupt-map", NULL);
+       if (prop == NULL)
+               return 0;
+
+       /* Grab one of the interrupts in there, keep the low 4 bits */
+       hw_irq = prop[5] & 0xf;
+
+       /* 0..4 for PHB 0 and 5..9 for PHB 1 */
+       if (hw_irq < 5)
+               hw_irq = 4;
+       else
+               hw_irq = 9;
+       hw_irq |= prop[5] & ~0xf;
+
+       err_debug("PCI: Using 0x%x as error IRQ for %s\n",
+                 hw_irq, np->parent->full_name);
+       return irq_create_mapping(NULL, hw_irq);
+}
+
+static const struct {
+       u32 offset;
+       const char *name;
+} wsp_pci_regs[] = {
+#define DREG(x) { PCIE_REG_##x, #x }
+#define DUTL(x) { PCIE_UTL_##x, "UTL_" #x }
+       /* Architected registers except CONFIG_ and IODA
+         * to avoid side effects
+        */
+       DREG(DMA_CHAN_STATUS),
+       DREG(CPU_LOADSTORE_STATUS),
+       DREG(LOCK0),
+       DREG(LOCK1),
+       DREG(PHB_CONFIG),
+       DREG(IO_BASE_ADDR),
+       DREG(IO_BASE_MASK),
+       DREG(IO_START_ADDR),
+       DREG(M32A_BASE_ADDR),
+       DREG(M32A_BASE_MASK),
+       DREG(M32A_START_ADDR),
+       DREG(M32B_BASE_ADDR),
+       DREG(M32B_BASE_MASK),
+       DREG(M32B_START_ADDR),
+       DREG(M64_BASE_ADDR),
+       DREG(M64_BASE_MASK),
+       DREG(M64_START_ADDR),
+       DREG(TCE_KILL),
+       DREG(LOCK2),
+       DREG(PHB_GEN_CAP),
+       DREG(PHB_TCE_CAP),
+       DREG(PHB_IRQ_CAP),
+       DREG(PHB_EEH_CAP),
+       DREG(PAPR_ERR_INJ_CONTROL),
+       DREG(PAPR_ERR_INJ_ADDR),
+       DREG(PAPR_ERR_INJ_MASK),
+
+       /* UTL core regs */
+       DUTL(SYS_BUS_CONTROL),
+       DUTL(STATUS),
+       DUTL(SYS_BUS_AGENT_STATUS),
+       DUTL(SYS_BUS_AGENT_ERR_SEV),
+       DUTL(SYS_BUS_AGENT_IRQ_EN),
+       DUTL(SYS_BUS_BURST_SZ_CONF),
+       DUTL(REVISION_ID),
+       DUTL(OUT_POST_HDR_BUF_ALLOC),
+       DUTL(OUT_POST_DAT_BUF_ALLOC),
+       DUTL(IN_POST_HDR_BUF_ALLOC),
+       DUTL(IN_POST_DAT_BUF_ALLOC),
+       DUTL(OUT_NP_BUF_ALLOC),
+       DUTL(IN_NP_BUF_ALLOC),
+       DUTL(PCIE_TAGS_ALLOC),
+       DUTL(GBIF_READ_TAGS_ALLOC),
+
+       DUTL(PCIE_PORT_CONTROL),
+       DUTL(PCIE_PORT_STATUS),
+       DUTL(PCIE_PORT_ERROR_SEV),
+       DUTL(PCIE_PORT_IRQ_EN),
+       DUTL(RC_STATUS),
+       DUTL(RC_ERR_SEVERITY),
+       DUTL(RC_IRQ_EN),
+       DUTL(EP_STATUS),
+       DUTL(EP_ERR_SEVERITY),
+       DUTL(EP_ERR_IRQ_EN),
+       DUTL(PCI_PM_CTRL1),
+       DUTL(PCI_PM_CTRL2),
+
+       /* PCIe stack regs */
+       DREG(SYSTEM_CONFIG1),
+       DREG(SYSTEM_CONFIG2),
+       DREG(EP_SYSTEM_CONFIG),
+       DREG(EP_FLR),
+       DREG(EP_BAR_CONFIG),
+       DREG(LINK_CONFIG),
+       DREG(PM_CONFIG),
+       DREG(DLP_CONTROL),
+       DREG(DLP_STATUS),
+       DREG(ERR_REPORT_CONTROL),
+       DREG(SLOT_CONTROL1),
+       DREG(SLOT_CONTROL2),
+       DREG(UTL_CONFIG),
+       DREG(BUFFERS_CONFIG),
+       DREG(ERROR_INJECT),
+       DREG(SRIOV_CONFIG),
+       DREG(PF0_SRIOV_STATUS),
+       DREG(PF1_SRIOV_STATUS),
+       DREG(PORT_NUMBER),
+       DREG(POR_SYSTEM_CONFIG),
+
+       /* Internal logic regs */
+       DREG(PHB_VERSION),
+       DREG(RESET),
+       DREG(PHB_CONTROL),
+       DREG(PHB_TIMEOUT_CONTROL1),
+       DREG(PHB_QUIESCE_DMA),
+       DREG(PHB_DMA_READ_TAG_ACTV),
+       DREG(PHB_TCE_READ_TAG_ACTV),
+
+       /* FIR registers */
+       DREG(LEM_FIR_ACCUM),
+       DREG(LEM_FIR_AND_MASK),
+       DREG(LEM_FIR_OR_MASK),
+       DREG(LEM_ACTION0),
+       DREG(LEM_ACTION1),
+       DREG(LEM_ERROR_MASK),
+       DREG(LEM_ERROR_AND_MASK),
+       DREG(LEM_ERROR_OR_MASK),
+
+       /* Error traps registers */
+       DREG(PHB_ERR_STATUS),
+       DREG(PHB_ERR_STATUS),
+       DREG(PHB_ERR1_STATUS),
+       DREG(PHB_ERR_INJECT),
+       DREG(PHB_ERR_LEM_ENABLE),
+       DREG(PHB_ERR_IRQ_ENABLE),
+       DREG(PHB_ERR_FREEZE_ENABLE),
+       DREG(PHB_ERR_SIDE_ENABLE),
+       DREG(PHB_ERR_LOG_0),
+       DREG(PHB_ERR_LOG_1),
+       DREG(PHB_ERR_STATUS_MASK),
+       DREG(PHB_ERR1_STATUS_MASK),
+       DREG(MMIO_ERR_STATUS),
+       DREG(MMIO_ERR1_STATUS),
+       DREG(MMIO_ERR_INJECT),
+       DREG(MMIO_ERR_LEM_ENABLE),
+       DREG(MMIO_ERR_IRQ_ENABLE),
+       DREG(MMIO_ERR_FREEZE_ENABLE),
+       DREG(MMIO_ERR_SIDE_ENABLE),
+       DREG(MMIO_ERR_LOG_0),
+       DREG(MMIO_ERR_LOG_1),
+       DREG(MMIO_ERR_STATUS_MASK),
+       DREG(MMIO_ERR1_STATUS_MASK),
+       DREG(DMA_ERR_STATUS),
+       DREG(DMA_ERR1_STATUS),
+       DREG(DMA_ERR_INJECT),
+       DREG(DMA_ERR_LEM_ENABLE),
+       DREG(DMA_ERR_IRQ_ENABLE),
+       DREG(DMA_ERR_FREEZE_ENABLE),
+       DREG(DMA_ERR_SIDE_ENABLE),
+       DREG(DMA_ERR_LOG_0),
+       DREG(DMA_ERR_LOG_1),
+       DREG(DMA_ERR_STATUS_MASK),
+       DREG(DMA_ERR1_STATUS_MASK),
+
+       /* Debug and Trace registers */
+       DREG(PHB_DEBUG_CONTROL0),
+       DREG(PHB_DEBUG_STATUS0),
+       DREG(PHB_DEBUG_CONTROL1),
+       DREG(PHB_DEBUG_STATUS1),
+       DREG(PHB_DEBUG_CONTROL2),
+       DREG(PHB_DEBUG_STATUS2),
+       DREG(PHB_DEBUG_CONTROL3),
+       DREG(PHB_DEBUG_STATUS3),
+       DREG(PHB_DEBUG_CONTROL4),
+       DREG(PHB_DEBUG_STATUS4),
+       DREG(PHB_DEBUG_CONTROL5),
+       DREG(PHB_DEBUG_STATUS5),
+
+       /* Don't seem to exist ...
+       DREG(PHB_DEBUG_CONTROL6),
+       DREG(PHB_DEBUG_STATUS6),
+       */
+};
+
+static int wsp_pci_regs_show(struct seq_file *m, void *private)
+{
+       struct wsp_phb *phb = m->private;
+       struct pci_controller *hose = phb->hose;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(wsp_pci_regs); i++) {
+               /* Skip write-only regs */
+               if (wsp_pci_regs[i].offset == 0xc08 ||
+                   wsp_pci_regs[i].offset == 0xc10 ||
+                   wsp_pci_regs[i].offset == 0xc38 ||
+                   wsp_pci_regs[i].offset == 0xc40)
+                       continue;
+               seq_printf(m, "0x%03x: 0x%016llx %s\n",
+                          wsp_pci_regs[i].offset,
+                          in_be64(hose->cfg_data + wsp_pci_regs[i].offset),
+                          wsp_pci_regs[i].name);
+       }
+       return 0;
+}
+
+static int wsp_pci_regs_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, wsp_pci_regs_show, inode->i_private);
+}
+
+static const struct file_operations wsp_pci_regs_fops = {
+       .open = wsp_pci_regs_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release,
+};
+
+static int wsp_pci_reg_set(void *data, u64 val)
+{
+       out_be64((void __iomem *)data, val);
+       return 0;
+}
+
+static int wsp_pci_reg_get(void *data, u64 *val)
+{
+       *val = in_be64((void __iomem *)data);
+       return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(wsp_pci_reg_fops, wsp_pci_reg_get, wsp_pci_reg_set, "0x%llx\n");
+
+static irqreturn_t wsp_pci_err_irq(int irq, void *dev_id)
+{
+       struct wsp_phb *phb = dev_id;
+       struct pci_controller *hose = phb->hose;
+       irqreturn_t handled = IRQ_NONE;
+       struct wsp_pcie_err_log_data ed;
+
+       pr_err("PCI: Error interrupt on %s (PHB %d)\n",
+              hose->dn->full_name, hose->global_number);
+ again:
+       memset(&ed, 0, sizeof(ed));
+
+       /* Read and clear UTL errors */
+       ed.utl_sys_err = in_be64(hose->cfg_data + PCIE_UTL_SYS_BUS_AGENT_STATUS);
+       if (ed.utl_sys_err)
+               out_be64(hose->cfg_data + PCIE_UTL_SYS_BUS_AGENT_STATUS, ed.utl_sys_err);
+       ed.utl_port_err = in_be64(hose->cfg_data + PCIE_UTL_PCIE_PORT_STATUS);
+       if (ed.utl_port_err)
+               out_be64(hose->cfg_data + PCIE_UTL_PCIE_PORT_STATUS, ed.utl_port_err);
+       ed.utl_rc_err = in_be64(hose->cfg_data + PCIE_UTL_RC_STATUS);
+       if (ed.utl_rc_err)
+               out_be64(hose->cfg_data + PCIE_UTL_RC_STATUS, ed.utl_rc_err);
+
+       /* Read and clear main trap errors */
+       ed.phb_err = in_be64(hose->cfg_data + PCIE_REG_PHB_ERR_STATUS);
+       if (ed.phb_err) {
+               ed.phb_err1 = in_be64(hose->cfg_data + PCIE_REG_PHB_ERR1_STATUS);
+               ed.phb_log0 = in_be64(hose->cfg_data + PCIE_REG_PHB_ERR_LOG_0);
+               ed.phb_log1 = in_be64(hose->cfg_data + PCIE_REG_PHB_ERR_LOG_1);
+               out_be64(hose->cfg_data + PCIE_REG_PHB_ERR1_STATUS, 0);
+               out_be64(hose->cfg_data + PCIE_REG_PHB_ERR_STATUS, 0);
+       }
+       ed.mmio_err = in_be64(hose->cfg_data + PCIE_REG_MMIO_ERR_STATUS);
+       if (ed.mmio_err) {
+               ed.mmio_err1 = in_be64(hose->cfg_data + PCIE_REG_MMIO_ERR1_STATUS);
+               ed.mmio_log0 = in_be64(hose->cfg_data + PCIE_REG_MMIO_ERR_LOG_0);
+               ed.mmio_log1 = in_be64(hose->cfg_data + PCIE_REG_MMIO_ERR_LOG_1);
+               out_be64(hose->cfg_data + PCIE_REG_MMIO_ERR1_STATUS, 0);
+               out_be64(hose->cfg_data + PCIE_REG_MMIO_ERR_STATUS, 0);
+       }
+       ed.dma_err = in_be64(hose->cfg_data + PCIE_REG_DMA_ERR_STATUS);
+       if (ed.dma_err) {
+               ed.dma_err1 = in_be64(hose->cfg_data + PCIE_REG_DMA_ERR1_STATUS);
+               ed.dma_log0 = in_be64(hose->cfg_data + PCIE_REG_DMA_ERR_LOG_0);
+               ed.dma_log1 = in_be64(hose->cfg_data + PCIE_REG_DMA_ERR_LOG_1);
+               out_be64(hose->cfg_data + PCIE_REG_DMA_ERR1_STATUS, 0);
+               out_be64(hose->cfg_data + PCIE_REG_DMA_ERR_STATUS, 0);
+       }
+
+       /* Now print things out */
+       if (ed.phb_err) {
+               pr_err("   PHB Error Status      : 0x%016llx\n", ed.phb_err);
+               pr_err("   PHB First Error Status: 0x%016llx\n", ed.phb_err1);
+               pr_err("   PHB Error Log 0       : 0x%016llx\n", ed.phb_log0);
+               pr_err("   PHB Error Log 1       : 0x%016llx\n", ed.phb_log1);
+       }
+       if (ed.mmio_err) {
+               pr_err("  MMIO Error Status      : 0x%016llx\n", ed.mmio_err);
+               pr_err("  MMIO First Error Status: 0x%016llx\n", ed.mmio_err1);
+               pr_err("  MMIO Error Log 0       : 0x%016llx\n", ed.mmio_log0);
+               pr_err("  MMIO Error Log 1       : 0x%016llx\n", ed.mmio_log1);
+       }
+       if (ed.dma_err) {
+               pr_err("   DMA Error Status      : 0x%016llx\n", ed.dma_err);
+               pr_err("   DMA First Error Status: 0x%016llx\n", ed.dma_err1);
+               pr_err("   DMA Error Log 0       : 0x%016llx\n", ed.dma_log0);
+               pr_err("   DMA Error Log 1       : 0x%016llx\n", ed.dma_log1);
+       }
+       if (ed.utl_sys_err)
+               pr_err("   UTL Sys Error Status  : 0x%016llx\n", ed.utl_sys_err);
+       if (ed.utl_port_err)
+               pr_err("   UTL Port Error Status : 0x%016llx\n", ed.utl_port_err);
+       if (ed.utl_rc_err)
+               pr_err("   UTL RC Error Status   : 0x%016llx\n", ed.utl_rc_err);
+
+       /* Interrupts are caused by the error traps. If we had any error there
+        * we loop again in case the UTL buffered some new stuff between
+        * going there and going to the traps
+        */
+       if (ed.dma_err || ed.mmio_err || ed.phb_err) {
+               handled = IRQ_HANDLED;
+               goto again;
+       }
+       return handled;
+}
+
+static void __init wsp_setup_pci_err_reporting(struct wsp_phb *phb)
+{
+       struct pci_controller *hose = phb->hose;
+       int err_irq, i, rc;
+       char fname[16];
+
+       /* Create a debugfs file for that PHB */
+       sprintf(fname, "phb%d", phb->hose->global_number);
+       phb->ddir = debugfs_create_dir(fname, powerpc_debugfs_root);
+
+       /* Some useful debug output */
+       if (phb->ddir) {
+               struct dentry *d = debugfs_create_dir("regs", phb->ddir);
+               char tmp[64];
+
+               for (i = 0; i < ARRAY_SIZE(wsp_pci_regs); i++) {
+                       sprintf(tmp, "%03x_%s", wsp_pci_regs[i].offset,
+                               wsp_pci_regs[i].name);
+                       debugfs_create_file(tmp, 0600, d,
+                                           hose->cfg_data + wsp_pci_regs[i].offset,
+                                           &wsp_pci_reg_fops);
+               }
+               debugfs_create_file("all_regs", 0600, phb->ddir, phb, &wsp_pci_regs_fops);
+       }
+
+       /* Find the IRQ number for that PHB */
+       err_irq = irq_of_parse_and_map(hose->dn, 0);
+       if (err_irq == 0)
+               /* XXX Error IRQ lacking from device-tree */
+               err_irq = wsp_pci_get_err_irq_no_dt(hose->dn);
+       if (err_irq == 0) {
+               pr_err("PCI: Failed to fetch error interrupt for %s\n",
+                      hose->dn->full_name);
+               return;
+       }
+       /* Request it */
+       rc = request_irq(err_irq, wsp_pci_err_irq, 0, "wsp_pci error", phb);
+       if (rc) {
+               pr_err("PCI: Failed to request interrupt for %s\n",
+                      hose->dn->full_name);
+       }
+       /* Enable interrupts for all errors for now */
+       out_be64(hose->cfg_data + PCIE_REG_PHB_ERR_IRQ_ENABLE, 0xffffffffffffffffull);
+       out_be64(hose->cfg_data + PCIE_REG_MMIO_ERR_IRQ_ENABLE, 0xffffffffffffffffull);
+       out_be64(hose->cfg_data + PCIE_REG_DMA_ERR_IRQ_ENABLE, 0xffffffffffffffffull);
+}
+
+/*
+ * This is called later to hookup with the error interrupt
+ */
+static int __init wsp_setup_pci_late(void)
+{
+       struct wsp_phb *phb;
+
+       list_for_each_entry(phb, &wsp_phbs, all)
+               wsp_setup_pci_err_reporting(phb);
+
+       return 0;
+}
+arch_initcall(wsp_setup_pci_late);
diff --git a/arch/powerpc/platforms/wsp/wsp_pci.h b/arch/powerpc/platforms/wsp/wsp_pci.h
new file mode 100644 (file)
index 0000000..52e9bd9
--- /dev/null
@@ -0,0 +1,268 @@
+/*
+ * Copyright 2010 Ben Herrenschmidt, IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef __WSP_PCI_H
+#define __WSP_PCI_H
+
+/* Architected registers */
+#define PCIE_REG_DMA_CHAN_STATUS       0x110
+#define PCIE_REG_CPU_LOADSTORE_STATUS  0x120
+
+#define PCIE_REG_CONFIG_DATA           0x130
+#define PCIE_REG_LOCK0                 0x138
+#define PCIE_REG_CONFIG_ADDRESS                0x140
+#define   PCIE_REG_CA_ENABLE                   0x8000000000000000ull
+#define          PCIE_REG_CA_BUS_MASK                  0x0ff0000000000000ull
+#define   PCIE_REG_CA_BUS_SHIFT                        (20+32)
+#define   PCIE_REG_CA_DEV_MASK                 0x000f800000000000ull
+#define   PCIE_REG_CA_DEV_SHIFT                        (15+32)
+#define   PCIE_REG_CA_FUNC_MASK                        0x0000700000000000ull
+#define   PCIE_REG_CA_FUNC_SHIFT               (12+32)
+#define   PCIE_REG_CA_REG_MASK                 0x00000fff00000000ull
+#define   PCIE_REG_CA_REG_SHIFT                        ( 0+32)
+#define   PCIE_REG_CA_BE_MASK                  0x00000000f0000000ull
+#define   PCIE_REG_CA_BE_SHIFT                 (   28)
+#define PCIE_REG_LOCK1                 0x148
+
+#define PCIE_REG_PHB_CONFIG            0x160
+#define   PCIE_REG_PHBC_64B_TCE_EN             0x2000000000000000ull
+#define   PCIE_REG_PHBC_MMIO_DMA_FREEZE_EN     0x1000000000000000ull
+#define   PCIE_REG_PHBC_32BIT_MSI_EN           0x0080000000000000ull
+#define   PCIE_REG_PHBC_M64_EN                 0x0040000000000000ull
+#define   PCIE_REG_PHBC_IO_EN                  0x0008000000000000ull
+#define   PCIE_REG_PHBC_64BIT_MSI_EN           0x0002000000000000ull
+#define   PCIE_REG_PHBC_M32A_EN                        0x0000800000000000ull
+#define   PCIE_REG_PHBC_M32B_EN                        0x0000400000000000ull
+#define   PCIE_REG_PHBC_MSI_PE_VALIDATE                0x0000200000000000ull
+#define   PCIE_REG_PHBC_DMA_XLATE_BYPASS       0x0000100000000000ull
+
+#define PCIE_REG_IO_BASE_ADDR          0x170
+#define PCIE_REG_IO_BASE_MASK          0x178
+#define PCIE_REG_IO_START_ADDR         0x180
+
+#define PCIE_REG_M32A_BASE_ADDR                0x190
+#define PCIE_REG_M32A_BASE_MASK                0x198
+#define PCIE_REG_M32A_START_ADDR       0x1a0
+
+#define PCIE_REG_M32B_BASE_ADDR                0x1b0
+#define PCIE_REG_M32B_BASE_MASK                0x1b8
+#define PCIE_REG_M32B_START_ADDR       0x1c0
+
+#define PCIE_REG_M64_BASE_ADDR         0x1e0
+#define PCIE_REG_M64_BASE_MASK         0x1e8
+#define PCIE_REG_M64_START_ADDR                0x1f0
+
+#define PCIE_REG_TCE_KILL              0x210
+#define   PCIE_REG_TCEKILL_SINGLE      0x8000000000000000ull
+#define   PCIE_REG_TCEKILL_ADDR_MASK   0x000003fffffffff8ull
+#define   PCIE_REG_TCEKILL_PS_4K       0
+#define   PCIE_REG_TCEKILL_PS_64K      1
+#define   PCIE_REG_TCEKILL_PS_16M      2
+#define   PCIE_REG_TCEKILL_PS_16G      3
+
+#define PCIE_REG_IODA_ADDR             0x220
+#define   PCIE_REG_IODA_AD_AUTOINC     0x8000000000000000ull
+#define   PCIE_REG_IODA_AD_TBL_MVT     0x0005000000000000ull
+#define   PCIE_REG_IODA_AD_TBL_PELT    0x0006000000000000ull
+#define   PCIE_REG_IODA_AD_TBL_PESTA   0x0007000000000000ull
+#define   PCIE_REG_IODA_AD_TBL_PESTB   0x0008000000000000ull
+#define   PCIE_REG_IODA_AD_TBL_TVT     0x0009000000000000ull
+#define   PCIE_REG_IODA_AD_TBL_TCE     0x000a000000000000ull
+#define PCIE_REG_IODA_DATA0            0x228
+#define PCIE_REG_IODA_DATA1            0x230
+
+#define PCIE_REG_LOCK2                 0x240
+
+#define PCIE_REG_PHB_GEN_CAP           0x250
+#define PCIE_REG_PHB_TCE_CAP           0x258
+#define PCIE_REG_PHB_IRQ_CAP           0x260
+#define PCIE_REG_PHB_EEH_CAP           0x268
+
+#define PCIE_REG_PAPR_ERR_INJ_CONTROL  0x2b0
+#define PCIE_REG_PAPR_ERR_INJ_ADDR     0x2b8
+#define PCIE_REG_PAPR_ERR_INJ_MASK     0x2c0
+
+
+#define PCIE_REG_SYS_CFG1              0x600
+#define   PCIE_REG_SYS_CFG1_CLASS_CODE 0x0000000000ffffffull
+
+#define IODA_TVT0_TTA_MASK             0x000fffffffff0000ull
+#define IODA_TVT0_TTA_SHIFT            4
+#define IODA_TVT0_BUSNUM_VALID_MASK    0x000000000000e000ull
+#define IODA_TVT0_TCE_TABLE_SIZE_MASK  0x0000000000001f00ull
+#define IODA_TVT0_TCE_TABLE_SIZE_SHIFT 8
+#define IODA_TVT0_BUSNUM_VALUE_MASK    0x00000000000000ffull
+#define IODA_TVT0_BUSNUM_VALID_SHIFT   0
+#define IODA_TVT1_DEVNUM_VALID         0x2000000000000000ull
+#define IODA_TVT1_DEVNUM_VALUE_MASK    0x1f00000000000000ull
+#define IODA_TVT1_DEVNUM_VALUE_SHIFT   56
+#define IODA_TVT1_FUNCNUM_VALID                0x0008000000000000ull
+#define IODA_TVT1_FUNCNUM_VALUE_MASK   0x0007000000000000ull
+#define IODA_TVT1_FUNCNUM_VALUE_SHIFT  48
+#define IODA_TVT1_IO_PAGE_SIZE_MASK    0x00001f0000000000ull
+#define IODA_TVT1_IO_PAGE_SIZE_SHIFT   40
+#define IODA_TVT1_PE_NUMBER_MASK       0x000000000000003full
+#define IODA_TVT1_PE_NUMBER_SHIFT      0
+
+#define IODA_TVT_COUNT                 64
+
+/* UTL Core registers */
+#define PCIE_UTL_SYS_BUS_CONTROL       0x400
+#define PCIE_UTL_STATUS                        0x408
+#define PCIE_UTL_SYS_BUS_AGENT_STATUS  0x410
+#define PCIE_UTL_SYS_BUS_AGENT_ERR_SEV 0x418
+#define PCIE_UTL_SYS_BUS_AGENT_IRQ_EN  0x420
+#define PCIE_UTL_SYS_BUS_BURST_SZ_CONF 0x440
+#define PCIE_UTL_REVISION_ID           0x448
+
+#define PCIE_UTL_OUT_POST_HDR_BUF_ALLOC        0x4c0
+#define PCIE_UTL_OUT_POST_DAT_BUF_ALLOC        0x4d0
+#define PCIE_UTL_IN_POST_HDR_BUF_ALLOC 0x4e0
+#define PCIE_UTL_IN_POST_DAT_BUF_ALLOC 0x4f0
+#define PCIE_UTL_OUT_NP_BUF_ALLOC      0x500
+#define PCIE_UTL_IN_NP_BUF_ALLOC       0x510
+#define PCIE_UTL_PCIE_TAGS_ALLOC       0x520
+#define PCIE_UTL_GBIF_READ_TAGS_ALLOC  0x530
+
+#define PCIE_UTL_PCIE_PORT_CONTROL     0x540
+#define PCIE_UTL_PCIE_PORT_STATUS      0x548
+#define PCIE_UTL_PCIE_PORT_ERROR_SEV   0x550
+#define PCIE_UTL_PCIE_PORT_IRQ_EN      0x558
+#define PCIE_UTL_RC_STATUS             0x560
+#define PCIE_UTL_RC_ERR_SEVERITY       0x568
+#define PCIE_UTL_RC_IRQ_EN             0x570
+#define PCIE_UTL_EP_STATUS             0x578
+#define PCIE_UTL_EP_ERR_SEVERITY       0x580
+#define PCIE_UTL_EP_ERR_IRQ_EN         0x588
+
+#define PCIE_UTL_PCI_PM_CTRL1          0x590
+#define PCIE_UTL_PCI_PM_CTRL2          0x598
+
+/* PCIe stack registers */
+#define PCIE_REG_SYSTEM_CONFIG1                0x600
+#define PCIE_REG_SYSTEM_CONFIG2                0x608
+#define PCIE_REG_EP_SYSTEM_CONFIG      0x618
+#define PCIE_REG_EP_FLR                        0x620
+#define PCIE_REG_EP_BAR_CONFIG         0x628
+#define PCIE_REG_LINK_CONFIG           0x630
+#define PCIE_REG_PM_CONFIG             0x640
+#define PCIE_REG_DLP_CONTROL           0x650
+#define PCIE_REG_DLP_STATUS            0x658
+#define PCIE_REG_ERR_REPORT_CONTROL    0x660
+#define PCIE_REG_SLOT_CONTROL1         0x670
+#define PCIE_REG_SLOT_CONTROL2         0x678
+#define PCIE_REG_UTL_CONFIG            0x680
+#define PCIE_REG_BUFFERS_CONFIG                0x690
+#define PCIE_REG_ERROR_INJECT          0x698
+#define PCIE_REG_SRIOV_CONFIG          0x6a0
+#define PCIE_REG_PF0_SRIOV_STATUS      0x6a8
+#define PCIE_REG_PF1_SRIOV_STATUS      0x6b0
+#define PCIE_REG_PORT_NUMBER           0x700
+#define PCIE_REG_POR_SYSTEM_CONFIG     0x708
+
+/* PHB internal logic registers */
+#define PCIE_REG_PHB_VERSION           0x800
+#define PCIE_REG_RESET                 0x808
+#define PCIE_REG_PHB_CONTROL           0x810
+#define PCIE_REG_PHB_TIMEOUT_CONTROL1  0x878
+#define PCIE_REG_PHB_QUIESCE_DMA       0x888
+#define PCIE_REG_PHB_DMA_READ_TAG_ACTV 0x900
+#define PCIE_REG_PHB_TCE_READ_TAG_ACTV 0x908
+
+/* FIR registers */
+#define PCIE_REG_LEM_FIR_ACCUM         0xc00
+#define PCIE_REG_LEM_FIR_AND_MASK      0xc08
+#define PCIE_REG_LEM_FIR_OR_MASK       0xc10
+#define PCIE_REG_LEM_ACTION0           0xc18
+#define PCIE_REG_LEM_ACTION1           0xc20
+#define PCIE_REG_LEM_ERROR_MASK                0xc30
+#define PCIE_REG_LEM_ERROR_AND_MASK    0xc38
+#define PCIE_REG_LEM_ERROR_OR_MASK     0xc40
+
+/* PHB Error registers */
+#define PCIE_REG_PHB_ERR_STATUS                0xc80
+#define PCIE_REG_PHB_ERR1_STATUS       0xc88
+#define PCIE_REG_PHB_ERR_INJECT                0xc90
+#define PCIE_REG_PHB_ERR_LEM_ENABLE    0xc98
+#define PCIE_REG_PHB_ERR_IRQ_ENABLE    0xca0
+#define PCIE_REG_PHB_ERR_FREEZE_ENABLE 0xca8
+#define PCIE_REG_PHB_ERR_SIDE_ENABLE   0xcb8
+#define PCIE_REG_PHB_ERR_LOG_0         0xcc0
+#define PCIE_REG_PHB_ERR_LOG_1         0xcc8
+#define PCIE_REG_PHB_ERR_STATUS_MASK   0xcd0
+#define PCIE_REG_PHB_ERR1_STATUS_MASK  0xcd8
+
+#define PCIE_REG_MMIO_ERR_STATUS       0xd00
+#define PCIE_REG_MMIO_ERR1_STATUS      0xd08
+#define PCIE_REG_MMIO_ERR_INJECT       0xd10
+#define PCIE_REG_MMIO_ERR_LEM_ENABLE   0xd18
+#define PCIE_REG_MMIO_ERR_IRQ_ENABLE   0xd20
+#define PCIE_REG_MMIO_ERR_FREEZE_ENABLE        0xd28
+#define PCIE_REG_MMIO_ERR_SIDE_ENABLE  0xd38
+#define PCIE_REG_MMIO_ERR_LOG_0                0xd40
+#define PCIE_REG_MMIO_ERR_LOG_1                0xd48
+#define PCIE_REG_MMIO_ERR_STATUS_MASK  0xd50
+#define PCIE_REG_MMIO_ERR1_STATUS_MASK 0xd58
+
+#define PCIE_REG_DMA_ERR_STATUS                0xd80
+#define PCIE_REG_DMA_ERR1_STATUS       0xd88
+#define PCIE_REG_DMA_ERR_INJECT                0xd90
+#define PCIE_REG_DMA_ERR_LEM_ENABLE    0xd98
+#define PCIE_REG_DMA_ERR_IRQ_ENABLE    0xda0
+#define PCIE_REG_DMA_ERR_FREEZE_ENABLE 0xda8
+#define PCIE_REG_DMA_ERR_SIDE_ENABLE   0xdb8
+#define PCIE_REG_DMA_ERR_LOG_0         0xdc0
+#define PCIE_REG_DMA_ERR_LOG_1         0xdc8
+#define PCIE_REG_DMA_ERR_STATUS_MASK   0xdd0
+#define PCIE_REG_DMA_ERR1_STATUS_MASK  0xdd8
+
+/* Shortcuts for access to the above using the PHB definitions
+ * with an offset
+ */
+#define PCIE_REG_ERR_PHB_OFFSET                0x0
+#define PCIE_REG_ERR_MMIO_OFFSET       0x80
+#define PCIE_REG_ERR_DMA_OFFSET                0x100
+
+/* Debug and Trace registers */
+#define PCIE_REG_PHB_DEBUG_CONTROL0    0xe00
+#define PCIE_REG_PHB_DEBUG_STATUS0     0xe08
+#define PCIE_REG_PHB_DEBUG_CONTROL1    0xe10
+#define PCIE_REG_PHB_DEBUG_STATUS1     0xe18
+#define PCIE_REG_PHB_DEBUG_CONTROL2    0xe20
+#define PCIE_REG_PHB_DEBUG_STATUS2     0xe28
+#define PCIE_REG_PHB_DEBUG_CONTROL3    0xe30
+#define PCIE_REG_PHB_DEBUG_STATUS3     0xe38
+#define PCIE_REG_PHB_DEBUG_CONTROL4    0xe40
+#define PCIE_REG_PHB_DEBUG_STATUS4     0xe48
+#define PCIE_REG_PHB_DEBUG_CONTROL5    0xe50
+#define PCIE_REG_PHB_DEBUG_STATUS5     0xe58
+#define PCIE_REG_PHB_DEBUG_CONTROL6    0xe60
+#define PCIE_REG_PHB_DEBUG_STATUS6     0xe68
+
+/* Definition for PCIe errors */
+struct wsp_pcie_err_log_data {
+       __u64   phb_err;
+       __u64   phb_err1;
+       __u64   phb_log0;
+       __u64   phb_log1;
+       __u64   mmio_err;
+       __u64   mmio_err1;
+       __u64   mmio_log0;
+       __u64   mmio_log1;
+       __u64   dma_err;
+       __u64   dma_err1;
+       __u64   dma_log0;
+       __u64   dma_log1;
+       __u64   utl_sys_err;
+       __u64   utl_port_err;
+       __u64   utl_rc_err;
+       __u64   unused;
+};
+
+#endif /* __WSP_PCI_H */
index cf736ca..84e1325 100644 (file)
@@ -18,7 +18,6 @@ obj-$(CONFIG_FSL_PCI)         += fsl_pci.o $(fsl-msi-obj-y)
 obj-$(CONFIG_FSL_PMC)          += fsl_pmc.o
 obj-$(CONFIG_FSL_LBC)          += fsl_lbc.o
 obj-$(CONFIG_FSL_GTM)          += fsl_gtm.o
-obj-$(CONFIG_MPC8xxx_GPIO)     += mpc8xxx_gpio.o
 obj-$(CONFIG_FSL_85XX_CACHE_SRAM)      += fsl_85xx_l2ctlr.o fsl_85xx_cache_sram.o
 obj-$(CONFIG_SIMPLE_GPIO)      += simple_gpio.o
 obj-$(CONFIG_FSL_RIO)          += fsl_rio.o
index 265f0f0..ba42719 100644 (file)
@@ -104,7 +104,7 @@ axon_ram_irq_handler(int irq, void *dev)
  * axon_ram_make_request - make_request() method for block device
  * @queue, @bio: see blk_queue_make_request()
  */
-static int
+static void
 axon_ram_make_request(struct request_queue *queue, struct bio *bio)
 {
        struct axon_ram_bank *bank = bio->bi_bdev->bd_disk->private_data;
@@ -113,7 +113,6 @@ axon_ram_make_request(struct request_queue *queue, struct bio *bio)
        struct bio_vec *vec;
        unsigned int transfered;
        unsigned short idx;
-       int rc = 0;
 
        phys_mem = bank->io_addr + (bio->bi_sector << AXON_RAM_SECTOR_SHIFT);
        phys_end = bank->io_addr + bank->size;
@@ -121,8 +120,7 @@ axon_ram_make_request(struct request_queue *queue, struct bio *bio)
        bio_for_each_segment(vec, bio, idx) {
                if (unlikely(phys_mem + vec->bv_len > phys_end)) {
                        bio_io_error(bio);
-                       rc = -ERANGE;
-                       break;
+                       return;
                }
 
                user_mem = page_address(vec->bv_page) + vec->bv_offset;
@@ -135,8 +133,6 @@ axon_ram_make_request(struct request_queue *queue, struct bio *bio)
                transfered += vec->bv_len;
        }
        bio_endio(bio, 0);
-
-       return rc;
 }
 
 /**
index d55d0ad..8db10bb 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Author: Scott Wood <scottwood@freescale.com>
  *
- * Copyright 2007 Freescale Semiconductor, Inc.
+ * Copyright 2007-2008,2010 Freescale Semiconductor, Inc.
  *
  * Some parts derived from commproc.c/cpm2_common.c, which is:
  * Copyright (c) 1997 Dan error_act (dmalek@jlc.net)
@@ -146,6 +146,7 @@ unsigned long cpm_muram_alloc(unsigned long size, unsigned long align)
        spin_lock_irqsave(&cpm_muram_lock, flags);
        cpm_muram_info.alignment = align;
        start = rh_alloc(&cpm_muram_info, size, "commproc");
+       memset(cpm_muram_addr(start), 0, size);
        spin_unlock_irqrestore(&cpm_muram_lock, flags);
 
        return start;
index 419a772..e5c344d 100644 (file)
@@ -30,7 +30,7 @@ LIST_HEAD(msi_head);
 
 struct fsl_msi_feature {
        u32 fsl_pic_ip;
-       u32 msiir_offset;
+       u32 msiir_offset; /* Offset of MSIIR, relative to start of MSIR bank */
 };
 
 struct fsl_msi_cascade_data {
@@ -126,10 +126,19 @@ static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq,
 {
        struct fsl_msi *msi_data = fsl_msi_data;
        struct pci_controller *hose = pci_bus_to_host(pdev->bus);
-       u64 base = fsl_pci_immrbar_base(hose);
+       u64 address; /* Physical address of the MSIIR */
+       int len;
+       const u64 *reg;
+
+       /* If the msi-address-64 property exists, then use it */
+       reg = of_get_property(hose->dn, "msi-address-64", &len);
+       if (reg && (len == sizeof(u64)))
+               address = be64_to_cpup(reg);
+       else
+               address = fsl_pci_immrbar_base(hose) + msi_data->msiir_offset;
 
-       msg->address_lo = msi_data->msi_addr_lo + lower_32_bits(base);
-       msg->address_hi = msi_data->msi_addr_hi + upper_32_bits(base);
+       msg->address_lo = lower_32_bits(address);
+       msg->address_hi = upper_32_bits(address);
 
        msg->data = hwirq;
 
@@ -296,7 +305,7 @@ static int __devinit fsl_msi_setup_hwirq(struct fsl_msi *msi,
        }
 
        msi->msi_virqs[irq_index] = virt_msir;
-       cascade_data->index = offset + irq_index;
+       cascade_data->index = offset;
        cascade_data->msi_data = msi;
        irq_set_handler_data(virt_msir, cascade_data);
        irq_set_chained_handler(virt_msir, fsl_msi_cascade);
@@ -359,8 +368,7 @@ static int __devinit fsl_of_msi_probe(struct platform_device *dev)
 
        msi->irqhost->host_data = msi;
 
-       msi->msi_addr_hi = 0x0;
-       msi->msi_addr_lo = features->msiir_offset + (res.start & 0xfffff);
+       msi->msiir_offset = features->msiir_offset + (res.start & 0xfffff);
 
        rc = fsl_msi_init_allocator(msi);
        if (rc) {
@@ -376,8 +384,10 @@ static int __devinit fsl_of_msi_probe(struct platform_device *dev)
                goto error_out;
        }
 
-       if (!p)
+       if (!p) {
                p = all_avail;
+               len = sizeof(all_avail);
+       }
 
        for (irq_index = 0, i = 0; i < len / (2 * sizeof(u32)); i++) {
                if (p[i * 2] % IRQS_PER_MSI_REG ||
@@ -393,7 +403,7 @@ static int __devinit fsl_of_msi_probe(struct platform_device *dev)
                count = p[i * 2 + 1] / IRQS_PER_MSI_REG;
 
                for (j = 0; j < count; j++, irq_index++) {
-                       err = fsl_msi_setup_hwirq(msi, dev, offset, irq_index);
+                       err = fsl_msi_setup_hwirq(msi, dev, offset + j, irq_index);
                        if (err)
                                goto error_out;
                }
index 624580c..1313abb 100644 (file)
@@ -28,8 +28,7 @@ struct fsl_msi {
 
        unsigned long cascade_irq;
 
-       u32 msi_addr_lo;
-       u32 msi_addr_hi;
+       u32 msiir_offset; /* Offset of MSIIR, relative to start of CCSR */
        void __iomem *msi_regs;
        u32 feature;
        int msi_virqs[NR_MSI_REG];
index d5d3ff3..0842c6f 100644 (file)
@@ -1285,13 +1285,11 @@ struct mpic * __init mpic_alloc(struct device_node *node,
                           mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
                           | MPIC_GREG_GCONF_MCK);
 
-       /* Read feature register, calculate num CPUs and, for non-ISU
-        * MPICs, num sources as well. On ISU MPICs, sources are counted
-        * as ISUs are added
+       /*
+        * Read feature register.  For non-ISU MPICs, num sources as well. On
+        * ISU MPICs, sources are counted as ISUs are added
         */
        greg_feature = mpic_read(mpic->gregs, MPIC_INFO(GREG_FEATURE_0));
-       mpic->num_cpus = ((greg_feature & MPIC_GREG_FEATURE_LAST_CPU_MASK)
-                         >> MPIC_GREG_FEATURE_LAST_CPU_SHIFT) + 1;
        if (isu_size == 0) {
                if (flags & MPIC_BROKEN_FRR_NIRQS)
                        mpic->num_sources = mpic->irq_count;
@@ -1301,10 +1299,18 @@ struct mpic * __init mpic_alloc(struct device_node *node,
                                 >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT) + 1;
        }
 
+       /*
+        * The MPIC driver will crash if there are more cores than we
+        * can initialize, so we may as well catch that problem here.
+        */
+       BUG_ON(num_possible_cpus() > MPIC_MAX_CPUS);
+
        /* Map the per-CPU registers */
-       for (i = 0; i < mpic->num_cpus; i++) {
-               mpic_map(mpic, node, paddr, &mpic->cpuregs[i],
-                        MPIC_INFO(CPU_BASE) + i * MPIC_INFO(CPU_STRIDE),
+       for_each_possible_cpu(i) {
+               unsigned int cpu = get_hard_smp_processor_id(i);
+
+               mpic_map(mpic, node, paddr, &mpic->cpuregs[cpu],
+                        MPIC_INFO(CPU_BASE) + cpu * MPIC_INFO(CPU_STRIDE),
                         0x1000);
        }
 
@@ -1343,7 +1349,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,
        }
        printk(KERN_INFO "mpic: Setting up MPIC \"%s\" version %s at %llx,"
               " max %d CPUs\n",
-              name, vers, (unsigned long long)paddr, mpic->num_cpus);
+              name, vers, (unsigned long long)paddr, num_possible_cpus());
        printk(KERN_INFO "mpic: ISU size: %d, shift: %d, mask: %x\n",
               mpic->isu_size, mpic->isu_shift, mpic->isu_mask);
 
@@ -1742,6 +1748,7 @@ void mpic_reset_core(int cpu)
        struct mpic *mpic = mpic_primary;
        u32 pir;
        int cpuid = get_hard_smp_processor_id(cpu);
+       int i;
 
        /* Set target bit for core reset */
        pir = mpic_read(mpic->gregs, MPIC_INFO(GREG_PROCESSOR_INIT));
@@ -1753,6 +1760,15 @@ void mpic_reset_core(int cpu)
        pir &= ~(1 << cpuid);
        mpic_write(mpic->gregs, MPIC_INFO(GREG_PROCESSOR_INIT), pir);
        mpic_read(mpic->gregs, MPIC_INFO(GREG_PROCESSOR_INIT));
+
+       /* Perform 15 EOI on each reset core to clear pending interrupts.
+        * This is required for FSL CoreNet based devices */
+       if (mpic->flags & MPIC_FSL) {
+               for (i = 0; i < 15; i++) {
+                       _mpic_write(mpic->reg_type, &mpic->cpuregs[cpuid],
+                                     MPIC_CPU_EOI, 0);
+               }
+       }
 }
 #endif /* CONFIG_SMP */
 
index dbfe96b..862f11b 100644 (file)
@@ -834,7 +834,7 @@ static int __init ppc440spe_pciex_core_init(struct device_node *np)
        return 3;
 }
 
-static int ppc440spe_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
+static int __init ppc440spe_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
 {
        u32 val = 1 << 24;
 
@@ -872,12 +872,12 @@ static int ppc440spe_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
        return ppc4xx_pciex_port_reset_sdr(port);
 }
 
-static int ppc440speA_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
+static int __init ppc440speA_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
 {
        return ppc440spe_pciex_init_port_hw(port);
 }
 
-static int ppc440speB_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
+static int __init ppc440speB_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
 {
        int rc = ppc440spe_pciex_init_port_hw(port);
 
@@ -936,7 +936,7 @@ static int __init ppc460ex_pciex_core_init(struct device_node *np)
        return 2;
 }
 
-static int ppc460ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
+static int __init ppc460ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
 {
        u32 val;
        u32 utlset1;
@@ -1092,6 +1092,10 @@ static int __init ppc460sx_pciex_core_init(struct device_node *np)
        mtdcri(SDR0, PESDR1_460SX_HSSSLEW, 0xFFFF0000);
        mtdcri(SDR0, PESDR2_460SX_HSSSLEW, 0xFFFF0000);
 
+       /* Set HSS PRBS enabled */
+       mtdcri(SDR0, PESDR0_460SX_HSSCTLSET, 0x00001130);
+       mtdcri(SDR0, PESDR2_460SX_HSSCTLSET, 0x00001130);
+
        udelay(100);
 
        /* De-assert PLLRESET */
@@ -1122,7 +1126,7 @@ static int __init ppc460sx_pciex_core_init(struct device_node *np)
        return 2;
 }
 
-static int ppc460sx_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
+static int __init ppc460sx_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
 {
 
        if (port->endpoint)
@@ -1132,9 +1136,6 @@ static int ppc460sx_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
                dcri_clrset(SDR0, port->sdr_base + PESDRn_UTLSET2,
                                0, 0x01000000);
 
-       /*Gen-1*/
-       mtdcri(SDR0, port->sdr_base + PESDRn_460SX_RCEI, 0x08000000);
-
        dcri_clrset(SDR0, port->sdr_base + PESDRn_RCSSET,
                        (PESDRx_RCSSET_RSTGU | PESDRx_RCSSET_RSTDL),
                        PESDRx_RCSSET_RSTPYN);
@@ -1148,14 +1149,42 @@ static int ppc460sx_pciex_init_utl(struct ppc4xx_pciex_port *port)
 {
        /* Max 128 Bytes */
        out_be32 (port->utl_base + PEUTL_PBBSZ,   0x00000000);
+       /* Assert VRB and TXE - per datasheet turn off addr validation */
+       out_be32(port->utl_base + PEUTL_PCTL,  0x80800000);
        return 0;
 }
 
+static void __init ppc460sx_pciex_check_link(struct ppc4xx_pciex_port *port)
+{
+       void __iomem *mbase;
+       int attempt = 50;
+
+       port->link = 0;
+
+       mbase = ioremap(port->cfg_space.start + 0x10000000, 0x1000);
+       if (mbase == NULL) {
+               printk(KERN_ERR "%s: Can't map internal config space !",
+                       port->node->full_name);
+               goto done;
+       }
+
+       while (attempt && (0 == (in_le32(mbase + PECFG_460SX_DLLSTA)
+                       & PECFG_460SX_DLLSTA_LINKUP))) {
+               attempt--;
+               mdelay(10);
+       }
+       if (attempt)
+               port->link = 1;
+done:
+       iounmap(mbase);
+
+}
+
 static struct ppc4xx_pciex_hwops ppc460sx_pcie_hwops __initdata = {
        .core_init      = ppc460sx_pciex_core_init,
        .port_init_hw   = ppc460sx_pciex_init_port_hw,
        .setup_utl      = ppc460sx_pciex_init_utl,
-       .check_link     = ppc4xx_pciex_check_link_sdr,
+       .check_link     = ppc460sx_pciex_check_link,
 };
 
 #endif /* CONFIG_44x */
@@ -1189,7 +1218,7 @@ static void ppc405ex_pcie_phy_reset(struct ppc4xx_pciex_port *port)
        mtdcri(SDR0, port->sdr_base + PESDRn_RCSSET, 0x00101000);
 }
 
-static int ppc405ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
+static int __init ppc405ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
 {
        u32 val;
 
@@ -1338,15 +1367,15 @@ static int __init ppc4xx_pciex_port_init(struct ppc4xx_pciex_port *port)
        if (rc != 0)
                return rc;
 
-       if (ppc4xx_pciex_hwops->check_link)
-               ppc4xx_pciex_hwops->check_link(port);
-
        /*
         * Initialize mapping: disable all regions and configure
         * CFG and REG regions based on resources in the device tree
         */
        ppc4xx_pciex_port_init_mapping(port);
 
+       if (ppc4xx_pciex_hwops->check_link)
+               ppc4xx_pciex_hwops->check_link(port);
+
        /*
         * Map UTL
         */
@@ -1360,13 +1389,23 @@ static int __init ppc4xx_pciex_port_init(struct ppc4xx_pciex_port *port)
                ppc4xx_pciex_hwops->setup_utl(port);
 
        /*
-        * Check for VC0 active and assert RDY.
+        * Check for VC0 active or PLL Locked and assert RDY.
         */
        if (port->sdr_base) {
-               if (port->link &&
-                   ppc4xx_pciex_wait_on_sdr(port, PESDRn_RCSSTS,
-                                            1 << 16, 1 << 16, 5000)) {
-                       printk(KERN_INFO "PCIE%d: VC0 not active\n", port->index);
+               if (of_device_is_compatible(port->node,
+                               "ibm,plb-pciex-460sx")){
+                       if (port->link && ppc4xx_pciex_wait_on_sdr(port,
+                                       PESDRn_RCSSTS,
+                                       1 << 12, 1 << 12, 5000)) {
+                               printk(KERN_INFO "PCIE%d: PLL not locked\n",
+                                               port->index);
+                               port->link = 0;
+                       }
+               } else if (port->link &&
+                       ppc4xx_pciex_wait_on_sdr(port, PESDRn_RCSSTS,
+                               1 << 16, 1 << 16, 5000)) {
+                       printk(KERN_INFO "PCIE%d: VC0 not active\n",
+                                       port->index);
                        port->link = 0;
                }
 
@@ -1573,8 +1612,15 @@ static int __init ppc4xx_setup_one_pciex_POM(struct ppc4xx_pciex_port    *port,
                dcr_write(port->dcrs, DCRO_PEGPL_OMR1BAH, lah);
                dcr_write(port->dcrs, DCRO_PEGPL_OMR1BAL, lal);
                dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKH, 0x7fffffff);
-               /* Note that 3 here means enabled | single region */
-               dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL, sa | 3);
+               /*Enabled and single region */
+               if (of_device_is_compatible(port->node, "ibm,plb-pciex-460sx"))
+                       dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL,
+                               sa | DCRO_PEGPL_460SX_OMR1MSKL_UOT
+                                       | DCRO_PEGPL_OMRxMSKL_VAL);
+               else
+                       dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL,
+                               sa | DCRO_PEGPL_OMR1MSKL_UOT
+                                       | DCRO_PEGPL_OMRxMSKL_VAL);
                break;
        case 1:
                out_le32(mbase + PECFG_POM1LAH, pciah);
@@ -1582,8 +1628,8 @@ static int __init ppc4xx_setup_one_pciex_POM(struct ppc4xx_pciex_port     *port,
                dcr_write(port->dcrs, DCRO_PEGPL_OMR2BAH, lah);
                dcr_write(port->dcrs, DCRO_PEGPL_OMR2BAL, lal);
                dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKH, 0x7fffffff);
-               /* Note that 3 here means enabled | single region */
-               dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKL, sa | 3);
+               dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKL,
+                               sa | DCRO_PEGPL_OMRxMSKL_VAL);
                break;
        case 2:
                out_le32(mbase + PECFG_POM2LAH, pciah);
@@ -1592,7 +1638,9 @@ static int __init ppc4xx_setup_one_pciex_POM(struct ppc4xx_pciex_port     *port,
                dcr_write(port->dcrs, DCRO_PEGPL_OMR3BAL, lal);
                dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKH, 0x7fffffff);
                /* Note that 3 here means enabled | IO space !!! */
-               dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKL, sa | 3);
+               dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKL,
+                               sa | DCRO_PEGPL_OMR3MSKL_IO
+                                       | DCRO_PEGPL_OMRxMSKL_VAL);
                break;
        }
 
@@ -1693,6 +1741,9 @@ static void __init ppc4xx_configure_pciex_PIMs(struct ppc4xx_pciex_port *port,
                if (res->flags & IORESOURCE_PREFETCH)
                        sa |= 0x8;
 
+               if (of_device_is_compatible(port->node, "ibm,plb-pciex-460sx"))
+                       sa |= PCI_BASE_ADDRESS_MEM_TYPE_64;
+
                out_le32(mbase + PECFG_BAR0HMPA, RES_TO_U32_HIGH(sa));
                out_le32(mbase + PECFG_BAR0LMPA, RES_TO_U32_LOW(sa));
 
@@ -1854,6 +1905,10 @@ static void __init ppc4xx_pciex_port_setup_hose(struct ppc4xx_pciex_port *port)
        }
        out_le16(mbase + 0x202, val);
 
+       /* Enable Bus master, memory, and io space */
+       if (of_device_is_compatible(port->node, "ibm,plb-pciex-460sx"))
+               out_le16(mbase + 0x204, 0x7);
+
        if (!port->endpoint) {
                /* Set Class Code to PCI-PCI bridge and Revision Id to 1 */
                out_le32(mbase + 0x208, 0x06040001);
index c39a134..32ce763 100644 (file)
 #define PECFG_POM2LAL          0x390
 #define PECFG_POM2LAH          0x394
 
+/* 460sx only */
+#define PECFG_460SX_DLLSTA     0x3f8
+
+/* 460sx Bit Mappings */
+#define PECFG_460SX_DLLSTA_LINKUP       0x00000010
+#define DCRO_PEGPL_460SX_OMR1MSKL_UOT   0x00000004
+
+/* PEGPL Bit Mappings */
+#define DCRO_PEGPL_OMRxMSKL_VAL         0x00000001
+#define DCRO_PEGPL_OMR1MSKL_UOT         0x00000002
+#define DCRO_PEGPL_OMR3MSKL_IO  0x00000002
+
 /* SDR Bit Mappings */
 #define PESDRx_RCSSET_HLDPLB   0x10000000
 #define PESDRx_RCSSET_RSTGU    0x01000000
index b75a605..c606aa8 100644 (file)
@@ -4,3 +4,4 @@ obj-y                           += xics-common.o
 obj-$(CONFIG_PPC_ICP_NATIVE)   += icp-native.o
 obj-$(CONFIG_PPC_ICP_HV)       += icp-hv.o
 obj-$(CONFIG_PPC_ICS_RTAS)     += ics-rtas.o
+obj-$(CONFIG_PPC_POWERNV)      += ics-opal.o
index 50e32af..4c79b6f 100644 (file)
@@ -276,7 +276,7 @@ static const struct icp_ops icp_native_ops = {
 #endif
 };
 
-int icp_native_init(void)
+int __init icp_native_init(void)
 {
        struct device_node *np;
        u32 indx = 0;
diff --git a/arch/powerpc/sysdev/xics/ics-opal.c b/arch/powerpc/sysdev/xics/ics-opal.c
new file mode 100644 (file)
index 0000000..f7e8609
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+ * ICS backend for OPAL managed interrupts.
+ *
+ * Copyright 2011 IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#undef DEBUG
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/irq.h>
+#include <linux/smp.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/cpu.h>
+#include <linux/of.h>
+#include <linux/spinlock.h>
+#include <linux/msi.h>
+
+#include <asm/prom.h>
+#include <asm/smp.h>
+#include <asm/machdep.h>
+#include <asm/irq.h>
+#include <asm/errno.h>
+#include <asm/xics.h>
+#include <asm/opal.h>
+#include <asm/firmware.h>
+
+static int ics_opal_mangle_server(int server)
+{
+       /* No link for now */
+       return server << 2;
+}
+
+static int ics_opal_unmangle_server(int server)
+{
+       /* No link for now */
+       return server >> 2;
+}
+
+static void ics_opal_unmask_irq(struct irq_data *d)
+{
+       unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d);
+       int64_t rc;
+       int server;
+
+       pr_devel("ics-hal: unmask virq %d [hw 0x%x]\n", d->irq, hw_irq);
+
+       if (hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS)
+               return;
+
+       server = xics_get_irq_server(d->irq, d->affinity, 0);
+       server = ics_opal_mangle_server(server);
+
+       rc = opal_set_xive(hw_irq, server, DEFAULT_PRIORITY);
+       if (rc != OPAL_SUCCESS)
+               pr_err("%s: opal_set_xive(irq=%d [hw 0x%x] server=%x)"
+                      " error %lld\n",
+                      __func__, d->irq, hw_irq, server, rc);
+}
+
+static unsigned int ics_opal_startup(struct irq_data *d)
+{
+#ifdef CONFIG_PCI_MSI
+       /*
+        * The generic MSI code returns with the interrupt disabled on the
+        * card, using the MSI mask bits. Firmware doesn't appear to unmask
+        * at that level, so we do it here by hand.
+        */
+       if (d->msi_desc)
+               unmask_msi_irq(d);
+#endif
+
+       /* unmask it */
+       ics_opal_unmask_irq(d);
+       return 0;
+}
+
+static void ics_opal_mask_real_irq(unsigned int hw_irq)
+{
+       int server = ics_opal_mangle_server(xics_default_server);
+       int64_t rc;
+
+       if (hw_irq == XICS_IPI)
+               return;
+
+       /* Have to set XIVE to 0xff to be able to remove a slot */
+       rc = opal_set_xive(hw_irq, server, 0xff);
+       if (rc != OPAL_SUCCESS)
+               pr_err("%s: opal_set_xive(0xff) irq=%u returned %lld\n",
+                      __func__, hw_irq, rc);
+}
+
+static void ics_opal_mask_irq(struct irq_data *d)
+{
+       unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d);
+
+       pr_devel("ics-hal: mask virq %d [hw 0x%x]\n", d->irq, hw_irq);
+
+       if (hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS)
+               return;
+       ics_opal_mask_real_irq(hw_irq);
+}
+
+static int ics_opal_set_affinity(struct irq_data *d,
+                                const struct cpumask *cpumask,
+                                bool force)
+{
+       unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d);
+       int16_t server;
+       int8_t priority;
+       int64_t rc;
+       int wanted_server;
+
+       if (hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS)
+               return -1;
+
+       rc = opal_get_xive(hw_irq, &server, &priority);
+       if (rc != OPAL_SUCCESS) {
+               pr_err("%s: opal_set_xive(irq=%d [hw 0x%x] server=%x)"
+                      " error %lld\n",
+                      __func__, d->irq, hw_irq, server, rc);
+               return -1;
+       }
+
+       wanted_server = xics_get_irq_server(d->irq, cpumask, 1);
+       if (wanted_server < 0) {
+               char cpulist[128];
+               cpumask_scnprintf(cpulist, sizeof(cpulist), cpumask);
+               pr_warning("%s: No online cpus in the mask %s for irq %d\n",
+                          __func__, cpulist, d->irq);
+               return -1;
+       }
+       server = ics_opal_mangle_server(wanted_server);
+
+       pr_devel("ics-hal: set-affinity irq %d [hw 0x%x] server: 0x%x/0x%x\n",
+                d->irq, hw_irq, wanted_server, server);
+
+       rc = opal_set_xive(hw_irq, server, priority);
+       if (rc != OPAL_SUCCESS) {
+               pr_err("%s: opal_set_xive(irq=%d [hw 0x%x] server=%x)"
+                      " error %lld\n",
+                      __func__, d->irq, hw_irq, server, rc);
+               return -1;
+       }
+       return 0;
+}
+
+static struct irq_chip ics_opal_irq_chip = {
+       .name = "OPAL ICS",
+       .irq_startup = ics_opal_startup,
+       .irq_mask = ics_opal_mask_irq,
+       .irq_unmask = ics_opal_unmask_irq,
+       .irq_eoi = NULL, /* Patched at init time */
+       .irq_set_affinity = ics_opal_set_affinity
+};
+
+static int ics_opal_map(struct ics *ics, unsigned int virq);
+static void ics_opal_mask_unknown(struct ics *ics, unsigned long vec);
+static long ics_opal_get_server(struct ics *ics, unsigned long vec);
+
+static int ics_opal_host_match(struct ics *ics, struct device_node *node)
+{
+       return 1;
+}
+
+/* Only one global & state struct ics */
+static struct ics ics_hal = {
+       .map            = ics_opal_map,
+       .mask_unknown   = ics_opal_mask_unknown,
+       .get_server     = ics_opal_get_server,
+       .host_match     = ics_opal_host_match,
+};
+
+static int ics_opal_map(struct ics *ics, unsigned int virq)
+{
+       unsigned int hw_irq = (unsigned int)virq_to_hw(virq);
+       int64_t rc;
+       int16_t server;
+       int8_t priority;
+
+       if (WARN_ON(hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS))
+               return -EINVAL;
+
+       /* Check if HAL knows about this interrupt */
+       rc = opal_get_xive(hw_irq, &server, &priority);
+       if (rc != OPAL_SUCCESS)
+               return -ENXIO;
+
+       irq_set_chip_and_handler(virq, &ics_opal_irq_chip, handle_fasteoi_irq);
+       irq_set_chip_data(virq, &ics_hal);
+
+       return 0;
+}
+
+static void ics_opal_mask_unknown(struct ics *ics, unsigned long vec)
+{
+       int64_t rc;
+       int16_t server;
+       int8_t priority;
+
+       /* Check if HAL knows about this interrupt */
+       rc = opal_get_xive(vec, &server, &priority);
+       if (rc != OPAL_SUCCESS)
+               return;
+
+       ics_opal_mask_real_irq(vec);
+}
+
+static long ics_opal_get_server(struct ics *ics, unsigned long vec)
+{
+       int64_t rc;
+       int16_t server;
+       int8_t priority;
+
+       /* Check if HAL knows about this interrupt */
+       rc = opal_get_xive(vec, &server, &priority);
+       if (rc != OPAL_SUCCESS)
+               return -1;
+       return ics_opal_unmangle_server(server);
+}
+
+int __init ics_opal_init(void)
+{
+       if (!firmware_has_feature(FW_FEATURE_OPAL))
+               return -ENODEV;
+
+       /* We need to patch our irq chip's EOI to point to the
+        * right ICP
+        */
+       ics_opal_irq_chip.irq_eoi = icp_ops->eoi;
+
+       /* Register ourselves */
+       xics_register_ics(&ics_hal);
+
+       pr_info("ICS OPAL backend registered\n");
+
+       return 0;
+}
index 445c5a0..3d93a8d 100644 (file)
@@ -409,14 +409,10 @@ void __init xics_init(void)
        int rc = -1;
 
        /* Fist locate ICP */
-#ifdef CONFIG_PPC_ICP_HV
        if (firmware_has_feature(FW_FEATURE_LPAR))
                rc = icp_hv_init();
-#endif
-#ifdef CONFIG_PPC_ICP_NATIVE
        if (rc < 0)
                rc = icp_native_init();
-#endif
        if (rc < 0) {
                pr_warning("XICS: Cannot find a Presentation Controller !\n");
                return;
@@ -429,9 +425,9 @@ void __init xics_init(void)
        xics_ipi_chip.irq_eoi = icp_ops->eoi;
 
        /* Now locate ICS */
-#ifdef CONFIG_PPC_ICS_RTAS
        rc = ics_rtas_init();
-#endif
+       if (rc < 0)
+               rc = ics_opal_init();
        if (rc < 0)
                pr_warning("XICS: Cannot find a Source Controller !\n");
 
index 42541bb..13f82f8 100644 (file)
@@ -340,8 +340,8 @@ int cpus_are_in_xmon(void)
 
 static inline int unrecoverable_excp(struct pt_regs *regs)
 {
-#ifdef CONFIG_4xx
-       /* We have no MSR_RI bit on 4xx, so we simply return false */
+#if defined(CONFIG_4xx) || defined(CONFIG_BOOK3E)
+       /* We have no MSR_RI bit on 4xx or Book3e, so we simply return false */
        return 0;
 #else
        return ((regs->msr & MSR_RI) == 0);
index d362657..7030f4c 100644 (file)
@@ -345,9 +345,10 @@ static struct soc_camera_platform_info camera_info = {
                .width = 640,
                .height = 480,
        },
-       .bus_param = SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH |
-       SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_MASTER | SOCAM_DATAWIDTH_8 |
-       SOCAM_DATA_ACTIVE_HIGH,
+       .mbus_param = V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_MASTER |
+       V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_HIGH |
+       V4L2_MBUS_DATA_ACTIVE_HIGH,
+       .mbus_type = V4L2_MBUS_PARALLEL,
        .set_capture = camera_set_capture,
 };
 
@@ -501,8 +502,7 @@ static struct i2c_board_info ap325rxa_i2c_camera[] = {
 };
 
 static struct ov772x_camera_info ov7725_info = {
-       .flags          = OV772X_FLAG_VFLIP | OV772X_FLAG_HFLIP | \
-                         OV772X_FLAG_8BIT,
+       .flags          = OV772X_FLAG_VFLIP | OV772X_FLAG_HFLIP,
        .edgectrl       = OV772X_AUTO_EDGECTRL(0xf, 0),
 };
 
index 2d4c9c8..e4c8119 100644 (file)
@@ -448,9 +448,7 @@ static struct i2c_board_info migor_i2c_camera[] = {
        },
 };
 
-static struct ov772x_camera_info ov7725_info = {
-       .flags          = OV772X_FLAG_8BIT,
-};
+static struct ov772x_camera_info ov7725_info;
 
 static struct soc_camera_link ov7725_link = {
        .power          = ov7725_power,
diff --git a/arch/tile/include/arch/Kbuild b/arch/tile/include/arch/Kbuild
new file mode 100644 (file)
index 0000000..9c0ea24
--- /dev/null
@@ -0,0 +1,17 @@
+header-y += abi.h
+header-y += chip.h
+header-y += chip_tile64.h
+header-y += chip_tilegx.h
+header-y += chip_tilepro.h
+header-y += icache.h
+header-y += interrupts.h
+header-y += interrupts_32.h
+header-y += interrupts_64.h
+header-y += opcode.h
+header-y += opcode_tilegx.h
+header-y += opcode_tilepro.h
+header-y += sim.h
+header-y += sim_def.h
+header-y += spr_def.h
+header-y += spr_def_32.h
+header-y += spr_def_64.h
index 8affc76..c55a3d4 100644 (file)
 /**
  * @file
  *
- * ABI-related register definitions helpful when writing assembly code.
+ * ABI-related register definitions.
  */
 
 #ifndef __ARCH_ABI_H__
-#define __ARCH_ABI_H__
 
-#include <arch/chip.h>
+#if !defined __need_int_reg_t && !defined __DOXYGEN__
+# define __ARCH_ABI_H__
+# include <arch/chip.h>
+#endif
+
+/* Provide the basic machine types. */
+#ifndef __INT_REG_BITS
+
+/** Number of bits in a register. */
+#if defined __tilegx__
+# define __INT_REG_BITS 64
+#elif defined __tilepro__
+# define __INT_REG_BITS 32
+#elif !defined __need_int_reg_t
+# include <arch/chip.h>
+# define __INT_REG_BITS CHIP_WORD_SIZE()
+#else
+# error Unrecognized architecture with __need_int_reg_t
+#endif
+
+#if __INT_REG_BITS == 64
+
+#ifndef __ASSEMBLER__
+/** Unsigned type that can hold a register. */
+typedef unsigned long long __uint_reg_t;
+
+/** Signed type that can hold a register. */
+typedef long long __int_reg_t;
+#endif
+
+/** String prefix to use for printf(). */
+#define __INT_REG_FMT "ll"
+
+#else
+
+#ifndef __ASSEMBLER__
+/** Unsigned type that can hold a register. */
+typedef unsigned long __uint_reg_t;
+
+/** Signed type that can hold a register. */
+typedef long __int_reg_t;
+#endif
+
+/** String prefix to use for printf(). */
+#define __INT_REG_FMT "l"
+
+#endif
+#endif /* __INT_REG_BITS */
+
+
+#ifndef __need_int_reg_t
+
+
+#ifndef __ASSEMBLER__
+/** Unsigned type that can hold a register. */
+typedef __uint_reg_t uint_reg_t;
+
+/** Signed type that can hold a register. */
+typedef __int_reg_t int_reg_t;
+#endif
+
+/** String prefix to use for printf(). */
+#define INT_REG_FMT __INT_REG_FMT
+
+/** Number of bits in a register. */
+#define INT_REG_BITS __INT_REG_BITS
+
 
 /* Registers 0 - 55 are "normal", but some perform special roles. */
 
  * The ABI requires callers to allocate a caller state save area of
  * this many bytes at the bottom of each stack frame.
  */
-#define C_ABI_SAVE_AREA_SIZE (2 * (CHIP_WORD_SIZE() / 8))
+#define C_ABI_SAVE_AREA_SIZE (2 * (INT_REG_BITS / 8))
 
 /**
  * The operand to an 'info' opcode directing the backtracer to not
  */
 #define INFO_OP_CANNOT_BACKTRACE 2
 
-#ifndef __ASSEMBLER__
-#if CHIP_WORD_SIZE() > 32
 
-/** Unsigned type that can hold a register. */
-typedef unsigned long long uint_reg_t;
+#endif /* !__need_int_reg_t */
 
-/** Signed type that can hold a register. */
-typedef long long int_reg_t;
-
-/** String prefix to use for printf(). */
-#define INT_REG_FMT "ll"
-
-#elif !defined(__LP64__)   /* avoid confusion with LP64 cross-build tools */
-
-/** Unsigned type that can hold a register. */
-typedef unsigned long uint_reg_t;
-
-/** Signed type that can hold a register. */
-typedef long int_reg_t;
-
-/** String prefix to use for printf(). */
-#define INT_REG_FMT "l"
-
-#endif
-#endif /* __ASSEMBLER__ */
+/* Make sure we later can get all the definitions and declarations.  */
+#undef __need_int_reg_t
 
 #endif /* !__ARCH_ABI_H__ */
similarity index 62%
rename from arch/tile/include/asm/opcode_constants.h
rename to arch/tile/include/arch/opcode.h
index 37a9f29..92d1522 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2010 Tilera Corporation. All Rights Reserved.
+ * Copyright 2011 Tilera Corporation. All Rights Reserved.
  *
  *   This program is free software; you can redistribute it and/or
  *   modify it under the terms of the GNU General Public License
  *   more details.
  */
 
-#ifndef _ASM_TILE_OPCODE_CONSTANTS_H
-#define _ASM_TILE_OPCODE_CONSTANTS_H
-
-#include <arch/chip.h>
-
-#if CHIP_WORD_SIZE() == 64
-#include <asm/opcode_constants_64.h>
+#if defined(__tilepro__)
+#include <arch/opcode_tilepro.h>
+#elif defined(__tilegx__)
+#include <arch/opcode_tilegx.h>
 #else
-#include <asm/opcode_constants_32.h>
+#error Unexpected Tilera chip type
 #endif
-
-#endif /* _ASM_TILE_OPCODE_CONSTANTS_H */
similarity index 50%
rename from arch/tile/include/asm/opcode_constants_64.h
rename to arch/tile/include/arch/opcode_tilegx.h
index 7101928..c14d02c 100644 (file)
@@ -1,4 +1,5 @@
-/*
+/* TILE-Gx opcode information.
+ *
  * Copyright 2011 Tilera Corporation. All Rights Reserved.
  *
  *   This program is free software; you can redistribute it and/or
  *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
  *   NON INFRINGEMENT.  See the GNU General Public License for
  *   more details.
+ *
+ *
+ *
+ *
+ *
  */
 
-/* This file is machine-generated; DO NOT EDIT! */
+#ifndef __ARCH_OPCODE_H__
+#define __ARCH_OPCODE_H__
+
+#ifndef __ASSEMBLER__
+
+typedef unsigned long long tilegx_bundle_bits;
+
+/* These are the bits that determine if a bundle is in the X encoding. */
+#define TILEGX_BUNDLE_MODE_MASK ((tilegx_bundle_bits)3 << 62)
+
+enum
+{
+  /* Maximum number of instructions in a bundle (2 for X, 3 for Y). */
+  TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE = 3,
+
+  /* How many different pipeline encodings are there? X0, X1, Y0, Y1, Y2. */
+  TILEGX_NUM_PIPELINE_ENCODINGS = 5,
+
+  /* Log base 2 of TILEGX_BUNDLE_SIZE_IN_BYTES. */
+  TILEGX_LOG2_BUNDLE_SIZE_IN_BYTES = 3,
+
+  /* Instructions take this many bytes. */
+  TILEGX_BUNDLE_SIZE_IN_BYTES = 1 << TILEGX_LOG2_BUNDLE_SIZE_IN_BYTES,
+
+  /* Log base 2 of TILEGX_BUNDLE_ALIGNMENT_IN_BYTES. */
+  TILEGX_LOG2_BUNDLE_ALIGNMENT_IN_BYTES = 3,
+
+  /* Bundles should be aligned modulo this number of bytes. */
+  TILEGX_BUNDLE_ALIGNMENT_IN_BYTES =
+    (1 << TILEGX_LOG2_BUNDLE_ALIGNMENT_IN_BYTES),
+
+  /* Number of registers (some are magic, such as network I/O). */
+  TILEGX_NUM_REGISTERS = 64,
+};
+
+/* Make a few "tile_" variables to simplify common code between
+   architectures.  */
+
+typedef tilegx_bundle_bits tile_bundle_bits;
+#define TILE_BUNDLE_SIZE_IN_BYTES TILEGX_BUNDLE_SIZE_IN_BYTES
+#define TILE_BUNDLE_ALIGNMENT_IN_BYTES TILEGX_BUNDLE_ALIGNMENT_IN_BYTES
+#define TILE_LOG2_BUNDLE_ALIGNMENT_IN_BYTES \
+  TILEGX_LOG2_BUNDLE_ALIGNMENT_IN_BYTES
+
+/* 64-bit pattern for a { bpt ; nop } bundle. */
+#define TILEGX_BPT_BUNDLE 0x286a44ae51485000ULL
+
+static __inline unsigned int
+get_BFEnd_X0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0x3f);
+}
+
+static __inline unsigned int
+get_BFOpcodeExtension_X0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 24)) & 0xf);
+}
+
+static __inline unsigned int
+get_BFStart_X0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 18)) & 0x3f);
+}
+
+static __inline unsigned int
+get_BrOff_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 31)) & 0x0000003f) |
+         (((unsigned int)(n >> 37)) & 0x0001ffc0);
+}
+
+static __inline unsigned int
+get_BrType_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 54)) & 0x1f);
+}
+
+static __inline unsigned int
+get_Dest_Imm8_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 31)) & 0x0000003f) |
+         (((unsigned int)(n >> 43)) & 0x000000c0);
+}
+
+static __inline unsigned int
+get_Dest_X0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 0)) & 0x3f);
+}
+
+static __inline unsigned int
+get_Dest_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 31)) & 0x3f);
+}
+
+static __inline unsigned int
+get_Dest_Y0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 0)) & 0x3f);
+}
+
+static __inline unsigned int
+get_Dest_Y1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 31)) & 0x3f);
+}
+
+static __inline unsigned int
+get_Imm16_X0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0xffff);
+}
+
+static __inline unsigned int
+get_Imm16_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0xffff);
+}
+
+static __inline unsigned int
+get_Imm8OpcodeExtension_X0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 20)) & 0xff);
+}
+
+static __inline unsigned int
+get_Imm8OpcodeExtension_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 51)) & 0xff);
+}
+
+static __inline unsigned int
+get_Imm8_X0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0xff);
+}
+
+static __inline unsigned int
+get_Imm8_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0xff);
+}
+
+static __inline unsigned int
+get_Imm8_Y0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0xff);
+}
+
+static __inline unsigned int
+get_Imm8_Y1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0xff);
+}
+
+static __inline unsigned int
+get_JumpOff_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 31)) & 0x7ffffff);
+}
+
+static __inline unsigned int
+get_JumpOpcodeExtension_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 58)) & 0x1);
+}
+
+static __inline unsigned int
+get_MF_Imm14_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 37)) & 0x3fff);
+}
+
+static __inline unsigned int
+get_MT_Imm14_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 31)) & 0x0000003f) |
+         (((unsigned int)(n >> 37)) & 0x00003fc0);
+}
+
+static __inline unsigned int
+get_Mode(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 62)) & 0x3);
+}
+
+static __inline unsigned int
+get_Opcode_X0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 28)) & 0x7);
+}
+
+static __inline unsigned int
+get_Opcode_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 59)) & 0x7);
+}
+
+static __inline unsigned int
+get_Opcode_Y0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 27)) & 0xf);
+}
+
+static __inline unsigned int
+get_Opcode_Y1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 58)) & 0xf);
+}
+
+static __inline unsigned int
+get_Opcode_Y2(tilegx_bundle_bits n)
+{
+  return (((n >> 26)) & 0x00000001) |
+         (((unsigned int)(n >> 56)) & 0x00000002);
+}
+
+static __inline unsigned int
+get_RRROpcodeExtension_X0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 18)) & 0x3ff);
+}
+
+static __inline unsigned int
+get_RRROpcodeExtension_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 49)) & 0x3ff);
+}
+
+static __inline unsigned int
+get_RRROpcodeExtension_Y0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 18)) & 0x3);
+}
+
+static __inline unsigned int
+get_RRROpcodeExtension_Y1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 49)) & 0x3);
+}
+
+static __inline unsigned int
+get_ShAmt_X0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0x3f);
+}
+
+static __inline unsigned int
+get_ShAmt_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0x3f);
+}
+
+static __inline unsigned int
+get_ShAmt_Y0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0x3f);
+}
+
+static __inline unsigned int
+get_ShAmt_Y1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0x3f);
+}
+
+static __inline unsigned int
+get_ShiftOpcodeExtension_X0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 18)) & 0x3ff);
+}
+
+static __inline unsigned int
+get_ShiftOpcodeExtension_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 49)) & 0x3ff);
+}
+
+static __inline unsigned int
+get_ShiftOpcodeExtension_Y0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 18)) & 0x3);
+}
+
+static __inline unsigned int
+get_ShiftOpcodeExtension_Y1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 49)) & 0x3);
+}
+
+static __inline unsigned int
+get_SrcA_X0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 6)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcA_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 37)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcA_Y0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 6)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcA_Y1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 37)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcA_Y2(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 20)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcBDest_Y2(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 51)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcB_X0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcB_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcB_Y0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcB_Y1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0x3f);
+}
+
+static __inline unsigned int
+get_UnaryOpcodeExtension_X0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0x3f);
+}
+
+static __inline unsigned int
+get_UnaryOpcodeExtension_X1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0x3f);
+}
+
+static __inline unsigned int
+get_UnaryOpcodeExtension_Y0(tilegx_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0x3f);
+}
+
+static __inline unsigned int
+get_UnaryOpcodeExtension_Y1(tilegx_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0x3f);
+}
+
+
+static __inline int
+sign_extend(int n, int num_bits)
+{
+  int shift = (int)(sizeof(int) * 8 - num_bits);
+  return (n << shift) >> shift;
+}
+
+
+
+static __inline tilegx_bundle_bits
+create_BFEnd_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 12);
+}
+
+static __inline tilegx_bundle_bits
+create_BFOpcodeExtension_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0xf) << 24);
+}
+
+static __inline tilegx_bundle_bits
+create_BFStart_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 18);
+}
+
+static __inline tilegx_bundle_bits
+create_BrOff_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x0000003f)) << 31) |
+         (((tilegx_bundle_bits)(n & 0x0001ffc0)) << 37);
+}
+
+static __inline tilegx_bundle_bits
+create_BrType_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x1f)) << 54);
+}
+
+static __inline tilegx_bundle_bits
+create_Dest_Imm8_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x0000003f)) << 31) |
+         (((tilegx_bundle_bits)(n & 0x000000c0)) << 43);
+}
+
+static __inline tilegx_bundle_bits
+create_Dest_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 0);
+}
+
+static __inline tilegx_bundle_bits
+create_Dest_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3f)) << 31);
+}
+
+static __inline tilegx_bundle_bits
+create_Dest_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 0);
+}
+
+static __inline tilegx_bundle_bits
+create_Dest_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3f)) << 31);
+}
+
+static __inline tilegx_bundle_bits
+create_Imm16_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0xffff) << 12);
+}
+
+static __inline tilegx_bundle_bits
+create_Imm16_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0xffff)) << 43);
+}
+
+static __inline tilegx_bundle_bits
+create_Imm8OpcodeExtension_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0xff) << 20);
+}
+
+static __inline tilegx_bundle_bits
+create_Imm8OpcodeExtension_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0xff)) << 51);
+}
+
+static __inline tilegx_bundle_bits
+create_Imm8_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0xff) << 12);
+}
+
+static __inline tilegx_bundle_bits
+create_Imm8_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0xff)) << 43);
+}
+
+static __inline tilegx_bundle_bits
+create_Imm8_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0xff) << 12);
+}
+
+static __inline tilegx_bundle_bits
+create_Imm8_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0xff)) << 43);
+}
+
+static __inline tilegx_bundle_bits
+create_JumpOff_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x7ffffff)) << 31);
+}
+
+static __inline tilegx_bundle_bits
+create_JumpOpcodeExtension_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x1)) << 58);
+}
+
+static __inline tilegx_bundle_bits
+create_MF_Imm14_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3fff)) << 37);
+}
+
+static __inline tilegx_bundle_bits
+create_MT_Imm14_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x0000003f)) << 31) |
+         (((tilegx_bundle_bits)(n & 0x00003fc0)) << 37);
+}
+
+static __inline tilegx_bundle_bits
+create_Mode(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3)) << 62);
+}
+
+static __inline tilegx_bundle_bits
+create_Opcode_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x7) << 28);
+}
+
+static __inline tilegx_bundle_bits
+create_Opcode_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x7)) << 59);
+}
+
+static __inline tilegx_bundle_bits
+create_Opcode_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0xf) << 27);
+}
+
+static __inline tilegx_bundle_bits
+create_Opcode_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0xf)) << 58);
+}
+
+static __inline tilegx_bundle_bits
+create_Opcode_Y2(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x00000001) << 26) |
+         (((tilegx_bundle_bits)(n & 0x00000002)) << 56);
+}
+
+static __inline tilegx_bundle_bits
+create_RRROpcodeExtension_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3ff) << 18);
+}
+
+static __inline tilegx_bundle_bits
+create_RRROpcodeExtension_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3ff)) << 49);
+}
+
+static __inline tilegx_bundle_bits
+create_RRROpcodeExtension_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3) << 18);
+}
+
+static __inline tilegx_bundle_bits
+create_RRROpcodeExtension_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3)) << 49);
+}
+
+static __inline tilegx_bundle_bits
+create_ShAmt_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 12);
+}
+
+static __inline tilegx_bundle_bits
+create_ShAmt_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3f)) << 43);
+}
+
+static __inline tilegx_bundle_bits
+create_ShAmt_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 12);
+}
+
+static __inline tilegx_bundle_bits
+create_ShAmt_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3f)) << 43);
+}
+
+static __inline tilegx_bundle_bits
+create_ShiftOpcodeExtension_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3ff) << 18);
+}
+
+static __inline tilegx_bundle_bits
+create_ShiftOpcodeExtension_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3ff)) << 49);
+}
+
+static __inline tilegx_bundle_bits
+create_ShiftOpcodeExtension_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3) << 18);
+}
+
+static __inline tilegx_bundle_bits
+create_ShiftOpcodeExtension_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3)) << 49);
+}
+
+static __inline tilegx_bundle_bits
+create_SrcA_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 6);
+}
+
+static __inline tilegx_bundle_bits
+create_SrcA_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3f)) << 37);
+}
+
+static __inline tilegx_bundle_bits
+create_SrcA_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 6);
+}
+
+static __inline tilegx_bundle_bits
+create_SrcA_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3f)) << 37);
+}
+
+static __inline tilegx_bundle_bits
+create_SrcA_Y2(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 20);
+}
+
+static __inline tilegx_bundle_bits
+create_SrcBDest_Y2(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3f)) << 51);
+}
+
+static __inline tilegx_bundle_bits
+create_SrcB_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 12);
+}
+
+static __inline tilegx_bundle_bits
+create_SrcB_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3f)) << 43);
+}
+
+static __inline tilegx_bundle_bits
+create_SrcB_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 12);
+}
+
+static __inline tilegx_bundle_bits
+create_SrcB_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3f)) << 43);
+}
+
+static __inline tilegx_bundle_bits
+create_UnaryOpcodeExtension_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 12);
+}
+
+static __inline tilegx_bundle_bits
+create_UnaryOpcodeExtension_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3f)) << 43);
+}
+
+static __inline tilegx_bundle_bits
+create_UnaryOpcodeExtension_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 12);
+}
+
+static __inline tilegx_bundle_bits
+create_UnaryOpcodeExtension_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilegx_bundle_bits)(n & 0x3f)) << 43);
+}
 
 
-#ifndef _TILE_OPCODE_CONSTANTS_H
-#define _TILE_OPCODE_CONSTANTS_H
 enum
 {
   ADDI_IMM8_OPCODE_X0 = 1,
@@ -606,4 +1399,7 @@ enum
   XOR_RRR_5_OPCODE_Y1 = 3
 };
 
-#endif /* !_TILE_OPCODE_CONSTANTS_H */
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* __ARCH_OPCODE_H__ */
diff --git a/arch/tile/include/arch/opcode_tilepro.h b/arch/tile/include/arch/opcode_tilepro.h
new file mode 100644 (file)
index 0000000..71b763b
--- /dev/null
@@ -0,0 +1,1471 @@
+/* TILEPro opcode information.
+ *
+ * Copyright 2011 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ *
+ *
+ *
+ *
+ *
+ */
+
+#ifndef __ARCH_OPCODE_H__
+#define __ARCH_OPCODE_H__
+
+#ifndef __ASSEMBLER__
+
+typedef unsigned long long tilepro_bundle_bits;
+
+/* This is the bit that determines if a bundle is in the Y encoding. */
+#define TILEPRO_BUNDLE_Y_ENCODING_MASK ((tilepro_bundle_bits)1 << 63)
+
+enum
+{
+  /* Maximum number of instructions in a bundle (2 for X, 3 for Y). */
+  TILEPRO_MAX_INSTRUCTIONS_PER_BUNDLE = 3,
+
+  /* How many different pipeline encodings are there? X0, X1, Y0, Y1, Y2. */
+  TILEPRO_NUM_PIPELINE_ENCODINGS = 5,
+
+  /* Log base 2 of TILEPRO_BUNDLE_SIZE_IN_BYTES. */
+  TILEPRO_LOG2_BUNDLE_SIZE_IN_BYTES = 3,
+
+  /* Instructions take this many bytes. */
+  TILEPRO_BUNDLE_SIZE_IN_BYTES = 1 << TILEPRO_LOG2_BUNDLE_SIZE_IN_BYTES,
+
+  /* Log base 2 of TILEPRO_BUNDLE_ALIGNMENT_IN_BYTES. */
+  TILEPRO_LOG2_BUNDLE_ALIGNMENT_IN_BYTES = 3,
+
+  /* Bundles should be aligned modulo this number of bytes. */
+  TILEPRO_BUNDLE_ALIGNMENT_IN_BYTES =
+    (1 << TILEPRO_LOG2_BUNDLE_ALIGNMENT_IN_BYTES),
+
+  /* Log base 2 of TILEPRO_SN_INSTRUCTION_SIZE_IN_BYTES. */
+  TILEPRO_LOG2_SN_INSTRUCTION_SIZE_IN_BYTES = 1,
+
+  /* Static network instructions take this many bytes. */
+  TILEPRO_SN_INSTRUCTION_SIZE_IN_BYTES =
+    (1 << TILEPRO_LOG2_SN_INSTRUCTION_SIZE_IN_BYTES),
+
+  /* Number of registers (some are magic, such as network I/O). */
+  TILEPRO_NUM_REGISTERS = 64,
+
+  /* Number of static network registers. */
+  TILEPRO_NUM_SN_REGISTERS = 4
+};
+
+/* Make a few "tile_" variables to simplify common code between
+   architectures.  */
+
+typedef tilepro_bundle_bits tile_bundle_bits;
+#define TILE_BUNDLE_SIZE_IN_BYTES TILEPRO_BUNDLE_SIZE_IN_BYTES
+#define TILE_BUNDLE_ALIGNMENT_IN_BYTES TILEPRO_BUNDLE_ALIGNMENT_IN_BYTES
+#define TILE_LOG2_BUNDLE_ALIGNMENT_IN_BYTES \
+  TILEPRO_LOG2_BUNDLE_ALIGNMENT_IN_BYTES
+
+/* 64-bit pattern for a { bpt ; nop } bundle. */
+#define TILEPRO_BPT_BUNDLE 0x400b3cae70166000ULL
+
+static __inline unsigned int
+get_BrOff_SN(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 0)) & 0x3ff);
+}
+
+static __inline unsigned int
+get_BrOff_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0x00007fff) |
+         (((unsigned int)(n >> 20)) & 0x00018000);
+}
+
+static __inline unsigned int
+get_BrType_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 31)) & 0xf);
+}
+
+static __inline unsigned int
+get_Dest_Imm8_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 31)) & 0x0000003f) |
+         (((unsigned int)(n >> 43)) & 0x000000c0);
+}
+
+static __inline unsigned int
+get_Dest_SN(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 2)) & 0x3);
+}
+
+static __inline unsigned int
+get_Dest_X0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 0)) & 0x3f);
+}
+
+static __inline unsigned int
+get_Dest_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 31)) & 0x3f);
+}
+
+static __inline unsigned int
+get_Dest_Y0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 0)) & 0x3f);
+}
+
+static __inline unsigned int
+get_Dest_Y1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 31)) & 0x3f);
+}
+
+static __inline unsigned int
+get_Imm16_X0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0xffff);
+}
+
+static __inline unsigned int
+get_Imm16_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0xffff);
+}
+
+static __inline unsigned int
+get_Imm8_SN(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 0)) & 0xff);
+}
+
+static __inline unsigned int
+get_Imm8_X0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0xff);
+}
+
+static __inline unsigned int
+get_Imm8_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0xff);
+}
+
+static __inline unsigned int
+get_Imm8_Y0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0xff);
+}
+
+static __inline unsigned int
+get_Imm8_Y1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0xff);
+}
+
+static __inline unsigned int
+get_ImmOpcodeExtension_X0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 20)) & 0x7f);
+}
+
+static __inline unsigned int
+get_ImmOpcodeExtension_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 51)) & 0x7f);
+}
+
+static __inline unsigned int
+get_ImmRROpcodeExtension_SN(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 8)) & 0x3);
+}
+
+static __inline unsigned int
+get_JOffLong_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0x00007fff) |
+         (((unsigned int)(n >> 20)) & 0x00018000) |
+         (((unsigned int)(n >> 14)) & 0x001e0000) |
+         (((unsigned int)(n >> 16)) & 0x07e00000) |
+         (((unsigned int)(n >> 31)) & 0x18000000);
+}
+
+static __inline unsigned int
+get_JOff_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0x00007fff) |
+         (((unsigned int)(n >> 20)) & 0x00018000) |
+         (((unsigned int)(n >> 14)) & 0x001e0000) |
+         (((unsigned int)(n >> 16)) & 0x07e00000) |
+         (((unsigned int)(n >> 31)) & 0x08000000);
+}
+
+static __inline unsigned int
+get_MF_Imm15_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 37)) & 0x00003fff) |
+         (((unsigned int)(n >> 44)) & 0x00004000);
+}
+
+static __inline unsigned int
+get_MMEnd_X0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 18)) & 0x1f);
+}
+
+static __inline unsigned int
+get_MMEnd_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 49)) & 0x1f);
+}
+
+static __inline unsigned int
+get_MMStart_X0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 23)) & 0x1f);
+}
+
+static __inline unsigned int
+get_MMStart_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 54)) & 0x1f);
+}
+
+static __inline unsigned int
+get_MT_Imm15_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 31)) & 0x0000003f) |
+         (((unsigned int)(n >> 37)) & 0x00003fc0) |
+         (((unsigned int)(n >> 44)) & 0x00004000);
+}
+
+static __inline unsigned int
+get_Mode(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 63)) & 0x1);
+}
+
+static __inline unsigned int
+get_NoRegOpcodeExtension_SN(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 0)) & 0xf);
+}
+
+static __inline unsigned int
+get_Opcode_SN(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 10)) & 0x3f);
+}
+
+static __inline unsigned int
+get_Opcode_X0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 28)) & 0x7);
+}
+
+static __inline unsigned int
+get_Opcode_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 59)) & 0xf);
+}
+
+static __inline unsigned int
+get_Opcode_Y0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 27)) & 0xf);
+}
+
+static __inline unsigned int
+get_Opcode_Y1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 59)) & 0xf);
+}
+
+static __inline unsigned int
+get_Opcode_Y2(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 56)) & 0x7);
+}
+
+static __inline unsigned int
+get_RROpcodeExtension_SN(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 4)) & 0xf);
+}
+
+static __inline unsigned int
+get_RRROpcodeExtension_X0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 18)) & 0x1ff);
+}
+
+static __inline unsigned int
+get_RRROpcodeExtension_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 49)) & 0x1ff);
+}
+
+static __inline unsigned int
+get_RRROpcodeExtension_Y0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 18)) & 0x3);
+}
+
+static __inline unsigned int
+get_RRROpcodeExtension_Y1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 49)) & 0x3);
+}
+
+static __inline unsigned int
+get_RouteOpcodeExtension_SN(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 0)) & 0x3ff);
+}
+
+static __inline unsigned int
+get_S_X0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 27)) & 0x1);
+}
+
+static __inline unsigned int
+get_S_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 58)) & 0x1);
+}
+
+static __inline unsigned int
+get_ShAmt_X0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0x1f);
+}
+
+static __inline unsigned int
+get_ShAmt_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0x1f);
+}
+
+static __inline unsigned int
+get_ShAmt_Y0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0x1f);
+}
+
+static __inline unsigned int
+get_ShAmt_Y1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0x1f);
+}
+
+static __inline unsigned int
+get_SrcA_X0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 6)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcA_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 37)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcA_Y0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 6)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcA_Y1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 37)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcA_Y2(tilepro_bundle_bits n)
+{
+  return (((n >> 26)) & 0x00000001) |
+         (((unsigned int)(n >> 50)) & 0x0000003e);
+}
+
+static __inline unsigned int
+get_SrcBDest_Y2(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 20)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcB_X0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcB_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcB_Y0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0x3f);
+}
+
+static __inline unsigned int
+get_SrcB_Y1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0x3f);
+}
+
+static __inline unsigned int
+get_Src_SN(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 0)) & 0x3);
+}
+
+static __inline unsigned int
+get_UnOpcodeExtension_X0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0x1f);
+}
+
+static __inline unsigned int
+get_UnOpcodeExtension_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0x1f);
+}
+
+static __inline unsigned int
+get_UnOpcodeExtension_Y0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 12)) & 0x1f);
+}
+
+static __inline unsigned int
+get_UnOpcodeExtension_Y1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 43)) & 0x1f);
+}
+
+static __inline unsigned int
+get_UnShOpcodeExtension_X0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 17)) & 0x3ff);
+}
+
+static __inline unsigned int
+get_UnShOpcodeExtension_X1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 48)) & 0x3ff);
+}
+
+static __inline unsigned int
+get_UnShOpcodeExtension_Y0(tilepro_bundle_bits num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((n >> 17)) & 0x7);
+}
+
+static __inline unsigned int
+get_UnShOpcodeExtension_Y1(tilepro_bundle_bits n)
+{
+  return (((unsigned int)(n >> 48)) & 0x7);
+}
+
+
+static __inline int
+sign_extend(int n, int num_bits)
+{
+  int shift = (int)(sizeof(int) * 8 - num_bits);
+  return (n << shift) >> shift;
+}
+
+
+
+static __inline tilepro_bundle_bits
+create_BrOff_SN(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3ff) << 0);
+}
+
+static __inline tilepro_bundle_bits
+create_BrOff_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x00007fff)) << 43) |
+         (((tilepro_bundle_bits)(n & 0x00018000)) << 20);
+}
+
+static __inline tilepro_bundle_bits
+create_BrType_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0xf)) << 31);
+}
+
+static __inline tilepro_bundle_bits
+create_Dest_Imm8_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x0000003f)) << 31) |
+         (((tilepro_bundle_bits)(n & 0x000000c0)) << 43);
+}
+
+static __inline tilepro_bundle_bits
+create_Dest_SN(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3) << 2);
+}
+
+static __inline tilepro_bundle_bits
+create_Dest_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 0);
+}
+
+static __inline tilepro_bundle_bits
+create_Dest_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x3f)) << 31);
+}
+
+static __inline tilepro_bundle_bits
+create_Dest_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 0);
+}
+
+static __inline tilepro_bundle_bits
+create_Dest_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x3f)) << 31);
+}
+
+static __inline tilepro_bundle_bits
+create_Imm16_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0xffff) << 12);
+}
+
+static __inline tilepro_bundle_bits
+create_Imm16_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0xffff)) << 43);
+}
+
+static __inline tilepro_bundle_bits
+create_Imm8_SN(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0xff) << 0);
+}
+
+static __inline tilepro_bundle_bits
+create_Imm8_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0xff) << 12);
+}
+
+static __inline tilepro_bundle_bits
+create_Imm8_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0xff)) << 43);
+}
+
+static __inline tilepro_bundle_bits
+create_Imm8_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0xff) << 12);
+}
+
+static __inline tilepro_bundle_bits
+create_Imm8_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0xff)) << 43);
+}
+
+static __inline tilepro_bundle_bits
+create_ImmOpcodeExtension_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x7f) << 20);
+}
+
+static __inline tilepro_bundle_bits
+create_ImmOpcodeExtension_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x7f)) << 51);
+}
+
+static __inline tilepro_bundle_bits
+create_ImmRROpcodeExtension_SN(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3) << 8);
+}
+
+static __inline tilepro_bundle_bits
+create_JOffLong_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x00007fff)) << 43) |
+         (((tilepro_bundle_bits)(n & 0x00018000)) << 20) |
+         (((tilepro_bundle_bits)(n & 0x001e0000)) << 14) |
+         (((tilepro_bundle_bits)(n & 0x07e00000)) << 16) |
+         (((tilepro_bundle_bits)(n & 0x18000000)) << 31);
+}
+
+static __inline tilepro_bundle_bits
+create_JOff_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x00007fff)) << 43) |
+         (((tilepro_bundle_bits)(n & 0x00018000)) << 20) |
+         (((tilepro_bundle_bits)(n & 0x001e0000)) << 14) |
+         (((tilepro_bundle_bits)(n & 0x07e00000)) << 16) |
+         (((tilepro_bundle_bits)(n & 0x08000000)) << 31);
+}
+
+static __inline tilepro_bundle_bits
+create_MF_Imm15_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x00003fff)) << 37) |
+         (((tilepro_bundle_bits)(n & 0x00004000)) << 44);
+}
+
+static __inline tilepro_bundle_bits
+create_MMEnd_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x1f) << 18);
+}
+
+static __inline tilepro_bundle_bits
+create_MMEnd_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x1f)) << 49);
+}
+
+static __inline tilepro_bundle_bits
+create_MMStart_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x1f) << 23);
+}
+
+static __inline tilepro_bundle_bits
+create_MMStart_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x1f)) << 54);
+}
+
+static __inline tilepro_bundle_bits
+create_MT_Imm15_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x0000003f)) << 31) |
+         (((tilepro_bundle_bits)(n & 0x00003fc0)) << 37) |
+         (((tilepro_bundle_bits)(n & 0x00004000)) << 44);
+}
+
+static __inline tilepro_bundle_bits
+create_Mode(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x1)) << 63);
+}
+
+static __inline tilepro_bundle_bits
+create_NoRegOpcodeExtension_SN(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0xf) << 0);
+}
+
+static __inline tilepro_bundle_bits
+create_Opcode_SN(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 10);
+}
+
+static __inline tilepro_bundle_bits
+create_Opcode_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x7) << 28);
+}
+
+static __inline tilepro_bundle_bits
+create_Opcode_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0xf)) << 59);
+}
+
+static __inline tilepro_bundle_bits
+create_Opcode_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0xf) << 27);
+}
+
+static __inline tilepro_bundle_bits
+create_Opcode_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0xf)) << 59);
+}
+
+static __inline tilepro_bundle_bits
+create_Opcode_Y2(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x7)) << 56);
+}
+
+static __inline tilepro_bundle_bits
+create_RROpcodeExtension_SN(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0xf) << 4);
+}
+
+static __inline tilepro_bundle_bits
+create_RRROpcodeExtension_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x1ff) << 18);
+}
+
+static __inline tilepro_bundle_bits
+create_RRROpcodeExtension_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x1ff)) << 49);
+}
+
+static __inline tilepro_bundle_bits
+create_RRROpcodeExtension_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3) << 18);
+}
+
+static __inline tilepro_bundle_bits
+create_RRROpcodeExtension_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x3)) << 49);
+}
+
+static __inline tilepro_bundle_bits
+create_RouteOpcodeExtension_SN(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3ff) << 0);
+}
+
+static __inline tilepro_bundle_bits
+create_S_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x1) << 27);
+}
+
+static __inline tilepro_bundle_bits
+create_S_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x1)) << 58);
+}
+
+static __inline tilepro_bundle_bits
+create_ShAmt_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x1f) << 12);
+}
+
+static __inline tilepro_bundle_bits
+create_ShAmt_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x1f)) << 43);
+}
+
+static __inline tilepro_bundle_bits
+create_ShAmt_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x1f) << 12);
+}
+
+static __inline tilepro_bundle_bits
+create_ShAmt_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x1f)) << 43);
+}
+
+static __inline tilepro_bundle_bits
+create_SrcA_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 6);
+}
+
+static __inline tilepro_bundle_bits
+create_SrcA_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x3f)) << 37);
+}
+
+static __inline tilepro_bundle_bits
+create_SrcA_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 6);
+}
+
+static __inline tilepro_bundle_bits
+create_SrcA_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x3f)) << 37);
+}
+
+static __inline tilepro_bundle_bits
+create_SrcA_Y2(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x00000001) << 26) |
+         (((tilepro_bundle_bits)(n & 0x0000003e)) << 50);
+}
+
+static __inline tilepro_bundle_bits
+create_SrcBDest_Y2(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 20);
+}
+
+static __inline tilepro_bundle_bits
+create_SrcB_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 12);
+}
+
+static __inline tilepro_bundle_bits
+create_SrcB_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x3f)) << 43);
+}
+
+static __inline tilepro_bundle_bits
+create_SrcB_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3f) << 12);
+}
+
+static __inline tilepro_bundle_bits
+create_SrcB_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x3f)) << 43);
+}
+
+static __inline tilepro_bundle_bits
+create_Src_SN(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3) << 0);
+}
+
+static __inline tilepro_bundle_bits
+create_UnOpcodeExtension_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x1f) << 12);
+}
+
+static __inline tilepro_bundle_bits
+create_UnOpcodeExtension_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x1f)) << 43);
+}
+
+static __inline tilepro_bundle_bits
+create_UnOpcodeExtension_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x1f) << 12);
+}
+
+static __inline tilepro_bundle_bits
+create_UnOpcodeExtension_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x1f)) << 43);
+}
+
+static __inline tilepro_bundle_bits
+create_UnShOpcodeExtension_X0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x3ff) << 17);
+}
+
+static __inline tilepro_bundle_bits
+create_UnShOpcodeExtension_X1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x3ff)) << 48);
+}
+
+static __inline tilepro_bundle_bits
+create_UnShOpcodeExtension_Y0(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return ((n & 0x7) << 17);
+}
+
+static __inline tilepro_bundle_bits
+create_UnShOpcodeExtension_Y1(int num)
+{
+  const unsigned int n = (unsigned int)num;
+  return (((tilepro_bundle_bits)(n & 0x7)) << 48);
+}
+
+
+enum
+{
+  ADDBS_U_SPECIAL_0_OPCODE_X0 = 98,
+  ADDBS_U_SPECIAL_0_OPCODE_X1 = 68,
+  ADDB_SPECIAL_0_OPCODE_X0 = 1,
+  ADDB_SPECIAL_0_OPCODE_X1 = 1,
+  ADDHS_SPECIAL_0_OPCODE_X0 = 99,
+  ADDHS_SPECIAL_0_OPCODE_X1 = 69,
+  ADDH_SPECIAL_0_OPCODE_X0 = 2,
+  ADDH_SPECIAL_0_OPCODE_X1 = 2,
+  ADDIB_IMM_0_OPCODE_X0 = 1,
+  ADDIB_IMM_0_OPCODE_X1 = 1,
+  ADDIH_IMM_0_OPCODE_X0 = 2,
+  ADDIH_IMM_0_OPCODE_X1 = 2,
+  ADDI_IMM_0_OPCODE_X0 = 3,
+  ADDI_IMM_0_OPCODE_X1 = 3,
+  ADDI_IMM_1_OPCODE_SN = 1,
+  ADDI_OPCODE_Y0 = 9,
+  ADDI_OPCODE_Y1 = 7,
+  ADDLIS_OPCODE_X0 = 1,
+  ADDLIS_OPCODE_X1 = 2,
+  ADDLI_OPCODE_X0 = 2,
+  ADDLI_OPCODE_X1 = 3,
+  ADDS_SPECIAL_0_OPCODE_X0 = 96,
+  ADDS_SPECIAL_0_OPCODE_X1 = 66,
+  ADD_SPECIAL_0_OPCODE_X0 = 3,
+  ADD_SPECIAL_0_OPCODE_X1 = 3,
+  ADD_SPECIAL_0_OPCODE_Y0 = 0,
+  ADD_SPECIAL_0_OPCODE_Y1 = 0,
+  ADIFFB_U_SPECIAL_0_OPCODE_X0 = 4,
+  ADIFFH_SPECIAL_0_OPCODE_X0 = 5,
+  ANDI_IMM_0_OPCODE_X0 = 1,
+  ANDI_IMM_0_OPCODE_X1 = 4,
+  ANDI_OPCODE_Y0 = 10,
+  ANDI_OPCODE_Y1 = 8,
+  AND_SPECIAL_0_OPCODE_X0 = 6,
+  AND_SPECIAL_0_OPCODE_X1 = 4,
+  AND_SPECIAL_2_OPCODE_Y0 = 0,
+  AND_SPECIAL_2_OPCODE_Y1 = 0,
+  AULI_OPCODE_X0 = 3,
+  AULI_OPCODE_X1 = 4,
+  AVGB_U_SPECIAL_0_OPCODE_X0 = 7,
+  AVGH_SPECIAL_0_OPCODE_X0 = 8,
+  BBNST_BRANCH_OPCODE_X1 = 15,
+  BBNS_BRANCH_OPCODE_X1 = 14,
+  BBNS_OPCODE_SN = 63,
+  BBST_BRANCH_OPCODE_X1 = 13,
+  BBS_BRANCH_OPCODE_X1 = 12,
+  BBS_OPCODE_SN = 62,
+  BGEZT_BRANCH_OPCODE_X1 = 7,
+  BGEZ_BRANCH_OPCODE_X1 = 6,
+  BGEZ_OPCODE_SN = 61,
+  BGZT_BRANCH_OPCODE_X1 = 5,
+  BGZ_BRANCH_OPCODE_X1 = 4,
+  BGZ_OPCODE_SN = 58,
+  BITX_UN_0_SHUN_0_OPCODE_X0 = 1,
+  BITX_UN_0_SHUN_0_OPCODE_Y0 = 1,
+  BLEZT_BRANCH_OPCODE_X1 = 11,
+  BLEZ_BRANCH_OPCODE_X1 = 10,
+  BLEZ_OPCODE_SN = 59,
+  BLZT_BRANCH_OPCODE_X1 = 9,
+  BLZ_BRANCH_OPCODE_X1 = 8,
+  BLZ_OPCODE_SN = 60,
+  BNZT_BRANCH_OPCODE_X1 = 3,
+  BNZ_BRANCH_OPCODE_X1 = 2,
+  BNZ_OPCODE_SN = 57,
+  BPT_NOREG_RR_IMM_0_OPCODE_SN = 1,
+  BRANCH_OPCODE_X1 = 5,
+  BYTEX_UN_0_SHUN_0_OPCODE_X0 = 2,
+  BYTEX_UN_0_SHUN_0_OPCODE_Y0 = 2,
+  BZT_BRANCH_OPCODE_X1 = 1,
+  BZ_BRANCH_OPCODE_X1 = 0,
+  BZ_OPCODE_SN = 56,
+  CLZ_UN_0_SHUN_0_OPCODE_X0 = 3,
+  CLZ_UN_0_SHUN_0_OPCODE_Y0 = 3,
+  CRC32_32_SPECIAL_0_OPCODE_X0 = 9,
+  CRC32_8_SPECIAL_0_OPCODE_X0 = 10,
+  CTZ_UN_0_SHUN_0_OPCODE_X0 = 4,
+  CTZ_UN_0_SHUN_0_OPCODE_Y0 = 4,
+  DRAIN_UN_0_SHUN_0_OPCODE_X1 = 1,
+  DTLBPR_UN_0_SHUN_0_OPCODE_X1 = 2,
+  DWORD_ALIGN_SPECIAL_0_OPCODE_X0 = 95,
+  FINV_UN_0_SHUN_0_OPCODE_X1 = 3,
+  FLUSH_UN_0_SHUN_0_OPCODE_X1 = 4,
+  FNOP_NOREG_RR_IMM_0_OPCODE_SN = 3,
+  FNOP_UN_0_SHUN_0_OPCODE_X0 = 5,
+  FNOP_UN_0_SHUN_0_OPCODE_X1 = 5,
+  FNOP_UN_0_SHUN_0_OPCODE_Y0 = 5,
+  FNOP_UN_0_SHUN_0_OPCODE_Y1 = 1,
+  HALT_NOREG_RR_IMM_0_OPCODE_SN = 0,
+  ICOH_UN_0_SHUN_0_OPCODE_X1 = 6,
+  ILL_UN_0_SHUN_0_OPCODE_X1 = 7,
+  ILL_UN_0_SHUN_0_OPCODE_Y1 = 2,
+  IMM_0_OPCODE_SN = 0,
+  IMM_0_OPCODE_X0 = 4,
+  IMM_0_OPCODE_X1 = 6,
+  IMM_1_OPCODE_SN = 1,
+  IMM_OPCODE_0_X0 = 5,
+  INTHB_SPECIAL_0_OPCODE_X0 = 11,
+  INTHB_SPECIAL_0_OPCODE_X1 = 5,
+  INTHH_SPECIAL_0_OPCODE_X0 = 12,
+  INTHH_SPECIAL_0_OPCODE_X1 = 6,
+  INTLB_SPECIAL_0_OPCODE_X0 = 13,
+  INTLB_SPECIAL_0_OPCODE_X1 = 7,
+  INTLH_SPECIAL_0_OPCODE_X0 = 14,
+  INTLH_SPECIAL_0_OPCODE_X1 = 8,
+  INV_UN_0_SHUN_0_OPCODE_X1 = 8,
+  IRET_UN_0_SHUN_0_OPCODE_X1 = 9,
+  JALB_OPCODE_X1 = 13,
+  JALF_OPCODE_X1 = 12,
+  JALRP_SPECIAL_0_OPCODE_X1 = 9,
+  JALRR_IMM_1_OPCODE_SN = 3,
+  JALR_RR_IMM_0_OPCODE_SN = 5,
+  JALR_SPECIAL_0_OPCODE_X1 = 10,
+  JB_OPCODE_X1 = 11,
+  JF_OPCODE_X1 = 10,
+  JRP_SPECIAL_0_OPCODE_X1 = 11,
+  JRR_IMM_1_OPCODE_SN = 2,
+  JR_RR_IMM_0_OPCODE_SN = 4,
+  JR_SPECIAL_0_OPCODE_X1 = 12,
+  LBADD_IMM_0_OPCODE_X1 = 22,
+  LBADD_U_IMM_0_OPCODE_X1 = 23,
+  LB_OPCODE_Y2 = 0,
+  LB_UN_0_SHUN_0_OPCODE_X1 = 10,
+  LB_U_OPCODE_Y2 = 1,
+  LB_U_UN_0_SHUN_0_OPCODE_X1 = 11,
+  LHADD_IMM_0_OPCODE_X1 = 24,
+  LHADD_U_IMM_0_OPCODE_X1 = 25,
+  LH_OPCODE_Y2 = 2,
+  LH_UN_0_SHUN_0_OPCODE_X1 = 12,
+  LH_U_OPCODE_Y2 = 3,
+  LH_U_UN_0_SHUN_0_OPCODE_X1 = 13,
+  LNK_SPECIAL_0_OPCODE_X1 = 13,
+  LWADD_IMM_0_OPCODE_X1 = 26,
+  LWADD_NA_IMM_0_OPCODE_X1 = 27,
+  LW_NA_UN_0_SHUN_0_OPCODE_X1 = 24,
+  LW_OPCODE_Y2 = 4,
+  LW_UN_0_SHUN_0_OPCODE_X1 = 14,
+  MAXB_U_SPECIAL_0_OPCODE_X0 = 15,
+  MAXB_U_SPECIAL_0_OPCODE_X1 = 14,
+  MAXH_SPECIAL_0_OPCODE_X0 = 16,
+  MAXH_SPECIAL_0_OPCODE_X1 = 15,
+  MAXIB_U_IMM_0_OPCODE_X0 = 4,
+  MAXIB_U_IMM_0_OPCODE_X1 = 5,
+  MAXIH_IMM_0_OPCODE_X0 = 5,
+  MAXIH_IMM_0_OPCODE_X1 = 6,
+  MFSPR_IMM_0_OPCODE_X1 = 7,
+  MF_UN_0_SHUN_0_OPCODE_X1 = 15,
+  MINB_U_SPECIAL_0_OPCODE_X0 = 17,
+  MINB_U_SPECIAL_0_OPCODE_X1 = 16,
+  MINH_SPECIAL_0_OPCODE_X0 = 18,
+  MINH_SPECIAL_0_OPCODE_X1 = 17,
+  MINIB_U_IMM_0_OPCODE_X0 = 6,
+  MINIB_U_IMM_0_OPCODE_X1 = 8,
+  MINIH_IMM_0_OPCODE_X0 = 7,
+  MINIH_IMM_0_OPCODE_X1 = 9,
+  MM_OPCODE_X0 = 6,
+  MM_OPCODE_X1 = 7,
+  MNZB_SPECIAL_0_OPCODE_X0 = 19,
+  MNZB_SPECIAL_0_OPCODE_X1 = 18,
+  MNZH_SPECIAL_0_OPCODE_X0 = 20,
+  MNZH_SPECIAL_0_OPCODE_X1 = 19,
+  MNZ_SPECIAL_0_OPCODE_X0 = 21,
+  MNZ_SPECIAL_0_OPCODE_X1 = 20,
+  MNZ_SPECIAL_1_OPCODE_Y0 = 0,
+  MNZ_SPECIAL_1_OPCODE_Y1 = 1,
+  MOVEI_IMM_1_OPCODE_SN = 0,
+  MOVE_RR_IMM_0_OPCODE_SN = 8,
+  MTSPR_IMM_0_OPCODE_X1 = 10,
+  MULHHA_SS_SPECIAL_0_OPCODE_X0 = 22,
+  MULHHA_SS_SPECIAL_7_OPCODE_Y0 = 0,
+  MULHHA_SU_SPECIAL_0_OPCODE_X0 = 23,
+  MULHHA_UU_SPECIAL_0_OPCODE_X0 = 24,
+  MULHHA_UU_SPECIAL_7_OPCODE_Y0 = 1,
+  MULHHSA_UU_SPECIAL_0_OPCODE_X0 = 25,
+  MULHH_SS_SPECIAL_0_OPCODE_X0 = 26,
+  MULHH_SS_SPECIAL_6_OPCODE_Y0 = 0,
+  MULHH_SU_SPECIAL_0_OPCODE_X0 = 27,
+  MULHH_UU_SPECIAL_0_OPCODE_X0 = 28,
+  MULHH_UU_SPECIAL_6_OPCODE_Y0 = 1,
+  MULHLA_SS_SPECIAL_0_OPCODE_X0 = 29,
+  MULHLA_SU_SPECIAL_0_OPCODE_X0 = 30,
+  MULHLA_US_SPECIAL_0_OPCODE_X0 = 31,
+  MULHLA_UU_SPECIAL_0_OPCODE_X0 = 32,
+  MULHLSA_UU_SPECIAL_0_OPCODE_X0 = 33,
+  MULHLSA_UU_SPECIAL_5_OPCODE_Y0 = 0,
+  MULHL_SS_SPECIAL_0_OPCODE_X0 = 34,
+  MULHL_SU_SPECIAL_0_OPCODE_X0 = 35,
+  MULHL_US_SPECIAL_0_OPCODE_X0 = 36,
+  MULHL_UU_SPECIAL_0_OPCODE_X0 = 37,
+  MULLLA_SS_SPECIAL_0_OPCODE_X0 = 38,
+  MULLLA_SS_SPECIAL_7_OPCODE_Y0 = 2,
+  MULLLA_SU_SPECIAL_0_OPCODE_X0 = 39,
+  MULLLA_UU_SPECIAL_0_OPCODE_X0 = 40,
+  MULLLA_UU_SPECIAL_7_OPCODE_Y0 = 3,
+  MULLLSA_UU_SPECIAL_0_OPCODE_X0 = 41,
+  MULLL_SS_SPECIAL_0_OPCODE_X0 = 42,
+  MULLL_SS_SPECIAL_6_OPCODE_Y0 = 2,
+  MULLL_SU_SPECIAL_0_OPCODE_X0 = 43,
+  MULLL_UU_SPECIAL_0_OPCODE_X0 = 44,
+  MULLL_UU_SPECIAL_6_OPCODE_Y0 = 3,
+  MVNZ_SPECIAL_0_OPCODE_X0 = 45,
+  MVNZ_SPECIAL_1_OPCODE_Y0 = 1,
+  MVZ_SPECIAL_0_OPCODE_X0 = 46,
+  MVZ_SPECIAL_1_OPCODE_Y0 = 2,
+  MZB_SPECIAL_0_OPCODE_X0 = 47,
+  MZB_SPECIAL_0_OPCODE_X1 = 21,
+  MZH_SPECIAL_0_OPCODE_X0 = 48,
+  MZH_SPECIAL_0_OPCODE_X1 = 22,
+  MZ_SPECIAL_0_OPCODE_X0 = 49,
+  MZ_SPECIAL_0_OPCODE_X1 = 23,
+  MZ_SPECIAL_1_OPCODE_Y0 = 3,
+  MZ_SPECIAL_1_OPCODE_Y1 = 2,
+  NAP_UN_0_SHUN_0_OPCODE_X1 = 16,
+  NOP_NOREG_RR_IMM_0_OPCODE_SN = 2,
+  NOP_UN_0_SHUN_0_OPCODE_X0 = 6,
+  NOP_UN_0_SHUN_0_OPCODE_X1 = 17,
+  NOP_UN_0_SHUN_0_OPCODE_Y0 = 6,
+  NOP_UN_0_SHUN_0_OPCODE_Y1 = 3,
+  NOREG_RR_IMM_0_OPCODE_SN = 0,
+  NOR_SPECIAL_0_OPCODE_X0 = 50,
+  NOR_SPECIAL_0_OPCODE_X1 = 24,
+  NOR_SPECIAL_2_OPCODE_Y0 = 1,
+  NOR_SPECIAL_2_OPCODE_Y1 = 1,
+  ORI_IMM_0_OPCODE_X0 = 8,
+  ORI_IMM_0_OPCODE_X1 = 11,
+  ORI_OPCODE_Y0 = 11,
+  ORI_OPCODE_Y1 = 9,
+  OR_SPECIAL_0_OPCODE_X0 = 51,
+  OR_SPECIAL_0_OPCODE_X1 = 25,
+  OR_SPECIAL_2_OPCODE_Y0 = 2,
+  OR_SPECIAL_2_OPCODE_Y1 = 2,
+  PACKBS_U_SPECIAL_0_OPCODE_X0 = 103,
+  PACKBS_U_SPECIAL_0_OPCODE_X1 = 73,
+  PACKHB_SPECIAL_0_OPCODE_X0 = 52,
+  PACKHB_SPECIAL_0_OPCODE_X1 = 26,
+  PACKHS_SPECIAL_0_OPCODE_X0 = 102,
+  PACKHS_SPECIAL_0_OPCODE_X1 = 72,
+  PACKLB_SPECIAL_0_OPCODE_X0 = 53,
+  PACKLB_SPECIAL_0_OPCODE_X1 = 27,
+  PCNT_UN_0_SHUN_0_OPCODE_X0 = 7,
+  PCNT_UN_0_SHUN_0_OPCODE_Y0 = 7,
+  RLI_SHUN_0_OPCODE_X0 = 1,
+  RLI_SHUN_0_OPCODE_X1 = 1,
+  RLI_SHUN_0_OPCODE_Y0 = 1,
+  RLI_SHUN_0_OPCODE_Y1 = 1,
+  RL_SPECIAL_0_OPCODE_X0 = 54,
+  RL_SPECIAL_0_OPCODE_X1 = 28,
+  RL_SPECIAL_3_OPCODE_Y0 = 0,
+  RL_SPECIAL_3_OPCODE_Y1 = 0,
+  RR_IMM_0_OPCODE_SN = 0,
+  S1A_SPECIAL_0_OPCODE_X0 = 55,
+  S1A_SPECIAL_0_OPCODE_X1 = 29,
+  S1A_SPECIAL_0_OPCODE_Y0 = 1,
+  S1A_SPECIAL_0_OPCODE_Y1 = 1,
+  S2A_SPECIAL_0_OPCODE_X0 = 56,
+  S2A_SPECIAL_0_OPCODE_X1 = 30,
+  S2A_SPECIAL_0_OPCODE_Y0 = 2,
+  S2A_SPECIAL_0_OPCODE_Y1 = 2,
+  S3A_SPECIAL_0_OPCODE_X0 = 57,
+  S3A_SPECIAL_0_OPCODE_X1 = 31,
+  S3A_SPECIAL_5_OPCODE_Y0 = 1,
+  S3A_SPECIAL_5_OPCODE_Y1 = 1,
+  SADAB_U_SPECIAL_0_OPCODE_X0 = 58,
+  SADAH_SPECIAL_0_OPCODE_X0 = 59,
+  SADAH_U_SPECIAL_0_OPCODE_X0 = 60,
+  SADB_U_SPECIAL_0_OPCODE_X0 = 61,
+  SADH_SPECIAL_0_OPCODE_X0 = 62,
+  SADH_U_SPECIAL_0_OPCODE_X0 = 63,
+  SBADD_IMM_0_OPCODE_X1 = 28,
+  SB_OPCODE_Y2 = 5,
+  SB_SPECIAL_0_OPCODE_X1 = 32,
+  SEQB_SPECIAL_0_OPCODE_X0 = 64,
+  SEQB_SPECIAL_0_OPCODE_X1 = 33,
+  SEQH_SPECIAL_0_OPCODE_X0 = 65,
+  SEQH_SPECIAL_0_OPCODE_X1 = 34,
+  SEQIB_IMM_0_OPCODE_X0 = 9,
+  SEQIB_IMM_0_OPCODE_X1 = 12,
+  SEQIH_IMM_0_OPCODE_X0 = 10,
+  SEQIH_IMM_0_OPCODE_X1 = 13,
+  SEQI_IMM_0_OPCODE_X0 = 11,
+  SEQI_IMM_0_OPCODE_X1 = 14,
+  SEQI_OPCODE_Y0 = 12,
+  SEQI_OPCODE_Y1 = 10,
+  SEQ_SPECIAL_0_OPCODE_X0 = 66,
+  SEQ_SPECIAL_0_OPCODE_X1 = 35,
+  SEQ_SPECIAL_5_OPCODE_Y0 = 2,
+  SEQ_SPECIAL_5_OPCODE_Y1 = 2,
+  SHADD_IMM_0_OPCODE_X1 = 29,
+  SHL8II_IMM_0_OPCODE_SN = 3,
+  SHLB_SPECIAL_0_OPCODE_X0 = 67,
+  SHLB_SPECIAL_0_OPCODE_X1 = 36,
+  SHLH_SPECIAL_0_OPCODE_X0 = 68,
+  SHLH_SPECIAL_0_OPCODE_X1 = 37,
+  SHLIB_SHUN_0_OPCODE_X0 = 2,
+  SHLIB_SHUN_0_OPCODE_X1 = 2,
+  SHLIH_SHUN_0_OPCODE_X0 = 3,
+  SHLIH_SHUN_0_OPCODE_X1 = 3,
+  SHLI_SHUN_0_OPCODE_X0 = 4,
+  SHLI_SHUN_0_OPCODE_X1 = 4,
+  SHLI_SHUN_0_OPCODE_Y0 = 2,
+  SHLI_SHUN_0_OPCODE_Y1 = 2,
+  SHL_SPECIAL_0_OPCODE_X0 = 69,
+  SHL_SPECIAL_0_OPCODE_X1 = 38,
+  SHL_SPECIAL_3_OPCODE_Y0 = 1,
+  SHL_SPECIAL_3_OPCODE_Y1 = 1,
+  SHR1_RR_IMM_0_OPCODE_SN = 9,
+  SHRB_SPECIAL_0_OPCODE_X0 = 70,
+  SHRB_SPECIAL_0_OPCODE_X1 = 39,
+  SHRH_SPECIAL_0_OPCODE_X0 = 71,
+  SHRH_SPECIAL_0_OPCODE_X1 = 40,
+  SHRIB_SHUN_0_OPCODE_X0 = 5,
+  SHRIB_SHUN_0_OPCODE_X1 = 5,
+  SHRIH_SHUN_0_OPCODE_X0 = 6,
+  SHRIH_SHUN_0_OPCODE_X1 = 6,
+  SHRI_SHUN_0_OPCODE_X0 = 7,
+  SHRI_SHUN_0_OPCODE_X1 = 7,
+  SHRI_SHUN_0_OPCODE_Y0 = 3,
+  SHRI_SHUN_0_OPCODE_Y1 = 3,
+  SHR_SPECIAL_0_OPCODE_X0 = 72,
+  SHR_SPECIAL_0_OPCODE_X1 = 41,
+  SHR_SPECIAL_3_OPCODE_Y0 = 2,
+  SHR_SPECIAL_3_OPCODE_Y1 = 2,
+  SHUN_0_OPCODE_X0 = 7,
+  SHUN_0_OPCODE_X1 = 8,
+  SHUN_0_OPCODE_Y0 = 13,
+  SHUN_0_OPCODE_Y1 = 11,
+  SH_OPCODE_Y2 = 6,
+  SH_SPECIAL_0_OPCODE_X1 = 42,
+  SLTB_SPECIAL_0_OPCODE_X0 = 73,
+  SLTB_SPECIAL_0_OPCODE_X1 = 43,
+  SLTB_U_SPECIAL_0_OPCODE_X0 = 74,
+  SLTB_U_SPECIAL_0_OPCODE_X1 = 44,
+  SLTEB_SPECIAL_0_OPCODE_X0 = 75,
+  SLTEB_SPECIAL_0_OPCODE_X1 = 45,
+  SLTEB_U_SPECIAL_0_OPCODE_X0 = 76,
+  SLTEB_U_SPECIAL_0_OPCODE_X1 = 46,
+  SLTEH_SPECIAL_0_OPCODE_X0 = 77,
+  SLTEH_SPECIAL_0_OPCODE_X1 = 47,
+  SLTEH_U_SPECIAL_0_OPCODE_X0 = 78,
+  SLTEH_U_SPECIAL_0_OPCODE_X1 = 48,
+  SLTE_SPECIAL_0_OPCODE_X0 = 79,
+  SLTE_SPECIAL_0_OPCODE_X1 = 49,
+  SLTE_SPECIAL_4_OPCODE_Y0 = 0,
+  SLTE_SPECIAL_4_OPCODE_Y1 = 0,
+  SLTE_U_SPECIAL_0_OPCODE_X0 = 80,
+  SLTE_U_SPECIAL_0_OPCODE_X1 = 50,
+  SLTE_U_SPECIAL_4_OPCODE_Y0 = 1,
+  SLTE_U_SPECIAL_4_OPCODE_Y1 = 1,
+  SLTH_SPECIAL_0_OPCODE_X0 = 81,
+  SLTH_SPECIAL_0_OPCODE_X1 = 51,
+  SLTH_U_SPECIAL_0_OPCODE_X0 = 82,
+  SLTH_U_SPECIAL_0_OPCODE_X1 = 52,
+  SLTIB_IMM_0_OPCODE_X0 = 12,
+  SLTIB_IMM_0_OPCODE_X1 = 15,
+  SLTIB_U_IMM_0_OPCODE_X0 = 13,
+  SLTIB_U_IMM_0_OPCODE_X1 = 16,
+  SLTIH_IMM_0_OPCODE_X0 = 14,
+  SLTIH_IMM_0_OPCODE_X1 = 17,
+  SLTIH_U_IMM_0_OPCODE_X0 = 15,
+  SLTIH_U_IMM_0_OPCODE_X1 = 18,
+  SLTI_IMM_0_OPCODE_X0 = 16,
+  SLTI_IMM_0_OPCODE_X1 = 19,
+  SLTI_OPCODE_Y0 = 14,
+  SLTI_OPCODE_Y1 = 12,
+  SLTI_U_IMM_0_OPCODE_X0 = 17,
+  SLTI_U_IMM_0_OPCODE_X1 = 20,
+  SLTI_U_OPCODE_Y0 = 15,
+  SLTI_U_OPCODE_Y1 = 13,
+  SLT_SPECIAL_0_OPCODE_X0 = 83,
+  SLT_SPECIAL_0_OPCODE_X1 = 53,
+  SLT_SPECIAL_4_OPCODE_Y0 = 2,
+  SLT_SPECIAL_4_OPCODE_Y1 = 2,
+  SLT_U_SPECIAL_0_OPCODE_X0 = 84,
+  SLT_U_SPECIAL_0_OPCODE_X1 = 54,
+  SLT_U_SPECIAL_4_OPCODE_Y0 = 3,
+  SLT_U_SPECIAL_4_OPCODE_Y1 = 3,
+  SNEB_SPECIAL_0_OPCODE_X0 = 85,
+  SNEB_SPECIAL_0_OPCODE_X1 = 55,
+  SNEH_SPECIAL_0_OPCODE_X0 = 86,
+  SNEH_SPECIAL_0_OPCODE_X1 = 56,
+  SNE_SPECIAL_0_OPCODE_X0 = 87,
+  SNE_SPECIAL_0_OPCODE_X1 = 57,
+  SNE_SPECIAL_5_OPCODE_Y0 = 3,
+  SNE_SPECIAL_5_OPCODE_Y1 = 3,
+  SPECIAL_0_OPCODE_X0 = 0,
+  SPECIAL_0_OPCODE_X1 = 1,
+  SPECIAL_0_OPCODE_Y0 = 1,
+  SPECIAL_0_OPCODE_Y1 = 1,
+  SPECIAL_1_OPCODE_Y0 = 2,
+  SPECIAL_1_OPCODE_Y1 = 2,
+  SPECIAL_2_OPCODE_Y0 = 3,
+  SPECIAL_2_OPCODE_Y1 = 3,
+  SPECIAL_3_OPCODE_Y0 = 4,
+  SPECIAL_3_OPCODE_Y1 = 4,
+  SPECIAL_4_OPCODE_Y0 = 5,
+  SPECIAL_4_OPCODE_Y1 = 5,
+  SPECIAL_5_OPCODE_Y0 = 6,
+  SPECIAL_5_OPCODE_Y1 = 6,
+  SPECIAL_6_OPCODE_Y0 = 7,
+  SPECIAL_7_OPCODE_Y0 = 8,
+  SRAB_SPECIAL_0_OPCODE_X0 = 88,
+  SRAB_SPECIAL_0_OPCODE_X1 = 58,
+  SRAH_SPECIAL_0_OPCODE_X0 = 89,
+  SRAH_SPECIAL_0_OPCODE_X1 = 59,
+  SRAIB_SHUN_0_OPCODE_X0 = 8,
+  SRAIB_SHUN_0_OPCODE_X1 = 8,
+  SRAIH_SHUN_0_OPCODE_X0 = 9,
+  SRAIH_SHUN_0_OPCODE_X1 = 9,
+  SRAI_SHUN_0_OPCODE_X0 = 10,
+  SRAI_SHUN_0_OPCODE_X1 = 10,
+  SRAI_SHUN_0_OPCODE_Y0 = 4,
+  SRAI_SHUN_0_OPCODE_Y1 = 4,
+  SRA_SPECIAL_0_OPCODE_X0 = 90,
+  SRA_SPECIAL_0_OPCODE_X1 = 60,
+  SRA_SPECIAL_3_OPCODE_Y0 = 3,
+  SRA_SPECIAL_3_OPCODE_Y1 = 3,
+  SUBBS_U_SPECIAL_0_OPCODE_X0 = 100,
+  SUBBS_U_SPECIAL_0_OPCODE_X1 = 70,
+  SUBB_SPECIAL_0_OPCODE_X0 = 91,
+  SUBB_SPECIAL_0_OPCODE_X1 = 61,
+  SUBHS_SPECIAL_0_OPCODE_X0 = 101,
+  SUBHS_SPECIAL_0_OPCODE_X1 = 71,
+  SUBH_SPECIAL_0_OPCODE_X0 = 92,
+  SUBH_SPECIAL_0_OPCODE_X1 = 62,
+  SUBS_SPECIAL_0_OPCODE_X0 = 97,
+  SUBS_SPECIAL_0_OPCODE_X1 = 67,
+  SUB_SPECIAL_0_OPCODE_X0 = 93,
+  SUB_SPECIAL_0_OPCODE_X1 = 63,
+  SUB_SPECIAL_0_OPCODE_Y0 = 3,
+  SUB_SPECIAL_0_OPCODE_Y1 = 3,
+  SWADD_IMM_0_OPCODE_X1 = 30,
+  SWINT0_UN_0_SHUN_0_OPCODE_X1 = 18,
+  SWINT1_UN_0_SHUN_0_OPCODE_X1 = 19,
+  SWINT2_UN_0_SHUN_0_OPCODE_X1 = 20,
+  SWINT3_UN_0_SHUN_0_OPCODE_X1 = 21,
+  SW_OPCODE_Y2 = 7,
+  SW_SPECIAL_0_OPCODE_X1 = 64,
+  TBLIDXB0_UN_0_SHUN_0_OPCODE_X0 = 8,
+  TBLIDXB0_UN_0_SHUN_0_OPCODE_Y0 = 8,
+  TBLIDXB1_UN_0_SHUN_0_OPCODE_X0 = 9,
+  TBLIDXB1_UN_0_SHUN_0_OPCODE_Y0 = 9,
+  TBLIDXB2_UN_0_SHUN_0_OPCODE_X0 = 10,
+  TBLIDXB2_UN_0_SHUN_0_OPCODE_Y0 = 10,
+  TBLIDXB3_UN_0_SHUN_0_OPCODE_X0 = 11,
+  TBLIDXB3_UN_0_SHUN_0_OPCODE_Y0 = 11,
+  TNS_UN_0_SHUN_0_OPCODE_X1 = 22,
+  UN_0_SHUN_0_OPCODE_X0 = 11,
+  UN_0_SHUN_0_OPCODE_X1 = 11,
+  UN_0_SHUN_0_OPCODE_Y0 = 5,
+  UN_0_SHUN_0_OPCODE_Y1 = 5,
+  WH64_UN_0_SHUN_0_OPCODE_X1 = 23,
+  XORI_IMM_0_OPCODE_X0 = 2,
+  XORI_IMM_0_OPCODE_X1 = 21,
+  XOR_SPECIAL_0_OPCODE_X0 = 94,
+  XOR_SPECIAL_0_OPCODE_X1 = 65,
+  XOR_SPECIAL_2_OPCODE_Y0 = 3,
+  XOR_SPECIAL_2_OPCODE_Y1 = 3
+};
+
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* __ARCH_OPCODE_H__ */
index aec60dc..0bb4264 100644 (file)
@@ -1,5 +1,7 @@
 include include/asm-generic/Kbuild.asm
 
+header-y += ../arch/
+
 header-y += ucontext.h
 header-y += hardwall.h
 
diff --git a/arch/tile/include/asm/opcode-tile_32.h b/arch/tile/include/asm/opcode-tile_32.h
deleted file mode 100644 (file)
index 03df7b1..0000000
+++ /dev/null
@@ -1,1513 +0,0 @@
-/* tile.h -- Header file for TILE opcode table
-   Copyright (C) 2005 Free Software Foundation, Inc.
-   Contributed by Tilera Corp. */
-
-#ifndef opcode_tile_h
-#define opcode_tile_h
-
-typedef unsigned long long tile_bundle_bits;
-
-
-enum
-{
-  TILE_MAX_OPERANDS = 5 /* mm */
-};
-
-typedef enum
-{
-  TILE_OPC_BPT,
-  TILE_OPC_INFO,
-  TILE_OPC_INFOL,
-  TILE_OPC_J,
-  TILE_OPC_JAL,
-  TILE_OPC_MOVE,
-  TILE_OPC_MOVE_SN,
-  TILE_OPC_MOVEI,
-  TILE_OPC_MOVEI_SN,
-  TILE_OPC_MOVELI,
-  TILE_OPC_MOVELI_SN,
-  TILE_OPC_MOVELIS,
-  TILE_OPC_PREFETCH,
-  TILE_OPC_RAISE,
-  TILE_OPC_ADD,
-  TILE_OPC_ADD_SN,
-  TILE_OPC_ADDB,
-  TILE_OPC_ADDB_SN,
-  TILE_OPC_ADDBS_U,
-  TILE_OPC_ADDBS_U_SN,
-  TILE_OPC_ADDH,
-  TILE_OPC_ADDH_SN,
-  TILE_OPC_ADDHS,
-  TILE_OPC_ADDHS_SN,
-  TILE_OPC_ADDI,
-  TILE_OPC_ADDI_SN,
-  TILE_OPC_ADDIB,
-  TILE_OPC_ADDIB_SN,
-  TILE_OPC_ADDIH,
-  TILE_OPC_ADDIH_SN,
-  TILE_OPC_ADDLI,
-  TILE_OPC_ADDLI_SN,
-  TILE_OPC_ADDLIS,
-  TILE_OPC_ADDS,
-  TILE_OPC_ADDS_SN,
-  TILE_OPC_ADIFFB_U,
-  TILE_OPC_ADIFFB_U_SN,
-  TILE_OPC_ADIFFH,
-  TILE_OPC_ADIFFH_SN,
-  TILE_OPC_AND,
-  TILE_OPC_AND_SN,
-  TILE_OPC_ANDI,
-  TILE_OPC_ANDI_SN,
-  TILE_OPC_AULI,
-  TILE_OPC_AVGB_U,
-  TILE_OPC_AVGB_U_SN,
-  TILE_OPC_AVGH,
-  TILE_OPC_AVGH_SN,
-  TILE_OPC_BBNS,
-  TILE_OPC_BBNS_SN,
-  TILE_OPC_BBNST,
-  TILE_OPC_BBNST_SN,
-  TILE_OPC_BBS,
-  TILE_OPC_BBS_SN,
-  TILE_OPC_BBST,
-  TILE_OPC_BBST_SN,
-  TILE_OPC_BGEZ,
-  TILE_OPC_BGEZ_SN,
-  TILE_OPC_BGEZT,
-  TILE_OPC_BGEZT_SN,
-  TILE_OPC_BGZ,
-  TILE_OPC_BGZ_SN,
-  TILE_OPC_BGZT,
-  TILE_OPC_BGZT_SN,
-  TILE_OPC_BITX,
-  TILE_OPC_BITX_SN,
-  TILE_OPC_BLEZ,
-  TILE_OPC_BLEZ_SN,
-  TILE_OPC_BLEZT,
-  TILE_OPC_BLEZT_SN,
-  TILE_OPC_BLZ,
-  TILE_OPC_BLZ_SN,
-  TILE_OPC_BLZT,
-  TILE_OPC_BLZT_SN,
-  TILE_OPC_BNZ,
-  TILE_OPC_BNZ_SN,
-  TILE_OPC_BNZT,
-  TILE_OPC_BNZT_SN,
-  TILE_OPC_BYTEX,
-  TILE_OPC_BYTEX_SN,
-  TILE_OPC_BZ,
-  TILE_OPC_BZ_SN,
-  TILE_OPC_BZT,
-  TILE_OPC_BZT_SN,
-  TILE_OPC_CLZ,
-  TILE_OPC_CLZ_SN,
-  TILE_OPC_CRC32_32,
-  TILE_OPC_CRC32_32_SN,
-  TILE_OPC_CRC32_8,
-  TILE_OPC_CRC32_8_SN,
-  TILE_OPC_CTZ,
-  TILE_OPC_CTZ_SN,
-  TILE_OPC_DRAIN,
-  TILE_OPC_DTLBPR,
-  TILE_OPC_DWORD_ALIGN,
-  TILE_OPC_DWORD_ALIGN_SN,
-  TILE_OPC_FINV,
-  TILE_OPC_FLUSH,
-  TILE_OPC_FNOP,
-  TILE_OPC_ICOH,
-  TILE_OPC_ILL,
-  TILE_OPC_INTHB,
-  TILE_OPC_INTHB_SN,
-  TILE_OPC_INTHH,
-  TILE_OPC_INTHH_SN,
-  TILE_OPC_INTLB,
-  TILE_OPC_INTLB_SN,
-  TILE_OPC_INTLH,
-  TILE_OPC_INTLH_SN,
-  TILE_OPC_INV,
-  TILE_OPC_IRET,
-  TILE_OPC_JALB,
-  TILE_OPC_JALF,
-  TILE_OPC_JALR,
-  TILE_OPC_JALRP,
-  TILE_OPC_JB,
-  TILE_OPC_JF,
-  TILE_OPC_JR,
-  TILE_OPC_JRP,
-  TILE_OPC_LB,
-  TILE_OPC_LB_SN,
-  TILE_OPC_LB_U,
-  TILE_OPC_LB_U_SN,
-  TILE_OPC_LBADD,
-  TILE_OPC_LBADD_SN,
-  TILE_OPC_LBADD_U,
-  TILE_OPC_LBADD_U_SN,
-  TILE_OPC_LH,
-  TILE_OPC_LH_SN,
-  TILE_OPC_LH_U,
-  TILE_OPC_LH_U_SN,
-  TILE_OPC_LHADD,
-  TILE_OPC_LHADD_SN,
-  TILE_OPC_LHADD_U,
-  TILE_OPC_LHADD_U_SN,
-  TILE_OPC_LNK,
-  TILE_OPC_LNK_SN,
-  TILE_OPC_LW,
-  TILE_OPC_LW_SN,
-  TILE_OPC_LW_NA,
-  TILE_OPC_LW_NA_SN,
-  TILE_OPC_LWADD,
-  TILE_OPC_LWADD_SN,
-  TILE_OPC_LWADD_NA,
-  TILE_OPC_LWADD_NA_SN,
-  TILE_OPC_MAXB_U,
-  TILE_OPC_MAXB_U_SN,
-  TILE_OPC_MAXH,
-  TILE_OPC_MAXH_SN,
-  TILE_OPC_MAXIB_U,
-  TILE_OPC_MAXIB_U_SN,
-  TILE_OPC_MAXIH,
-  TILE_OPC_MAXIH_SN,
-  TILE_OPC_MF,
-  TILE_OPC_MFSPR,
-  TILE_OPC_MINB_U,
-  TILE_OPC_MINB_U_SN,
-  TILE_OPC_MINH,
-  TILE_OPC_MINH_SN,
-  TILE_OPC_MINIB_U,
-  TILE_OPC_MINIB_U_SN,
-  TILE_OPC_MINIH,
-  TILE_OPC_MINIH_SN,
-  TILE_OPC_MM,
-  TILE_OPC_MNZ,
-  TILE_OPC_MNZ_SN,
-  TILE_OPC_MNZB,
-  TILE_OPC_MNZB_SN,
-  TILE_OPC_MNZH,
-  TILE_OPC_MNZH_SN,
-  TILE_OPC_MTSPR,
-  TILE_OPC_MULHH_SS,
-  TILE_OPC_MULHH_SS_SN,
-  TILE_OPC_MULHH_SU,
-  TILE_OPC_MULHH_SU_SN,
-  TILE_OPC_MULHH_UU,
-  TILE_OPC_MULHH_UU_SN,
-  TILE_OPC_MULHHA_SS,
-  TILE_OPC_MULHHA_SS_SN,
-  TILE_OPC_MULHHA_SU,
-  TILE_OPC_MULHHA_SU_SN,
-  TILE_OPC_MULHHA_UU,
-  TILE_OPC_MULHHA_UU_SN,
-  TILE_OPC_MULHHSA_UU,
-  TILE_OPC_MULHHSA_UU_SN,
-  TILE_OPC_MULHL_SS,
-  TILE_OPC_MULHL_SS_SN,
-  TILE_OPC_MULHL_SU,
-  TILE_OPC_MULHL_SU_SN,
-  TILE_OPC_MULHL_US,
-  TILE_OPC_MULHL_US_SN,
-  TILE_OPC_MULHL_UU,
-  TILE_OPC_MULHL_UU_SN,
-  TILE_OPC_MULHLA_SS,
-  TILE_OPC_MULHLA_SS_SN,
-  TILE_OPC_MULHLA_SU,
-  TILE_OPC_MULHLA_SU_SN,
-  TILE_OPC_MULHLA_US,
-  TILE_OPC_MULHLA_US_SN,
-  TILE_OPC_MULHLA_UU,
-  TILE_OPC_MULHLA_UU_SN,
-  TILE_OPC_MULHLSA_UU,
-  TILE_OPC_MULHLSA_UU_SN,
-  TILE_OPC_MULLL_SS,
-  TILE_OPC_MULLL_SS_SN,
-  TILE_OPC_MULLL_SU,
-  TILE_OPC_MULLL_SU_SN,
-  TILE_OPC_MULLL_UU,
-  TILE_OPC_MULLL_UU_SN,
-  TILE_OPC_MULLLA_SS,
-  TILE_OPC_MULLLA_SS_SN,
-  TILE_OPC_MULLLA_SU,
-  TILE_OPC_MULLLA_SU_SN,
-  TILE_OPC_MULLLA_UU,
-  TILE_OPC_MULLLA_UU_SN,
-  TILE_OPC_MULLLSA_UU,
-  TILE_OPC_MULLLSA_UU_SN,
-  TILE_OPC_MVNZ,
-  TILE_OPC_MVNZ_SN,
-  TILE_OPC_MVZ,
-  TILE_OPC_MVZ_SN,
-  TILE_OPC_MZ,
-  TILE_OPC_MZ_SN,
-  TILE_OPC_MZB,
-  TILE_OPC_MZB_SN,
-  TILE_OPC_MZH,
-  TILE_OPC_MZH_SN,
-  TILE_OPC_NAP,
-  TILE_OPC_NOP,
-  TILE_OPC_NOR,
-  TILE_OPC_NOR_SN,
-  TILE_OPC_OR,
-  TILE_OPC_OR_SN,
-  TILE_OPC_ORI,
-  TILE_OPC_ORI_SN,
-  TILE_OPC_PACKBS_U,
-  TILE_OPC_PACKBS_U_SN,
-  TILE_OPC_PACKHB,
-  TILE_OPC_PACKHB_SN,
-  TILE_OPC_PACKHS,
-  TILE_OPC_PACKHS_SN,
-  TILE_OPC_PACKLB,
-  TILE_OPC_PACKLB_SN,
-  TILE_OPC_PCNT,
-  TILE_OPC_PCNT_SN,
-  TILE_OPC_RL,
-  TILE_OPC_RL_SN,
-  TILE_OPC_RLI,
-  TILE_OPC_RLI_SN,
-  TILE_OPC_S1A,
-  TILE_OPC_S1A_SN,
-  TILE_OPC_S2A,
-  TILE_OPC_S2A_SN,
-  TILE_OPC_S3A,
-  TILE_OPC_S3A_SN,
-  TILE_OPC_SADAB_U,
-  TILE_OPC_SADAB_U_SN,
-  TILE_OPC_SADAH,
-  TILE_OPC_SADAH_SN,
-  TILE_OPC_SADAH_U,
-  TILE_OPC_SADAH_U_SN,
-  TILE_OPC_SADB_U,
-  TILE_OPC_SADB_U_SN,
-  TILE_OPC_SADH,
-  TILE_OPC_SADH_SN,
-  TILE_OPC_SADH_U,
-  TILE_OPC_SADH_U_SN,
-  TILE_OPC_SB,
-  TILE_OPC_SBADD,
-  TILE_OPC_SEQ,
-  TILE_OPC_SEQ_SN,
-  TILE_OPC_SEQB,
-  TILE_OPC_SEQB_SN,
-  TILE_OPC_SEQH,
-  TILE_OPC_SEQH_SN,
-  TILE_OPC_SEQI,
-  TILE_OPC_SEQI_SN,
-  TILE_OPC_SEQIB,
-  TILE_OPC_SEQIB_SN,
-  TILE_OPC_SEQIH,
-  TILE_OPC_SEQIH_SN,
-  TILE_OPC_SH,
-  TILE_OPC_SHADD,
-  TILE_OPC_SHL,
-  TILE_OPC_SHL_SN,
-  TILE_OPC_SHLB,
-  TILE_OPC_SHLB_SN,
-  TILE_OPC_SHLH,
-  TILE_OPC_SHLH_SN,
-  TILE_OPC_SHLI,
-  TILE_OPC_SHLI_SN,
-  TILE_OPC_SHLIB,
-  TILE_OPC_SHLIB_SN,
-  TILE_OPC_SHLIH,
-  TILE_OPC_SHLIH_SN,
-  TILE_OPC_SHR,
-  TILE_OPC_SHR_SN,
-  TILE_OPC_SHRB,
-  TILE_OPC_SHRB_SN,
-  TILE_OPC_SHRH,
-  TILE_OPC_SHRH_SN,
-  TILE_OPC_SHRI,
-  TILE_OPC_SHRI_SN,
-  TILE_OPC_SHRIB,
-  TILE_OPC_SHRIB_SN,
-  TILE_OPC_SHRIH,
-  TILE_OPC_SHRIH_SN,
-  TILE_OPC_SLT,
-  TILE_OPC_SLT_SN,
-  TILE_OPC_SLT_U,
-  TILE_OPC_SLT_U_SN,
-  TILE_OPC_SLTB,
-  TILE_OPC_SLTB_SN,
-  TILE_OPC_SLTB_U,
-  TILE_OPC_SLTB_U_SN,
-  TILE_OPC_SLTE,
-  TILE_OPC_SLTE_SN,
-  TILE_OPC_SLTE_U,
-  TILE_OPC_SLTE_U_SN,
-  TILE_OPC_SLTEB,
-  TILE_OPC_SLTEB_SN,
-  TILE_OPC_SLTEB_U,
-  TILE_OPC_SLTEB_U_SN,
-  TILE_OPC_SLTEH,
-  TILE_OPC_SLTEH_SN,
-  TILE_OPC_SLTEH_U,
-  TILE_OPC_SLTEH_U_SN,
-  TILE_OPC_SLTH,
-  TILE_OPC_SLTH_SN,
-  TILE_OPC_SLTH_U,
-  TILE_OPC_SLTH_U_SN,
-  TILE_OPC_SLTI,
-  TILE_OPC_SLTI_SN,
-  TILE_OPC_SLTI_U,
-  TILE_OPC_SLTI_U_SN,
-  TILE_OPC_SLTIB,
-  TILE_OPC_SLTIB_SN,
-  TILE_OPC_SLTIB_U,
-  TILE_OPC_SLTIB_U_SN,
-  TILE_OPC_SLTIH,
-  TILE_OPC_SLTIH_SN,
-  TILE_OPC_SLTIH_U,
-  TILE_OPC_SLTIH_U_SN,
-  TILE_OPC_SNE,
-  TILE_OPC_SNE_SN,
-  TILE_OPC_SNEB,
-  TILE_OPC_SNEB_SN,
-  TILE_OPC_SNEH,
-  TILE_OPC_SNEH_SN,
-  TILE_OPC_SRA,
-  TILE_OPC_SRA_SN,
-  TILE_OPC_SRAB,
-  TILE_OPC_SRAB_SN,
-  TILE_OPC_SRAH,
-  TILE_OPC_SRAH_SN,
-  TILE_OPC_SRAI,
-  TILE_OPC_SRAI_SN,
-  TILE_OPC_SRAIB,
-  TILE_OPC_SRAIB_SN,
-  TILE_OPC_SRAIH,
-  TILE_OPC_SRAIH_SN,
-  TILE_OPC_SUB,
-  TILE_OPC_SUB_SN,
-  TILE_OPC_SUBB,
-  TILE_OPC_SUBB_SN,
-  TILE_OPC_SUBBS_U,
-  TILE_OPC_SUBBS_U_SN,
-  TILE_OPC_SUBH,
-  TILE_OPC_SUBH_SN,
-  TILE_OPC_SUBHS,
-  TILE_OPC_SUBHS_SN,
-  TILE_OPC_SUBS,
-  TILE_OPC_SUBS_SN,
-  TILE_OPC_SW,
-  TILE_OPC_SWADD,
-  TILE_OPC_SWINT0,
-  TILE_OPC_SWINT1,
-  TILE_OPC_SWINT2,
-  TILE_OPC_SWINT3,
-  TILE_OPC_TBLIDXB0,
-  TILE_OPC_TBLIDXB0_SN,
-  TILE_OPC_TBLIDXB1,
-  TILE_OPC_TBLIDXB1_SN,
-  TILE_OPC_TBLIDXB2,
-  TILE_OPC_TBLIDXB2_SN,
-  TILE_OPC_TBLIDXB3,
-  TILE_OPC_TBLIDXB3_SN,
-  TILE_OPC_TNS,
-  TILE_OPC_TNS_SN,
-  TILE_OPC_WH64,
-  TILE_OPC_XOR,
-  TILE_OPC_XOR_SN,
-  TILE_OPC_XORI,
-  TILE_OPC_XORI_SN,
-  TILE_OPC_NONE
-} tile_mnemonic;
-
-/* 64-bit pattern for a { bpt ; nop } bundle. */
-#define TILE_BPT_BUNDLE 0x400b3cae70166000ULL
-
-
-#define TILE_ELF_MACHINE_CODE EM_TILEPRO
-
-#define TILE_ELF_NAME "elf32-tilepro"
-
-
-static __inline unsigned int
-get_BrOff_SN(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 0)) & 0x3ff);
-}
-
-static __inline unsigned int
-get_BrOff_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0x00007fff) |
-         (((unsigned int)(n >> 20)) & 0x00018000);
-}
-
-static __inline unsigned int
-get_BrType_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 31)) & 0xf);
-}
-
-static __inline unsigned int
-get_Dest_Imm8_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 31)) & 0x0000003f) |
-         (((unsigned int)(n >> 43)) & 0x000000c0);
-}
-
-static __inline unsigned int
-get_Dest_SN(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 2)) & 0x3);
-}
-
-static __inline unsigned int
-get_Dest_X0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 0)) & 0x3f);
-}
-
-static __inline unsigned int
-get_Dest_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 31)) & 0x3f);
-}
-
-static __inline unsigned int
-get_Dest_Y0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 0)) & 0x3f);
-}
-
-static __inline unsigned int
-get_Dest_Y1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 31)) & 0x3f);
-}
-
-static __inline unsigned int
-get_Imm16_X0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0xffff);
-}
-
-static __inline unsigned int
-get_Imm16_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0xffff);
-}
-
-static __inline unsigned int
-get_Imm8_SN(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 0)) & 0xff);
-}
-
-static __inline unsigned int
-get_Imm8_X0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0xff);
-}
-
-static __inline unsigned int
-get_Imm8_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0xff);
-}
-
-static __inline unsigned int
-get_Imm8_Y0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0xff);
-}
-
-static __inline unsigned int
-get_Imm8_Y1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0xff);
-}
-
-static __inline unsigned int
-get_ImmOpcodeExtension_X0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 20)) & 0x7f);
-}
-
-static __inline unsigned int
-get_ImmOpcodeExtension_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 51)) & 0x7f);
-}
-
-static __inline unsigned int
-get_ImmRROpcodeExtension_SN(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 8)) & 0x3);
-}
-
-static __inline unsigned int
-get_JOffLong_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0x00007fff) |
-         (((unsigned int)(n >> 20)) & 0x00018000) |
-         (((unsigned int)(n >> 14)) & 0x001e0000) |
-         (((unsigned int)(n >> 16)) & 0x07e00000) |
-         (((unsigned int)(n >> 31)) & 0x18000000);
-}
-
-static __inline unsigned int
-get_JOff_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0x00007fff) |
-         (((unsigned int)(n >> 20)) & 0x00018000) |
-         (((unsigned int)(n >> 14)) & 0x001e0000) |
-         (((unsigned int)(n >> 16)) & 0x07e00000) |
-         (((unsigned int)(n >> 31)) & 0x08000000);
-}
-
-static __inline unsigned int
-get_MF_Imm15_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 37)) & 0x00003fff) |
-         (((unsigned int)(n >> 44)) & 0x00004000);
-}
-
-static __inline unsigned int
-get_MMEnd_X0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 18)) & 0x1f);
-}
-
-static __inline unsigned int
-get_MMEnd_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 49)) & 0x1f);
-}
-
-static __inline unsigned int
-get_MMStart_X0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 23)) & 0x1f);
-}
-
-static __inline unsigned int
-get_MMStart_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 54)) & 0x1f);
-}
-
-static __inline unsigned int
-get_MT_Imm15_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 31)) & 0x0000003f) |
-         (((unsigned int)(n >> 37)) & 0x00003fc0) |
-         (((unsigned int)(n >> 44)) & 0x00004000);
-}
-
-static __inline unsigned int
-get_Mode(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 63)) & 0x1);
-}
-
-static __inline unsigned int
-get_NoRegOpcodeExtension_SN(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 0)) & 0xf);
-}
-
-static __inline unsigned int
-get_Opcode_SN(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 10)) & 0x3f);
-}
-
-static __inline unsigned int
-get_Opcode_X0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 28)) & 0x7);
-}
-
-static __inline unsigned int
-get_Opcode_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 59)) & 0xf);
-}
-
-static __inline unsigned int
-get_Opcode_Y0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 27)) & 0xf);
-}
-
-static __inline unsigned int
-get_Opcode_Y1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 59)) & 0xf);
-}
-
-static __inline unsigned int
-get_Opcode_Y2(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 56)) & 0x7);
-}
-
-static __inline unsigned int
-get_RROpcodeExtension_SN(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 4)) & 0xf);
-}
-
-static __inline unsigned int
-get_RRROpcodeExtension_X0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 18)) & 0x1ff);
-}
-
-static __inline unsigned int
-get_RRROpcodeExtension_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 49)) & 0x1ff);
-}
-
-static __inline unsigned int
-get_RRROpcodeExtension_Y0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 18)) & 0x3);
-}
-
-static __inline unsigned int
-get_RRROpcodeExtension_Y1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 49)) & 0x3);
-}
-
-static __inline unsigned int
-get_RouteOpcodeExtension_SN(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 0)) & 0x3ff);
-}
-
-static __inline unsigned int
-get_S_X0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 27)) & 0x1);
-}
-
-static __inline unsigned int
-get_S_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 58)) & 0x1);
-}
-
-static __inline unsigned int
-get_ShAmt_X0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0x1f);
-}
-
-static __inline unsigned int
-get_ShAmt_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0x1f);
-}
-
-static __inline unsigned int
-get_ShAmt_Y0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0x1f);
-}
-
-static __inline unsigned int
-get_ShAmt_Y1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0x1f);
-}
-
-static __inline unsigned int
-get_SrcA_X0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 6)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcA_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 37)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcA_Y0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 6)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcA_Y1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 37)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcA_Y2(tile_bundle_bits n)
-{
-  return (((n >> 26)) & 0x00000001) |
-         (((unsigned int)(n >> 50)) & 0x0000003e);
-}
-
-static __inline unsigned int
-get_SrcBDest_Y2(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 20)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcB_X0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcB_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcB_Y0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcB_Y1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0x3f);
-}
-
-static __inline unsigned int
-get_Src_SN(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 0)) & 0x3);
-}
-
-static __inline unsigned int
-get_UnOpcodeExtension_X0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0x1f);
-}
-
-static __inline unsigned int
-get_UnOpcodeExtension_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0x1f);
-}
-
-static __inline unsigned int
-get_UnOpcodeExtension_Y0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0x1f);
-}
-
-static __inline unsigned int
-get_UnOpcodeExtension_Y1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0x1f);
-}
-
-static __inline unsigned int
-get_UnShOpcodeExtension_X0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 17)) & 0x3ff);
-}
-
-static __inline unsigned int
-get_UnShOpcodeExtension_X1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 48)) & 0x3ff);
-}
-
-static __inline unsigned int
-get_UnShOpcodeExtension_Y0(tile_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 17)) & 0x7);
-}
-
-static __inline unsigned int
-get_UnShOpcodeExtension_Y1(tile_bundle_bits n)
-{
-  return (((unsigned int)(n >> 48)) & 0x7);
-}
-
-
-static __inline int
-sign_extend(int n, int num_bits)
-{
-  int shift = (int)(sizeof(int) * 8 - num_bits);
-  return (n << shift) >> shift;
-}
-
-
-
-static __inline tile_bundle_bits
-create_BrOff_SN(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3ff) << 0);
-}
-
-static __inline tile_bundle_bits
-create_BrOff_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x00007fff)) << 43) |
-         (((tile_bundle_bits)(n & 0x00018000)) << 20);
-}
-
-static __inline tile_bundle_bits
-create_BrType_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0xf)) << 31);
-}
-
-static __inline tile_bundle_bits
-create_Dest_Imm8_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x0000003f)) << 31) |
-         (((tile_bundle_bits)(n & 0x000000c0)) << 43);
-}
-
-static __inline tile_bundle_bits
-create_Dest_SN(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3) << 2);
-}
-
-static __inline tile_bundle_bits
-create_Dest_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 0);
-}
-
-static __inline tile_bundle_bits
-create_Dest_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x3f)) << 31);
-}
-
-static __inline tile_bundle_bits
-create_Dest_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 0);
-}
-
-static __inline tile_bundle_bits
-create_Dest_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x3f)) << 31);
-}
-
-static __inline tile_bundle_bits
-create_Imm16_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0xffff) << 12);
-}
-
-static __inline tile_bundle_bits
-create_Imm16_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0xffff)) << 43);
-}
-
-static __inline tile_bundle_bits
-create_Imm8_SN(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0xff) << 0);
-}
-
-static __inline tile_bundle_bits
-create_Imm8_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0xff) << 12);
-}
-
-static __inline tile_bundle_bits
-create_Imm8_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0xff)) << 43);
-}
-
-static __inline tile_bundle_bits
-create_Imm8_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0xff) << 12);
-}
-
-static __inline tile_bundle_bits
-create_Imm8_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0xff)) << 43);
-}
-
-static __inline tile_bundle_bits
-create_ImmOpcodeExtension_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x7f) << 20);
-}
-
-static __inline tile_bundle_bits
-create_ImmOpcodeExtension_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x7f)) << 51);
-}
-
-static __inline tile_bundle_bits
-create_ImmRROpcodeExtension_SN(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3) << 8);
-}
-
-static __inline tile_bundle_bits
-create_JOffLong_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x00007fff)) << 43) |
-         (((tile_bundle_bits)(n & 0x00018000)) << 20) |
-         (((tile_bundle_bits)(n & 0x001e0000)) << 14) |
-         (((tile_bundle_bits)(n & 0x07e00000)) << 16) |
-         (((tile_bundle_bits)(n & 0x18000000)) << 31);
-}
-
-static __inline tile_bundle_bits
-create_JOff_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x00007fff)) << 43) |
-         (((tile_bundle_bits)(n & 0x00018000)) << 20) |
-         (((tile_bundle_bits)(n & 0x001e0000)) << 14) |
-         (((tile_bundle_bits)(n & 0x07e00000)) << 16) |
-         (((tile_bundle_bits)(n & 0x08000000)) << 31);
-}
-
-static __inline tile_bundle_bits
-create_MF_Imm15_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x00003fff)) << 37) |
-         (((tile_bundle_bits)(n & 0x00004000)) << 44);
-}
-
-static __inline tile_bundle_bits
-create_MMEnd_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x1f) << 18);
-}
-
-static __inline tile_bundle_bits
-create_MMEnd_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x1f)) << 49);
-}
-
-static __inline tile_bundle_bits
-create_MMStart_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x1f) << 23);
-}
-
-static __inline tile_bundle_bits
-create_MMStart_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x1f)) << 54);
-}
-
-static __inline tile_bundle_bits
-create_MT_Imm15_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x0000003f)) << 31) |
-         (((tile_bundle_bits)(n & 0x00003fc0)) << 37) |
-         (((tile_bundle_bits)(n & 0x00004000)) << 44);
-}
-
-static __inline tile_bundle_bits
-create_Mode(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x1)) << 63);
-}
-
-static __inline tile_bundle_bits
-create_NoRegOpcodeExtension_SN(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0xf) << 0);
-}
-
-static __inline tile_bundle_bits
-create_Opcode_SN(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 10);
-}
-
-static __inline tile_bundle_bits
-create_Opcode_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x7) << 28);
-}
-
-static __inline tile_bundle_bits
-create_Opcode_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0xf)) << 59);
-}
-
-static __inline tile_bundle_bits
-create_Opcode_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0xf) << 27);
-}
-
-static __inline tile_bundle_bits
-create_Opcode_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0xf)) << 59);
-}
-
-static __inline tile_bundle_bits
-create_Opcode_Y2(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x7)) << 56);
-}
-
-static __inline tile_bundle_bits
-create_RROpcodeExtension_SN(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0xf) << 4);
-}
-
-static __inline tile_bundle_bits
-create_RRROpcodeExtension_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x1ff) << 18);
-}
-
-static __inline tile_bundle_bits
-create_RRROpcodeExtension_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x1ff)) << 49);
-}
-
-static __inline tile_bundle_bits
-create_RRROpcodeExtension_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3) << 18);
-}
-
-static __inline tile_bundle_bits
-create_RRROpcodeExtension_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x3)) << 49);
-}
-
-static __inline tile_bundle_bits
-create_RouteOpcodeExtension_SN(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3ff) << 0);
-}
-
-static __inline tile_bundle_bits
-create_S_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x1) << 27);
-}
-
-static __inline tile_bundle_bits
-create_S_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x1)) << 58);
-}
-
-static __inline tile_bundle_bits
-create_ShAmt_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x1f) << 12);
-}
-
-static __inline tile_bundle_bits
-create_ShAmt_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x1f)) << 43);
-}
-
-static __inline tile_bundle_bits
-create_ShAmt_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x1f) << 12);
-}
-
-static __inline tile_bundle_bits
-create_ShAmt_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x1f)) << 43);
-}
-
-static __inline tile_bundle_bits
-create_SrcA_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 6);
-}
-
-static __inline tile_bundle_bits
-create_SrcA_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x3f)) << 37);
-}
-
-static __inline tile_bundle_bits
-create_SrcA_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 6);
-}
-
-static __inline tile_bundle_bits
-create_SrcA_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x3f)) << 37);
-}
-
-static __inline tile_bundle_bits
-create_SrcA_Y2(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x00000001) << 26) |
-         (((tile_bundle_bits)(n & 0x0000003e)) << 50);
-}
-
-static __inline tile_bundle_bits
-create_SrcBDest_Y2(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 20);
-}
-
-static __inline tile_bundle_bits
-create_SrcB_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 12);
-}
-
-static __inline tile_bundle_bits
-create_SrcB_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x3f)) << 43);
-}
-
-static __inline tile_bundle_bits
-create_SrcB_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 12);
-}
-
-static __inline tile_bundle_bits
-create_SrcB_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x3f)) << 43);
-}
-
-static __inline tile_bundle_bits
-create_Src_SN(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3) << 0);
-}
-
-static __inline tile_bundle_bits
-create_UnOpcodeExtension_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x1f) << 12);
-}
-
-static __inline tile_bundle_bits
-create_UnOpcodeExtension_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x1f)) << 43);
-}
-
-static __inline tile_bundle_bits
-create_UnOpcodeExtension_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x1f) << 12);
-}
-
-static __inline tile_bundle_bits
-create_UnOpcodeExtension_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x1f)) << 43);
-}
-
-static __inline tile_bundle_bits
-create_UnShOpcodeExtension_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3ff) << 17);
-}
-
-static __inline tile_bundle_bits
-create_UnShOpcodeExtension_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x3ff)) << 48);
-}
-
-static __inline tile_bundle_bits
-create_UnShOpcodeExtension_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x7) << 17);
-}
-
-static __inline tile_bundle_bits
-create_UnShOpcodeExtension_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tile_bundle_bits)(n & 0x7)) << 48);
-}
-
-
-
-typedef enum
-{
-  TILE_PIPELINE_X0,
-  TILE_PIPELINE_X1,
-  TILE_PIPELINE_Y0,
-  TILE_PIPELINE_Y1,
-  TILE_PIPELINE_Y2,
-} tile_pipeline;
-
-#define tile_is_x_pipeline(p) ((int)(p) <= (int)TILE_PIPELINE_X1)
-
-typedef enum
-{
-  TILE_OP_TYPE_REGISTER,
-  TILE_OP_TYPE_IMMEDIATE,
-  TILE_OP_TYPE_ADDRESS,
-  TILE_OP_TYPE_SPR
-} tile_operand_type;
-
-/* This is the bit that determines if a bundle is in the Y encoding. */
-#define TILE_BUNDLE_Y_ENCODING_MASK ((tile_bundle_bits)1 << 63)
-
-enum
-{
-  /* Maximum number of instructions in a bundle (2 for X, 3 for Y). */
-  TILE_MAX_INSTRUCTIONS_PER_BUNDLE = 3,
-
-  /* How many different pipeline encodings are there? X0, X1, Y0, Y1, Y2. */
-  TILE_NUM_PIPELINE_ENCODINGS = 5,
-
-  /* Log base 2 of TILE_BUNDLE_SIZE_IN_BYTES. */
-  TILE_LOG2_BUNDLE_SIZE_IN_BYTES = 3,
-
-  /* Instructions take this many bytes. */
-  TILE_BUNDLE_SIZE_IN_BYTES = 1 << TILE_LOG2_BUNDLE_SIZE_IN_BYTES,
-
-  /* Log base 2 of TILE_BUNDLE_ALIGNMENT_IN_BYTES. */
-  TILE_LOG2_BUNDLE_ALIGNMENT_IN_BYTES = 3,
-
-  /* Bundles should be aligned modulo this number of bytes. */
-  TILE_BUNDLE_ALIGNMENT_IN_BYTES =
-    (1 << TILE_LOG2_BUNDLE_ALIGNMENT_IN_BYTES),
-
-  /* Log base 2 of TILE_SN_INSTRUCTION_SIZE_IN_BYTES. */
-  TILE_LOG2_SN_INSTRUCTION_SIZE_IN_BYTES = 1,
-
-  /* Static network instructions take this many bytes. */
-  TILE_SN_INSTRUCTION_SIZE_IN_BYTES =
-    (1 << TILE_LOG2_SN_INSTRUCTION_SIZE_IN_BYTES),
-
-  /* Number of registers (some are magic, such as network I/O). */
-  TILE_NUM_REGISTERS = 64,
-
-  /* Number of static network registers. */
-  TILE_NUM_SN_REGISTERS = 4
-};
-
-
-struct tile_operand
-{
-  /* Is this operand a register, immediate or address? */
-  tile_operand_type type;
-
-  /* The default relocation type for this operand.  */
-  signed int default_reloc : 16;
-
-  /* How many bits is this value? (used for range checking) */
-  unsigned int num_bits : 5;
-
-  /* Is the value signed? (used for range checking) */
-  unsigned int is_signed : 1;
-
-  /* Is this operand a source register? */
-  unsigned int is_src_reg : 1;
-
-  /* Is this operand written? (i.e. is it a destination register) */
-  unsigned int is_dest_reg : 1;
-
-  /* Is this operand PC-relative? */
-  unsigned int is_pc_relative : 1;
-
-  /* By how many bits do we right shift the value before inserting? */
-  unsigned int rightshift : 2;
-
-  /* Return the bits for this operand to be ORed into an existing bundle. */
-  tile_bundle_bits (*insert) (int op);
-
-  /* Extract this operand and return it. */
-  unsigned int (*extract) (tile_bundle_bits bundle);
-};
-
-
-extern const struct tile_operand tile_operands[];
-
-/* One finite-state machine per pipe for rapid instruction decoding. */
-extern const unsigned short * const
-tile_bundle_decoder_fsms[TILE_NUM_PIPELINE_ENCODINGS];
-
-
-struct tile_opcode
-{
-  /* The opcode mnemonic, e.g. "add" */
-  const char *name;
-
-  /* The enum value for this mnemonic. */
-  tile_mnemonic mnemonic;
-
-  /* A bit mask of which of the five pipes this instruction
-     is compatible with:
-     X0  0x01
-     X1  0x02
-     Y0  0x04
-     Y1  0x08
-     Y2  0x10 */
-  unsigned char pipes;
-
-  /* How many operands are there? */
-  unsigned char num_operands;
-
-  /* Which register does this write implicitly, or TREG_ZERO if none? */
-  unsigned char implicitly_written_register;
-
-  /* Can this be bundled with other instructions (almost always true). */
-  unsigned char can_bundle;
-
-  /* The description of the operands. Each of these is an
-   * index into the tile_operands[] table. */
-  unsigned char operands[TILE_NUM_PIPELINE_ENCODINGS][TILE_MAX_OPERANDS];
-
-};
-
-extern const struct tile_opcode tile_opcodes[];
-
-
-/* Used for non-textual disassembly into structs. */
-struct tile_decoded_instruction
-{
-  const struct tile_opcode *opcode;
-  const struct tile_operand *operands[TILE_MAX_OPERANDS];
-  int operand_values[TILE_MAX_OPERANDS];
-};
-
-
-/* Disassemble a bundle into a struct for machine processing. */
-extern int parse_insn_tile(tile_bundle_bits bits,
-                           unsigned int pc,
-                           struct tile_decoded_instruction
-                           decoded[TILE_MAX_INSTRUCTIONS_PER_BUNDLE]);
-
-
-/* Given a set of bundle bits and a specific pipe, returns which
- * instruction the bundle contains in that pipe.
- */
-extern const struct tile_opcode *
-find_opcode(tile_bundle_bits bits, tile_pipeline pipe);
-
-
-
-#endif /* opcode_tile_h */
diff --git a/arch/tile/include/asm/opcode-tile_64.h b/arch/tile/include/asm/opcode-tile_64.h
deleted file mode 100644 (file)
index c063346..0000000
+++ /dev/null
@@ -1,1248 +0,0 @@
-/* tile.h -- Header file for TILE opcode table
-   Copyright (C) 2005 Free Software Foundation, Inc.
-   Contributed by Tilera Corp. */
-
-#ifndef opcode_tile_h
-#define opcode_tile_h
-
-typedef unsigned long long tilegx_bundle_bits;
-
-
-enum
-{
-  TILEGX_MAX_OPERANDS = 4 /* bfexts */
-};
-
-typedef enum
-{
-  TILEGX_OPC_BPT,
-  TILEGX_OPC_INFO,
-  TILEGX_OPC_INFOL,
-  TILEGX_OPC_MOVE,
-  TILEGX_OPC_MOVEI,
-  TILEGX_OPC_MOVELI,
-  TILEGX_OPC_PREFETCH,
-  TILEGX_OPC_PREFETCH_ADD_L1,
-  TILEGX_OPC_PREFETCH_ADD_L1_FAULT,
-  TILEGX_OPC_PREFETCH_ADD_L2,
-  TILEGX_OPC_PREFETCH_ADD_L2_FAULT,
-  TILEGX_OPC_PREFETCH_ADD_L3,
-  TILEGX_OPC_PREFETCH_ADD_L3_FAULT,
-  TILEGX_OPC_PREFETCH_L1,
-  TILEGX_OPC_PREFETCH_L1_FAULT,
-  TILEGX_OPC_PREFETCH_L2,
-  TILEGX_OPC_PREFETCH_L2_FAULT,
-  TILEGX_OPC_PREFETCH_L3,
-  TILEGX_OPC_PREFETCH_L3_FAULT,
-  TILEGX_OPC_RAISE,
-  TILEGX_OPC_ADD,
-  TILEGX_OPC_ADDI,
-  TILEGX_OPC_ADDLI,
-  TILEGX_OPC_ADDX,
-  TILEGX_OPC_ADDXI,
-  TILEGX_OPC_ADDXLI,
-  TILEGX_OPC_ADDXSC,
-  TILEGX_OPC_AND,
-  TILEGX_OPC_ANDI,
-  TILEGX_OPC_BEQZ,
-  TILEGX_OPC_BEQZT,
-  TILEGX_OPC_BFEXTS,
-  TILEGX_OPC_BFEXTU,
-  TILEGX_OPC_BFINS,
-  TILEGX_OPC_BGEZ,
-  TILEGX_OPC_BGEZT,
-  TILEGX_OPC_BGTZ,
-  TILEGX_OPC_BGTZT,
-  TILEGX_OPC_BLBC,
-  TILEGX_OPC_BLBCT,
-  TILEGX_OPC_BLBS,
-  TILEGX_OPC_BLBST,
-  TILEGX_OPC_BLEZ,
-  TILEGX_OPC_BLEZT,
-  TILEGX_OPC_BLTZ,
-  TILEGX_OPC_BLTZT,
-  TILEGX_OPC_BNEZ,
-  TILEGX_OPC_BNEZT,
-  TILEGX_OPC_CLZ,
-  TILEGX_OPC_CMOVEQZ,
-  TILEGX_OPC_CMOVNEZ,
-  TILEGX_OPC_CMPEQ,
-  TILEGX_OPC_CMPEQI,
-  TILEGX_OPC_CMPEXCH,
-  TILEGX_OPC_CMPEXCH4,
-  TILEGX_OPC_CMPLES,
-  TILEGX_OPC_CMPLEU,
-  TILEGX_OPC_CMPLTS,
-  TILEGX_OPC_CMPLTSI,
-  TILEGX_OPC_CMPLTU,
-  TILEGX_OPC_CMPLTUI,
-  TILEGX_OPC_CMPNE,
-  TILEGX_OPC_CMUL,
-  TILEGX_OPC_CMULA,
-  TILEGX_OPC_CMULAF,
-  TILEGX_OPC_CMULF,
-  TILEGX_OPC_CMULFR,
-  TILEGX_OPC_CMULH,
-  TILEGX_OPC_CMULHR,
-  TILEGX_OPC_CRC32_32,
-  TILEGX_OPC_CRC32_8,
-  TILEGX_OPC_CTZ,
-  TILEGX_OPC_DBLALIGN,
-  TILEGX_OPC_DBLALIGN2,
-  TILEGX_OPC_DBLALIGN4,
-  TILEGX_OPC_DBLALIGN6,
-  TILEGX_OPC_DRAIN,
-  TILEGX_OPC_DTLBPR,
-  TILEGX_OPC_EXCH,
-  TILEGX_OPC_EXCH4,
-  TILEGX_OPC_FDOUBLE_ADD_FLAGS,
-  TILEGX_OPC_FDOUBLE_ADDSUB,
-  TILEGX_OPC_FDOUBLE_MUL_FLAGS,
-  TILEGX_OPC_FDOUBLE_PACK1,
-  TILEGX_OPC_FDOUBLE_PACK2,
-  TILEGX_OPC_FDOUBLE_SUB_FLAGS,
-  TILEGX_OPC_FDOUBLE_UNPACK_MAX,
-  TILEGX_OPC_FDOUBLE_UNPACK_MIN,
-  TILEGX_OPC_FETCHADD,
-  TILEGX_OPC_FETCHADD4,
-  TILEGX_OPC_FETCHADDGEZ,
-  TILEGX_OPC_FETCHADDGEZ4,
-  TILEGX_OPC_FETCHAND,
-  TILEGX_OPC_FETCHAND4,
-  TILEGX_OPC_FETCHOR,
-  TILEGX_OPC_FETCHOR4,
-  TILEGX_OPC_FINV,
-  TILEGX_OPC_FLUSH,
-  TILEGX_OPC_FLUSHWB,
-  TILEGX_OPC_FNOP,
-  TILEGX_OPC_FSINGLE_ADD1,
-  TILEGX_OPC_FSINGLE_ADDSUB2,
-  TILEGX_OPC_FSINGLE_MUL1,
-  TILEGX_OPC_FSINGLE_MUL2,
-  TILEGX_OPC_FSINGLE_PACK1,
-  TILEGX_OPC_FSINGLE_PACK2,
-  TILEGX_OPC_FSINGLE_SUB1,
-  TILEGX_OPC_ICOH,
-  TILEGX_OPC_ILL,
-  TILEGX_OPC_INV,
-  TILEGX_OPC_IRET,
-  TILEGX_OPC_J,
-  TILEGX_OPC_JAL,
-  TILEGX_OPC_JALR,
-  TILEGX_OPC_JALRP,
-  TILEGX_OPC_JR,
-  TILEGX_OPC_JRP,
-  TILEGX_OPC_LD,
-  TILEGX_OPC_LD1S,
-  TILEGX_OPC_LD1S_ADD,
-  TILEGX_OPC_LD1U,
-  TILEGX_OPC_LD1U_ADD,
-  TILEGX_OPC_LD2S,
-  TILEGX_OPC_LD2S_ADD,
-  TILEGX_OPC_LD2U,
-  TILEGX_OPC_LD2U_ADD,
-  TILEGX_OPC_LD4S,
-  TILEGX_OPC_LD4S_ADD,
-  TILEGX_OPC_LD4U,
-  TILEGX_OPC_LD4U_ADD,
-  TILEGX_OPC_LD_ADD,
-  TILEGX_OPC_LDNA,
-  TILEGX_OPC_LDNA_ADD,
-  TILEGX_OPC_LDNT,
-  TILEGX_OPC_LDNT1S,
-  TILEGX_OPC_LDNT1S_ADD,
-  TILEGX_OPC_LDNT1U,
-  TILEGX_OPC_LDNT1U_ADD,
-  TILEGX_OPC_LDNT2S,
-  TILEGX_OPC_LDNT2S_ADD,
-  TILEGX_OPC_LDNT2U,
-  TILEGX_OPC_LDNT2U_ADD,
-  TILEGX_OPC_LDNT4S,
-  TILEGX_OPC_LDNT4S_ADD,
-  TILEGX_OPC_LDNT4U,
-  TILEGX_OPC_LDNT4U_ADD,
-  TILEGX_OPC_LDNT_ADD,
-  TILEGX_OPC_LNK,
-  TILEGX_OPC_MF,
-  TILEGX_OPC_MFSPR,
-  TILEGX_OPC_MM,
-  TILEGX_OPC_MNZ,
-  TILEGX_OPC_MTSPR,
-  TILEGX_OPC_MUL_HS_HS,
-  TILEGX_OPC_MUL_HS_HU,
-  TILEGX_OPC_MUL_HS_LS,
-  TILEGX_OPC_MUL_HS_LU,
-  TILEGX_OPC_MUL_HU_HU,
-  TILEGX_OPC_MUL_HU_LS,
-  TILEGX_OPC_MUL_HU_LU,
-  TILEGX_OPC_MUL_LS_LS,
-  TILEGX_OPC_MUL_LS_LU,
-  TILEGX_OPC_MUL_LU_LU,
-  TILEGX_OPC_MULA_HS_HS,
-  TILEGX_OPC_MULA_HS_HU,
-  TILEGX_OPC_MULA_HS_LS,
-  TILEGX_OPC_MULA_HS_LU,
-  TILEGX_OPC_MULA_HU_HU,
-  TILEGX_OPC_MULA_HU_LS,
-  TILEGX_OPC_MULA_HU_LU,
-  TILEGX_OPC_MULA_LS_LS,
-  TILEGX_OPC_MULA_LS_LU,
-  TILEGX_OPC_MULA_LU_LU,
-  TILEGX_OPC_MULAX,
-  TILEGX_OPC_MULX,
-  TILEGX_OPC_MZ,
-  TILEGX_OPC_NAP,
-  TILEGX_OPC_NOP,
-  TILEGX_OPC_NOR,
-  TILEGX_OPC_OR,
-  TILEGX_OPC_ORI,
-  TILEGX_OPC_PCNT,
-  TILEGX_OPC_REVBITS,
-  TILEGX_OPC_REVBYTES,
-  TILEGX_OPC_ROTL,
-  TILEGX_OPC_ROTLI,
-  TILEGX_OPC_SHL,
-  TILEGX_OPC_SHL16INSLI,
-  TILEGX_OPC_SHL1ADD,
-  TILEGX_OPC_SHL1ADDX,
-  TILEGX_OPC_SHL2ADD,
-  TILEGX_OPC_SHL2ADDX,
-  TILEGX_OPC_SHL3ADD,
-  TILEGX_OPC_SHL3ADDX,
-  TILEGX_OPC_SHLI,
-  TILEGX_OPC_SHLX,
-  TILEGX_OPC_SHLXI,
-  TILEGX_OPC_SHRS,
-  TILEGX_OPC_SHRSI,
-  TILEGX_OPC_SHRU,
-  TILEGX_OPC_SHRUI,
-  TILEGX_OPC_SHRUX,
-  TILEGX_OPC_SHRUXI,
-  TILEGX_OPC_SHUFFLEBYTES,
-  TILEGX_OPC_ST,
-  TILEGX_OPC_ST1,
-  TILEGX_OPC_ST1_ADD,
-  TILEGX_OPC_ST2,
-  TILEGX_OPC_ST2_ADD,
-  TILEGX_OPC_ST4,
-  TILEGX_OPC_ST4_ADD,
-  TILEGX_OPC_ST_ADD,
-  TILEGX_OPC_STNT,
-  TILEGX_OPC_STNT1,
-  TILEGX_OPC_STNT1_ADD,
-  TILEGX_OPC_STNT2,
-  TILEGX_OPC_STNT2_ADD,
-  TILEGX_OPC_STNT4,
-  TILEGX_OPC_STNT4_ADD,
-  TILEGX_OPC_STNT_ADD,
-  TILEGX_OPC_SUB,
-  TILEGX_OPC_SUBX,
-  TILEGX_OPC_SUBXSC,
-  TILEGX_OPC_SWINT0,
-  TILEGX_OPC_SWINT1,
-  TILEGX_OPC_SWINT2,
-  TILEGX_OPC_SWINT3,
-  TILEGX_OPC_TBLIDXB0,
-  TILEGX_OPC_TBLIDXB1,
-  TILEGX_OPC_TBLIDXB2,
-  TILEGX_OPC_TBLIDXB3,
-  TILEGX_OPC_V1ADD,
-  TILEGX_OPC_V1ADDI,
-  TILEGX_OPC_V1ADDUC,
-  TILEGX_OPC_V1ADIFFU,
-  TILEGX_OPC_V1AVGU,
-  TILEGX_OPC_V1CMPEQ,
-  TILEGX_OPC_V1CMPEQI,
-  TILEGX_OPC_V1CMPLES,
-  TILEGX_OPC_V1CMPLEU,
-  TILEGX_OPC_V1CMPLTS,
-  TILEGX_OPC_V1CMPLTSI,
-  TILEGX_OPC_V1CMPLTU,
-  TILEGX_OPC_V1CMPLTUI,
-  TILEGX_OPC_V1CMPNE,
-  TILEGX_OPC_V1DDOTPU,
-  TILEGX_OPC_V1DDOTPUA,
-  TILEGX_OPC_V1DDOTPUS,
-  TILEGX_OPC_V1DDOTPUSA,
-  TILEGX_OPC_V1DOTP,
-  TILEGX_OPC_V1DOTPA,
-  TILEGX_OPC_V1DOTPU,
-  TILEGX_OPC_V1DOTPUA,
-  TILEGX_OPC_V1DOTPUS,
-  TILEGX_OPC_V1DOTPUSA,
-  TILEGX_OPC_V1INT_H,
-  TILEGX_OPC_V1INT_L,
-  TILEGX_OPC_V1MAXU,
-  TILEGX_OPC_V1MAXUI,
-  TILEGX_OPC_V1MINU,
-  TILEGX_OPC_V1MINUI,
-  TILEGX_OPC_V1MNZ,
-  TILEGX_OPC_V1MULTU,
-  TILEGX_OPC_V1MULU,
-  TILEGX_OPC_V1MULUS,
-  TILEGX_OPC_V1MZ,
-  TILEGX_OPC_V1SADAU,
-  TILEGX_OPC_V1SADU,
-  TILEGX_OPC_V1SHL,
-  TILEGX_OPC_V1SHLI,
-  TILEGX_OPC_V1SHRS,
-  TILEGX_OPC_V1SHRSI,
-  TILEGX_OPC_V1SHRU,
-  TILEGX_OPC_V1SHRUI,
-  TILEGX_OPC_V1SUB,
-  TILEGX_OPC_V1SUBUC,
-  TILEGX_OPC_V2ADD,
-  TILEGX_OPC_V2ADDI,
-  TILEGX_OPC_V2ADDSC,
-  TILEGX_OPC_V2ADIFFS,
-  TILEGX_OPC_V2AVGS,
-  TILEGX_OPC_V2CMPEQ,
-  TILEGX_OPC_V2CMPEQI,
-  TILEGX_OPC_V2CMPLES,
-  TILEGX_OPC_V2CMPLEU,
-  TILEGX_OPC_V2CMPLTS,
-  TILEGX_OPC_V2CMPLTSI,
-  TILEGX_OPC_V2CMPLTU,
-  TILEGX_OPC_V2CMPLTUI,
-  TILEGX_OPC_V2CMPNE,
-  TILEGX_OPC_V2DOTP,
-  TILEGX_OPC_V2DOTPA,
-  TILEGX_OPC_V2INT_H,
-  TILEGX_OPC_V2INT_L,
-  TILEGX_OPC_V2MAXS,
-  TILEGX_OPC_V2MAXSI,
-  TILEGX_OPC_V2MINS,
-  TILEGX_OPC_V2MINSI,
-  TILEGX_OPC_V2MNZ,
-  TILEGX_OPC_V2MULFSC,
-  TILEGX_OPC_V2MULS,
-  TILEGX_OPC_V2MULTS,
-  TILEGX_OPC_V2MZ,
-  TILEGX_OPC_V2PACKH,
-  TILEGX_OPC_V2PACKL,
-  TILEGX_OPC_V2PACKUC,
-  TILEGX_OPC_V2SADAS,
-  TILEGX_OPC_V2SADAU,
-  TILEGX_OPC_V2SADS,
-  TILEGX_OPC_V2SADU,
-  TILEGX_OPC_V2SHL,
-  TILEGX_OPC_V2SHLI,
-  TILEGX_OPC_V2SHLSC,
-  TILEGX_OPC_V2SHRS,
-  TILEGX_OPC_V2SHRSI,
-  TILEGX_OPC_V2SHRU,
-  TILEGX_OPC_V2SHRUI,
-  TILEGX_OPC_V2SUB,
-  TILEGX_OPC_V2SUBSC,
-  TILEGX_OPC_V4ADD,
-  TILEGX_OPC_V4ADDSC,
-  TILEGX_OPC_V4INT_H,
-  TILEGX_OPC_V4INT_L,
-  TILEGX_OPC_V4PACKSC,
-  TILEGX_OPC_V4SHL,
-  TILEGX_OPC_V4SHLSC,
-  TILEGX_OPC_V4SHRS,
-  TILEGX_OPC_V4SHRU,
-  TILEGX_OPC_V4SUB,
-  TILEGX_OPC_V4SUBSC,
-  TILEGX_OPC_WH64,
-  TILEGX_OPC_XOR,
-  TILEGX_OPC_XORI,
-  TILEGX_OPC_NONE
-} tilegx_mnemonic;
-
-/* 64-bit pattern for a { bpt ; nop } bundle. */
-#define TILEGX_BPT_BUNDLE 0x286a44ae51485000ULL
-
-
-#define TILE_ELF_MACHINE_CODE EM_TILE64
-
-#define TILE_ELF_NAME "elf32-tile64"
-
-
-static __inline unsigned int
-get_BFEnd_X0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0x3f);
-}
-
-static __inline unsigned int
-get_BFOpcodeExtension_X0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 24)) & 0xf);
-}
-
-static __inline unsigned int
-get_BFStart_X0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 18)) & 0x3f);
-}
-
-static __inline unsigned int
-get_BrOff_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 31)) & 0x0000003f) |
-         (((unsigned int)(n >> 37)) & 0x0001ffc0);
-}
-
-static __inline unsigned int
-get_BrType_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 54)) & 0x1f);
-}
-
-static __inline unsigned int
-get_Dest_Imm8_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 31)) & 0x0000003f) |
-         (((unsigned int)(n >> 43)) & 0x000000c0);
-}
-
-static __inline unsigned int
-get_Dest_X0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 0)) & 0x3f);
-}
-
-static __inline unsigned int
-get_Dest_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 31)) & 0x3f);
-}
-
-static __inline unsigned int
-get_Dest_Y0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 0)) & 0x3f);
-}
-
-static __inline unsigned int
-get_Dest_Y1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 31)) & 0x3f);
-}
-
-static __inline unsigned int
-get_Imm16_X0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0xffff);
-}
-
-static __inline unsigned int
-get_Imm16_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0xffff);
-}
-
-static __inline unsigned int
-get_Imm8OpcodeExtension_X0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 20)) & 0xff);
-}
-
-static __inline unsigned int
-get_Imm8OpcodeExtension_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 51)) & 0xff);
-}
-
-static __inline unsigned int
-get_Imm8_X0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0xff);
-}
-
-static __inline unsigned int
-get_Imm8_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0xff);
-}
-
-static __inline unsigned int
-get_Imm8_Y0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0xff);
-}
-
-static __inline unsigned int
-get_Imm8_Y1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0xff);
-}
-
-static __inline unsigned int
-get_JumpOff_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 31)) & 0x7ffffff);
-}
-
-static __inline unsigned int
-get_JumpOpcodeExtension_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 58)) & 0x1);
-}
-
-static __inline unsigned int
-get_MF_Imm14_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 37)) & 0x3fff);
-}
-
-static __inline unsigned int
-get_MT_Imm14_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 31)) & 0x0000003f) |
-         (((unsigned int)(n >> 37)) & 0x00003fc0);
-}
-
-static __inline unsigned int
-get_Mode(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 62)) & 0x3);
-}
-
-static __inline unsigned int
-get_Opcode_X0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 28)) & 0x7);
-}
-
-static __inline unsigned int
-get_Opcode_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 59)) & 0x7);
-}
-
-static __inline unsigned int
-get_Opcode_Y0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 27)) & 0xf);
-}
-
-static __inline unsigned int
-get_Opcode_Y1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 58)) & 0xf);
-}
-
-static __inline unsigned int
-get_Opcode_Y2(tilegx_bundle_bits n)
-{
-  return (((n >> 26)) & 0x00000001) |
-         (((unsigned int)(n >> 56)) & 0x00000002);
-}
-
-static __inline unsigned int
-get_RRROpcodeExtension_X0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 18)) & 0x3ff);
-}
-
-static __inline unsigned int
-get_RRROpcodeExtension_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 49)) & 0x3ff);
-}
-
-static __inline unsigned int
-get_RRROpcodeExtension_Y0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 18)) & 0x3);
-}
-
-static __inline unsigned int
-get_RRROpcodeExtension_Y1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 49)) & 0x3);
-}
-
-static __inline unsigned int
-get_ShAmt_X0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0x3f);
-}
-
-static __inline unsigned int
-get_ShAmt_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0x3f);
-}
-
-static __inline unsigned int
-get_ShAmt_Y0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0x3f);
-}
-
-static __inline unsigned int
-get_ShAmt_Y1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0x3f);
-}
-
-static __inline unsigned int
-get_ShiftOpcodeExtension_X0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 18)) & 0x3ff);
-}
-
-static __inline unsigned int
-get_ShiftOpcodeExtension_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 49)) & 0x3ff);
-}
-
-static __inline unsigned int
-get_ShiftOpcodeExtension_Y0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 18)) & 0x3);
-}
-
-static __inline unsigned int
-get_ShiftOpcodeExtension_Y1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 49)) & 0x3);
-}
-
-static __inline unsigned int
-get_SrcA_X0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 6)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcA_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 37)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcA_Y0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 6)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcA_Y1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 37)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcA_Y2(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 20)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcBDest_Y2(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 51)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcB_X0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcB_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcB_Y0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0x3f);
-}
-
-static __inline unsigned int
-get_SrcB_Y1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0x3f);
-}
-
-static __inline unsigned int
-get_UnaryOpcodeExtension_X0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0x3f);
-}
-
-static __inline unsigned int
-get_UnaryOpcodeExtension_X1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0x3f);
-}
-
-static __inline unsigned int
-get_UnaryOpcodeExtension_Y0(tilegx_bundle_bits num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((n >> 12)) & 0x3f);
-}
-
-static __inline unsigned int
-get_UnaryOpcodeExtension_Y1(tilegx_bundle_bits n)
-{
-  return (((unsigned int)(n >> 43)) & 0x3f);
-}
-
-
-static __inline int
-sign_extend(int n, int num_bits)
-{
-  int shift = (int)(sizeof(int) * 8 - num_bits);
-  return (n << shift) >> shift;
-}
-
-
-
-static __inline tilegx_bundle_bits
-create_BFEnd_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 12);
-}
-
-static __inline tilegx_bundle_bits
-create_BFOpcodeExtension_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0xf) << 24);
-}
-
-static __inline tilegx_bundle_bits
-create_BFStart_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 18);
-}
-
-static __inline tilegx_bundle_bits
-create_BrOff_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x0000003f)) << 31) |
-         (((tilegx_bundle_bits)(n & 0x0001ffc0)) << 37);
-}
-
-static __inline tilegx_bundle_bits
-create_BrType_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x1f)) << 54);
-}
-
-static __inline tilegx_bundle_bits
-create_Dest_Imm8_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x0000003f)) << 31) |
-         (((tilegx_bundle_bits)(n & 0x000000c0)) << 43);
-}
-
-static __inline tilegx_bundle_bits
-create_Dest_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 0);
-}
-
-static __inline tilegx_bundle_bits
-create_Dest_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3f)) << 31);
-}
-
-static __inline tilegx_bundle_bits
-create_Dest_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 0);
-}
-
-static __inline tilegx_bundle_bits
-create_Dest_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3f)) << 31);
-}
-
-static __inline tilegx_bundle_bits
-create_Imm16_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0xffff) << 12);
-}
-
-static __inline tilegx_bundle_bits
-create_Imm16_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0xffff)) << 43);
-}
-
-static __inline tilegx_bundle_bits
-create_Imm8OpcodeExtension_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0xff) << 20);
-}
-
-static __inline tilegx_bundle_bits
-create_Imm8OpcodeExtension_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0xff)) << 51);
-}
-
-static __inline tilegx_bundle_bits
-create_Imm8_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0xff) << 12);
-}
-
-static __inline tilegx_bundle_bits
-create_Imm8_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0xff)) << 43);
-}
-
-static __inline tilegx_bundle_bits
-create_Imm8_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0xff) << 12);
-}
-
-static __inline tilegx_bundle_bits
-create_Imm8_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0xff)) << 43);
-}
-
-static __inline tilegx_bundle_bits
-create_JumpOff_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x7ffffff)) << 31);
-}
-
-static __inline tilegx_bundle_bits
-create_JumpOpcodeExtension_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x1)) << 58);
-}
-
-static __inline tilegx_bundle_bits
-create_MF_Imm14_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3fff)) << 37);
-}
-
-static __inline tilegx_bundle_bits
-create_MT_Imm14_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x0000003f)) << 31) |
-         (((tilegx_bundle_bits)(n & 0x00003fc0)) << 37);
-}
-
-static __inline tilegx_bundle_bits
-create_Mode(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3)) << 62);
-}
-
-static __inline tilegx_bundle_bits
-create_Opcode_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x7) << 28);
-}
-
-static __inline tilegx_bundle_bits
-create_Opcode_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x7)) << 59);
-}
-
-static __inline tilegx_bundle_bits
-create_Opcode_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0xf) << 27);
-}
-
-static __inline tilegx_bundle_bits
-create_Opcode_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0xf)) << 58);
-}
-
-static __inline tilegx_bundle_bits
-create_Opcode_Y2(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x00000001) << 26) |
-         (((tilegx_bundle_bits)(n & 0x00000002)) << 56);
-}
-
-static __inline tilegx_bundle_bits
-create_RRROpcodeExtension_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3ff) << 18);
-}
-
-static __inline tilegx_bundle_bits
-create_RRROpcodeExtension_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3ff)) << 49);
-}
-
-static __inline tilegx_bundle_bits
-create_RRROpcodeExtension_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3) << 18);
-}
-
-static __inline tilegx_bundle_bits
-create_RRROpcodeExtension_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3)) << 49);
-}
-
-static __inline tilegx_bundle_bits
-create_ShAmt_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 12);
-}
-
-static __inline tilegx_bundle_bits
-create_ShAmt_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3f)) << 43);
-}
-
-static __inline tilegx_bundle_bits
-create_ShAmt_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 12);
-}
-
-static __inline tilegx_bundle_bits
-create_ShAmt_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3f)) << 43);
-}
-
-static __inline tilegx_bundle_bits
-create_ShiftOpcodeExtension_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3ff) << 18);
-}
-
-static __inline tilegx_bundle_bits
-create_ShiftOpcodeExtension_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3ff)) << 49);
-}
-
-static __inline tilegx_bundle_bits
-create_ShiftOpcodeExtension_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3) << 18);
-}
-
-static __inline tilegx_bundle_bits
-create_ShiftOpcodeExtension_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3)) << 49);
-}
-
-static __inline tilegx_bundle_bits
-create_SrcA_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 6);
-}
-
-static __inline tilegx_bundle_bits
-create_SrcA_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3f)) << 37);
-}
-
-static __inline tilegx_bundle_bits
-create_SrcA_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 6);
-}
-
-static __inline tilegx_bundle_bits
-create_SrcA_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3f)) << 37);
-}
-
-static __inline tilegx_bundle_bits
-create_SrcA_Y2(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 20);
-}
-
-static __inline tilegx_bundle_bits
-create_SrcBDest_Y2(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3f)) << 51);
-}
-
-static __inline tilegx_bundle_bits
-create_SrcB_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 12);
-}
-
-static __inline tilegx_bundle_bits
-create_SrcB_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3f)) << 43);
-}
-
-static __inline tilegx_bundle_bits
-create_SrcB_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 12);
-}
-
-static __inline tilegx_bundle_bits
-create_SrcB_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3f)) << 43);
-}
-
-static __inline tilegx_bundle_bits
-create_UnaryOpcodeExtension_X0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 12);
-}
-
-static __inline tilegx_bundle_bits
-create_UnaryOpcodeExtension_X1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3f)) << 43);
-}
-
-static __inline tilegx_bundle_bits
-create_UnaryOpcodeExtension_Y0(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return ((n & 0x3f) << 12);
-}
-
-static __inline tilegx_bundle_bits
-create_UnaryOpcodeExtension_Y1(int num)
-{
-  const unsigned int n = (unsigned int)num;
-  return (((tilegx_bundle_bits)(n & 0x3f)) << 43);
-}
-
-
-typedef enum
-{
-  TILEGX_PIPELINE_X0,
-  TILEGX_PIPELINE_X1,
-  TILEGX_PIPELINE_Y0,
-  TILEGX_PIPELINE_Y1,
-  TILEGX_PIPELINE_Y2,
-} tilegx_pipeline;
-
-#define tilegx_is_x_pipeline(p) ((int)(p) <= (int)TILEGX_PIPELINE_X1)
-
-typedef enum
-{
-  TILEGX_OP_TYPE_REGISTER,
-  TILEGX_OP_TYPE_IMMEDIATE,
-  TILEGX_OP_TYPE_ADDRESS,
-  TILEGX_OP_TYPE_SPR
-} tilegx_operand_type;
-
-/* These are the bits that determine if a bundle is in the X encoding. */
-#define TILEGX_BUNDLE_MODE_MASK ((tilegx_bundle_bits)3 << 62)
-
-enum
-{
-  /* Maximum number of instructions in a bundle (2 for X, 3 for Y). */
-  TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE = 3,
-
-  /* How many different pipeline encodings are there? X0, X1, Y0, Y1, Y2. */
-  TILEGX_NUM_PIPELINE_ENCODINGS = 5,
-
-  /* Log base 2 of TILEGX_BUNDLE_SIZE_IN_BYTES. */
-  TILEGX_LOG2_BUNDLE_SIZE_IN_BYTES = 3,
-
-  /* Instructions take this many bytes. */
-  TILEGX_BUNDLE_SIZE_IN_BYTES = 1 << TILEGX_LOG2_BUNDLE_SIZE_IN_BYTES,
-
-  /* Log base 2 of TILEGX_BUNDLE_ALIGNMENT_IN_BYTES. */
-  TILEGX_LOG2_BUNDLE_ALIGNMENT_IN_BYTES = 3,
-
-  /* Bundles should be aligned modulo this number of bytes. */
-  TILEGX_BUNDLE_ALIGNMENT_IN_BYTES =
-    (1 << TILEGX_LOG2_BUNDLE_ALIGNMENT_IN_BYTES),
-
-  /* Number of registers (some are magic, such as network I/O). */
-  TILEGX_NUM_REGISTERS = 64,
-};
-
-
-struct tilegx_operand
-{
-  /* Is this operand a register, immediate or address? */
-  tilegx_operand_type type;
-
-  /* The default relocation type for this operand.  */
-  signed int default_reloc : 16;
-
-  /* How many bits is this value? (used for range checking) */
-  unsigned int num_bits : 5;
-
-  /* Is the value signed? (used for range checking) */
-  unsigned int is_signed : 1;
-
-  /* Is this operand a source register? */
-  unsigned int is_src_reg : 1;
-
-  /* Is this operand written? (i.e. is it a destination register) */
-  unsigned int is_dest_reg : 1;
-
-  /* Is this operand PC-relative? */
-  unsigned int is_pc_relative : 1;
-
-  /* By how many bits do we right shift the value before inserting? */
-  unsigned int rightshift : 2;
-
-  /* Return the bits for this operand to be ORed into an existing bundle. */
-  tilegx_bundle_bits (*insert) (int op);
-
-  /* Extract this operand and return it. */
-  unsigned int (*extract) (tilegx_bundle_bits bundle);
-};
-
-
-extern const struct tilegx_operand tilegx_operands[];
-
-/* One finite-state machine per pipe for rapid instruction decoding. */
-extern const unsigned short * const
-tilegx_bundle_decoder_fsms[TILEGX_NUM_PIPELINE_ENCODINGS];
-
-
-struct tilegx_opcode
-{
-  /* The opcode mnemonic, e.g. "add" */
-  const char *name;
-
-  /* The enum value for this mnemonic. */
-  tilegx_mnemonic mnemonic;
-
-  /* A bit mask of which of the five pipes this instruction
-     is compatible with:
-     X0  0x01
-     X1  0x02
-     Y0  0x04
-     Y1  0x08
-     Y2  0x10 */
-  unsigned char pipes;
-
-  /* How many operands are there? */
-  unsigned char num_operands;
-
-  /* Which register does this write implicitly, or TREG_ZERO if none? */
-  unsigned char implicitly_written_register;
-
-  /* Can this be bundled with other instructions (almost always true). */
-  unsigned char can_bundle;
-
-  /* The description of the operands. Each of these is an
-   * index into the tilegx_operands[] table. */
-  unsigned char operands[TILEGX_NUM_PIPELINE_ENCODINGS][TILEGX_MAX_OPERANDS];
-
-};
-
-extern const struct tilegx_opcode tilegx_opcodes[];
-
-/* Used for non-textual disassembly into structs. */
-struct tilegx_decoded_instruction
-{
-  const struct tilegx_opcode *opcode;
-  const struct tilegx_operand *operands[TILEGX_MAX_OPERANDS];
-  long long operand_values[TILEGX_MAX_OPERANDS];
-};
-
-
-/* Disassemble a bundle into a struct for machine processing. */
-extern int parse_insn_tilegx(tilegx_bundle_bits bits,
-                             unsigned long long pc,
-                             struct tilegx_decoded_instruction
-                             decoded[TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE]);
-
-
-
-#endif /* opcode_tilegx_h */
diff --git a/arch/tile/include/asm/opcode_constants_32.h b/arch/tile/include/asm/opcode_constants_32.h
deleted file mode 100644 (file)
index 227d033..0000000
+++ /dev/null
@@ -1,480 +0,0 @@
-/*
- * Copyright 2010 Tilera Corporation. All Rights Reserved.
- *
- *   This program is free software; you can redistribute it and/or
- *   modify it under the terms of the GNU General Public License
- *   as published by the Free Software Foundation, version 2.
- *
- *   This program is distributed in the hope that it will be useful, but
- *   WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- *   NON INFRINGEMENT.  See the GNU General Public License for
- *   more details.
- */
-
-/* This file is machine-generated; DO NOT EDIT! */
-
-
-#ifndef _TILE_OPCODE_CONSTANTS_H
-#define _TILE_OPCODE_CONSTANTS_H
-enum
-{
-  ADDBS_U_SPECIAL_0_OPCODE_X0 = 98,
-  ADDBS_U_SPECIAL_0_OPCODE_X1 = 68,
-  ADDB_SPECIAL_0_OPCODE_X0 = 1,
-  ADDB_SPECIAL_0_OPCODE_X1 = 1,
-  ADDHS_SPECIAL_0_OPCODE_X0 = 99,
-  ADDHS_SPECIAL_0_OPCODE_X1 = 69,
-  ADDH_SPECIAL_0_OPCODE_X0 = 2,
-  ADDH_SPECIAL_0_OPCODE_X1 = 2,
-  ADDIB_IMM_0_OPCODE_X0 = 1,
-  ADDIB_IMM_0_OPCODE_X1 = 1,
-  ADDIH_IMM_0_OPCODE_X0 = 2,
-  ADDIH_IMM_0_OPCODE_X1 = 2,
-  ADDI_IMM_0_OPCODE_X0 = 3,
-  ADDI_IMM_0_OPCODE_X1 = 3,
-  ADDI_IMM_1_OPCODE_SN = 1,
-  ADDI_OPCODE_Y0 = 9,
-  ADDI_OPCODE_Y1 = 7,
-  ADDLIS_OPCODE_X0 = 1,
-  ADDLIS_OPCODE_X1 = 2,
-  ADDLI_OPCODE_X0 = 2,
-  ADDLI_OPCODE_X1 = 3,
-  ADDS_SPECIAL_0_OPCODE_X0 = 96,
-  ADDS_SPECIAL_0_OPCODE_X1 = 66,
-  ADD_SPECIAL_0_OPCODE_X0 = 3,
-  ADD_SPECIAL_0_OPCODE_X1 = 3,
-  ADD_SPECIAL_0_OPCODE_Y0 = 0,
-  ADD_SPECIAL_0_OPCODE_Y1 = 0,
-  ADIFFB_U_SPECIAL_0_OPCODE_X0 = 4,
-  ADIFFH_SPECIAL_0_OPCODE_X0 = 5,
-  ANDI_IMM_0_OPCODE_X0 = 1,
-  ANDI_IMM_0_OPCODE_X1 = 4,
-  ANDI_OPCODE_Y0 = 10,
-  ANDI_OPCODE_Y1 = 8,
-  AND_SPECIAL_0_OPCODE_X0 = 6,
-  AND_SPECIAL_0_OPCODE_X1 = 4,
-  AND_SPECIAL_2_OPCODE_Y0 = 0,
-  AND_SPECIAL_2_OPCODE_Y1 = 0,
-  AULI_OPCODE_X0 = 3,
-  AULI_OPCODE_X1 = 4,
-  AVGB_U_SPECIAL_0_OPCODE_X0 = 7,
-  AVGH_SPECIAL_0_OPCODE_X0 = 8,
-  BBNST_BRANCH_OPCODE_X1 = 15,
-  BBNS_BRANCH_OPCODE_X1 = 14,
-  BBNS_OPCODE_SN = 63,
-  BBST_BRANCH_OPCODE_X1 = 13,
-  BBS_BRANCH_OPCODE_X1 = 12,
-  BBS_OPCODE_SN = 62,
-  BGEZT_BRANCH_OPCODE_X1 = 7,
-  BGEZ_BRANCH_OPCODE_X1 = 6,
-  BGEZ_OPCODE_SN = 61,
-  BGZT_BRANCH_OPCODE_X1 = 5,
-  BGZ_BRANCH_OPCODE_X1 = 4,
-  BGZ_OPCODE_SN = 58,
-  BITX_UN_0_SHUN_0_OPCODE_X0 = 1,
-  BITX_UN_0_SHUN_0_OPCODE_Y0 = 1,
-  BLEZT_BRANCH_OPCODE_X1 = 11,
-  BLEZ_BRANCH_OPCODE_X1 = 10,
-  BLEZ_OPCODE_SN = 59,
-  BLZT_BRANCH_OPCODE_X1 = 9,
-  BLZ_BRANCH_OPCODE_X1 = 8,
-  BLZ_OPCODE_SN = 60,
-  BNZT_BRANCH_OPCODE_X1 = 3,
-  BNZ_BRANCH_OPCODE_X1 = 2,
-  BNZ_OPCODE_SN = 57,
-  BPT_NOREG_RR_IMM_0_OPCODE_SN = 1,
-  BRANCH_OPCODE_X1 = 5,
-  BYTEX_UN_0_SHUN_0_OPCODE_X0 = 2,
-  BYTEX_UN_0_SHUN_0_OPCODE_Y0 = 2,
-  BZT_BRANCH_OPCODE_X1 = 1,
-  BZ_BRANCH_OPCODE_X1 = 0,
-  BZ_OPCODE_SN = 56,
-  CLZ_UN_0_SHUN_0_OPCODE_X0 = 3,
-  CLZ_UN_0_SHUN_0_OPCODE_Y0 = 3,
-  CRC32_32_SPECIAL_0_OPCODE_X0 = 9,
-  CRC32_8_SPECIAL_0_OPCODE_X0 = 10,
-  CTZ_UN_0_SHUN_0_OPCODE_X0 = 4,
-  CTZ_UN_0_SHUN_0_OPCODE_Y0 = 4,
-  DRAIN_UN_0_SHUN_0_OPCODE_X1 = 1,
-  DTLBPR_UN_0_SHUN_0_OPCODE_X1 = 2,
-  DWORD_ALIGN_SPECIAL_0_OPCODE_X0 = 95,
-  FINV_UN_0_SHUN_0_OPCODE_X1 = 3,
-  FLUSH_UN_0_SHUN_0_OPCODE_X1 = 4,
-  FNOP_NOREG_RR_IMM_0_OPCODE_SN = 3,
-  FNOP_UN_0_SHUN_0_OPCODE_X0 = 5,
-  FNOP_UN_0_SHUN_0_OPCODE_X1 = 5,
-  FNOP_UN_0_SHUN_0_OPCODE_Y0 = 5,
-  FNOP_UN_0_SHUN_0_OPCODE_Y1 = 1,
-  HALT_NOREG_RR_IMM_0_OPCODE_SN = 0,
-  ICOH_UN_0_SHUN_0_OPCODE_X1 = 6,
-  ILL_UN_0_SHUN_0_OPCODE_X1 = 7,
-  ILL_UN_0_SHUN_0_OPCODE_Y1 = 2,
-  IMM_0_OPCODE_SN = 0,
-  IMM_0_OPCODE_X0 = 4,
-  IMM_0_OPCODE_X1 = 6,
-  IMM_1_OPCODE_SN = 1,
-  IMM_OPCODE_0_X0 = 5,
-  INTHB_SPECIAL_0_OPCODE_X0 = 11,
-  INTHB_SPECIAL_0_OPCODE_X1 = 5,
-  INTHH_SPECIAL_0_OPCODE_X0 = 12,
-  INTHH_SPECIAL_0_OPCODE_X1 = 6,
-  INTLB_SPECIAL_0_OPCODE_X0 = 13,
-  INTLB_SPECIAL_0_OPCODE_X1 = 7,
-  INTLH_SPECIAL_0_OPCODE_X0 = 14,
-  INTLH_SPECIAL_0_OPCODE_X1 = 8,
-  INV_UN_0_SHUN_0_OPCODE_X1 = 8,
-  IRET_UN_0_SHUN_0_OPCODE_X1 = 9,
-  JALB_OPCODE_X1 = 13,
-  JALF_OPCODE_X1 = 12,
-  JALRP_SPECIAL_0_OPCODE_X1 = 9,
-  JALRR_IMM_1_OPCODE_SN = 3,
-  JALR_RR_IMM_0_OPCODE_SN = 5,
-  JALR_SPECIAL_0_OPCODE_X1 = 10,
-  JB_OPCODE_X1 = 11,
-  JF_OPCODE_X1 = 10,
-  JRP_SPECIAL_0_OPCODE_X1 = 11,
-  JRR_IMM_1_OPCODE_SN = 2,
-  JR_RR_IMM_0_OPCODE_SN = 4,
-  JR_SPECIAL_0_OPCODE_X1 = 12,
-  LBADD_IMM_0_OPCODE_X1 = 22,
-  LBADD_U_IMM_0_OPCODE_X1 = 23,
-  LB_OPCODE_Y2 = 0,
-  LB_UN_0_SHUN_0_OPCODE_X1 = 10,
-  LB_U_OPCODE_Y2 = 1,
-  LB_U_UN_0_SHUN_0_OPCODE_X1 = 11,
-  LHADD_IMM_0_OPCODE_X1 = 24,
-  LHADD_U_IMM_0_OPCODE_X1 = 25,
-  LH_OPCODE_Y2 = 2,
-  LH_UN_0_SHUN_0_OPCODE_X1 = 12,
-  LH_U_OPCODE_Y2 = 3,
-  LH_U_UN_0_SHUN_0_OPCODE_X1 = 13,
-  LNK_SPECIAL_0_OPCODE_X1 = 13,
-  LWADD_IMM_0_OPCODE_X1 = 26,
-  LWADD_NA_IMM_0_OPCODE_X1 = 27,
-  LW_NA_UN_0_SHUN_0_OPCODE_X1 = 24,
-  LW_OPCODE_Y2 = 4,
-  LW_UN_0_SHUN_0_OPCODE_X1 = 14,
-  MAXB_U_SPECIAL_0_OPCODE_X0 = 15,
-  MAXB_U_SPECIAL_0_OPCODE_X1 = 14,
-  MAXH_SPECIAL_0_OPCODE_X0 = 16,
-  MAXH_SPECIAL_0_OPCODE_X1 = 15,
-  MAXIB_U_IMM_0_OPCODE_X0 = 4,
-  MAXIB_U_IMM_0_OPCODE_X1 = 5,
-  MAXIH_IMM_0_OPCODE_X0 = 5,
-  MAXIH_IMM_0_OPCODE_X1 = 6,
-  MFSPR_IMM_0_OPCODE_X1 = 7,
-  MF_UN_0_SHUN_0_OPCODE_X1 = 15,
-  MINB_U_SPECIAL_0_OPCODE_X0 = 17,
-  MINB_U_SPECIAL_0_OPCODE_X1 = 16,
-  MINH_SPECIAL_0_OPCODE_X0 = 18,
-  MINH_SPECIAL_0_OPCODE_X1 = 17,
-  MINIB_U_IMM_0_OPCODE_X0 = 6,
-  MINIB_U_IMM_0_OPCODE_X1 = 8,
-  MINIH_IMM_0_OPCODE_X0 = 7,
-  MINIH_IMM_0_OPCODE_X1 = 9,
-  MM_OPCODE_X0 = 6,
-  MM_OPCODE_X1 = 7,
-  MNZB_SPECIAL_0_OPCODE_X0 = 19,
-  MNZB_SPECIAL_0_OPCODE_X1 = 18,
-  MNZH_SPECIAL_0_OPCODE_X0 = 20,
-  MNZH_SPECIAL_0_OPCODE_X1 = 19,
-  MNZ_SPECIAL_0_OPCODE_X0 = 21,
-  MNZ_SPECIAL_0_OPCODE_X1 = 20,
-  MNZ_SPECIAL_1_OPCODE_Y0 = 0,
-  MNZ_SPECIAL_1_OPCODE_Y1 = 1,
-  MOVEI_IMM_1_OPCODE_SN = 0,
-  MOVE_RR_IMM_0_OPCODE_SN = 8,
-  MTSPR_IMM_0_OPCODE_X1 = 10,
-  MULHHA_SS_SPECIAL_0_OPCODE_X0 = 22,
-  MULHHA_SS_SPECIAL_7_OPCODE_Y0 = 0,
-  MULHHA_SU_SPECIAL_0_OPCODE_X0 = 23,
-  MULHHA_UU_SPECIAL_0_OPCODE_X0 = 24,
-  MULHHA_UU_SPECIAL_7_OPCODE_Y0 = 1,
-  MULHHSA_UU_SPECIAL_0_OPCODE_X0 = 25,
-  MULHH_SS_SPECIAL_0_OPCODE_X0 = 26,
-  MULHH_SS_SPECIAL_6_OPCODE_Y0 = 0,
-  MULHH_SU_SPECIAL_0_OPCODE_X0 = 27,
-  MULHH_UU_SPECIAL_0_OPCODE_X0 = 28,
-  MULHH_UU_SPECIAL_6_OPCODE_Y0 = 1,
-  MULHLA_SS_SPECIAL_0_OPCODE_X0 = 29,
-  MULHLA_SU_SPECIAL_0_OPCODE_X0 = 30,
-  MULHLA_US_SPECIAL_0_OPCODE_X0 = 31,
-  MULHLA_UU_SPECIAL_0_OPCODE_X0 = 32,
-  MULHLSA_UU_SPECIAL_0_OPCODE_X0 = 33,
-  MULHLSA_UU_SPECIAL_5_OPCODE_Y0 = 0,
-  MULHL_SS_SPECIAL_0_OPCODE_X0 = 34,
-  MULHL_SU_SPECIAL_0_OPCODE_X0 = 35,
-  MULHL_US_SPECIAL_0_OPCODE_X0 = 36,
-  MULHL_UU_SPECIAL_0_OPCODE_X0 = 37,
-  MULLLA_SS_SPECIAL_0_OPCODE_X0 = 38,
-  MULLLA_SS_SPECIAL_7_OPCODE_Y0 = 2,
-  MULLLA_SU_SPECIAL_0_OPCODE_X0 = 39,
-  MULLLA_UU_SPECIAL_0_OPCODE_X0 = 40,
-  MULLLA_UU_SPECIAL_7_OPCODE_Y0 = 3,
-  MULLLSA_UU_SPECIAL_0_OPCODE_X0 = 41,
-  MULLL_SS_SPECIAL_0_OPCODE_X0 = 42,
-  MULLL_SS_SPECIAL_6_OPCODE_Y0 = 2,
-  MULLL_SU_SPECIAL_0_OPCODE_X0 = 43,
-  MULLL_UU_SPECIAL_0_OPCODE_X0 = 44,
-  MULLL_UU_SPECIAL_6_OPCODE_Y0 = 3,
-  MVNZ_SPECIAL_0_OPCODE_X0 = 45,
-  MVNZ_SPECIAL_1_OPCODE_Y0 = 1,
-  MVZ_SPECIAL_0_OPCODE_X0 = 46,
-  MVZ_SPECIAL_1_OPCODE_Y0 = 2,
-  MZB_SPECIAL_0_OPCODE_X0 = 47,
-  MZB_SPECIAL_0_OPCODE_X1 = 21,
-  MZH_SPECIAL_0_OPCODE_X0 = 48,
-  MZH_SPECIAL_0_OPCODE_X1 = 22,
-  MZ_SPECIAL_0_OPCODE_X0 = 49,
-  MZ_SPECIAL_0_OPCODE_X1 = 23,
-  MZ_SPECIAL_1_OPCODE_Y0 = 3,
-  MZ_SPECIAL_1_OPCODE_Y1 = 2,
-  NAP_UN_0_SHUN_0_OPCODE_X1 = 16,
-  NOP_NOREG_RR_IMM_0_OPCODE_SN = 2,
-  NOP_UN_0_SHUN_0_OPCODE_X0 = 6,
-  NOP_UN_0_SHUN_0_OPCODE_X1 = 17,
-  NOP_UN_0_SHUN_0_OPCODE_Y0 = 6,
-  NOP_UN_0_SHUN_0_OPCODE_Y1 = 3,
-  NOREG_RR_IMM_0_OPCODE_SN = 0,
-  NOR_SPECIAL_0_OPCODE_X0 = 50,
-  NOR_SPECIAL_0_OPCODE_X1 = 24,
-  NOR_SPECIAL_2_OPCODE_Y0 = 1,
-  NOR_SPECIAL_2_OPCODE_Y1 = 1,
-  ORI_IMM_0_OPCODE_X0 = 8,
-  ORI_IMM_0_OPCODE_X1 = 11,
-  ORI_OPCODE_Y0 = 11,
-  ORI_OPCODE_Y1 = 9,
-  OR_SPECIAL_0_OPCODE_X0 = 51,
-  OR_SPECIAL_0_OPCODE_X1 = 25,
-  OR_SPECIAL_2_OPCODE_Y0 = 2,
-  OR_SPECIAL_2_OPCODE_Y1 = 2,
-  PACKBS_U_SPECIAL_0_OPCODE_X0 = 103,
-  PACKBS_U_SPECIAL_0_OPCODE_X1 = 73,
-  PACKHB_SPECIAL_0_OPCODE_X0 = 52,
-  PACKHB_SPECIAL_0_OPCODE_X1 = 26,
-  PACKHS_SPECIAL_0_OPCODE_X0 = 102,
-  PACKHS_SPECIAL_0_OPCODE_X1 = 72,
-  PACKLB_SPECIAL_0_OPCODE_X0 = 53,
-  PACKLB_SPECIAL_0_OPCODE_X1 = 27,
-  PCNT_UN_0_SHUN_0_OPCODE_X0 = 7,
-  PCNT_UN_0_SHUN_0_OPCODE_Y0 = 7,
-  RLI_SHUN_0_OPCODE_X0 = 1,
-  RLI_SHUN_0_OPCODE_X1 = 1,
-  RLI_SHUN_0_OPCODE_Y0 = 1,
-  RLI_SHUN_0_OPCODE_Y1 = 1,
-  RL_SPECIAL_0_OPCODE_X0 = 54,
-  RL_SPECIAL_0_OPCODE_X1 = 28,
-  RL_SPECIAL_3_OPCODE_Y0 = 0,
-  RL_SPECIAL_3_OPCODE_Y1 = 0,
-  RR_IMM_0_OPCODE_SN = 0,
-  S1A_SPECIAL_0_OPCODE_X0 = 55,
-  S1A_SPECIAL_0_OPCODE_X1 = 29,
-  S1A_SPECIAL_0_OPCODE_Y0 = 1,
-  S1A_SPECIAL_0_OPCODE_Y1 = 1,
-  S2A_SPECIAL_0_OPCODE_X0 = 56,
-  S2A_SPECIAL_0_OPCODE_X1 = 30,
-  S2A_SPECIAL_0_OPCODE_Y0 = 2,
-  S2A_SPECIAL_0_OPCODE_Y1 = 2,
-  S3A_SPECIAL_0_OPCODE_X0 = 57,
-  S3A_SPECIAL_0_OPCODE_X1 = 31,
-  S3A_SPECIAL_5_OPCODE_Y0 = 1,
-  S3A_SPECIAL_5_OPCODE_Y1 = 1,
-  SADAB_U_SPECIAL_0_OPCODE_X0 = 58,
-  SADAH_SPECIAL_0_OPCODE_X0 = 59,
-  SADAH_U_SPECIAL_0_OPCODE_X0 = 60,
-  SADB_U_SPECIAL_0_OPCODE_X0 = 61,
-  SADH_SPECIAL_0_OPCODE_X0 = 62,
-  SADH_U_SPECIAL_0_OPCODE_X0 = 63,
-  SBADD_IMM_0_OPCODE_X1 = 28,
-  SB_OPCODE_Y2 = 5,
-  SB_SPECIAL_0_OPCODE_X1 = 32,
-  SEQB_SPECIAL_0_OPCODE_X0 = 64,
-  SEQB_SPECIAL_0_OPCODE_X1 = 33,
-  SEQH_SPECIAL_0_OPCODE_X0 = 65,
-  SEQH_SPECIAL_0_OPCODE_X1 = 34,
-  SEQIB_IMM_0_OPCODE_X0 = 9,
-  SEQIB_IMM_0_OPCODE_X1 = 12,
-  SEQIH_IMM_0_OPCODE_X0 = 10,
-  SEQIH_IMM_0_OPCODE_X1 = 13,
-  SEQI_IMM_0_OPCODE_X0 = 11,
-  SEQI_IMM_0_OPCODE_X1 = 14,
-  SEQI_OPCODE_Y0 = 12,
-  SEQI_OPCODE_Y1 = 10,
-  SEQ_SPECIAL_0_OPCODE_X0 = 66,
-  SEQ_SPECIAL_0_OPCODE_X1 = 35,
-  SEQ_SPECIAL_5_OPCODE_Y0 = 2,
-  SEQ_SPECIAL_5_OPCODE_Y1 = 2,
-  SHADD_IMM_0_OPCODE_X1 = 29,
-  SHL8II_IMM_0_OPCODE_SN = 3,
-  SHLB_SPECIAL_0_OPCODE_X0 = 67,
-  SHLB_SPECIAL_0_OPCODE_X1 = 36,
-  SHLH_SPECIAL_0_OPCODE_X0 = 68,
-  SHLH_SPECIAL_0_OPCODE_X1 = 37,
-  SHLIB_SHUN_0_OPCODE_X0 = 2,
-  SHLIB_SHUN_0_OPCODE_X1 = 2,
-  SHLIH_SHUN_0_OPCODE_X0 = 3,
-  SHLIH_SHUN_0_OPCODE_X1 = 3,
-  SHLI_SHUN_0_OPCODE_X0 = 4,
-  SHLI_SHUN_0_OPCODE_X1 = 4,
-  SHLI_SHUN_0_OPCODE_Y0 = 2,
-  SHLI_SHUN_0_OPCODE_Y1 = 2,
-  SHL_SPECIAL_0_OPCODE_X0 = 69,
-  SHL_SPECIAL_0_OPCODE_X1 = 38,
-  SHL_SPECIAL_3_OPCODE_Y0 = 1,
-  SHL_SPECIAL_3_OPCODE_Y1 = 1,
-  SHR1_RR_IMM_0_OPCODE_SN = 9,
-  SHRB_SPECIAL_0_OPCODE_X0 = 70,
-  SHRB_SPECIAL_0_OPCODE_X1 = 39,
-  SHRH_SPECIAL_0_OPCODE_X0 = 71,
-  SHRH_SPECIAL_0_OPCODE_X1 = 40,
-  SHRIB_SHUN_0_OPCODE_X0 = 5,
-  SHRIB_SHUN_0_OPCODE_X1 = 5,
-  SHRIH_SHUN_0_OPCODE_X0 = 6,
-  SHRIH_SHUN_0_OPCODE_X1 = 6,
-  SHRI_SHUN_0_OPCODE_X0 = 7,
-  SHRI_SHUN_0_OPCODE_X1 = 7,
-  SHRI_SHUN_0_OPCODE_Y0 = 3,
-  SHRI_SHUN_0_OPCODE_Y1 = 3,
-  SHR_SPECIAL_0_OPCODE_X0 = 72,
-  SHR_SPECIAL_0_OPCODE_X1 = 41,
-  SHR_SPECIAL_3_OPCODE_Y0 = 2,
-  SHR_SPECIAL_3_OPCODE_Y1 = 2,
-  SHUN_0_OPCODE_X0 = 7,
-  SHUN_0_OPCODE_X1 = 8,
-  SHUN_0_OPCODE_Y0 = 13,
-  SHUN_0_OPCODE_Y1 = 11,
-  SH_OPCODE_Y2 = 6,
-  SH_SPECIAL_0_OPCODE_X1 = 42,
-  SLTB_SPECIAL_0_OPCODE_X0 = 73,
-  SLTB_SPECIAL_0_OPCODE_X1 = 43,
-  SLTB_U_SPECIAL_0_OPCODE_X0 = 74,
-  SLTB_U_SPECIAL_0_OPCODE_X1 = 44,
-  SLTEB_SPECIAL_0_OPCODE_X0 = 75,
-  SLTEB_SPECIAL_0_OPCODE_X1 = 45,
-  SLTEB_U_SPECIAL_0_OPCODE_X0 = 76,
-  SLTEB_U_SPECIAL_0_OPCODE_X1 = 46,
-  SLTEH_SPECIAL_0_OPCODE_X0 = 77,
-  SLTEH_SPECIAL_0_OPCODE_X1 = 47,
-  SLTEH_U_SPECIAL_0_OPCODE_X0 = 78,
-  SLTEH_U_SPECIAL_0_OPCODE_X1 = 48,
-  SLTE_SPECIAL_0_OPCODE_X0 = 79,
-  SLTE_SPECIAL_0_OPCODE_X1 = 49,
-  SLTE_SPECIAL_4_OPCODE_Y0 = 0,
-  SLTE_SPECIAL_4_OPCODE_Y1 = 0,
-  SLTE_U_SPECIAL_0_OPCODE_X0 = 80,
-  SLTE_U_SPECIAL_0_OPCODE_X1 = 50,
-  SLTE_U_SPECIAL_4_OPCODE_Y0 = 1,
-  SLTE_U_SPECIAL_4_OPCODE_Y1 = 1,
-  SLTH_SPECIAL_0_OPCODE_X0 = 81,
-  SLTH_SPECIAL_0_OPCODE_X1 = 51,
-  SLTH_U_SPECIAL_0_OPCODE_X0 = 82,
-  SLTH_U_SPECIAL_0_OPCODE_X1 = 52,
-  SLTIB_IMM_0_OPCODE_X0 = 12,
-  SLTIB_IMM_0_OPCODE_X1 = 15,
-  SLTIB_U_IMM_0_OPCODE_X0 = 13,
-  SLTIB_U_IMM_0_OPCODE_X1 = 16,
-  SLTIH_IMM_0_OPCODE_X0 = 14,
-  SLTIH_IMM_0_OPCODE_X1 = 17,
-  SLTIH_U_IMM_0_OPCODE_X0 = 15,
-  SLTIH_U_IMM_0_OPCODE_X1 = 18,
-  SLTI_IMM_0_OPCODE_X0 = 16,
-  SLTI_IMM_0_OPCODE_X1 = 19,
-  SLTI_OPCODE_Y0 = 14,
-  SLTI_OPCODE_Y1 = 12,
-  SLTI_U_IMM_0_OPCODE_X0 = 17,
-  SLTI_U_IMM_0_OPCODE_X1 = 20,
-  SLTI_U_OPCODE_Y0 = 15,
-  SLTI_U_OPCODE_Y1 = 13,
-  SLT_SPECIAL_0_OPCODE_X0 = 83,
-  SLT_SPECIAL_0_OPCODE_X1 = 53,
-  SLT_SPECIAL_4_OPCODE_Y0 = 2,
-  SLT_SPECIAL_4_OPCODE_Y1 = 2,
-  SLT_U_SPECIAL_0_OPCODE_X0 = 84,
-  SLT_U_SPECIAL_0_OPCODE_X1 = 54,
-  SLT_U_SPECIAL_4_OPCODE_Y0 = 3,
-  SLT_U_SPECIAL_4_OPCODE_Y1 = 3,
-  SNEB_SPECIAL_0_OPCODE_X0 = 85,
-  SNEB_SPECIAL_0_OPCODE_X1 = 55,
-  SNEH_SPECIAL_0_OPCODE_X0 = 86,
-  SNEH_SPECIAL_0_OPCODE_X1 = 56,
-  SNE_SPECIAL_0_OPCODE_X0 = 87,
-  SNE_SPECIAL_0_OPCODE_X1 = 57,
-  SNE_SPECIAL_5_OPCODE_Y0 = 3,
-  SNE_SPECIAL_5_OPCODE_Y1 = 3,
-  SPECIAL_0_OPCODE_X0 = 0,
-  SPECIAL_0_OPCODE_X1 = 1,
-  SPECIAL_0_OPCODE_Y0 = 1,
-  SPECIAL_0_OPCODE_Y1 = 1,
-  SPECIAL_1_OPCODE_Y0 = 2,
-  SPECIAL_1_OPCODE_Y1 = 2,
-  SPECIAL_2_OPCODE_Y0 = 3,
-  SPECIAL_2_OPCODE_Y1 = 3,
-  SPECIAL_3_OPCODE_Y0 = 4,
-  SPECIAL_3_OPCODE_Y1 = 4,
-  SPECIAL_4_OPCODE_Y0 = 5,
-  SPECIAL_4_OPCODE_Y1 = 5,
-  SPECIAL_5_OPCODE_Y0 = 6,
-  SPECIAL_5_OPCODE_Y1 = 6,
-  SPECIAL_6_OPCODE_Y0 = 7,
-  SPECIAL_7_OPCODE_Y0 = 8,
-  SRAB_SPECIAL_0_OPCODE_X0 = 88,
-  SRAB_SPECIAL_0_OPCODE_X1 = 58,
-  SRAH_SPECIAL_0_OPCODE_X0 = 89,
-  SRAH_SPECIAL_0_OPCODE_X1 = 59,
-  SRAIB_SHUN_0_OPCODE_X0 = 8,
-  SRAIB_SHUN_0_OPCODE_X1 = 8,
-  SRAIH_SHUN_0_OPCODE_X0 = 9,
-  SRAIH_SHUN_0_OPCODE_X1 = 9,
-  SRAI_SHUN_0_OPCODE_X0 = 10,
-  SRAI_SHUN_0_OPCODE_X1 = 10,
-  SRAI_SHUN_0_OPCODE_Y0 = 4,
-  SRAI_SHUN_0_OPCODE_Y1 = 4,
-  SRA_SPECIAL_0_OPCODE_X0 = 90,
-  SRA_SPECIAL_0_OPCODE_X1 = 60,
-  SRA_SPECIAL_3_OPCODE_Y0 = 3,
-  SRA_SPECIAL_3_OPCODE_Y1 = 3,
-  SUBBS_U_SPECIAL_0_OPCODE_X0 = 100,
-  SUBBS_U_SPECIAL_0_OPCODE_X1 = 70,
-  SUBB_SPECIAL_0_OPCODE_X0 = 91,
-  SUBB_SPECIAL_0_OPCODE_X1 = 61,
-  SUBHS_SPECIAL_0_OPCODE_X0 = 101,
-  SUBHS_SPECIAL_0_OPCODE_X1 = 71,
-  SUBH_SPECIAL_0_OPCODE_X0 = 92,
-  SUBH_SPECIAL_0_OPCODE_X1 = 62,
-  SUBS_SPECIAL_0_OPCODE_X0 = 97,
-  SUBS_SPECIAL_0_OPCODE_X1 = 67,
-  SUB_SPECIAL_0_OPCODE_X0 = 93,
-  SUB_SPECIAL_0_OPCODE_X1 = 63,
-  SUB_SPECIAL_0_OPCODE_Y0 = 3,
-  SUB_SPECIAL_0_OPCODE_Y1 = 3,
-  SWADD_IMM_0_OPCODE_X1 = 30,
-  SWINT0_UN_0_SHUN_0_OPCODE_X1 = 18,
-  SWINT1_UN_0_SHUN_0_OPCODE_X1 = 19,
-  SWINT2_UN_0_SHUN_0_OPCODE_X1 = 20,
-  SWINT3_UN_0_SHUN_0_OPCODE_X1 = 21,
-  SW_OPCODE_Y2 = 7,
-  SW_SPECIAL_0_OPCODE_X1 = 64,
-  TBLIDXB0_UN_0_SHUN_0_OPCODE_X0 = 8,
-  TBLIDXB0_UN_0_SHUN_0_OPCODE_Y0 = 8,
-  TBLIDXB1_UN_0_SHUN_0_OPCODE_X0 = 9,
-  TBLIDXB1_UN_0_SHUN_0_OPCODE_Y0 = 9,
-  TBLIDXB2_UN_0_SHUN_0_OPCODE_X0 = 10,
-  TBLIDXB2_UN_0_SHUN_0_OPCODE_Y0 = 10,
-  TBLIDXB3_UN_0_SHUN_0_OPCODE_X0 = 11,
-  TBLIDXB3_UN_0_SHUN_0_OPCODE_Y0 = 11,
-  TNS_UN_0_SHUN_0_OPCODE_X1 = 22,
-  UN_0_SHUN_0_OPCODE_X0 = 11,
-  UN_0_SHUN_0_OPCODE_X1 = 11,
-  UN_0_SHUN_0_OPCODE_Y0 = 5,
-  UN_0_SHUN_0_OPCODE_Y1 = 5,
-  WH64_UN_0_SHUN_0_OPCODE_X1 = 23,
-  XORI_IMM_0_OPCODE_X0 = 2,
-  XORI_IMM_0_OPCODE_X1 = 21,
-  XOR_SPECIAL_0_OPCODE_X0 = 94,
-  XOR_SPECIAL_0_OPCODE_X1 = 65,
-  XOR_SPECIAL_2_OPCODE_Y0 = 3,
-  XOR_SPECIAL_2_OPCODE_Y1 = 3
-};
-
-#endif /* !_TILE_OPCODE_CONSTANTS_H */
index 5e2d033..6348e59 100644 (file)
@@ -15,6 +15,8 @@
 #ifndef _ASM_TILE_SIGCONTEXT_H
 #define _ASM_TILE_SIGCONTEXT_H
 
+/* Don't pollute the namespace since <signal.h> includes this file. */
+#define __need_int_reg_t
 #include <arch/abi.h>
 
 /*
  * but is simplified since we know the fault is from userspace.
  */
 struct sigcontext {
-       uint_reg_t gregs[53];   /* General-purpose registers.  */
-       uint_reg_t tp;          /* Aliases gregs[TREG_TP].  */
-       uint_reg_t sp;          /* Aliases gregs[TREG_SP].  */
-       uint_reg_t lr;          /* Aliases gregs[TREG_LR].  */
-       uint_reg_t pc;          /* Program counter.  */
-       uint_reg_t ics;         /* In Interrupt Critical Section?  */
-       uint_reg_t faultnum;    /* Fault number.  */
-       uint_reg_t pad[5];
+       __uint_reg_t gregs[53]; /* General-purpose registers.  */
+       __uint_reg_t tp;        /* Aliases gregs[TREG_TP].  */
+       __uint_reg_t sp;        /* Aliases gregs[TREG_SP].  */
+       __uint_reg_t lr;        /* Aliases gregs[TREG_LR].  */
+       __uint_reg_t pc;        /* Program counter.  */
+       __uint_reg_t ics;       /* In Interrupt Critical Section?  */
+       __uint_reg_t faultnum;  /* Fault number.  */
+       __uint_reg_t pad[5];
 };
 
 #endif /* _ASM_TILE_SIGCONTEXT_H */
similarity index 56%
rename from arch/tile/include/asm/opcode-tile.h
rename to arch/tile/include/asm/tile-desc.h
index ba38959..43849bf 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2010 Tilera Corporation. All Rights Reserved.
+ * Copyright 2011 Tilera Corporation. All Rights Reserved.
  *
  *   This program is free software; you can redistribute it and/or
  *   modify it under the terms of the GNU General Public License
  *   more details.
  */
 
-#ifndef _ASM_TILE_OPCODE_TILE_H
-#define _ASM_TILE_OPCODE_TILE_H
-
-#include <arch/chip.h>
-
-#if CHIP_WORD_SIZE() == 64
-#include <asm/opcode-tile_64.h>
+#ifndef __tilegx__
+#include <asm/tile-desc_32.h>
 #else
-#include <asm/opcode-tile_32.h>
+#include <asm/tile-desc_64.h>
 #endif
-
-/* These definitions are not correct for TILE64, so just avoid them. */
-#undef TILE_ELF_MACHINE_CODE
-#undef TILE_ELF_NAME
-
-#endif /* _ASM_TILE_OPCODE_TILE_H */
diff --git a/arch/tile/include/asm/tile-desc_32.h b/arch/tile/include/asm/tile-desc_32.h
new file mode 100644 (file)
index 0000000..f09c5c4
--- /dev/null
@@ -0,0 +1,553 @@
+/* TILEPro opcode information.
+ *
+ * Copyright 2011 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ *
+ *
+ *
+ *
+ *
+ */
+
+#ifndef opcode_tilepro_h
+#define opcode_tilepro_h
+
+#include <arch/opcode.h>
+
+
+enum
+{
+  TILEPRO_MAX_OPERANDS = 5 /* mm */
+};
+
+typedef enum
+{
+  TILEPRO_OPC_BPT,
+  TILEPRO_OPC_INFO,
+  TILEPRO_OPC_INFOL,
+  TILEPRO_OPC_J,
+  TILEPRO_OPC_JAL,
+  TILEPRO_OPC_MOVE,
+  TILEPRO_OPC_MOVE_SN,
+  TILEPRO_OPC_MOVEI,
+  TILEPRO_OPC_MOVEI_SN,
+  TILEPRO_OPC_MOVELI,
+  TILEPRO_OPC_MOVELI_SN,
+  TILEPRO_OPC_MOVELIS,
+  TILEPRO_OPC_PREFETCH,
+  TILEPRO_OPC_RAISE,
+  TILEPRO_OPC_ADD,
+  TILEPRO_OPC_ADD_SN,
+  TILEPRO_OPC_ADDB,
+  TILEPRO_OPC_ADDB_SN,
+  TILEPRO_OPC_ADDBS_U,
+  TILEPRO_OPC_ADDBS_U_SN,
+  TILEPRO_OPC_ADDH,
+  TILEPRO_OPC_ADDH_SN,
+  TILEPRO_OPC_ADDHS,
+  TILEPRO_OPC_ADDHS_SN,
+  TILEPRO_OPC_ADDI,
+  TILEPRO_OPC_ADDI_SN,
+  TILEPRO_OPC_ADDIB,
+  TILEPRO_OPC_ADDIB_SN,
+  TILEPRO_OPC_ADDIH,
+  TILEPRO_OPC_ADDIH_SN,
+  TILEPRO_OPC_ADDLI,
+  TILEPRO_OPC_ADDLI_SN,
+  TILEPRO_OPC_ADDLIS,
+  TILEPRO_OPC_ADDS,
+  TILEPRO_OPC_ADDS_SN,
+  TILEPRO_OPC_ADIFFB_U,
+  TILEPRO_OPC_ADIFFB_U_SN,
+  TILEPRO_OPC_ADIFFH,
+  TILEPRO_OPC_ADIFFH_SN,
+  TILEPRO_OPC_AND,
+  TILEPRO_OPC_AND_SN,
+  TILEPRO_OPC_ANDI,
+  TILEPRO_OPC_ANDI_SN,
+  TILEPRO_OPC_AULI,
+  TILEPRO_OPC_AVGB_U,
+  TILEPRO_OPC_AVGB_U_SN,
+  TILEPRO_OPC_AVGH,
+  TILEPRO_OPC_AVGH_SN,
+  TILEPRO_OPC_BBNS,
+  TILEPRO_OPC_BBNS_SN,
+  TILEPRO_OPC_BBNST,
+  TILEPRO_OPC_BBNST_SN,
+  TILEPRO_OPC_BBS,
+  TILEPRO_OPC_BBS_SN,
+  TILEPRO_OPC_BBST,
+  TILEPRO_OPC_BBST_SN,
+  TILEPRO_OPC_BGEZ,
+  TILEPRO_OPC_BGEZ_SN,
+  TILEPRO_OPC_BGEZT,
+  TILEPRO_OPC_BGEZT_SN,
+  TILEPRO_OPC_BGZ,
+  TILEPRO_OPC_BGZ_SN,
+  TILEPRO_OPC_BGZT,
+  TILEPRO_OPC_BGZT_SN,
+  TILEPRO_OPC_BITX,
+  TILEPRO_OPC_BITX_SN,
+  TILEPRO_OPC_BLEZ,
+  TILEPRO_OPC_BLEZ_SN,
+  TILEPRO_OPC_BLEZT,
+  TILEPRO_OPC_BLEZT_SN,
+  TILEPRO_OPC_BLZ,
+  TILEPRO_OPC_BLZ_SN,
+  TILEPRO_OPC_BLZT,
+  TILEPRO_OPC_BLZT_SN,
+  TILEPRO_OPC_BNZ,
+  TILEPRO_OPC_BNZ_SN,
+  TILEPRO_OPC_BNZT,
+  TILEPRO_OPC_BNZT_SN,
+  TILEPRO_OPC_BYTEX,
+  TILEPRO_OPC_BYTEX_SN,
+  TILEPRO_OPC_BZ,
+  TILEPRO_OPC_BZ_SN,
+  TILEPRO_OPC_BZT,
+  TILEPRO_OPC_BZT_SN,
+  TILEPRO_OPC_CLZ,
+  TILEPRO_OPC_CLZ_SN,
+  TILEPRO_OPC_CRC32_32,
+  TILEPRO_OPC_CRC32_32_SN,
+  TILEPRO_OPC_CRC32_8,
+  TILEPRO_OPC_CRC32_8_SN,
+  TILEPRO_OPC_CTZ,
+  TILEPRO_OPC_CTZ_SN,
+  TILEPRO_OPC_DRAIN,
+  TILEPRO_OPC_DTLBPR,
+  TILEPRO_OPC_DWORD_ALIGN,
+  TILEPRO_OPC_DWORD_ALIGN_SN,
+  TILEPRO_OPC_FINV,
+  TILEPRO_OPC_FLUSH,
+  TILEPRO_OPC_FNOP,
+  TILEPRO_OPC_ICOH,
+  TILEPRO_OPC_ILL,
+  TILEPRO_OPC_INTHB,
+  TILEPRO_OPC_INTHB_SN,
+  TILEPRO_OPC_INTHH,
+  TILEPRO_OPC_INTHH_SN,
+  TILEPRO_OPC_INTLB,
+  TILEPRO_OPC_INTLB_SN,
+  TILEPRO_OPC_INTLH,
+  TILEPRO_OPC_INTLH_SN,
+  TILEPRO_OPC_INV,
+  TILEPRO_OPC_IRET,
+  TILEPRO_OPC_JALB,
+  TILEPRO_OPC_JALF,
+  TILEPRO_OPC_JALR,
+  TILEPRO_OPC_JALRP,
+  TILEPRO_OPC_JB,
+  TILEPRO_OPC_JF,
+  TILEPRO_OPC_JR,
+  TILEPRO_OPC_JRP,
+  TILEPRO_OPC_LB,
+  TILEPRO_OPC_LB_SN,
+  TILEPRO_OPC_LB_U,
+  TILEPRO_OPC_LB_U_SN,
+  TILEPRO_OPC_LBADD,
+  TILEPRO_OPC_LBADD_SN,
+  TILEPRO_OPC_LBADD_U,
+  TILEPRO_OPC_LBADD_U_SN,
+  TILEPRO_OPC_LH,
+  TILEPRO_OPC_LH_SN,
+  TILEPRO_OPC_LH_U,
+  TILEPRO_OPC_LH_U_SN,
+  TILEPRO_OPC_LHADD,
+  TILEPRO_OPC_LHADD_SN,
+  TILEPRO_OPC_LHADD_U,
+  TILEPRO_OPC_LHADD_U_SN,
+  TILEPRO_OPC_LNK,
+  TILEPRO_OPC_LNK_SN,
+  TILEPRO_OPC_LW,
+  TILEPRO_OPC_LW_SN,
+  TILEPRO_OPC_LW_NA,
+  TILEPRO_OPC_LW_NA_SN,
+  TILEPRO_OPC_LWADD,
+  TILEPRO_OPC_LWADD_SN,
+  TILEPRO_OPC_LWADD_NA,
+  TILEPRO_OPC_LWADD_NA_SN,
+  TILEPRO_OPC_MAXB_U,
+  TILEPRO_OPC_MAXB_U_SN,
+  TILEPRO_OPC_MAXH,
+  TILEPRO_OPC_MAXH_SN,
+  TILEPRO_OPC_MAXIB_U,
+  TILEPRO_OPC_MAXIB_U_SN,
+  TILEPRO_OPC_MAXIH,
+  TILEPRO_OPC_MAXIH_SN,
+  TILEPRO_OPC_MF,
+  TILEPRO_OPC_MFSPR,
+  TILEPRO_OPC_MINB_U,
+  TILEPRO_OPC_MINB_U_SN,
+  TILEPRO_OPC_MINH,
+  TILEPRO_OPC_MINH_SN,
+  TILEPRO_OPC_MINIB_U,
+  TILEPRO_OPC_MINIB_U_SN,
+  TILEPRO_OPC_MINIH,
+  TILEPRO_OPC_MINIH_SN,
+  TILEPRO_OPC_MM,
+  TILEPRO_OPC_MNZ,
+  TILEPRO_OPC_MNZ_SN,
+  TILEPRO_OPC_MNZB,
+  TILEPRO_OPC_MNZB_SN,
+  TILEPRO_OPC_MNZH,
+  TILEPRO_OPC_MNZH_SN,
+  TILEPRO_OPC_MTSPR,
+  TILEPRO_OPC_MULHH_SS,
+  TILEPRO_OPC_MULHH_SS_SN,
+  TILEPRO_OPC_MULHH_SU,
+  TILEPRO_OPC_MULHH_SU_SN,
+  TILEPRO_OPC_MULHH_UU,
+  TILEPRO_OPC_MULHH_UU_SN,
+  TILEPRO_OPC_MULHHA_SS,
+  TILEPRO_OPC_MULHHA_SS_SN,
+  TILEPRO_OPC_MULHHA_SU,
+  TILEPRO_OPC_MULHHA_SU_SN,
+  TILEPRO_OPC_MULHHA_UU,
+  TILEPRO_OPC_MULHHA_UU_SN,
+  TILEPRO_OPC_MULHHSA_UU,
+  TILEPRO_OPC_MULHHSA_UU_SN,
+  TILEPRO_OPC_MULHL_SS,
+  TILEPRO_OPC_MULHL_SS_SN,
+  TILEPRO_OPC_MULHL_SU,
+  TILEPRO_OPC_MULHL_SU_SN,
+  TILEPRO_OPC_MULHL_US,
+  TILEPRO_OPC_MULHL_US_SN,
+  TILEPRO_OPC_MULHL_UU,
+  TILEPRO_OPC_MULHL_UU_SN,
+  TILEPRO_OPC_MULHLA_SS,
+  TILEPRO_OPC_MULHLA_SS_SN,
+  TILEPRO_OPC_MULHLA_SU,
+  TILEPRO_OPC_MULHLA_SU_SN,
+  TILEPRO_OPC_MULHLA_US,
+  TILEPRO_OPC_MULHLA_US_SN,
+  TILEPRO_OPC_MULHLA_UU,
+  TILEPRO_OPC_MULHLA_UU_SN,
+  TILEPRO_OPC_MULHLSA_UU,
+  TILEPRO_OPC_MULHLSA_UU_SN,
+  TILEPRO_OPC_MULLL_SS,
+  TILEPRO_OPC_MULLL_SS_SN,
+  TILEPRO_OPC_MULLL_SU,
+  TILEPRO_OPC_MULLL_SU_SN,
+  TILEPRO_OPC_MULLL_UU,
+  TILEPRO_OPC_MULLL_UU_SN,
+  TILEPRO_OPC_MULLLA_SS,
+  TILEPRO_OPC_MULLLA_SS_SN,
+  TILEPRO_OPC_MULLLA_SU,
+  TILEPRO_OPC_MULLLA_SU_SN,
+  TILEPRO_OPC_MULLLA_UU,
+  TILEPRO_OPC_MULLLA_UU_SN,
+  TILEPRO_OPC_MULLLSA_UU,
+  TILEPRO_OPC_MULLLSA_UU_SN,
+  TILEPRO_OPC_MVNZ,
+  TILEPRO_OPC_MVNZ_SN,
+  TILEPRO_OPC_MVZ,
+  TILEPRO_OPC_MVZ_SN,
+  TILEPRO_OPC_MZ,
+  TILEPRO_OPC_MZ_SN,
+  TILEPRO_OPC_MZB,
+  TILEPRO_OPC_MZB_SN,
+  TILEPRO_OPC_MZH,
+  TILEPRO_OPC_MZH_SN,
+  TILEPRO_OPC_NAP,
+  TILEPRO_OPC_NOP,
+  TILEPRO_OPC_NOR,
+  TILEPRO_OPC_NOR_SN,
+  TILEPRO_OPC_OR,
+  TILEPRO_OPC_OR_SN,
+  TILEPRO_OPC_ORI,
+  TILEPRO_OPC_ORI_SN,
+  TILEPRO_OPC_PACKBS_U,
+  TILEPRO_OPC_PACKBS_U_SN,
+  TILEPRO_OPC_PACKHB,
+  TILEPRO_OPC_PACKHB_SN,
+  TILEPRO_OPC_PACKHS,
+  TILEPRO_OPC_PACKHS_SN,
+  TILEPRO_OPC_PACKLB,
+  TILEPRO_OPC_PACKLB_SN,
+  TILEPRO_OPC_PCNT,
+  TILEPRO_OPC_PCNT_SN,
+  TILEPRO_OPC_RL,
+  TILEPRO_OPC_RL_SN,
+  TILEPRO_OPC_RLI,
+  TILEPRO_OPC_RLI_SN,
+  TILEPRO_OPC_S1A,
+  TILEPRO_OPC_S1A_SN,
+  TILEPRO_OPC_S2A,
+  TILEPRO_OPC_S2A_SN,
+  TILEPRO_OPC_S3A,
+  TILEPRO_OPC_S3A_SN,
+  TILEPRO_OPC_SADAB_U,
+  TILEPRO_OPC_SADAB_U_SN,
+  TILEPRO_OPC_SADAH,
+  TILEPRO_OPC_SADAH_SN,
+  TILEPRO_OPC_SADAH_U,
+  TILEPRO_OPC_SADAH_U_SN,
+  TILEPRO_OPC_SADB_U,
+  TILEPRO_OPC_SADB_U_SN,
+  TILEPRO_OPC_SADH,
+  TILEPRO_OPC_SADH_SN,
+  TILEPRO_OPC_SADH_U,
+  TILEPRO_OPC_SADH_U_SN,
+  TILEPRO_OPC_SB,
+  TILEPRO_OPC_SBADD,
+  TILEPRO_OPC_SEQ,
+  TILEPRO_OPC_SEQ_SN,
+  TILEPRO_OPC_SEQB,
+  TILEPRO_OPC_SEQB_SN,
+  TILEPRO_OPC_SEQH,
+  TILEPRO_OPC_SEQH_SN,
+  TILEPRO_OPC_SEQI,
+  TILEPRO_OPC_SEQI_SN,
+  TILEPRO_OPC_SEQIB,
+  TILEPRO_OPC_SEQIB_SN,
+  TILEPRO_OPC_SEQIH,
+  TILEPRO_OPC_SEQIH_SN,
+  TILEPRO_OPC_SH,
+  TILEPRO_OPC_SHADD,
+  TILEPRO_OPC_SHL,
+  TILEPRO_OPC_SHL_SN,
+  TILEPRO_OPC_SHLB,
+  TILEPRO_OPC_SHLB_SN,
+  TILEPRO_OPC_SHLH,
+  TILEPRO_OPC_SHLH_SN,
+  TILEPRO_OPC_SHLI,
+  TILEPRO_OPC_SHLI_SN,
+  TILEPRO_OPC_SHLIB,
+  TILEPRO_OPC_SHLIB_SN,
+  TILEPRO_OPC_SHLIH,
+  TILEPRO_OPC_SHLIH_SN,
+  TILEPRO_OPC_SHR,
+  TILEPRO_OPC_SHR_SN,
+  TILEPRO_OPC_SHRB,
+  TILEPRO_OPC_SHRB_SN,
+  TILEPRO_OPC_SHRH,
+  TILEPRO_OPC_SHRH_SN,
+  TILEPRO_OPC_SHRI,
+  TILEPRO_OPC_SHRI_SN,
+  TILEPRO_OPC_SHRIB,
+  TILEPRO_OPC_SHRIB_SN,
+  TILEPRO_OPC_SHRIH,
+  TILEPRO_OPC_SHRIH_SN,
+  TILEPRO_OPC_SLT,
+  TILEPRO_OPC_SLT_SN,
+  TILEPRO_OPC_SLT_U,
+  TILEPRO_OPC_SLT_U_SN,
+  TILEPRO_OPC_SLTB,
+  TILEPRO_OPC_SLTB_SN,
+  TILEPRO_OPC_SLTB_U,
+  TILEPRO_OPC_SLTB_U_SN,
+  TILEPRO_OPC_SLTE,
+  TILEPRO_OPC_SLTE_SN,
+  TILEPRO_OPC_SLTE_U,
+  TILEPRO_OPC_SLTE_U_SN,
+  TILEPRO_OPC_SLTEB,
+  TILEPRO_OPC_SLTEB_SN,
+  TILEPRO_OPC_SLTEB_U,
+  TILEPRO_OPC_SLTEB_U_SN,
+  TILEPRO_OPC_SLTEH,
+  TILEPRO_OPC_SLTEH_SN,
+  TILEPRO_OPC_SLTEH_U,
+  TILEPRO_OPC_SLTEH_U_SN,
+  TILEPRO_OPC_SLTH,
+  TILEPRO_OPC_SLTH_SN,
+  TILEPRO_OPC_SLTH_U,
+  TILEPRO_OPC_SLTH_U_SN,
+  TILEPRO_OPC_SLTI,
+  TILEPRO_OPC_SLTI_SN,
+  TILEPRO_OPC_SLTI_U,
+  TILEPRO_OPC_SLTI_U_SN,
+  TILEPRO_OPC_SLTIB,
+  TILEPRO_OPC_SLTIB_SN,
+  TILEPRO_OPC_SLTIB_U,
+  TILEPRO_OPC_SLTIB_U_SN,
+  TILEPRO_OPC_SLTIH,
+  TILEPRO_OPC_SLTIH_SN,
+  TILEPRO_OPC_SLTIH_U,
+  TILEPRO_OPC_SLTIH_U_SN,
+  TILEPRO_OPC_SNE,
+  TILEPRO_OPC_SNE_SN,
+  TILEPRO_OPC_SNEB,
+  TILEPRO_OPC_SNEB_SN,
+  TILEPRO_OPC_SNEH,
+  TILEPRO_OPC_SNEH_SN,
+  TILEPRO_OPC_SRA,
+  TILEPRO_OPC_SRA_SN,
+  TILEPRO_OPC_SRAB,
+  TILEPRO_OPC_SRAB_SN,
+  TILEPRO_OPC_SRAH,
+  TILEPRO_OPC_SRAH_SN,
+  TILEPRO_OPC_SRAI,
+  TILEPRO_OPC_SRAI_SN,
+  TILEPRO_OPC_SRAIB,
+  TILEPRO_OPC_SRAIB_SN,
+  TILEPRO_OPC_SRAIH,
+  TILEPRO_OPC_SRAIH_SN,
+  TILEPRO_OPC_SUB,
+  TILEPRO_OPC_SUB_SN,
+  TILEPRO_OPC_SUBB,
+  TILEPRO_OPC_SUBB_SN,
+  TILEPRO_OPC_SUBBS_U,
+  TILEPRO_OPC_SUBBS_U_SN,
+  TILEPRO_OPC_SUBH,
+  TILEPRO_OPC_SUBH_SN,
+  TILEPRO_OPC_SUBHS,
+  TILEPRO_OPC_SUBHS_SN,
+  TILEPRO_OPC_SUBS,
+  TILEPRO_OPC_SUBS_SN,
+  TILEPRO_OPC_SW,
+  TILEPRO_OPC_SWADD,
+  TILEPRO_OPC_SWINT0,
+  TILEPRO_OPC_SWINT1,
+  TILEPRO_OPC_SWINT2,
+  TILEPRO_OPC_SWINT3,
+  TILEPRO_OPC_TBLIDXB0,
+  TILEPRO_OPC_TBLIDXB0_SN,
+  TILEPRO_OPC_TBLIDXB1,
+  TILEPRO_OPC_TBLIDXB1_SN,
+  TILEPRO_OPC_TBLIDXB2,
+  TILEPRO_OPC_TBLIDXB2_SN,
+  TILEPRO_OPC_TBLIDXB3,
+  TILEPRO_OPC_TBLIDXB3_SN,
+  TILEPRO_OPC_TNS,
+  TILEPRO_OPC_TNS_SN,
+  TILEPRO_OPC_WH64,
+  TILEPRO_OPC_XOR,
+  TILEPRO_OPC_XOR_SN,
+  TILEPRO_OPC_XORI,
+  TILEPRO_OPC_XORI_SN,
+  TILEPRO_OPC_NONE
+} tilepro_mnemonic;
+
+
+
+
+typedef enum
+{
+  TILEPRO_PIPELINE_X0,
+  TILEPRO_PIPELINE_X1,
+  TILEPRO_PIPELINE_Y0,
+  TILEPRO_PIPELINE_Y1,
+  TILEPRO_PIPELINE_Y2,
+} tilepro_pipeline;
+
+#define tilepro_is_x_pipeline(p) ((int)(p) <= (int)TILEPRO_PIPELINE_X1)
+
+typedef enum
+{
+  TILEPRO_OP_TYPE_REGISTER,
+  TILEPRO_OP_TYPE_IMMEDIATE,
+  TILEPRO_OP_TYPE_ADDRESS,
+  TILEPRO_OP_TYPE_SPR
+} tilepro_operand_type;
+
+struct tilepro_operand
+{
+  /* Is this operand a register, immediate or address? */
+  tilepro_operand_type type;
+
+  /* The default relocation type for this operand.  */
+  signed int default_reloc : 16;
+
+  /* How many bits is this value? (used for range checking) */
+  unsigned int num_bits : 5;
+
+  /* Is the value signed? (used for range checking) */
+  unsigned int is_signed : 1;
+
+  /* Is this operand a source register? */
+  unsigned int is_src_reg : 1;
+
+  /* Is this operand written? (i.e. is it a destination register) */
+  unsigned int is_dest_reg : 1;
+
+  /* Is this operand PC-relative? */
+  unsigned int is_pc_relative : 1;
+
+  /* By how many bits do we right shift the value before inserting? */
+  unsigned int rightshift : 2;
+
+  /* Return the bits for this operand to be ORed into an existing bundle. */
+  tilepro_bundle_bits (*insert) (int op);
+
+  /* Extract this operand and return it. */
+  unsigned int (*extract) (tilepro_bundle_bits bundle);
+};
+
+
+extern const struct tilepro_operand tilepro_operands[];
+
+/* One finite-state machine per pipe for rapid instruction decoding. */
+extern const unsigned short * const
+tilepro_bundle_decoder_fsms[TILEPRO_NUM_PIPELINE_ENCODINGS];
+
+
+struct tilepro_opcode
+{
+  /* The opcode mnemonic, e.g. "add" */
+  const char *name;
+
+  /* The enum value for this mnemonic. */
+  tilepro_mnemonic mnemonic;
+
+  /* A bit mask of which of the five pipes this instruction
+     is compatible with:
+     X0  0x01
+     X1  0x02
+     Y0  0x04
+     Y1  0x08
+     Y2  0x10 */
+  unsigned char pipes;
+
+  /* How many operands are there? */
+  unsigned char num_operands;
+
+  /* Which register does this write implicitly, or TREG_ZERO if none? */
+  unsigned char implicitly_written_register;
+
+  /* Can this be bundled with other instructions (almost always true). */
+  unsigned char can_bundle;
+
+  /* The description of the operands. Each of these is an
+   * index into the tilepro_operands[] table. */
+  unsigned char operands[TILEPRO_NUM_PIPELINE_ENCODINGS][TILEPRO_MAX_OPERANDS];
+
+};
+
+extern const struct tilepro_opcode tilepro_opcodes[];
+
+
+/* Used for non-textual disassembly into structs. */
+struct tilepro_decoded_instruction
+{
+  const struct tilepro_opcode *opcode;
+  const struct tilepro_operand *operands[TILEPRO_MAX_OPERANDS];
+  int operand_values[TILEPRO_MAX_OPERANDS];
+};
+
+
+/* Disassemble a bundle into a struct for machine processing. */
+extern int parse_insn_tilepro(tilepro_bundle_bits bits,
+                              unsigned int pc,
+                              struct tilepro_decoded_instruction
+                              decoded[TILEPRO_MAX_INSTRUCTIONS_PER_BUNDLE]);
+
+
+/* Given a set of bundle bits and a specific pipe, returns which
+ * instruction the bundle contains in that pipe.
+ */
+extern const struct tilepro_opcode *
+find_opcode(tilepro_bundle_bits bits, tilepro_pipeline pipe);
+
+
+
+#endif /* opcode_tilepro_h */
diff --git a/arch/tile/include/asm/tile-desc_64.h b/arch/tile/include/asm/tile-desc_64.h
new file mode 100644 (file)
index 0000000..1819efc
--- /dev/null
@@ -0,0 +1,483 @@
+/* TILE-Gx opcode information.
+ *
+ * Copyright 2011 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ *
+ *
+ *
+ *
+ *
+ */
+
+#ifndef opcode_tile_h
+#define opcode_tile_h
+
+#include <arch/opcode.h>
+
+
+enum
+{
+  TILEGX_MAX_OPERANDS = 4 /* bfexts */
+};
+
+typedef enum
+{
+  TILEGX_OPC_BPT,
+  TILEGX_OPC_INFO,
+  TILEGX_OPC_INFOL,
+  TILEGX_OPC_MOVE,
+  TILEGX_OPC_MOVEI,
+  TILEGX_OPC_MOVELI,
+  TILEGX_OPC_PREFETCH,
+  TILEGX_OPC_PREFETCH_ADD_L1,
+  TILEGX_OPC_PREFETCH_ADD_L1_FAULT,
+  TILEGX_OPC_PREFETCH_ADD_L2,
+  TILEGX_OPC_PREFETCH_ADD_L2_FAULT,
+  TILEGX_OPC_PREFETCH_ADD_L3,
+  TILEGX_OPC_PREFETCH_ADD_L3_FAULT,
+  TILEGX_OPC_PREFETCH_L1,
+  TILEGX_OPC_PREFETCH_L1_FAULT,
+  TILEGX_OPC_PREFETCH_L2,
+  TILEGX_OPC_PREFETCH_L2_FAULT,
+  TILEGX_OPC_PREFETCH_L3,
+  TILEGX_OPC_PREFETCH_L3_FAULT,
+  TILEGX_OPC_RAISE,
+  TILEGX_OPC_ADD,
+  TILEGX_OPC_ADDI,
+  TILEGX_OPC_ADDLI,
+  TILEGX_OPC_ADDX,
+  TILEGX_OPC_ADDXI,
+  TILEGX_OPC_ADDXLI,
+  TILEGX_OPC_ADDXSC,
+  TILEGX_OPC_AND,
+  TILEGX_OPC_ANDI,
+  TILEGX_OPC_BEQZ,
+  TILEGX_OPC_BEQZT,
+  TILEGX_OPC_BFEXTS,
+  TILEGX_OPC_BFEXTU,
+  TILEGX_OPC_BFINS,
+  TILEGX_OPC_BGEZ,
+  TILEGX_OPC_BGEZT,
+  TILEGX_OPC_BGTZ,
+  TILEGX_OPC_BGTZT,
+  TILEGX_OPC_BLBC,
+  TILEGX_OPC_BLBCT,
+  TILEGX_OPC_BLBS,
+  TILEGX_OPC_BLBST,
+  TILEGX_OPC_BLEZ,
+  TILEGX_OPC_BLEZT,
+  TILEGX_OPC_BLTZ,
+  TILEGX_OPC_BLTZT,
+  TILEGX_OPC_BNEZ,
+  TILEGX_OPC_BNEZT,
+  TILEGX_OPC_CLZ,
+  TILEGX_OPC_CMOVEQZ,
+  TILEGX_OPC_CMOVNEZ,
+  TILEGX_OPC_CMPEQ,
+  TILEGX_OPC_CMPEQI,
+  TILEGX_OPC_CMPEXCH,
+  TILEGX_OPC_CMPEXCH4,
+  TILEGX_OPC_CMPLES,
+  TILEGX_OPC_CMPLEU,
+  TILEGX_OPC_CMPLTS,
+  TILEGX_OPC_CMPLTSI,
+  TILEGX_OPC_CMPLTU,
+  TILEGX_OPC_CMPLTUI,
+  TILEGX_OPC_CMPNE,
+  TILEGX_OPC_CMUL,
+  TILEGX_OPC_CMULA,
+  TILEGX_OPC_CMULAF,
+  TILEGX_OPC_CMULF,
+  TILEGX_OPC_CMULFR,
+  TILEGX_OPC_CMULH,
+  TILEGX_OPC_CMULHR,
+  TILEGX_OPC_CRC32_32,
+  TILEGX_OPC_CRC32_8,
+  TILEGX_OPC_CTZ,
+  TILEGX_OPC_DBLALIGN,
+  TILEGX_OPC_DBLALIGN2,
+  TILEGX_OPC_DBLALIGN4,
+  TILEGX_OPC_DBLALIGN6,
+  TILEGX_OPC_DRAIN,
+  TILEGX_OPC_DTLBPR,
+  TILEGX_OPC_EXCH,
+  TILEGX_OPC_EXCH4,
+  TILEGX_OPC_FDOUBLE_ADD_FLAGS,
+  TILEGX_OPC_FDOUBLE_ADDSUB,
+  TILEGX_OPC_FDOUBLE_MUL_FLAGS,
+  TILEGX_OPC_FDOUBLE_PACK1,
+  TILEGX_OPC_FDOUBLE_PACK2,
+  TILEGX_OPC_FDOUBLE_SUB_FLAGS,
+  TILEGX_OPC_FDOUBLE_UNPACK_MAX,
+  TILEGX_OPC_FDOUBLE_UNPACK_MIN,
+  TILEGX_OPC_FETCHADD,
+  TILEGX_OPC_FETCHADD4,
+  TILEGX_OPC_FETCHADDGEZ,
+  TILEGX_OPC_FETCHADDGEZ4,
+  TILEGX_OPC_FETCHAND,
+  TILEGX_OPC_FETCHAND4,
+  TILEGX_OPC_FETCHOR,
+  TILEGX_OPC_FETCHOR4,
+  TILEGX_OPC_FINV,
+  TILEGX_OPC_FLUSH,
+  TILEGX_OPC_FLUSHWB,
+  TILEGX_OPC_FNOP,
+  TILEGX_OPC_FSINGLE_ADD1,
+  TILEGX_OPC_FSINGLE_ADDSUB2,
+  TILEGX_OPC_FSINGLE_MUL1,
+  TILEGX_OPC_FSINGLE_MUL2,
+  TILEGX_OPC_FSINGLE_PACK1,
+  TILEGX_OPC_FSINGLE_PACK2,
+  TILEGX_OPC_FSINGLE_SUB1,
+  TILEGX_OPC_ICOH,
+  TILEGX_OPC_ILL,
+  TILEGX_OPC_INV,
+  TILEGX_OPC_IRET,
+  TILEGX_OPC_J,
+  TILEGX_OPC_JAL,
+  TILEGX_OPC_JALR,
+  TILEGX_OPC_JALRP,
+  TILEGX_OPC_JR,
+  TILEGX_OPC_JRP,
+  TILEGX_OPC_LD,
+  TILEGX_OPC_LD1S,
+  TILEGX_OPC_LD1S_ADD,
+  TILEGX_OPC_LD1U,
+  TILEGX_OPC_LD1U_ADD,
+  TILEGX_OPC_LD2S,
+  TILEGX_OPC_LD2S_ADD,
+  TILEGX_OPC_LD2U,
+  TILEGX_OPC_LD2U_ADD,
+  TILEGX_OPC_LD4S,
+  TILEGX_OPC_LD4S_ADD,
+  TILEGX_OPC_LD4U,
+  TILEGX_OPC_LD4U_ADD,
+  TILEGX_OPC_LD_ADD,
+  TILEGX_OPC_LDNA,
+  TILEGX_OPC_LDNA_ADD,
+  TILEGX_OPC_LDNT,
+  TILEGX_OPC_LDNT1S,
+  TILEGX_OPC_LDNT1S_ADD,
+  TILEGX_OPC_LDNT1U,
+  TILEGX_OPC_LDNT1U_ADD,
+  TILEGX_OPC_LDNT2S,
+  TILEGX_OPC_LDNT2S_ADD,
+  TILEGX_OPC_LDNT2U,
+  TILEGX_OPC_LDNT2U_ADD,
+  TILEGX_OPC_LDNT4S,
+  TILEGX_OPC_LDNT4S_ADD,
+  TILEGX_OPC_LDNT4U,
+  TILEGX_OPC_LDNT4U_ADD,
+  TILEGX_OPC_LDNT_ADD,
+  TILEGX_OPC_LNK,
+  TILEGX_OPC_MF,
+  TILEGX_OPC_MFSPR,
+  TILEGX_OPC_MM,
+  TILEGX_OPC_MNZ,
+  TILEGX_OPC_MTSPR,
+  TILEGX_OPC_MUL_HS_HS,
+  TILEGX_OPC_MUL_HS_HU,
+  TILEGX_OPC_MUL_HS_LS,
+  TILEGX_OPC_MUL_HS_LU,
+  TILEGX_OPC_MUL_HU_HU,
+  TILEGX_OPC_MUL_HU_LS,
+  TILEGX_OPC_MUL_HU_LU,
+  TILEGX_OPC_MUL_LS_LS,
+  TILEGX_OPC_MUL_LS_LU,
+  TILEGX_OPC_MUL_LU_LU,
+  TILEGX_OPC_MULA_HS_HS,
+  TILEGX_OPC_MULA_HS_HU,
+  TILEGX_OPC_MULA_HS_LS,
+  TILEGX_OPC_MULA_HS_LU,
+  TILEGX_OPC_MULA_HU_HU,
+  TILEGX_OPC_MULA_HU_LS,
+  TILEGX_OPC_MULA_HU_LU,
+  TILEGX_OPC_MULA_LS_LS,
+  TILEGX_OPC_MULA_LS_LU,
+  TILEGX_OPC_MULA_LU_LU,
+  TILEGX_OPC_MULAX,
+  TILEGX_OPC_MULX,
+  TILEGX_OPC_MZ,
+  TILEGX_OPC_NAP,
+  TILEGX_OPC_NOP,
+  TILEGX_OPC_NOR,
+  TILEGX_OPC_OR,
+  TILEGX_OPC_ORI,
+  TILEGX_OPC_PCNT,
+  TILEGX_OPC_REVBITS,
+  TILEGX_OPC_REVBYTES,
+  TILEGX_OPC_ROTL,
+  TILEGX_OPC_ROTLI,
+  TILEGX_OPC_SHL,
+  TILEGX_OPC_SHL16INSLI,
+  TILEGX_OPC_SHL1ADD,
+  TILEGX_OPC_SHL1ADDX,
+  TILEGX_OPC_SHL2ADD,
+  TILEGX_OPC_SHL2ADDX,
+  TILEGX_OPC_SHL3ADD,
+  TILEGX_OPC_SHL3ADDX,
+  TILEGX_OPC_SHLI,
+  TILEGX_OPC_SHLX,
+  TILEGX_OPC_SHLXI,
+  TILEGX_OPC_SHRS,
+  TILEGX_OPC_SHRSI,
+  TILEGX_OPC_SHRU,
+  TILEGX_OPC_SHRUI,
+  TILEGX_OPC_SHRUX,
+  TILEGX_OPC_SHRUXI,
+  TILEGX_OPC_SHUFFLEBYTES,
+  TILEGX_OPC_ST,
+  TILEGX_OPC_ST1,
+  TILEGX_OPC_ST1_ADD,
+  TILEGX_OPC_ST2,
+  TILEGX_OPC_ST2_ADD,
+  TILEGX_OPC_ST4,
+  TILEGX_OPC_ST4_ADD,
+  TILEGX_OPC_ST_ADD,
+  TILEGX_OPC_STNT,
+  TILEGX_OPC_STNT1,
+  TILEGX_OPC_STNT1_ADD,
+  TILEGX_OPC_STNT2,
+  TILEGX_OPC_STNT2_ADD,
+  TILEGX_OPC_STNT4,
+  TILEGX_OPC_STNT4_ADD,
+  TILEGX_OPC_STNT_ADD,
+  TILEGX_OPC_SUB,
+  TILEGX_OPC_SUBX,
+  TILEGX_OPC_SUBXSC,
+  TILEGX_OPC_SWINT0,
+  TILEGX_OPC_SWINT1,
+  TILEGX_OPC_SWINT2,
+  TILEGX_OPC_SWINT3,
+  TILEGX_OPC_TBLIDXB0,
+  TILEGX_OPC_TBLIDXB1,
+  TILEGX_OPC_TBLIDXB2,
+  TILEGX_OPC_TBLIDXB3,
+  TILEGX_OPC_V1ADD,
+  TILEGX_OPC_V1ADDI,
+  TILEGX_OPC_V1ADDUC,
+  TILEGX_OPC_V1ADIFFU,
+  TILEGX_OPC_V1AVGU,
+  TILEGX_OPC_V1CMPEQ,
+  TILEGX_OPC_V1CMPEQI,
+  TILEGX_OPC_V1CMPLES,
+  TILEGX_OPC_V1CMPLEU,
+  TILEGX_OPC_V1CMPLTS,
+  TILEGX_OPC_V1CMPLTSI,
+  TILEGX_OPC_V1CMPLTU,
+  TILEGX_OPC_V1CMPLTUI,
+  TILEGX_OPC_V1CMPNE,
+  TILEGX_OPC_V1DDOTPU,
+  TILEGX_OPC_V1DDOTPUA,
+  TILEGX_OPC_V1DDOTPUS,
+  TILEGX_OPC_V1DDOTPUSA,
+  TILEGX_OPC_V1DOTP,
+  TILEGX_OPC_V1DOTPA,
+  TILEGX_OPC_V1DOTPU,
+  TILEGX_OPC_V1DOTPUA,
+  TILEGX_OPC_V1DOTPUS,
+  TILEGX_OPC_V1DOTPUSA,
+  TILEGX_OPC_V1INT_H,
+  TILEGX_OPC_V1INT_L,
+  TILEGX_OPC_V1MAXU,
+  TILEGX_OPC_V1MAXUI,
+  TILEGX_OPC_V1MINU,
+  TILEGX_OPC_V1MINUI,
+  TILEGX_OPC_V1MNZ,
+  TILEGX_OPC_V1MULTU,
+  TILEGX_OPC_V1MULU,
+  TILEGX_OPC_V1MULUS,
+  TILEGX_OPC_V1MZ,
+  TILEGX_OPC_V1SADAU,
+  TILEGX_OPC_V1SADU,
+  TILEGX_OPC_V1SHL,
+  TILEGX_OPC_V1SHLI,
+  TILEGX_OPC_V1SHRS,
+  TILEGX_OPC_V1SHRSI,
+  TILEGX_OPC_V1SHRU,
+  TILEGX_OPC_V1SHRUI,
+  TILEGX_OPC_V1SUB,
+  TILEGX_OPC_V1SUBUC,
+  TILEGX_OPC_V2ADD,
+  TILEGX_OPC_V2ADDI,
+  TILEGX_OPC_V2ADDSC,
+  TILEGX_OPC_V2ADIFFS,
+  TILEGX_OPC_V2AVGS,
+  TILEGX_OPC_V2CMPEQ,
+  TILEGX_OPC_V2CMPEQI,
+  TILEGX_OPC_V2CMPLES,
+  TILEGX_OPC_V2CMPLEU,
+  TILEGX_OPC_V2CMPLTS,
+  TILEGX_OPC_V2CMPLTSI,
+  TILEGX_OPC_V2CMPLTU,
+  TILEGX_OPC_V2CMPLTUI,
+  TILEGX_OPC_V2CMPNE,
+  TILEGX_OPC_V2DOTP,
+  TILEGX_OPC_V2DOTPA,
+  TILEGX_OPC_V2INT_H,
+  TILEGX_OPC_V2INT_L,
+  TILEGX_OPC_V2MAXS,
+  TILEGX_OPC_V2MAXSI,
+  TILEGX_OPC_V2MINS,
+  TILEGX_OPC_V2MINSI,
+  TILEGX_OPC_V2MNZ,
+  TILEGX_OPC_V2MULFSC,
+  TILEGX_OPC_V2MULS,
+  TILEGX_OPC_V2MULTS,
+  TILEGX_OPC_V2MZ,
+  TILEGX_OPC_V2PACKH,
+  TILEGX_OPC_V2PACKL,
+  TILEGX_OPC_V2PACKUC,
+  TILEGX_OPC_V2SADAS,
+  TILEGX_OPC_V2SADAU,
+  TILEGX_OPC_V2SADS,
+  TILEGX_OPC_V2SADU,
+  TILEGX_OPC_V2SHL,
+  TILEGX_OPC_V2SHLI,
+  TILEGX_OPC_V2SHLSC,
+  TILEGX_OPC_V2SHRS,
+  TILEGX_OPC_V2SHRSI,
+  TILEGX_OPC_V2SHRU,
+  TILEGX_OPC_V2SHRUI,
+  TILEGX_OPC_V2SUB,
+  TILEGX_OPC_V2SUBSC,
+  TILEGX_OPC_V4ADD,
+  TILEGX_OPC_V4ADDSC,
+  TILEGX_OPC_V4INT_H,
+  TILEGX_OPC_V4INT_L,
+  TILEGX_OPC_V4PACKSC,
+  TILEGX_OPC_V4SHL,
+  TILEGX_OPC_V4SHLSC,
+  TILEGX_OPC_V4SHRS,
+  TILEGX_OPC_V4SHRU,
+  TILEGX_OPC_V4SUB,
+  TILEGX_OPC_V4SUBSC,
+  TILEGX_OPC_WH64,
+  TILEGX_OPC_XOR,
+  TILEGX_OPC_XORI,
+  TILEGX_OPC_NONE
+} tilegx_mnemonic;
+
+
+
+typedef enum
+{
+  TILEGX_PIPELINE_X0,
+  TILEGX_PIPELINE_X1,
+  TILEGX_PIPELINE_Y0,
+  TILEGX_PIPELINE_Y1,
+  TILEGX_PIPELINE_Y2,
+} tilegx_pipeline;
+
+#define tilegx_is_x_pipeline(p) ((int)(p) <= (int)TILEGX_PIPELINE_X1)
+
+typedef enum
+{
+  TILEGX_OP_TYPE_REGISTER,
+  TILEGX_OP_TYPE_IMMEDIATE,
+  TILEGX_OP_TYPE_ADDRESS,
+  TILEGX_OP_TYPE_SPR
+} tilegx_operand_type;
+
+struct tilegx_operand
+{
+  /* Is this operand a register, immediate or address? */
+  tilegx_operand_type type;
+
+  /* The default relocation type for this operand.  */
+  signed int default_reloc : 16;
+
+  /* How many bits is this value? (used for range checking) */
+  unsigned int num_bits : 5;
+
+  /* Is the value signed? (used for range checking) */
+  unsigned int is_signed : 1;
+
+  /* Is this operand a source register? */
+  unsigned int is_src_reg : 1;
+
+  /* Is this operand written? (i.e. is it a destination register) */
+  unsigned int is_dest_reg : 1;
+
+  /* Is this operand PC-relative? */
+  unsigned int is_pc_relative : 1;
+
+  /* By how many bits do we right shift the value before inserting? */
+  unsigned int rightshift : 2;
+
+  /* Return the bits for this operand to be ORed into an existing bundle. */
+  tilegx_bundle_bits (*insert) (int op);
+
+  /* Extract this operand and return it. */
+  unsigned int (*extract) (tilegx_bundle_bits bundle);
+};
+
+
+extern const struct tilegx_operand tilegx_operands[];
+
+/* One finite-state machine per pipe for rapid instruction decoding. */
+extern const unsigned short * const
+tilegx_bundle_decoder_fsms[TILEGX_NUM_PIPELINE_ENCODINGS];
+
+
+struct tilegx_opcode
+{
+  /* The opcode mnemonic, e.g. "add" */
+  const char *name;
+
+  /* The enum value for this mnemonic. */
+  tilegx_mnemonic mnemonic;
+
+  /* A bit mask of which of the five pipes this instruction
+     is compatible with:
+     X0  0x01
+     X1  0x02
+     Y0  0x04
+     Y1  0x08
+     Y2  0x10 */
+  unsigned char pipes;
+
+  /* How many operands are there? */
+  unsigned char num_operands;
+
+  /* Which register does this write implicitly, or TREG_ZERO if none? */
+  unsigned char implicitly_written_register;
+
+  /* Can this be bundled with other instructions (almost always true). */
+  unsigned char can_bundle;
+
+  /* The description of the operands. Each of these is an
+   * index into the tilegx_operands[] table. */
+  unsigned char operands[TILEGX_NUM_PIPELINE_ENCODINGS][TILEGX_MAX_OPERANDS];
+
+};
+
+extern const struct tilegx_opcode tilegx_opcodes[];
+
+/* Used for non-textual disassembly into structs. */
+struct tilegx_decoded_instruction
+{
+  const struct tilegx_opcode *opcode;
+  const struct tilegx_operand *operands[TILEGX_MAX_OPERANDS];
+  long long operand_values[TILEGX_MAX_OPERANDS];
+};
+
+
+/* Disassemble a bundle into a struct for machine processing. */
+extern int parse_insn_tilegx(tilegx_bundle_bits bits,
+                             unsigned long long pc,
+                             struct tilegx_decoded_instruction
+                             decoded[TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE]);
+
+
+
+#endif /* opcode_tilegx_h */
index 1dc71ea..9092ce8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2010 Tilera Corporation. All Rights Reserved.
+ * Copyright 2011 Tilera Corporation. All Rights Reserved.
  *
  *   This program is free software; you can redistribute it and/or
  *   modify it under the terms of the GNU General Public License
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <asm/backtrace.h>
-#include <asm/opcode-tile.h>
+#include <asm/tile-desc.h>
 #include <arch/abi.h>
 
 #ifdef __tilegx__
-#define tile_bundle_bits tilegx_bundle_bits
 #define TILE_MAX_INSTRUCTIONS_PER_BUNDLE TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE
-#define TILE_BUNDLE_ALIGNMENT_IN_BYTES TILEGX_BUNDLE_ALIGNMENT_IN_BYTES
 #define tile_decoded_instruction tilegx_decoded_instruction
 #define tile_mnemonic tilegx_mnemonic
 #define parse_insn_tile parse_insn_tilegx
 #define OPCODE_STORE TILEGX_OPC_ST
 typedef long long bt_int_reg_t;
 #else
-#define OPCODE_STORE TILE_OPC_SW
+#define TILE_MAX_INSTRUCTIONS_PER_BUNDLE TILEPRO_MAX_INSTRUCTIONS_PER_BUNDLE
+#define tile_decoded_instruction tilepro_decoded_instruction
+#define tile_mnemonic tilepro_mnemonic
+#define parse_insn_tile parse_insn_tilepro
+#define TILE_OPC_IRET TILEPRO_OPC_IRET
+#define TILE_OPC_ADDI TILEPRO_OPC_ADDI
+#define TILE_OPC_ADDLI TILEPRO_OPC_ADDLI
+#define TILE_OPC_INFO TILEPRO_OPC_INFO
+#define TILE_OPC_INFOL TILEPRO_OPC_INFOL
+#define TILE_OPC_JRP TILEPRO_OPC_JRP
+#define TILE_OPC_MOVE TILEPRO_OPC_MOVE
+#define OPCODE_STORE TILEPRO_OPC_SW
 typedef int bt_int_reg_t;
 #endif
 
index 28fa6ec..b90ab99 100644 (file)
@@ -20,9 +20,9 @@
 #include <linux/fs.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
-#include <asm/opcode-tile.h>
 #include <asm/pgtable.h>
 #include <asm/homecache.h>
+#include <arch/opcode.h>
 
 #ifdef __tilegx__
 # define Elf_Rela Elf64_Rela
index 4032ca8..b7a8795 100644 (file)
@@ -25,9 +25,8 @@
 #include <linux/types.h>
 #include <linux/err.h>
 #include <asm/cacheflush.h>
-#include <asm/opcode-tile.h>
-#include <asm/opcode_constants.h>
 #include <arch/abi.h>
+#include <arch/opcode.h>
 
 #define signExtend17(val) sign_extend((val), 17)
 #define TILE_X1_MASK (0xffffffffULL << 31)
@@ -118,7 +117,7 @@ static tile_bundle_bits rewrite_load_store_unaligned(
        int val_reg, addr_reg, err, val;
 
        /* Get address and value registers */
-       if (bundle & TILE_BUNDLE_Y_ENCODING_MASK) {
+       if (bundle & TILEPRO_BUNDLE_Y_ENCODING_MASK) {
                addr_reg = get_SrcA_Y2(bundle);
                val_reg = get_SrcBDest_Y2(bundle);
        } else if (mem_op == MEMOP_LOAD || mem_op == MEMOP_LOAD_POSTINCR) {
@@ -229,7 +228,7 @@ P("\n");
        }
        ++unaligned_fixup_count;
 
-       if (bundle & TILE_BUNDLE_Y_ENCODING_MASK) {
+       if (bundle & TILEPRO_BUNDLE_Y_ENCODING_MASK) {
                /* Convert the Y2 instruction to a prefetch. */
                bundle &= ~(create_SrcBDest_Y2(-1) |
                            create_Opcode_Y2(-1));
@@ -389,7 +388,7 @@ void single_step_once(struct pt_regs *regs)
        state->branch_next_pc = 0;
        state->update = 0;
 
-       if (!(bundle & TILE_BUNDLE_Y_ENCODING_MASK)) {
+       if (!(bundle & TILEPRO_BUNDLE_Y_ENCODING_MASK)) {
                /* two wide, check for control flow */
                int opcode = get_Opcode_X1(bundle);
 
index 7e31a12..dd7bd1d 100644 (file)
@@ -1,3 +1,23 @@
+/* TILEPro opcode information.
+ *
+ * Copyright 2011 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ *
+ *
+ *
+ *
+ *
+ */
+
 /* This define is BFD_RELOC_##x for real bfd, or -1 for everyone else. */
 #define BFD_RELOC(x) -1
 
 #define TREG_SN 56
 #define TREG_ZERO 63
 
-/* FIXME: Rename this. */
-#include <asm/opcode-tile.h>
-
 #include <linux/stddef.h>
+#include <asm/tile-desc.h>
 
-const struct tile_opcode tile_opcodes[395] =
+const struct tilepro_opcode tilepro_opcodes[395] =
 {
- { "bpt", TILE_OPC_BPT, 0x2, 0, TREG_ZERO, 0,
+ { "bpt", TILEPRO_OPC_BPT, 0x2, 0, TREG_ZERO, 0,
     { { 0, }, {  }, { 0, }, { 0, }, { 0, } },
   },
-  { "info", TILE_OPC_INFO, 0xf, 1, TREG_ZERO, 1,
+  { "info", TILEPRO_OPC_INFO, 0xf, 1, TREG_ZERO, 1,
     { { 0 }, { 1 }, { 2 }, { 3 }, { 0, } },
   },
-  { "infol", TILE_OPC_INFOL, 0x3, 1, TREG_ZERO, 1,
+  { "infol", TILEPRO_OPC_INFOL, 0x3, 1, TREG_ZERO, 1,
     { { 4 }, { 5 }, { 0, }, { 0, }, { 0, } },
   },
-  { "j", TILE_OPC_J, 0x2, 1, TREG_ZERO, 1,
+  { "j", TILEPRO_OPC_J, 0x2, 1, TREG_ZERO, 1,
     { { 0, }, { 6 }, { 0, }, { 0, }, { 0, } },
   },
-  { "jal", TILE_OPC_JAL, 0x2, 1, TREG_LR, 1,
+  { "jal", TILEPRO_OPC_JAL, 0x2, 1, TREG_LR, 1,
     { { 0, }, { 6 }, { 0, }, { 0, }, { 0, } },
   },
-  { "move", TILE_OPC_MOVE, 0xf, 2, TREG_ZERO, 1,
+  { "move", TILEPRO_OPC_MOVE, 0xf, 2, TREG_ZERO, 1,
     { { 7, 8 }, { 9, 10 }, { 11, 12 }, { 13, 14 }, { 0, } },
   },
-  { "move.sn", TILE_OPC_MOVE_SN, 0x3, 2, TREG_SN, 1,
+  { "move.sn", TILEPRO_OPC_MOVE_SN, 0x3, 2, TREG_SN, 1,
     { { 7, 8 }, { 9, 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "movei", TILE_OPC_MOVEI, 0xf, 2, TREG_ZERO, 1,
+  { "movei", TILEPRO_OPC_MOVEI, 0xf, 2, TREG_ZERO, 1,
     { { 7, 0 }, { 9, 1 }, { 11, 2 }, { 13, 3 }, { 0, } },
   },
-  { "movei.sn", TILE_OPC_MOVEI_SN, 0x3, 2, TREG_SN, 1,
+  { "movei.sn", TILEPRO_OPC_MOVEI_SN, 0x3, 2, TREG_SN, 1,
     { { 7, 0 }, { 9, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "moveli", TILE_OPC_MOVELI, 0x3, 2, TREG_ZERO, 1,
+  { "moveli", TILEPRO_OPC_MOVELI, 0x3, 2, TREG_ZERO, 1,
     { { 7, 4 }, { 9, 5 }, { 0, }, { 0, }, { 0, } },
   },
-  { "moveli.sn", TILE_OPC_MOVELI_SN, 0x3, 2, TREG_SN, 1,
+  { "moveli.sn", TILEPRO_OPC_MOVELI_SN, 0x3, 2, TREG_SN, 1,
     { { 7, 4 }, { 9, 5 }, { 0, }, { 0, }, { 0, } },
   },
-  { "movelis", TILE_OPC_MOVELIS, 0x3, 2, TREG_SN, 1,
+  { "movelis", TILEPRO_OPC_MOVELIS, 0x3, 2, TREG_SN, 1,
     { { 7, 4 }, { 9, 5 }, { 0, }, { 0, }, { 0, } },
   },
-  { "prefetch", TILE_OPC_PREFETCH, 0x12, 1, TREG_ZERO, 1,
+  { "prefetch", TILEPRO_OPC_PREFETCH, 0x12, 1, TREG_ZERO, 1,
     { { 0, }, { 10 }, { 0, }, { 0, }, { 15 } },
   },
-  { "raise", TILE_OPC_RAISE, 0x2, 0, TREG_ZERO, 1,
+  { "raise", TILEPRO_OPC_RAISE, 0x2, 0, TREG_ZERO, 1,
     { { 0, }, {  }, { 0, }, { 0, }, { 0, } },
   },
-  { "add", TILE_OPC_ADD, 0xf, 3, TREG_ZERO, 1,
+  { "add", TILEPRO_OPC_ADD, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "add.sn", TILE_OPC_ADD_SN, 0x3, 3, TREG_SN, 1,
+  { "add.sn", TILEPRO_OPC_ADD_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "addb", TILE_OPC_ADDB, 0x3, 3, TREG_ZERO, 1,
+  { "addb", TILEPRO_OPC_ADDB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "addb.sn", TILE_OPC_ADDB_SN, 0x3, 3, TREG_SN, 1,
+  { "addb.sn", TILEPRO_OPC_ADDB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "addbs_u", TILE_OPC_ADDBS_U, 0x3, 3, TREG_ZERO, 1,
+  { "addbs_u", TILEPRO_OPC_ADDBS_U, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "addbs_u.sn", TILE_OPC_ADDBS_U_SN, 0x3, 3, TREG_SN, 1,
+  { "addbs_u.sn", TILEPRO_OPC_ADDBS_U_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "addh", TILE_OPC_ADDH, 0x3, 3, TREG_ZERO, 1,
+  { "addh", TILEPRO_OPC_ADDH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "addh.sn", TILE_OPC_ADDH_SN, 0x3, 3, TREG_SN, 1,
+  { "addh.sn", TILEPRO_OPC_ADDH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "addhs", TILE_OPC_ADDHS, 0x3, 3, TREG_ZERO, 1,
+  { "addhs", TILEPRO_OPC_ADDHS, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "addhs.sn", TILE_OPC_ADDHS_SN, 0x3, 3, TREG_SN, 1,
+  { "addhs.sn", TILEPRO_OPC_ADDHS_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "addi", TILE_OPC_ADDI, 0xf, 3, TREG_ZERO, 1,
+  { "addi", TILEPRO_OPC_ADDI, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 11, 12, 2 }, { 13, 14, 3 }, { 0, } },
   },
-  { "addi.sn", TILE_OPC_ADDI_SN, 0x3, 3, TREG_SN, 1,
+  { "addi.sn", TILEPRO_OPC_ADDI_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "addib", TILE_OPC_ADDIB, 0x3, 3, TREG_ZERO, 1,
+  { "addib", TILEPRO_OPC_ADDIB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "addib.sn", TILE_OPC_ADDIB_SN, 0x3, 3, TREG_SN, 1,
+  { "addib.sn", TILEPRO_OPC_ADDIB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "addih", TILE_OPC_ADDIH, 0x3, 3, TREG_ZERO, 1,
+  { "addih", TILEPRO_OPC_ADDIH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "addih.sn", TILE_OPC_ADDIH_SN, 0x3, 3, TREG_SN, 1,
+  { "addih.sn", TILEPRO_OPC_ADDIH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "addli", TILE_OPC_ADDLI, 0x3, 3, TREG_ZERO, 1,
+  { "addli", TILEPRO_OPC_ADDLI, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 4 }, { 9, 10, 5 }, { 0, }, { 0, }, { 0, } },
   },
-  { "addli.sn", TILE_OPC_ADDLI_SN, 0x3, 3, TREG_SN, 1,
+  { "addli.sn", TILEPRO_OPC_ADDLI_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 4 }, { 9, 10, 5 }, { 0, }, { 0, }, { 0, } },
   },
-  { "addlis", TILE_OPC_ADDLIS, 0x3, 3, TREG_SN, 1,
+  { "addlis", TILEPRO_OPC_ADDLIS, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 4 }, { 9, 10, 5 }, { 0, }, { 0, }, { 0, } },
   },
-  { "adds", TILE_OPC_ADDS, 0x3, 3, TREG_ZERO, 1,
+  { "adds", TILEPRO_OPC_ADDS, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "adds.sn", TILE_OPC_ADDS_SN, 0x3, 3, TREG_SN, 1,
+  { "adds.sn", TILEPRO_OPC_ADDS_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "adiffb_u", TILE_OPC_ADIFFB_U, 0x1, 3, TREG_ZERO, 1,
+  { "adiffb_u", TILEPRO_OPC_ADIFFB_U, 0x1, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "adiffb_u.sn", TILE_OPC_ADIFFB_U_SN, 0x1, 3, TREG_SN, 1,
+  { "adiffb_u.sn", TILEPRO_OPC_ADIFFB_U_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "adiffh", TILE_OPC_ADIFFH, 0x1, 3, TREG_ZERO, 1,
+  { "adiffh", TILEPRO_OPC_ADIFFH, 0x1, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "adiffh.sn", TILE_OPC_ADIFFH_SN, 0x1, 3, TREG_SN, 1,
+  { "adiffh.sn", TILEPRO_OPC_ADIFFH_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "and", TILE_OPC_AND, 0xf, 3, TREG_ZERO, 1,
+  { "and", TILEPRO_OPC_AND, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "and.sn", TILE_OPC_AND_SN, 0x3, 3, TREG_SN, 1,
+  { "and.sn", TILEPRO_OPC_AND_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "andi", TILE_OPC_ANDI, 0xf, 3, TREG_ZERO, 1,
+  { "andi", TILEPRO_OPC_ANDI, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 11, 12, 2 }, { 13, 14, 3 }, { 0, } },
   },
-  { "andi.sn", TILE_OPC_ANDI_SN, 0x3, 3, TREG_SN, 1,
+  { "andi.sn", TILEPRO_OPC_ANDI_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "auli", TILE_OPC_AULI, 0x3, 3, TREG_ZERO, 1,
+  { "auli", TILEPRO_OPC_AULI, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 4 }, { 9, 10, 5 }, { 0, }, { 0, }, { 0, } },
   },
-  { "avgb_u", TILE_OPC_AVGB_U, 0x1, 3, TREG_ZERO, 1,
+  { "avgb_u", TILEPRO_OPC_AVGB_U, 0x1, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "avgb_u.sn", TILE_OPC_AVGB_U_SN, 0x1, 3, TREG_SN, 1,
+  { "avgb_u.sn", TILEPRO_OPC_AVGB_U_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "avgh", TILE_OPC_AVGH, 0x1, 3, TREG_ZERO, 1,
+  { "avgh", TILEPRO_OPC_AVGH, 0x1, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "avgh.sn", TILE_OPC_AVGH_SN, 0x1, 3, TREG_SN, 1,
+  { "avgh.sn", TILEPRO_OPC_AVGH_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "bbns", TILE_OPC_BBNS, 0x2, 2, TREG_ZERO, 1,
+  { "bbns", TILEPRO_OPC_BBNS, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bbns.sn", TILE_OPC_BBNS_SN, 0x2, 2, TREG_SN, 1,
+  { "bbns.sn", TILEPRO_OPC_BBNS_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bbnst", TILE_OPC_BBNST, 0x2, 2, TREG_ZERO, 1,
+  { "bbnst", TILEPRO_OPC_BBNST, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bbnst.sn", TILE_OPC_BBNST_SN, 0x2, 2, TREG_SN, 1,
+  { "bbnst.sn", TILEPRO_OPC_BBNST_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bbs", TILE_OPC_BBS, 0x2, 2, TREG_ZERO, 1,
+  { "bbs", TILEPRO_OPC_BBS, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bbs.sn", TILE_OPC_BBS_SN, 0x2, 2, TREG_SN, 1,
+  { "bbs.sn", TILEPRO_OPC_BBS_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bbst", TILE_OPC_BBST, 0x2, 2, TREG_ZERO, 1,
+  { "bbst", TILEPRO_OPC_BBST, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bbst.sn", TILE_OPC_BBST_SN, 0x2, 2, TREG_SN, 1,
+  { "bbst.sn", TILEPRO_OPC_BBST_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bgez", TILE_OPC_BGEZ, 0x2, 2, TREG_ZERO, 1,
+  { "bgez", TILEPRO_OPC_BGEZ, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bgez.sn", TILE_OPC_BGEZ_SN, 0x2, 2, TREG_SN, 1,
+  { "bgez.sn", TILEPRO_OPC_BGEZ_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bgezt", TILE_OPC_BGEZT, 0x2, 2, TREG_ZERO, 1,
+  { "bgezt", TILEPRO_OPC_BGEZT, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bgezt.sn", TILE_OPC_BGEZT_SN, 0x2, 2, TREG_SN, 1,
+  { "bgezt.sn", TILEPRO_OPC_BGEZT_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bgz", TILE_OPC_BGZ, 0x2, 2, TREG_ZERO, 1,
+  { "bgz", TILEPRO_OPC_BGZ, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bgz.sn", TILE_OPC_BGZ_SN, 0x2, 2, TREG_SN, 1,
+  { "bgz.sn", TILEPRO_OPC_BGZ_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bgzt", TILE_OPC_BGZT, 0x2, 2, TREG_ZERO, 1,
+  { "bgzt", TILEPRO_OPC_BGZT, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bgzt.sn", TILE_OPC_BGZT_SN, 0x2, 2, TREG_SN, 1,
+  { "bgzt.sn", TILEPRO_OPC_BGZT_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bitx", TILE_OPC_BITX, 0x5, 2, TREG_ZERO, 1,
+  { "bitx", TILEPRO_OPC_BITX, 0x5, 2, TREG_ZERO, 1,
     { { 7, 8 }, { 0, }, { 11, 12 }, { 0, }, { 0, } },
   },
-  { "bitx.sn", TILE_OPC_BITX_SN, 0x1, 2, TREG_SN, 1,
+  { "bitx.sn", TILEPRO_OPC_BITX_SN, 0x1, 2, TREG_SN, 1,
     { { 7, 8 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "blez", TILE_OPC_BLEZ, 0x2, 2, TREG_ZERO, 1,
+  { "blez", TILEPRO_OPC_BLEZ, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "blez.sn", TILE_OPC_BLEZ_SN, 0x2, 2, TREG_SN, 1,
+  { "blez.sn", TILEPRO_OPC_BLEZ_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "blezt", TILE_OPC_BLEZT, 0x2, 2, TREG_ZERO, 1,
+  { "blezt", TILEPRO_OPC_BLEZT, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "blezt.sn", TILE_OPC_BLEZT_SN, 0x2, 2, TREG_SN, 1,
+  { "blezt.sn", TILEPRO_OPC_BLEZT_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "blz", TILE_OPC_BLZ, 0x2, 2, TREG_ZERO, 1,
+  { "blz", TILEPRO_OPC_BLZ, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "blz.sn", TILE_OPC_BLZ_SN, 0x2, 2, TREG_SN, 1,
+  { "blz.sn", TILEPRO_OPC_BLZ_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "blzt", TILE_OPC_BLZT, 0x2, 2, TREG_ZERO, 1,
+  { "blzt", TILEPRO_OPC_BLZT, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "blzt.sn", TILE_OPC_BLZT_SN, 0x2, 2, TREG_SN, 1,
+  { "blzt.sn", TILEPRO_OPC_BLZT_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bnz", TILE_OPC_BNZ, 0x2, 2, TREG_ZERO, 1,
+  { "bnz", TILEPRO_OPC_BNZ, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bnz.sn", TILE_OPC_BNZ_SN, 0x2, 2, TREG_SN, 1,
+  { "bnz.sn", TILEPRO_OPC_BNZ_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bnzt", TILE_OPC_BNZT, 0x2, 2, TREG_ZERO, 1,
+  { "bnzt", TILEPRO_OPC_BNZT, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bnzt.sn", TILE_OPC_BNZT_SN, 0x2, 2, TREG_SN, 1,
+  { "bnzt.sn", TILEPRO_OPC_BNZT_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bytex", TILE_OPC_BYTEX, 0x5, 2, TREG_ZERO, 1,
+  { "bytex", TILEPRO_OPC_BYTEX, 0x5, 2, TREG_ZERO, 1,
     { { 7, 8 }, { 0, }, { 11, 12 }, { 0, }, { 0, } },
   },
-  { "bytex.sn", TILE_OPC_BYTEX_SN, 0x1, 2, TREG_SN, 1,
+  { "bytex.sn", TILEPRO_OPC_BYTEX_SN, 0x1, 2, TREG_SN, 1,
     { { 7, 8 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "bz", TILE_OPC_BZ, 0x2, 2, TREG_ZERO, 1,
+  { "bz", TILEPRO_OPC_BZ, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bz.sn", TILE_OPC_BZ_SN, 0x2, 2, TREG_SN, 1,
+  { "bz.sn", TILEPRO_OPC_BZ_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bzt", TILE_OPC_BZT, 0x2, 2, TREG_ZERO, 1,
+  { "bzt", TILEPRO_OPC_BZT, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "bzt.sn", TILE_OPC_BZT_SN, 0x2, 2, TREG_SN, 1,
+  { "bzt.sn", TILEPRO_OPC_BZT_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 10, 20 }, { 0, }, { 0, }, { 0, } },
   },
-  { "clz", TILE_OPC_CLZ, 0x5, 2, TREG_ZERO, 1,
+  { "clz", TILEPRO_OPC_CLZ, 0x5, 2, TREG_ZERO, 1,
     { { 7, 8 }, { 0, }, { 11, 12 }, { 0, }, { 0, } },
   },
-  { "clz.sn", TILE_OPC_CLZ_SN, 0x1, 2, TREG_SN, 1,
+  { "clz.sn", TILEPRO_OPC_CLZ_SN, 0x1, 2, TREG_SN, 1,
     { { 7, 8 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "crc32_32", TILE_OPC_CRC32_32, 0x1, 3, TREG_ZERO, 1,
+  { "crc32_32", TILEPRO_OPC_CRC32_32, 0x1, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "crc32_32.sn", TILE_OPC_CRC32_32_SN, 0x1, 3, TREG_SN, 1,
+  { "crc32_32.sn", TILEPRO_OPC_CRC32_32_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "crc32_8", TILE_OPC_CRC32_8, 0x1, 3, TREG_ZERO, 1,
+  { "crc32_8", TILEPRO_OPC_CRC32_8, 0x1, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "crc32_8.sn", TILE_OPC_CRC32_8_SN, 0x1, 3, TREG_SN, 1,
+  { "crc32_8.sn", TILEPRO_OPC_CRC32_8_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "ctz", TILE_OPC_CTZ, 0x5, 2, TREG_ZERO, 1,
+  { "ctz", TILEPRO_OPC_CTZ, 0x5, 2, TREG_ZERO, 1,
     { { 7, 8 }, { 0, }, { 11, 12 }, { 0, }, { 0, } },
   },
-  { "ctz.sn", TILE_OPC_CTZ_SN, 0x1, 2, TREG_SN, 1,
+  { "ctz.sn", TILEPRO_OPC_CTZ_SN, 0x1, 2, TREG_SN, 1,
     { { 7, 8 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "drain", TILE_OPC_DRAIN, 0x2, 0, TREG_ZERO, 0,
+  { "drain", TILEPRO_OPC_DRAIN, 0x2, 0, TREG_ZERO, 0,
     { { 0, }, {  }, { 0, }, { 0, }, { 0, } },
   },
-  { "dtlbpr", TILE_OPC_DTLBPR, 0x2, 1, TREG_ZERO, 1,
+  { "dtlbpr", TILEPRO_OPC_DTLBPR, 0x2, 1, TREG_ZERO, 1,
     { { 0, }, { 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "dword_align", TILE_OPC_DWORD_ALIGN, 0x1, 3, TREG_ZERO, 1,
+  { "dword_align", TILEPRO_OPC_DWORD_ALIGN, 0x1, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "dword_align.sn", TILE_OPC_DWORD_ALIGN_SN, 0x1, 3, TREG_SN, 1,
+  { "dword_align.sn", TILEPRO_OPC_DWORD_ALIGN_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "finv", TILE_OPC_FINV, 0x2, 1, TREG_ZERO, 1,
+  { "finv", TILEPRO_OPC_FINV, 0x2, 1, TREG_ZERO, 1,
     { { 0, }, { 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "flush", TILE_OPC_FLUSH, 0x2, 1, TREG_ZERO, 1,
+  { "flush", TILEPRO_OPC_FLUSH, 0x2, 1, TREG_ZERO, 1,
     { { 0, }, { 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "fnop", TILE_OPC_FNOP, 0xf, 0, TREG_ZERO, 1,
+  { "fnop", TILEPRO_OPC_FNOP, 0xf, 0, TREG_ZERO, 1,
     { {  }, {  }, {  }, {  }, { 0, } },
   },
-  { "icoh", TILE_OPC_ICOH, 0x2, 1, TREG_ZERO, 1,
+  { "icoh", TILEPRO_OPC_ICOH, 0x2, 1, TREG_ZERO, 1,
     { { 0, }, { 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "ill", TILE_OPC_ILL, 0xa, 0, TREG_ZERO, 1,
+  { "ill", TILEPRO_OPC_ILL, 0xa, 0, TREG_ZERO, 1,
     { { 0, }, {  }, { 0, }, {  }, { 0, } },
   },
-  { "inthb", TILE_OPC_INTHB, 0x3, 3, TREG_ZERO, 1,
+  { "inthb", TILEPRO_OPC_INTHB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "inthb.sn", TILE_OPC_INTHB_SN, 0x3, 3, TREG_SN, 1,
+  { "inthb.sn", TILEPRO_OPC_INTHB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "inthh", TILE_OPC_INTHH, 0x3, 3, TREG_ZERO, 1,
+  { "inthh", TILEPRO_OPC_INTHH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "inthh.sn", TILE_OPC_INTHH_SN, 0x3, 3, TREG_SN, 1,
+  { "inthh.sn", TILEPRO_OPC_INTHH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "intlb", TILE_OPC_INTLB, 0x3, 3, TREG_ZERO, 1,
+  { "intlb", TILEPRO_OPC_INTLB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "intlb.sn", TILE_OPC_INTLB_SN, 0x3, 3, TREG_SN, 1,
+  { "intlb.sn", TILEPRO_OPC_INTLB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "intlh", TILE_OPC_INTLH, 0x3, 3, TREG_ZERO, 1,
+  { "intlh", TILEPRO_OPC_INTLH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "intlh.sn", TILE_OPC_INTLH_SN, 0x3, 3, TREG_SN, 1,
+  { "intlh.sn", TILEPRO_OPC_INTLH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "inv", TILE_OPC_INV, 0x2, 1, TREG_ZERO, 1,
+  { "inv", TILEPRO_OPC_INV, 0x2, 1, TREG_ZERO, 1,
     { { 0, }, { 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "iret", TILE_OPC_IRET, 0x2, 0, TREG_ZERO, 1,
+  { "iret", TILEPRO_OPC_IRET, 0x2, 0, TREG_ZERO, 1,
     { { 0, }, {  }, { 0, }, { 0, }, { 0, } },
   },
-  { "jalb", TILE_OPC_JALB, 0x2, 1, TREG_LR, 1,
+  { "jalb", TILEPRO_OPC_JALB, 0x2, 1, TREG_LR, 1,
     { { 0, }, { 22 }, { 0, }, { 0, }, { 0, } },
   },
-  { "jalf", TILE_OPC_JALF, 0x2, 1, TREG_LR, 1,
+  { "jalf", TILEPRO_OPC_JALF, 0x2, 1, TREG_LR, 1,
     { { 0, }, { 22 }, { 0, }, { 0, }, { 0, } },
   },
-  { "jalr", TILE_OPC_JALR, 0x2, 1, TREG_LR, 1,
+  { "jalr", TILEPRO_OPC_JALR, 0x2, 1, TREG_LR, 1,
     { { 0, }, { 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "jalrp", TILE_OPC_JALRP, 0x2, 1, TREG_LR, 1,
+  { "jalrp", TILEPRO_OPC_JALRP, 0x2, 1, TREG_LR, 1,
     { { 0, }, { 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "jb", TILE_OPC_JB, 0x2, 1, TREG_ZERO, 1,
+  { "jb", TILEPRO_OPC_JB, 0x2, 1, TREG_ZERO, 1,
     { { 0, }, { 22 }, { 0, }, { 0, }, { 0, } },
   },
-  { "jf", TILE_OPC_JF, 0x2, 1, TREG_ZERO, 1,
+  { "jf", TILEPRO_OPC_JF, 0x2, 1, TREG_ZERO, 1,
     { { 0, }, { 22 }, { 0, }, { 0, }, { 0, } },
   },
-  { "jr", TILE_OPC_JR, 0x2, 1, TREG_ZERO, 1,
+  { "jr", TILEPRO_OPC_JR, 0x2, 1, TREG_ZERO, 1,
     { { 0, }, { 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "jrp", TILE_OPC_JRP, 0x2, 1, TREG_ZERO, 1,
+  { "jrp", TILEPRO_OPC_JRP, 0x2, 1, TREG_ZERO, 1,
     { { 0, }, { 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lb", TILE_OPC_LB, 0x12, 2, TREG_ZERO, 1,
+  { "lb", TILEPRO_OPC_LB, 0x12, 2, TREG_ZERO, 1,
     { { 0, }, { 9, 10 }, { 0, }, { 0, }, { 23, 15 } },
   },
-  { "lb.sn", TILE_OPC_LB_SN, 0x2, 2, TREG_SN, 1,
+  { "lb.sn", TILEPRO_OPC_LB_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 9, 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lb_u", TILE_OPC_LB_U, 0x12, 2, TREG_ZERO, 1,
+  { "lb_u", TILEPRO_OPC_LB_U, 0x12, 2, TREG_ZERO, 1,
     { { 0, }, { 9, 10 }, { 0, }, { 0, }, { 23, 15 } },
   },
-  { "lb_u.sn", TILE_OPC_LB_U_SN, 0x2, 2, TREG_SN, 1,
+  { "lb_u.sn", TILEPRO_OPC_LB_U_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 9, 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lbadd", TILE_OPC_LBADD, 0x2, 3, TREG_ZERO, 1,
+  { "lbadd", TILEPRO_OPC_LBADD, 0x2, 3, TREG_ZERO, 1,
     { { 0, }, { 9, 24, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lbadd.sn", TILE_OPC_LBADD_SN, 0x2, 3, TREG_SN, 1,
+  { "lbadd.sn", TILEPRO_OPC_LBADD_SN, 0x2, 3, TREG_SN, 1,
     { { 0, }, { 9, 24, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lbadd_u", TILE_OPC_LBADD_U, 0x2, 3, TREG_ZERO, 1,
+  { "lbadd_u", TILEPRO_OPC_LBADD_U, 0x2, 3, TREG_ZERO, 1,
     { { 0, }, { 9, 24, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lbadd_u.sn", TILE_OPC_LBADD_U_SN, 0x2, 3, TREG_SN, 1,
+  { "lbadd_u.sn", TILEPRO_OPC_LBADD_U_SN, 0x2, 3, TREG_SN, 1,
     { { 0, }, { 9, 24, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lh", TILE_OPC_LH, 0x12, 2, TREG_ZERO, 1,
+  { "lh", TILEPRO_OPC_LH, 0x12, 2, TREG_ZERO, 1,
     { { 0, }, { 9, 10 }, { 0, }, { 0, }, { 23, 15 } },
   },
-  { "lh.sn", TILE_OPC_LH_SN, 0x2, 2, TREG_SN, 1,
+  { "lh.sn", TILEPRO_OPC_LH_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 9, 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lh_u", TILE_OPC_LH_U, 0x12, 2, TREG_ZERO, 1,
+  { "lh_u", TILEPRO_OPC_LH_U, 0x12, 2, TREG_ZERO, 1,
     { { 0, }, { 9, 10 }, { 0, }, { 0, }, { 23, 15 } },
   },
-  { "lh_u.sn", TILE_OPC_LH_U_SN, 0x2, 2, TREG_SN, 1,
+  { "lh_u.sn", TILEPRO_OPC_LH_U_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 9, 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lhadd", TILE_OPC_LHADD, 0x2, 3, TREG_ZERO, 1,
+  { "lhadd", TILEPRO_OPC_LHADD, 0x2, 3, TREG_ZERO, 1,
     { { 0, }, { 9, 24, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lhadd.sn", TILE_OPC_LHADD_SN, 0x2, 3, TREG_SN, 1,
+  { "lhadd.sn", TILEPRO_OPC_LHADD_SN, 0x2, 3, TREG_SN, 1,
     { { 0, }, { 9, 24, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lhadd_u", TILE_OPC_LHADD_U, 0x2, 3, TREG_ZERO, 1,
+  { "lhadd_u", TILEPRO_OPC_LHADD_U, 0x2, 3, TREG_ZERO, 1,
     { { 0, }, { 9, 24, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lhadd_u.sn", TILE_OPC_LHADD_U_SN, 0x2, 3, TREG_SN, 1,
+  { "lhadd_u.sn", TILEPRO_OPC_LHADD_U_SN, 0x2, 3, TREG_SN, 1,
     { { 0, }, { 9, 24, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lnk", TILE_OPC_LNK, 0x2, 1, TREG_ZERO, 1,
+  { "lnk", TILEPRO_OPC_LNK, 0x2, 1, TREG_ZERO, 1,
     { { 0, }, { 9 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lnk.sn", TILE_OPC_LNK_SN, 0x2, 1, TREG_SN, 1,
+  { "lnk.sn", TILEPRO_OPC_LNK_SN, 0x2, 1, TREG_SN, 1,
     { { 0, }, { 9 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lw", TILE_OPC_LW, 0x12, 2, TREG_ZERO, 1,
+  { "lw", TILEPRO_OPC_LW, 0x12, 2, TREG_ZERO, 1,
     { { 0, }, { 9, 10 }, { 0, }, { 0, }, { 23, 15 } },
   },
-  { "lw.sn", TILE_OPC_LW_SN, 0x2, 2, TREG_SN, 1,
+  { "lw.sn", TILEPRO_OPC_LW_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 9, 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lw_na", TILE_OPC_LW_NA, 0x2, 2, TREG_ZERO, 1,
+  { "lw_na", TILEPRO_OPC_LW_NA, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 9, 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lw_na.sn", TILE_OPC_LW_NA_SN, 0x2, 2, TREG_SN, 1,
+  { "lw_na.sn", TILEPRO_OPC_LW_NA_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 9, 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lwadd", TILE_OPC_LWADD, 0x2, 3, TREG_ZERO, 1,
+  { "lwadd", TILEPRO_OPC_LWADD, 0x2, 3, TREG_ZERO, 1,
     { { 0, }, { 9, 24, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lwadd.sn", TILE_OPC_LWADD_SN, 0x2, 3, TREG_SN, 1,
+  { "lwadd.sn", TILEPRO_OPC_LWADD_SN, 0x2, 3, TREG_SN, 1,
     { { 0, }, { 9, 24, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lwadd_na", TILE_OPC_LWADD_NA, 0x2, 3, TREG_ZERO, 1,
+  { "lwadd_na", TILEPRO_OPC_LWADD_NA, 0x2, 3, TREG_ZERO, 1,
     { { 0, }, { 9, 24, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "lwadd_na.sn", TILE_OPC_LWADD_NA_SN, 0x2, 3, TREG_SN, 1,
+  { "lwadd_na.sn", TILEPRO_OPC_LWADD_NA_SN, 0x2, 3, TREG_SN, 1,
     { { 0, }, { 9, 24, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "maxb_u", TILE_OPC_MAXB_U, 0x3, 3, TREG_ZERO, 1,
+  { "maxb_u", TILEPRO_OPC_MAXB_U, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "maxb_u.sn", TILE_OPC_MAXB_U_SN, 0x3, 3, TREG_SN, 1,
+  { "maxb_u.sn", TILEPRO_OPC_MAXB_U_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "maxh", TILE_OPC_MAXH, 0x3, 3, TREG_ZERO, 1,
+  { "maxh", TILEPRO_OPC_MAXH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "maxh.sn", TILE_OPC_MAXH_SN, 0x3, 3, TREG_SN, 1,
+  { "maxh.sn", TILEPRO_OPC_MAXH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "maxib_u", TILE_OPC_MAXIB_U, 0x3, 3, TREG_ZERO, 1,
+  { "maxib_u", TILEPRO_OPC_MAXIB_U, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "maxib_u.sn", TILE_OPC_MAXIB_U_SN, 0x3, 3, TREG_SN, 1,
+  { "maxib_u.sn", TILEPRO_OPC_MAXIB_U_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "maxih", TILE_OPC_MAXIH, 0x3, 3, TREG_ZERO, 1,
+  { "maxih", TILEPRO_OPC_MAXIH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "maxih.sn", TILE_OPC_MAXIH_SN, 0x3, 3, TREG_SN, 1,
+  { "maxih.sn", TILEPRO_OPC_MAXIH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "mf", TILE_OPC_MF, 0x2, 0, TREG_ZERO, 1,
+  { "mf", TILEPRO_OPC_MF, 0x2, 0, TREG_ZERO, 1,
     { { 0, }, {  }, { 0, }, { 0, }, { 0, } },
   },
-  { "mfspr", TILE_OPC_MFSPR, 0x2, 2, TREG_ZERO, 1,
+  { "mfspr", TILEPRO_OPC_MFSPR, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 9, 25 }, { 0, }, { 0, }, { 0, } },
   },
-  { "minb_u", TILE_OPC_MINB_U, 0x3, 3, TREG_ZERO, 1,
+  { "minb_u", TILEPRO_OPC_MINB_U, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "minb_u.sn", TILE_OPC_MINB_U_SN, 0x3, 3, TREG_SN, 1,
+  { "minb_u.sn", TILEPRO_OPC_MINB_U_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "minh", TILE_OPC_MINH, 0x3, 3, TREG_ZERO, 1,
+  { "minh", TILEPRO_OPC_MINH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "minh.sn", TILE_OPC_MINH_SN, 0x3, 3, TREG_SN, 1,
+  { "minh.sn", TILEPRO_OPC_MINH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "minib_u", TILE_OPC_MINIB_U, 0x3, 3, TREG_ZERO, 1,
+  { "minib_u", TILEPRO_OPC_MINIB_U, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "minib_u.sn", TILE_OPC_MINIB_U_SN, 0x3, 3, TREG_SN, 1,
+  { "minib_u.sn", TILEPRO_OPC_MINIB_U_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "minih", TILE_OPC_MINIH, 0x3, 3, TREG_ZERO, 1,
+  { "minih", TILEPRO_OPC_MINIH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "minih.sn", TILE_OPC_MINIH_SN, 0x3, 3, TREG_SN, 1,
+  { "minih.sn", TILEPRO_OPC_MINIH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "mm", TILE_OPC_MM, 0x3, 5, TREG_ZERO, 1,
+  { "mm", TILEPRO_OPC_MM, 0x3, 5, TREG_ZERO, 1,
     { { 7, 8, 16, 26, 27 }, { 9, 10, 17, 28, 29 }, { 0, }, { 0, }, { 0, } },
   },
-  { "mnz", TILE_OPC_MNZ, 0xf, 3, TREG_ZERO, 1,
+  { "mnz", TILEPRO_OPC_MNZ, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "mnz.sn", TILE_OPC_MNZ_SN, 0x3, 3, TREG_SN, 1,
+  { "mnz.sn", TILEPRO_OPC_MNZ_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "mnzb", TILE_OPC_MNZB, 0x3, 3, TREG_ZERO, 1,
+  { "mnzb", TILEPRO_OPC_MNZB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "mnzb.sn", TILE_OPC_MNZB_SN, 0x3, 3, TREG_SN, 1,
+  { "mnzb.sn", TILEPRO_OPC_MNZB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "mnzh", TILE_OPC_MNZH, 0x3, 3, TREG_ZERO, 1,
+  { "mnzh", TILEPRO_OPC_MNZH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "mnzh.sn", TILE_OPC_MNZH_SN, 0x3, 3, TREG_SN, 1,
+  { "mnzh.sn", TILEPRO_OPC_MNZH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "mtspr", TILE_OPC_MTSPR, 0x2, 2, TREG_ZERO, 1,
+  { "mtspr", TILEPRO_OPC_MTSPR, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 30, 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhh_ss", TILE_OPC_MULHH_SS, 0x5, 3, TREG_ZERO, 1,
+  { "mulhh_ss", TILEPRO_OPC_MULHH_SS, 0x5, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 11, 12, 18 }, { 0, }, { 0, } },
   },
-  { "mulhh_ss.sn", TILE_OPC_MULHH_SS_SN, 0x1, 3, TREG_SN, 1,
+  { "mulhh_ss.sn", TILEPRO_OPC_MULHH_SS_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhh_su", TILE_OPC_MULHH_SU, 0x1, 3, TREG_ZERO, 1,
+  { "mulhh_su", TILEPRO_OPC_MULHH_SU, 0x1, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhh_su.sn", TILE_OPC_MULHH_SU_SN, 0x1, 3, TREG_SN, 1,
+  { "mulhh_su.sn", TILEPRO_OPC_MULHH_SU_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhh_uu", TILE_OPC_MULHH_UU, 0x5, 3, TREG_ZERO, 1,
+  { "mulhh_uu", TILEPRO_OPC_MULHH_UU, 0x5, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 11, 12, 18 }, { 0, }, { 0, } },
   },
-  { "mulhh_uu.sn", TILE_OPC_MULHH_UU_SN, 0x1, 3, TREG_SN, 1,
+  { "mulhh_uu.sn", TILEPRO_OPC_MULHH_UU_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhha_ss", TILE_OPC_MULHHA_SS, 0x5, 3, TREG_ZERO, 1,
+  { "mulhha_ss", TILEPRO_OPC_MULHHA_SS, 0x5, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 31, 12, 18 }, { 0, }, { 0, } },
   },
-  { "mulhha_ss.sn", TILE_OPC_MULHHA_SS_SN, 0x1, 3, TREG_SN, 1,
+  { "mulhha_ss.sn", TILEPRO_OPC_MULHHA_SS_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhha_su", TILE_OPC_MULHHA_SU, 0x1, 3, TREG_ZERO, 1,
+  { "mulhha_su", TILEPRO_OPC_MULHHA_SU, 0x1, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhha_su.sn", TILE_OPC_MULHHA_SU_SN, 0x1, 3, TREG_SN, 1,
+  { "mulhha_su.sn", TILEPRO_OPC_MULHHA_SU_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhha_uu", TILE_OPC_MULHHA_UU, 0x5, 3, TREG_ZERO, 1,
+  { "mulhha_uu", TILEPRO_OPC_MULHHA_UU, 0x5, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 31, 12, 18 }, { 0, }, { 0, } },
   },
-  { "mulhha_uu.sn", TILE_OPC_MULHHA_UU_SN, 0x1, 3, TREG_SN, 1,
+  { "mulhha_uu.sn", TILEPRO_OPC_MULHHA_UU_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhhsa_uu", TILE_OPC_MULHHSA_UU, 0x1, 3, TREG_ZERO, 1,
+  { "mulhhsa_uu", TILEPRO_OPC_MULHHSA_UU, 0x1, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhhsa_uu.sn", TILE_OPC_MULHHSA_UU_SN, 0x1, 3, TREG_SN, 1,
+  { "mulhhsa_uu.sn", TILEPRO_OPC_MULHHSA_UU_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhl_ss", TILE_OPC_MULHL_SS, 0x1, 3, TREG_ZERO, 1,
+  { "mulhl_ss", TILEPRO_OPC_MULHL_SS, 0x1, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhl_ss.sn", TILE_OPC_MULHL_SS_SN, 0x1, 3, TREG_SN, 1,
+  { "mulhl_ss.sn", TILEPRO_OPC_MULHL_SS_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhl_su", TILE_OPC_MULHL_SU, 0x1, 3, TREG_ZERO, 1,
+  { "mulhl_su", TILEPRO_OPC_MULHL_SU, 0x1, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhl_su.sn", TILE_OPC_MULHL_SU_SN, 0x1, 3, TREG_SN, 1,
+  { "mulhl_su.sn", TILEPRO_OPC_MULHL_SU_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhl_us", TILE_OPC_MULHL_US, 0x1, 3, TREG_ZERO, 1,
+  { "mulhl_us", TILEPRO_OPC_MULHL_US, 0x1, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhl_us.sn", TILE_OPC_MULHL_US_SN, 0x1, 3, TREG_SN, 1,
+  { "mulhl_us.sn", TILEPRO_OPC_MULHL_US_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhl_uu", TILE_OPC_MULHL_UU, 0x1, 3, TREG_ZERO, 1,
+  { "mulhl_uu", TILEPRO_OPC_MULHL_UU, 0x1, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhl_uu.sn", TILE_OPC_MULHL_UU_SN, 0x1, 3, TREG_SN, 1,
+  { "mulhl_uu.sn", TILEPRO_OPC_MULHL_UU_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhla_ss", TILE_OPC_MULHLA_SS, 0x1, 3, TREG_ZERO, 1,
+  { "mulhla_ss", TILEPRO_OPC_MULHLA_SS, 0x1, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhla_ss.sn", TILE_OPC_MULHLA_SS_SN, 0x1, 3, TREG_SN, 1,
+  { "mulhla_ss.sn", TILEPRO_OPC_MULHLA_SS_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhla_su", TILE_OPC_MULHLA_SU, 0x1, 3, TREG_ZERO, 1,
+  { "mulhla_su", TILEPRO_OPC_MULHLA_SU, 0x1, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhla_su.sn", TILE_OPC_MULHLA_SU_SN, 0x1, 3, TREG_SN, 1,
+  { "mulhla_su.sn", TILEPRO_OPC_MULHLA_SU_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhla_us", TILE_OPC_MULHLA_US, 0x1, 3, TREG_ZERO, 1,
+  { "mulhla_us", TILEPRO_OPC_MULHLA_US, 0x1, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhla_us.sn", TILE_OPC_MULHLA_US_SN, 0x1, 3, TREG_SN, 1,
+  { "mulhla_us.sn", TILEPRO_OPC_MULHLA_US_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhla_uu", TILE_OPC_MULHLA_UU, 0x1, 3, TREG_ZERO, 1,
+  { "mulhla_uu", TILEPRO_OPC_MULHLA_UU, 0x1, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhla_uu.sn", TILE_OPC_MULHLA_UU_SN, 0x1, 3, TREG_SN, 1,
+  { "mulhla_uu.sn", TILEPRO_OPC_MULHLA_UU_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulhlsa_uu", TILE_OPC_MULHLSA_UU, 0x5, 3, TREG_ZERO, 1,
+  { "mulhlsa_uu", TILEPRO_OPC_MULHLSA_UU, 0x5, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 31, 12, 18 }, { 0, }, { 0, } },
   },
-  { "mulhlsa_uu.sn", TILE_OPC_MULHLSA_UU_SN, 0x1, 3, TREG_SN, 1,
+  { "mulhlsa_uu.sn", TILEPRO_OPC_MULHLSA_UU_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulll_ss", TILE_OPC_MULLL_SS, 0x5, 3, TREG_ZERO, 1,
+  { "mulll_ss", TILEPRO_OPC_MULLL_SS, 0x5, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 11, 12, 18 }, { 0, }, { 0, } },
   },
-  { "mulll_ss.sn", TILE_OPC_MULLL_SS_SN, 0x1, 3, TREG_SN, 1,
+  { "mulll_ss.sn", TILEPRO_OPC_MULLL_SS_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulll_su", TILE_OPC_MULLL_SU, 0x1, 3, TREG_ZERO, 1,
+  { "mulll_su", TILEPRO_OPC_MULLL_SU, 0x1, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulll_su.sn", TILE_OPC_MULLL_SU_SN, 0x1, 3, TREG_SN, 1,
+  { "mulll_su.sn", TILEPRO_OPC_MULLL_SU_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulll_uu", TILE_OPC_MULLL_UU, 0x5, 3, TREG_ZERO, 1,
+  { "mulll_uu", TILEPRO_OPC_MULLL_UU, 0x5, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 11, 12, 18 }, { 0, }, { 0, } },
   },
-  { "mulll_uu.sn", TILE_OPC_MULLL_UU_SN, 0x1, 3, TREG_SN, 1,
+  { "mulll_uu.sn", TILEPRO_OPC_MULLL_UU_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mullla_ss", TILE_OPC_MULLLA_SS, 0x5, 3, TREG_ZERO, 1,
+  { "mullla_ss", TILEPRO_OPC_MULLLA_SS, 0x5, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 31, 12, 18 }, { 0, }, { 0, } },
   },
-  { "mullla_ss.sn", TILE_OPC_MULLLA_SS_SN, 0x1, 3, TREG_SN, 1,
+  { "mullla_ss.sn", TILEPRO_OPC_MULLLA_SS_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mullla_su", TILE_OPC_MULLLA_SU, 0x1, 3, TREG_ZERO, 1,
+  { "mullla_su", TILEPRO_OPC_MULLLA_SU, 0x1, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mullla_su.sn", TILE_OPC_MULLLA_SU_SN, 0x1, 3, TREG_SN, 1,
+  { "mullla_su.sn", TILEPRO_OPC_MULLLA_SU_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mullla_uu", TILE_OPC_MULLLA_UU, 0x5, 3, TREG_ZERO, 1,
+  { "mullla_uu", TILEPRO_OPC_MULLLA_UU, 0x5, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 31, 12, 18 }, { 0, }, { 0, } },
   },
-  { "mullla_uu.sn", TILE_OPC_MULLLA_UU_SN, 0x1, 3, TREG_SN, 1,
+  { "mullla_uu.sn", TILEPRO_OPC_MULLLA_UU_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulllsa_uu", TILE_OPC_MULLLSA_UU, 0x1, 3, TREG_ZERO, 1,
+  { "mulllsa_uu", TILEPRO_OPC_MULLLSA_UU, 0x1, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mulllsa_uu.sn", TILE_OPC_MULLLSA_UU_SN, 0x1, 3, TREG_SN, 1,
+  { "mulllsa_uu.sn", TILEPRO_OPC_MULLLSA_UU_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mvnz", TILE_OPC_MVNZ, 0x5, 3, TREG_ZERO, 1,
+  { "mvnz", TILEPRO_OPC_MVNZ, 0x5, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 31, 12, 18 }, { 0, }, { 0, } },
   },
-  { "mvnz.sn", TILE_OPC_MVNZ_SN, 0x1, 3, TREG_SN, 1,
+  { "mvnz.sn", TILEPRO_OPC_MVNZ_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mvz", TILE_OPC_MVZ, 0x5, 3, TREG_ZERO, 1,
+  { "mvz", TILEPRO_OPC_MVZ, 0x5, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 31, 12, 18 }, { 0, }, { 0, } },
   },
-  { "mvz.sn", TILE_OPC_MVZ_SN, 0x1, 3, TREG_SN, 1,
+  { "mvz.sn", TILEPRO_OPC_MVZ_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "mz", TILE_OPC_MZ, 0xf, 3, TREG_ZERO, 1,
+  { "mz", TILEPRO_OPC_MZ, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "mz.sn", TILE_OPC_MZ_SN, 0x3, 3, TREG_SN, 1,
+  { "mz.sn", TILEPRO_OPC_MZ_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "mzb", TILE_OPC_MZB, 0x3, 3, TREG_ZERO, 1,
+  { "mzb", TILEPRO_OPC_MZB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "mzb.sn", TILE_OPC_MZB_SN, 0x3, 3, TREG_SN, 1,
+  { "mzb.sn", TILEPRO_OPC_MZB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "mzh", TILE_OPC_MZH, 0x3, 3, TREG_ZERO, 1,
+  { "mzh", TILEPRO_OPC_MZH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "mzh.sn", TILE_OPC_MZH_SN, 0x3, 3, TREG_SN, 1,
+  { "mzh.sn", TILEPRO_OPC_MZH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "nap", TILE_OPC_NAP, 0x2, 0, TREG_ZERO, 0,
+  { "nap", TILEPRO_OPC_NAP, 0x2, 0, TREG_ZERO, 0,
     { { 0, }, {  }, { 0, }, { 0, }, { 0, } },
   },
-  { "nop", TILE_OPC_NOP, 0xf, 0, TREG_ZERO, 1,
+  { "nop", TILEPRO_OPC_NOP, 0xf, 0, TREG_ZERO, 1,
     { {  }, {  }, {  }, {  }, { 0, } },
   },
-  { "nor", TILE_OPC_NOR, 0xf, 3, TREG_ZERO, 1,
+  { "nor", TILEPRO_OPC_NOR, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "nor.sn", TILE_OPC_NOR_SN, 0x3, 3, TREG_SN, 1,
+  { "nor.sn", TILEPRO_OPC_NOR_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "or", TILE_OPC_OR, 0xf, 3, TREG_ZERO, 1,
+  { "or", TILEPRO_OPC_OR, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "or.sn", TILE_OPC_OR_SN, 0x3, 3, TREG_SN, 1,
+  { "or.sn", TILEPRO_OPC_OR_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "ori", TILE_OPC_ORI, 0xf, 3, TREG_ZERO, 1,
+  { "ori", TILEPRO_OPC_ORI, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 11, 12, 2 }, { 13, 14, 3 }, { 0, } },
   },
-  { "ori.sn", TILE_OPC_ORI_SN, 0x3, 3, TREG_SN, 1,
+  { "ori.sn", TILEPRO_OPC_ORI_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "packbs_u", TILE_OPC_PACKBS_U, 0x3, 3, TREG_ZERO, 1,
+  { "packbs_u", TILEPRO_OPC_PACKBS_U, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "packbs_u.sn", TILE_OPC_PACKBS_U_SN, 0x3, 3, TREG_SN, 1,
+  { "packbs_u.sn", TILEPRO_OPC_PACKBS_U_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "packhb", TILE_OPC_PACKHB, 0x3, 3, TREG_ZERO, 1,
+  { "packhb", TILEPRO_OPC_PACKHB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "packhb.sn", TILE_OPC_PACKHB_SN, 0x3, 3, TREG_SN, 1,
+  { "packhb.sn", TILEPRO_OPC_PACKHB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "packhs", TILE_OPC_PACKHS, 0x3, 3, TREG_ZERO, 1,
+  { "packhs", TILEPRO_OPC_PACKHS, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "packhs.sn", TILE_OPC_PACKHS_SN, 0x3, 3, TREG_SN, 1,
+  { "packhs.sn", TILEPRO_OPC_PACKHS_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "packlb", TILE_OPC_PACKLB, 0x3, 3, TREG_ZERO, 1,
+  { "packlb", TILEPRO_OPC_PACKLB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "packlb.sn", TILE_OPC_PACKLB_SN, 0x3, 3, TREG_SN, 1,
+  { "packlb.sn", TILEPRO_OPC_PACKLB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "pcnt", TILE_OPC_PCNT, 0x5, 2, TREG_ZERO, 1,
+  { "pcnt", TILEPRO_OPC_PCNT, 0x5, 2, TREG_ZERO, 1,
     { { 7, 8 }, { 0, }, { 11, 12 }, { 0, }, { 0, } },
   },
-  { "pcnt.sn", TILE_OPC_PCNT_SN, 0x1, 2, TREG_SN, 1,
+  { "pcnt.sn", TILEPRO_OPC_PCNT_SN, 0x1, 2, TREG_SN, 1,
     { { 7, 8 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "rl", TILE_OPC_RL, 0xf, 3, TREG_ZERO, 1,
+  { "rl", TILEPRO_OPC_RL, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "rl.sn", TILE_OPC_RL_SN, 0x3, 3, TREG_SN, 1,
+  { "rl.sn", TILEPRO_OPC_RL_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "rli", TILE_OPC_RLI, 0xf, 3, TREG_ZERO, 1,
+  { "rli", TILEPRO_OPC_RLI, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 11, 12, 34 }, { 13, 14, 35 }, { 0, } },
   },
-  { "rli.sn", TILE_OPC_RLI_SN, 0x3, 3, TREG_SN, 1,
+  { "rli.sn", TILEPRO_OPC_RLI_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 0, }, { 0, }, { 0, } },
   },
-  { "s1a", TILE_OPC_S1A, 0xf, 3, TREG_ZERO, 1,
+  { "s1a", TILEPRO_OPC_S1A, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "s1a.sn", TILE_OPC_S1A_SN, 0x3, 3, TREG_SN, 1,
+  { "s1a.sn", TILEPRO_OPC_S1A_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "s2a", TILE_OPC_S2A, 0xf, 3, TREG_ZERO, 1,
+  { "s2a", TILEPRO_OPC_S2A, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "s2a.sn", TILE_OPC_S2A_SN, 0x3, 3, TREG_SN, 1,
+  { "s2a.sn", TILEPRO_OPC_S2A_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "s3a", TILE_OPC_S3A, 0xf, 3, TREG_ZERO, 1,
+  { "s3a", TILEPRO_OPC_S3A, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "s3a.sn", TILE_OPC_S3A_SN, 0x3, 3, TREG_SN, 1,
+  { "s3a.sn", TILEPRO_OPC_S3A_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sadab_u", TILE_OPC_SADAB_U, 0x1, 3, TREG_ZERO, 1,
+  { "sadab_u", TILEPRO_OPC_SADAB_U, 0x1, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "sadab_u.sn", TILE_OPC_SADAB_U_SN, 0x1, 3, TREG_SN, 1,
+  { "sadab_u.sn", TILEPRO_OPC_SADAB_U_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "sadah", TILE_OPC_SADAH, 0x1, 3, TREG_ZERO, 1,
+  { "sadah", TILEPRO_OPC_SADAH, 0x1, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "sadah.sn", TILE_OPC_SADAH_SN, 0x1, 3, TREG_SN, 1,
+  { "sadah.sn", TILEPRO_OPC_SADAH_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "sadah_u", TILE_OPC_SADAH_U, 0x1, 3, TREG_ZERO, 1,
+  { "sadah_u", TILEPRO_OPC_SADAH_U, 0x1, 3, TREG_ZERO, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "sadah_u.sn", TILE_OPC_SADAH_U_SN, 0x1, 3, TREG_SN, 1,
+  { "sadah_u.sn", TILEPRO_OPC_SADAH_U_SN, 0x1, 3, TREG_SN, 1,
     { { 21, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "sadb_u", TILE_OPC_SADB_U, 0x1, 3, TREG_ZERO, 1,
+  { "sadb_u", TILEPRO_OPC_SADB_U, 0x1, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "sadb_u.sn", TILE_OPC_SADB_U_SN, 0x1, 3, TREG_SN, 1,
+  { "sadb_u.sn", TILEPRO_OPC_SADB_U_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "sadh", TILE_OPC_SADH, 0x1, 3, TREG_ZERO, 1,
+  { "sadh", TILEPRO_OPC_SADH, 0x1, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "sadh.sn", TILE_OPC_SADH_SN, 0x1, 3, TREG_SN, 1,
+  { "sadh.sn", TILEPRO_OPC_SADH_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "sadh_u", TILE_OPC_SADH_U, 0x1, 3, TREG_ZERO, 1,
+  { "sadh_u", TILEPRO_OPC_SADH_U, 0x1, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "sadh_u.sn", TILE_OPC_SADH_U_SN, 0x1, 3, TREG_SN, 1,
+  { "sadh_u.sn", TILEPRO_OPC_SADH_U_SN, 0x1, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "sb", TILE_OPC_SB, 0x12, 2, TREG_ZERO, 1,
+  { "sb", TILEPRO_OPC_SB, 0x12, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 17 }, { 0, }, { 0, }, { 15, 36 } },
   },
-  { "sbadd", TILE_OPC_SBADD, 0x2, 3, TREG_ZERO, 1,
+  { "sbadd", TILEPRO_OPC_SBADD, 0x2, 3, TREG_ZERO, 1,
     { { 0, }, { 24, 17, 37 }, { 0, }, { 0, }, { 0, } },
   },
-  { "seq", TILE_OPC_SEQ, 0xf, 3, TREG_ZERO, 1,
+  { "seq", TILEPRO_OPC_SEQ, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "seq.sn", TILE_OPC_SEQ_SN, 0x3, 3, TREG_SN, 1,
+  { "seq.sn", TILEPRO_OPC_SEQ_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "seqb", TILE_OPC_SEQB, 0x3, 3, TREG_ZERO, 1,
+  { "seqb", TILEPRO_OPC_SEQB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "seqb.sn", TILE_OPC_SEQB_SN, 0x3, 3, TREG_SN, 1,
+  { "seqb.sn", TILEPRO_OPC_SEQB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "seqh", TILE_OPC_SEQH, 0x3, 3, TREG_ZERO, 1,
+  { "seqh", TILEPRO_OPC_SEQH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "seqh.sn", TILE_OPC_SEQH_SN, 0x3, 3, TREG_SN, 1,
+  { "seqh.sn", TILEPRO_OPC_SEQH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "seqi", TILE_OPC_SEQI, 0xf, 3, TREG_ZERO, 1,
+  { "seqi", TILEPRO_OPC_SEQI, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 11, 12, 2 }, { 13, 14, 3 }, { 0, } },
   },
-  { "seqi.sn", TILE_OPC_SEQI_SN, 0x3, 3, TREG_SN, 1,
+  { "seqi.sn", TILEPRO_OPC_SEQI_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "seqib", TILE_OPC_SEQIB, 0x3, 3, TREG_ZERO, 1,
+  { "seqib", TILEPRO_OPC_SEQIB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "seqib.sn", TILE_OPC_SEQIB_SN, 0x3, 3, TREG_SN, 1,
+  { "seqib.sn", TILEPRO_OPC_SEQIB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "seqih", TILE_OPC_SEQIH, 0x3, 3, TREG_ZERO, 1,
+  { "seqih", TILEPRO_OPC_SEQIH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "seqih.sn", TILE_OPC_SEQIH_SN, 0x3, 3, TREG_SN, 1,
+  { "seqih.sn", TILEPRO_OPC_SEQIH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sh", TILE_OPC_SH, 0x12, 2, TREG_ZERO, 1,
+  { "sh", TILEPRO_OPC_SH, 0x12, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 17 }, { 0, }, { 0, }, { 15, 36 } },
   },
-  { "shadd", TILE_OPC_SHADD, 0x2, 3, TREG_ZERO, 1,
+  { "shadd", TILEPRO_OPC_SHADD, 0x2, 3, TREG_ZERO, 1,
     { { 0, }, { 24, 17, 37 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shl", TILE_OPC_SHL, 0xf, 3, TREG_ZERO, 1,
+  { "shl", TILEPRO_OPC_SHL, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "shl.sn", TILE_OPC_SHL_SN, 0x3, 3, TREG_SN, 1,
+  { "shl.sn", TILEPRO_OPC_SHL_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shlb", TILE_OPC_SHLB, 0x3, 3, TREG_ZERO, 1,
+  { "shlb", TILEPRO_OPC_SHLB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shlb.sn", TILE_OPC_SHLB_SN, 0x3, 3, TREG_SN, 1,
+  { "shlb.sn", TILEPRO_OPC_SHLB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shlh", TILE_OPC_SHLH, 0x3, 3, TREG_ZERO, 1,
+  { "shlh", TILEPRO_OPC_SHLH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shlh.sn", TILE_OPC_SHLH_SN, 0x3, 3, TREG_SN, 1,
+  { "shlh.sn", TILEPRO_OPC_SHLH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shli", TILE_OPC_SHLI, 0xf, 3, TREG_ZERO, 1,
+  { "shli", TILEPRO_OPC_SHLI, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 11, 12, 34 }, { 13, 14, 35 }, { 0, } },
   },
-  { "shli.sn", TILE_OPC_SHLI_SN, 0x3, 3, TREG_SN, 1,
+  { "shli.sn", TILEPRO_OPC_SHLI_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shlib", TILE_OPC_SHLIB, 0x3, 3, TREG_ZERO, 1,
+  { "shlib", TILEPRO_OPC_SHLIB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shlib.sn", TILE_OPC_SHLIB_SN, 0x3, 3, TREG_SN, 1,
+  { "shlib.sn", TILEPRO_OPC_SHLIB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shlih", TILE_OPC_SHLIH, 0x3, 3, TREG_ZERO, 1,
+  { "shlih", TILEPRO_OPC_SHLIH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shlih.sn", TILE_OPC_SHLIH_SN, 0x3, 3, TREG_SN, 1,
+  { "shlih.sn", TILEPRO_OPC_SHLIH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shr", TILE_OPC_SHR, 0xf, 3, TREG_ZERO, 1,
+  { "shr", TILEPRO_OPC_SHR, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "shr.sn", TILE_OPC_SHR_SN, 0x3, 3, TREG_SN, 1,
+  { "shr.sn", TILEPRO_OPC_SHR_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shrb", TILE_OPC_SHRB, 0x3, 3, TREG_ZERO, 1,
+  { "shrb", TILEPRO_OPC_SHRB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shrb.sn", TILE_OPC_SHRB_SN, 0x3, 3, TREG_SN, 1,
+  { "shrb.sn", TILEPRO_OPC_SHRB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shrh", TILE_OPC_SHRH, 0x3, 3, TREG_ZERO, 1,
+  { "shrh", TILEPRO_OPC_SHRH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shrh.sn", TILE_OPC_SHRH_SN, 0x3, 3, TREG_SN, 1,
+  { "shrh.sn", TILEPRO_OPC_SHRH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shri", TILE_OPC_SHRI, 0xf, 3, TREG_ZERO, 1,
+  { "shri", TILEPRO_OPC_SHRI, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 11, 12, 34 }, { 13, 14, 35 }, { 0, } },
   },
-  { "shri.sn", TILE_OPC_SHRI_SN, 0x3, 3, TREG_SN, 1,
+  { "shri.sn", TILEPRO_OPC_SHRI_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shrib", TILE_OPC_SHRIB, 0x3, 3, TREG_ZERO, 1,
+  { "shrib", TILEPRO_OPC_SHRIB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shrib.sn", TILE_OPC_SHRIB_SN, 0x3, 3, TREG_SN, 1,
+  { "shrib.sn", TILEPRO_OPC_SHRIB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shrih", TILE_OPC_SHRIH, 0x3, 3, TREG_ZERO, 1,
+  { "shrih", TILEPRO_OPC_SHRIH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 0, }, { 0, }, { 0, } },
   },
-  { "shrih.sn", TILE_OPC_SHRIH_SN, 0x3, 3, TREG_SN, 1,
+  { "shrih.sn", TILEPRO_OPC_SHRIH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slt", TILE_OPC_SLT, 0xf, 3, TREG_ZERO, 1,
+  { "slt", TILEPRO_OPC_SLT, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "slt.sn", TILE_OPC_SLT_SN, 0x3, 3, TREG_SN, 1,
+  { "slt.sn", TILEPRO_OPC_SLT_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slt_u", TILE_OPC_SLT_U, 0xf, 3, TREG_ZERO, 1,
+  { "slt_u", TILEPRO_OPC_SLT_U, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "slt_u.sn", TILE_OPC_SLT_U_SN, 0x3, 3, TREG_SN, 1,
+  { "slt_u.sn", TILEPRO_OPC_SLT_U_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sltb", TILE_OPC_SLTB, 0x3, 3, TREG_ZERO, 1,
+  { "sltb", TILEPRO_OPC_SLTB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sltb.sn", TILE_OPC_SLTB_SN, 0x3, 3, TREG_SN, 1,
+  { "sltb.sn", TILEPRO_OPC_SLTB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sltb_u", TILE_OPC_SLTB_U, 0x3, 3, TREG_ZERO, 1,
+  { "sltb_u", TILEPRO_OPC_SLTB_U, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sltb_u.sn", TILE_OPC_SLTB_U_SN, 0x3, 3, TREG_SN, 1,
+  { "sltb_u.sn", TILEPRO_OPC_SLTB_U_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slte", TILE_OPC_SLTE, 0xf, 3, TREG_ZERO, 1,
+  { "slte", TILEPRO_OPC_SLTE, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "slte.sn", TILE_OPC_SLTE_SN, 0x3, 3, TREG_SN, 1,
+  { "slte.sn", TILEPRO_OPC_SLTE_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slte_u", TILE_OPC_SLTE_U, 0xf, 3, TREG_ZERO, 1,
+  { "slte_u", TILEPRO_OPC_SLTE_U, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "slte_u.sn", TILE_OPC_SLTE_U_SN, 0x3, 3, TREG_SN, 1,
+  { "slte_u.sn", TILEPRO_OPC_SLTE_U_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slteb", TILE_OPC_SLTEB, 0x3, 3, TREG_ZERO, 1,
+  { "slteb", TILEPRO_OPC_SLTEB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slteb.sn", TILE_OPC_SLTEB_SN, 0x3, 3, TREG_SN, 1,
+  { "slteb.sn", TILEPRO_OPC_SLTEB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slteb_u", TILE_OPC_SLTEB_U, 0x3, 3, TREG_ZERO, 1,
+  { "slteb_u", TILEPRO_OPC_SLTEB_U, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slteb_u.sn", TILE_OPC_SLTEB_U_SN, 0x3, 3, TREG_SN, 1,
+  { "slteb_u.sn", TILEPRO_OPC_SLTEB_U_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slteh", TILE_OPC_SLTEH, 0x3, 3, TREG_ZERO, 1,
+  { "slteh", TILEPRO_OPC_SLTEH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slteh.sn", TILE_OPC_SLTEH_SN, 0x3, 3, TREG_SN, 1,
+  { "slteh.sn", TILEPRO_OPC_SLTEH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slteh_u", TILE_OPC_SLTEH_U, 0x3, 3, TREG_ZERO, 1,
+  { "slteh_u", TILEPRO_OPC_SLTEH_U, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slteh_u.sn", TILE_OPC_SLTEH_U_SN, 0x3, 3, TREG_SN, 1,
+  { "slteh_u.sn", TILEPRO_OPC_SLTEH_U_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slth", TILE_OPC_SLTH, 0x3, 3, TREG_ZERO, 1,
+  { "slth", TILEPRO_OPC_SLTH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slth.sn", TILE_OPC_SLTH_SN, 0x3, 3, TREG_SN, 1,
+  { "slth.sn", TILEPRO_OPC_SLTH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slth_u", TILE_OPC_SLTH_U, 0x3, 3, TREG_ZERO, 1,
+  { "slth_u", TILEPRO_OPC_SLTH_U, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slth_u.sn", TILE_OPC_SLTH_U_SN, 0x3, 3, TREG_SN, 1,
+  { "slth_u.sn", TILEPRO_OPC_SLTH_U_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slti", TILE_OPC_SLTI, 0xf, 3, TREG_ZERO, 1,
+  { "slti", TILEPRO_OPC_SLTI, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 11, 12, 2 }, { 13, 14, 3 }, { 0, } },
   },
-  { "slti.sn", TILE_OPC_SLTI_SN, 0x3, 3, TREG_SN, 1,
+  { "slti.sn", TILEPRO_OPC_SLTI_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "slti_u", TILE_OPC_SLTI_U, 0xf, 3, TREG_ZERO, 1,
+  { "slti_u", TILEPRO_OPC_SLTI_U, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 11, 12, 2 }, { 13, 14, 3 }, { 0, } },
   },
-  { "slti_u.sn", TILE_OPC_SLTI_U_SN, 0x3, 3, TREG_SN, 1,
+  { "slti_u.sn", TILEPRO_OPC_SLTI_U_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sltib", TILE_OPC_SLTIB, 0x3, 3, TREG_ZERO, 1,
+  { "sltib", TILEPRO_OPC_SLTIB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sltib.sn", TILE_OPC_SLTIB_SN, 0x3, 3, TREG_SN, 1,
+  { "sltib.sn", TILEPRO_OPC_SLTIB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sltib_u", TILE_OPC_SLTIB_U, 0x3, 3, TREG_ZERO, 1,
+  { "sltib_u", TILEPRO_OPC_SLTIB_U, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sltib_u.sn", TILE_OPC_SLTIB_U_SN, 0x3, 3, TREG_SN, 1,
+  { "sltib_u.sn", TILEPRO_OPC_SLTIB_U_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sltih", TILE_OPC_SLTIH, 0x3, 3, TREG_ZERO, 1,
+  { "sltih", TILEPRO_OPC_SLTIH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sltih.sn", TILE_OPC_SLTIH_SN, 0x3, 3, TREG_SN, 1,
+  { "sltih.sn", TILEPRO_OPC_SLTIH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sltih_u", TILE_OPC_SLTIH_U, 0x3, 3, TREG_ZERO, 1,
+  { "sltih_u", TILEPRO_OPC_SLTIH_U, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sltih_u.sn", TILE_OPC_SLTIH_U_SN, 0x3, 3, TREG_SN, 1,
+  { "sltih_u.sn", TILEPRO_OPC_SLTIH_U_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sne", TILE_OPC_SNE, 0xf, 3, TREG_ZERO, 1,
+  { "sne", TILEPRO_OPC_SNE, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "sne.sn", TILE_OPC_SNE_SN, 0x3, 3, TREG_SN, 1,
+  { "sne.sn", TILEPRO_OPC_SNE_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sneb", TILE_OPC_SNEB, 0x3, 3, TREG_ZERO, 1,
+  { "sneb", TILEPRO_OPC_SNEB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sneb.sn", TILE_OPC_SNEB_SN, 0x3, 3, TREG_SN, 1,
+  { "sneb.sn", TILEPRO_OPC_SNEB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sneh", TILE_OPC_SNEH, 0x3, 3, TREG_ZERO, 1,
+  { "sneh", TILEPRO_OPC_SNEH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sneh.sn", TILE_OPC_SNEH_SN, 0x3, 3, TREG_SN, 1,
+  { "sneh.sn", TILEPRO_OPC_SNEH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sra", TILE_OPC_SRA, 0xf, 3, TREG_ZERO, 1,
+  { "sra", TILEPRO_OPC_SRA, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "sra.sn", TILE_OPC_SRA_SN, 0x3, 3, TREG_SN, 1,
+  { "sra.sn", TILEPRO_OPC_SRA_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "srab", TILE_OPC_SRAB, 0x3, 3, TREG_ZERO, 1,
+  { "srab", TILEPRO_OPC_SRAB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "srab.sn", TILE_OPC_SRAB_SN, 0x3, 3, TREG_SN, 1,
+  { "srab.sn", TILEPRO_OPC_SRAB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "srah", TILE_OPC_SRAH, 0x3, 3, TREG_ZERO, 1,
+  { "srah", TILEPRO_OPC_SRAH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "srah.sn", TILE_OPC_SRAH_SN, 0x3, 3, TREG_SN, 1,
+  { "srah.sn", TILEPRO_OPC_SRAH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "srai", TILE_OPC_SRAI, 0xf, 3, TREG_ZERO, 1,
+  { "srai", TILEPRO_OPC_SRAI, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 11, 12, 34 }, { 13, 14, 35 }, { 0, } },
   },
-  { "srai.sn", TILE_OPC_SRAI_SN, 0x3, 3, TREG_SN, 1,
+  { "srai.sn", TILEPRO_OPC_SRAI_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sraib", TILE_OPC_SRAIB, 0x3, 3, TREG_ZERO, 1,
+  { "sraib", TILEPRO_OPC_SRAIB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sraib.sn", TILE_OPC_SRAIB_SN, 0x3, 3, TREG_SN, 1,
+  { "sraib.sn", TILEPRO_OPC_SRAIB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sraih", TILE_OPC_SRAIH, 0x3, 3, TREG_ZERO, 1,
+  { "sraih", TILEPRO_OPC_SRAIH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sraih.sn", TILE_OPC_SRAIH_SN, 0x3, 3, TREG_SN, 1,
+  { "sraih.sn", TILEPRO_OPC_SRAIH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 32 }, { 9, 10, 33 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sub", TILE_OPC_SUB, 0xf, 3, TREG_ZERO, 1,
+  { "sub", TILEPRO_OPC_SUB, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "sub.sn", TILE_OPC_SUB_SN, 0x3, 3, TREG_SN, 1,
+  { "sub.sn", TILEPRO_OPC_SUB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "subb", TILE_OPC_SUBB, 0x3, 3, TREG_ZERO, 1,
+  { "subb", TILEPRO_OPC_SUBB, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "subb.sn", TILE_OPC_SUBB_SN, 0x3, 3, TREG_SN, 1,
+  { "subb.sn", TILEPRO_OPC_SUBB_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "subbs_u", TILE_OPC_SUBBS_U, 0x3, 3, TREG_ZERO, 1,
+  { "subbs_u", TILEPRO_OPC_SUBBS_U, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "subbs_u.sn", TILE_OPC_SUBBS_U_SN, 0x3, 3, TREG_SN, 1,
+  { "subbs_u.sn", TILEPRO_OPC_SUBBS_U_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "subh", TILE_OPC_SUBH, 0x3, 3, TREG_ZERO, 1,
+  { "subh", TILEPRO_OPC_SUBH, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "subh.sn", TILE_OPC_SUBH_SN, 0x3, 3, TREG_SN, 1,
+  { "subh.sn", TILEPRO_OPC_SUBH_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "subhs", TILE_OPC_SUBHS, 0x3, 3, TREG_ZERO, 1,
+  { "subhs", TILEPRO_OPC_SUBHS, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "subhs.sn", TILE_OPC_SUBHS_SN, 0x3, 3, TREG_SN, 1,
+  { "subhs.sn", TILEPRO_OPC_SUBHS_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "subs", TILE_OPC_SUBS, 0x3, 3, TREG_ZERO, 1,
+  { "subs", TILEPRO_OPC_SUBS, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "subs.sn", TILE_OPC_SUBS_SN, 0x3, 3, TREG_SN, 1,
+  { "subs.sn", TILEPRO_OPC_SUBS_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "sw", TILE_OPC_SW, 0x12, 2, TREG_ZERO, 1,
+  { "sw", TILEPRO_OPC_SW, 0x12, 2, TREG_ZERO, 1,
     { { 0, }, { 10, 17 }, { 0, }, { 0, }, { 15, 36 } },
   },
-  { "swadd", TILE_OPC_SWADD, 0x2, 3, TREG_ZERO, 1,
+  { "swadd", TILEPRO_OPC_SWADD, 0x2, 3, TREG_ZERO, 1,
     { { 0, }, { 24, 17, 37 }, { 0, }, { 0, }, { 0, } },
   },
-  { "swint0", TILE_OPC_SWINT0, 0x2, 0, TREG_ZERO, 0,
+  { "swint0", TILEPRO_OPC_SWINT0, 0x2, 0, TREG_ZERO, 0,
     { { 0, }, {  }, { 0, }, { 0, }, { 0, } },
   },
-  { "swint1", TILE_OPC_SWINT1, 0x2, 0, TREG_ZERO, 0,
+  { "swint1", TILEPRO_OPC_SWINT1, 0x2, 0, TREG_ZERO, 0,
     { { 0, }, {  }, { 0, }, { 0, }, { 0, } },
   },
-  { "swint2", TILE_OPC_SWINT2, 0x2, 0, TREG_ZERO, 0,
+  { "swint2", TILEPRO_OPC_SWINT2, 0x2, 0, TREG_ZERO, 0,
     { { 0, }, {  }, { 0, }, { 0, }, { 0, } },
   },
-  { "swint3", TILE_OPC_SWINT3, 0x2, 0, TREG_ZERO, 0,
+  { "swint3", TILEPRO_OPC_SWINT3, 0x2, 0, TREG_ZERO, 0,
     { { 0, }, {  }, { 0, }, { 0, }, { 0, } },
   },
-  { "tblidxb0", TILE_OPC_TBLIDXB0, 0x5, 2, TREG_ZERO, 1,
+  { "tblidxb0", TILEPRO_OPC_TBLIDXB0, 0x5, 2, TREG_ZERO, 1,
     { { 21, 8 }, { 0, }, { 31, 12 }, { 0, }, { 0, } },
   },
-  { "tblidxb0.sn", TILE_OPC_TBLIDXB0_SN, 0x1, 2, TREG_SN, 1,
+  { "tblidxb0.sn", TILEPRO_OPC_TBLIDXB0_SN, 0x1, 2, TREG_SN, 1,
     { { 21, 8 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "tblidxb1", TILE_OPC_TBLIDXB1, 0x5, 2, TREG_ZERO, 1,
+  { "tblidxb1", TILEPRO_OPC_TBLIDXB1, 0x5, 2, TREG_ZERO, 1,
     { { 21, 8 }, { 0, }, { 31, 12 }, { 0, }, { 0, } },
   },
-  { "tblidxb1.sn", TILE_OPC_TBLIDXB1_SN, 0x1, 2, TREG_SN, 1,
+  { "tblidxb1.sn", TILEPRO_OPC_TBLIDXB1_SN, 0x1, 2, TREG_SN, 1,
     { { 21, 8 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "tblidxb2", TILE_OPC_TBLIDXB2, 0x5, 2, TREG_ZERO, 1,
+  { "tblidxb2", TILEPRO_OPC_TBLIDXB2, 0x5, 2, TREG_ZERO, 1,
     { { 21, 8 }, { 0, }, { 31, 12 }, { 0, }, { 0, } },
   },
-  { "tblidxb2.sn", TILE_OPC_TBLIDXB2_SN, 0x1, 2, TREG_SN, 1,
+  { "tblidxb2.sn", TILEPRO_OPC_TBLIDXB2_SN, 0x1, 2, TREG_SN, 1,
     { { 21, 8 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "tblidxb3", TILE_OPC_TBLIDXB3, 0x5, 2, TREG_ZERO, 1,
+  { "tblidxb3", TILEPRO_OPC_TBLIDXB3, 0x5, 2, TREG_ZERO, 1,
     { { 21, 8 }, { 0, }, { 31, 12 }, { 0, }, { 0, } },
   },
-  { "tblidxb3.sn", TILE_OPC_TBLIDXB3_SN, 0x1, 2, TREG_SN, 1,
+  { "tblidxb3.sn", TILEPRO_OPC_TBLIDXB3_SN, 0x1, 2, TREG_SN, 1,
     { { 21, 8 }, { 0, }, { 0, }, { 0, }, { 0, } },
   },
-  { "tns", TILE_OPC_TNS, 0x2, 2, TREG_ZERO, 1,
+  { "tns", TILEPRO_OPC_TNS, 0x2, 2, TREG_ZERO, 1,
     { { 0, }, { 9, 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "tns.sn", TILE_OPC_TNS_SN, 0x2, 2, TREG_SN, 1,
+  { "tns.sn", TILEPRO_OPC_TNS_SN, 0x2, 2, TREG_SN, 1,
     { { 0, }, { 9, 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "wh64", TILE_OPC_WH64, 0x2, 1, TREG_ZERO, 1,
+  { "wh64", TILEPRO_OPC_WH64, 0x2, 1, TREG_ZERO, 1,
     { { 0, }, { 10 }, { 0, }, { 0, }, { 0, } },
   },
-  { "xor", TILE_OPC_XOR, 0xf, 3, TREG_ZERO, 1,
+  { "xor", TILEPRO_OPC_XOR, 0xf, 3, TREG_ZERO, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 11, 12, 18 }, { 13, 14, 19 }, { 0, } },
   },
-  { "xor.sn", TILE_OPC_XOR_SN, 0x3, 3, TREG_SN, 1,
+  { "xor.sn", TILEPRO_OPC_XOR_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 16 }, { 9, 10, 17 }, { 0, }, { 0, }, { 0, } },
   },
-  { "xori", TILE_OPC_XORI, 0x3, 3, TREG_ZERO, 1,
+  { "xori", TILEPRO_OPC_XORI, 0x3, 3, TREG_ZERO, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { "xori.sn", TILE_OPC_XORI_SN, 0x3, 3, TREG_SN, 1,
+  { "xori.sn", TILEPRO_OPC_XORI_SN, 0x3, 3, TREG_SN, 1,
     { { 7, 8, 0 }, { 9, 10, 1 }, { 0, }, { 0, }, { 0, } },
   },
-  { NULL, TILE_OPC_NONE, 0, 0, TREG_ZERO, 0, { { 0, } },
+  { NULL, TILEPRO_OPC_NONE, 0, 0, TREG_ZERO, 0, { { 0, } },
   }
 };
 #define BITFIELD(start, size) ((start) | (((1 << (size)) - 1) << 6))
-#define CHILD(array_index) (TILE_OPC_NONE + (array_index))
+#define CHILD(array_index) (TILEPRO_OPC_NONE + (array_index))
 
 static const unsigned short decode_X0_fsm[1153] =
 {
   BITFIELD(22, 9) /* index 0 */,
   CHILD(513), CHILD(530), CHILD(547), CHILD(564), CHILD(596), CHILD(613),
-  CHILD(630), TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, CHILD(663), CHILD(680), CHILD(697), CHILD(714), CHILD(746),
-  CHILD(763), CHILD(780), TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, CHILD(813), CHILD(813), CHILD(813),
+  CHILD(630), TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, CHILD(663), CHILD(680), CHILD(697),
+  CHILD(714), CHILD(746), CHILD(763), CHILD(780), TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813),
   CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813),
   CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813),
@@ -1227,7 +1247,8 @@ static const unsigned short decode_X0_fsm[1153] =
   CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813),
   CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813),
   CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(813),
-  CHILD(813), CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828),
+  CHILD(813), CHILD(813), CHILD(813), CHILD(813), CHILD(828), CHILD(828),
+  CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828),
   CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828),
   CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828),
   CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828),
@@ -1237,7 +1258,7 @@ static const unsigned short decode_X0_fsm[1153] =
   CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828),
   CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828),
   CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828),
-  CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(828), CHILD(843),
+  CHILD(828), CHILD(828), CHILD(843), CHILD(843), CHILD(843), CHILD(843),
   CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843),
   CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843),
   CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843),
@@ -1248,333 +1269,371 @@ static const unsigned short decode_X0_fsm[1153] =
   CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843),
   CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843),
   CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843),
-  CHILD(843), CHILD(843), CHILD(843), CHILD(873), CHILD(878), CHILD(883),
-  CHILD(903), CHILD(908), TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, CHILD(913),
-  CHILD(918), CHILD(923), CHILD(943), CHILD(948), TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, CHILD(953), TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, CHILD(988), TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, CHILD(993),
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, CHILD(1076), TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
+  CHILD(873), CHILD(878), CHILD(883), CHILD(903), CHILD(908),
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, CHILD(913),
+  CHILD(918), CHILD(923), CHILD(943), CHILD(948), TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, CHILD(953), TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, CHILD(988), TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, CHILD(993), TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, CHILD(1076), TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   BITFIELD(18, 4) /* index 513 */,
-  TILE_OPC_NONE, TILE_OPC_ADDB, TILE_OPC_ADDH, TILE_OPC_ADD,
-  TILE_OPC_ADIFFB_U, TILE_OPC_ADIFFH, TILE_OPC_AND, TILE_OPC_AVGB_U,
-  TILE_OPC_AVGH, TILE_OPC_CRC32_32, TILE_OPC_CRC32_8, TILE_OPC_INTHB,
-  TILE_OPC_INTHH, TILE_OPC_INTLB, TILE_OPC_INTLH, TILE_OPC_MAXB_U,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_ADDB, TILEPRO_OPC_ADDH, TILEPRO_OPC_ADD,
+  TILEPRO_OPC_ADIFFB_U, TILEPRO_OPC_ADIFFH, TILEPRO_OPC_AND,
+  TILEPRO_OPC_AVGB_U, TILEPRO_OPC_AVGH, TILEPRO_OPC_CRC32_32,
+  TILEPRO_OPC_CRC32_8, TILEPRO_OPC_INTHB, TILEPRO_OPC_INTHH,
+  TILEPRO_OPC_INTLB, TILEPRO_OPC_INTLH, TILEPRO_OPC_MAXB_U,
   BITFIELD(18, 4) /* index 530 */,
-  TILE_OPC_MAXH, TILE_OPC_MINB_U, TILE_OPC_MINH, TILE_OPC_MNZB, TILE_OPC_MNZH,
-  TILE_OPC_MNZ, TILE_OPC_MULHHA_SS, TILE_OPC_MULHHA_SU, TILE_OPC_MULHHA_UU,
-  TILE_OPC_MULHHSA_UU, TILE_OPC_MULHH_SS, TILE_OPC_MULHH_SU,
-  TILE_OPC_MULHH_UU, TILE_OPC_MULHLA_SS, TILE_OPC_MULHLA_SU,
-  TILE_OPC_MULHLA_US,
+  TILEPRO_OPC_MAXH, TILEPRO_OPC_MINB_U, TILEPRO_OPC_MINH, TILEPRO_OPC_MNZB,
+  TILEPRO_OPC_MNZH, TILEPRO_OPC_MNZ, TILEPRO_OPC_MULHHA_SS,
+  TILEPRO_OPC_MULHHA_SU, TILEPRO_OPC_MULHHA_UU, TILEPRO_OPC_MULHHSA_UU,
+  TILEPRO_OPC_MULHH_SS, TILEPRO_OPC_MULHH_SU, TILEPRO_OPC_MULHH_UU,
+  TILEPRO_OPC_MULHLA_SS, TILEPRO_OPC_MULHLA_SU, TILEPRO_OPC_MULHLA_US,
   BITFIELD(18, 4) /* index 547 */,
-  TILE_OPC_MULHLA_UU, TILE_OPC_MULHLSA_UU, TILE_OPC_MULHL_SS,
-  TILE_OPC_MULHL_SU, TILE_OPC_MULHL_US, TILE_OPC_MULHL_UU, TILE_OPC_MULLLA_SS,
-  TILE_OPC_MULLLA_SU, TILE_OPC_MULLLA_UU, TILE_OPC_MULLLSA_UU,
-  TILE_OPC_MULLL_SS, TILE_OPC_MULLL_SU, TILE_OPC_MULLL_UU, TILE_OPC_MVNZ,
-  TILE_OPC_MVZ, TILE_OPC_MZB,
+  TILEPRO_OPC_MULHLA_UU, TILEPRO_OPC_MULHLSA_UU, TILEPRO_OPC_MULHL_SS,
+  TILEPRO_OPC_MULHL_SU, TILEPRO_OPC_MULHL_US, TILEPRO_OPC_MULHL_UU,
+  TILEPRO_OPC_MULLLA_SS, TILEPRO_OPC_MULLLA_SU, TILEPRO_OPC_MULLLA_UU,
+  TILEPRO_OPC_MULLLSA_UU, TILEPRO_OPC_MULLL_SS, TILEPRO_OPC_MULLL_SU,
+  TILEPRO_OPC_MULLL_UU, TILEPRO_OPC_MVNZ, TILEPRO_OPC_MVZ, TILEPRO_OPC_MZB,
   BITFIELD(18, 4) /* index 564 */,
-  TILE_OPC_MZH, TILE_OPC_MZ, TILE_OPC_NOR, CHILD(581), TILE_OPC_PACKHB,
-  TILE_OPC_PACKLB, TILE_OPC_RL, TILE_OPC_S1A, TILE_OPC_S2A, TILE_OPC_S3A,
-  TILE_OPC_SADAB_U, TILE_OPC_SADAH, TILE_OPC_SADAH_U, TILE_OPC_SADB_U,
-  TILE_OPC_SADH, TILE_OPC_SADH_U,
+  TILEPRO_OPC_MZH, TILEPRO_OPC_MZ, TILEPRO_OPC_NOR, CHILD(581),
+  TILEPRO_OPC_PACKHB, TILEPRO_OPC_PACKLB, TILEPRO_OPC_RL, TILEPRO_OPC_S1A,
+  TILEPRO_OPC_S2A, TILEPRO_OPC_S3A, TILEPRO_OPC_SADAB_U, TILEPRO_OPC_SADAH,
+  TILEPRO_OPC_SADAH_U, TILEPRO_OPC_SADB_U, TILEPRO_OPC_SADH,
+  TILEPRO_OPC_SADH_U,
   BITFIELD(12, 2) /* index 581 */,
-  TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_OR, CHILD(586),
+  TILEPRO_OPC_OR, TILEPRO_OPC_OR, TILEPRO_OPC_OR, CHILD(586),
   BITFIELD(14, 2) /* index 586 */,
-  TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_OR, CHILD(591),
+  TILEPRO_OPC_OR, TILEPRO_OPC_OR, TILEPRO_OPC_OR, CHILD(591),
   BITFIELD(16, 2) /* index 591 */,
-  TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_MOVE,
+  TILEPRO_OPC_OR, TILEPRO_OPC_OR, TILEPRO_OPC_OR, TILEPRO_OPC_MOVE,
   BITFIELD(18, 4) /* index 596 */,
-  TILE_OPC_SEQB, TILE_OPC_SEQH, TILE_OPC_SEQ, TILE_OPC_SHLB, TILE_OPC_SHLH,
-  TILE_OPC_SHL, TILE_OPC_SHRB, TILE_OPC_SHRH, TILE_OPC_SHR, TILE_OPC_SLTB,
-  TILE_OPC_SLTB_U, TILE_OPC_SLTEB, TILE_OPC_SLTEB_U, TILE_OPC_SLTEH,
-  TILE_OPC_SLTEH_U, TILE_OPC_SLTE,
+  TILEPRO_OPC_SEQB, TILEPRO_OPC_SEQH, TILEPRO_OPC_SEQ, TILEPRO_OPC_SHLB,
+  TILEPRO_OPC_SHLH, TILEPRO_OPC_SHL, TILEPRO_OPC_SHRB, TILEPRO_OPC_SHRH,
+  TILEPRO_OPC_SHR, TILEPRO_OPC_SLTB, TILEPRO_OPC_SLTB_U, TILEPRO_OPC_SLTEB,
+  TILEPRO_OPC_SLTEB_U, TILEPRO_OPC_SLTEH, TILEPRO_OPC_SLTEH_U,
+  TILEPRO_OPC_SLTE,
   BITFIELD(18, 4) /* index 613 */,
-  TILE_OPC_SLTE_U, TILE_OPC_SLTH, TILE_OPC_SLTH_U, TILE_OPC_SLT,
-  TILE_OPC_SLT_U, TILE_OPC_SNEB, TILE_OPC_SNEH, TILE_OPC_SNE, TILE_OPC_SRAB,
-  TILE_OPC_SRAH, TILE_OPC_SRA, TILE_OPC_SUBB, TILE_OPC_SUBH, TILE_OPC_SUB,
-  TILE_OPC_XOR, TILE_OPC_DWORD_ALIGN,
+  TILEPRO_OPC_SLTE_U, TILEPRO_OPC_SLTH, TILEPRO_OPC_SLTH_U, TILEPRO_OPC_SLT,
+  TILEPRO_OPC_SLT_U, TILEPRO_OPC_SNEB, TILEPRO_OPC_SNEH, TILEPRO_OPC_SNE,
+  TILEPRO_OPC_SRAB, TILEPRO_OPC_SRAH, TILEPRO_OPC_SRA, TILEPRO_OPC_SUBB,
+  TILEPRO_OPC_SUBH, TILEPRO_OPC_SUB, TILEPRO_OPC_XOR, TILEPRO_OPC_DWORD_ALIGN,
   BITFIELD(18, 3) /* index 630 */,
   CHILD(639), CHILD(642), CHILD(645), CHILD(648), CHILD(651), CHILD(654),
   CHILD(657), CHILD(660),
   BITFIELD(21, 1) /* index 639 */,
-  TILE_OPC_ADDS, TILE_OPC_NONE,
+  TILEPRO_OPC_ADDS, TILEPRO_OPC_NONE,
   BITFIELD(21, 1) /* index 642 */,
-  TILE_OPC_SUBS, TILE_OPC_NONE,
+  TILEPRO_OPC_SUBS, TILEPRO_OPC_NONE,
   BITFIELD(21, 1) /* index 645 */,
-  TILE_OPC_ADDBS_U, TILE_OPC_NONE,
+  TILEPRO_OPC_ADDBS_U, TILEPRO_OPC_NONE,
   BITFIELD(21, 1) /* index 648 */,
-  TILE_OPC_ADDHS, TILE_OPC_NONE,
+  TILEPRO_OPC_ADDHS, TILEPRO_OPC_NONE,
   BITFIELD(21, 1) /* index 651 */,
-  TILE_OPC_SUBBS_U, TILE_OPC_NONE,
+  TILEPRO_OPC_SUBBS_U, TILEPRO_OPC_NONE,
   BITFIELD(21, 1) /* index 654 */,
-  TILE_OPC_SUBHS, TILE_OPC_NONE,
+  TILEPRO_OPC_SUBHS, TILEPRO_OPC_NONE,
   BITFIELD(21, 1) /* index 657 */,
-  TILE_OPC_PACKHS, TILE_OPC_NONE,
+  TILEPRO_OPC_PACKHS, TILEPRO_OPC_NONE,
   BITFIELD(21, 1) /* index 660 */,
-  TILE_OPC_PACKBS_U, TILE_OPC_NONE,
+  TILEPRO_OPC_PACKBS_U, TILEPRO_OPC_NONE,
   BITFIELD(18, 4) /* index 663 */,
-  TILE_OPC_NONE, TILE_OPC_ADDB_SN, TILE_OPC_ADDH_SN, TILE_OPC_ADD_SN,
-  TILE_OPC_ADIFFB_U_SN, TILE_OPC_ADIFFH_SN, TILE_OPC_AND_SN,
-  TILE_OPC_AVGB_U_SN, TILE_OPC_AVGH_SN, TILE_OPC_CRC32_32_SN,
-  TILE_OPC_CRC32_8_SN, TILE_OPC_INTHB_SN, TILE_OPC_INTHH_SN,
-  TILE_OPC_INTLB_SN, TILE_OPC_INTLH_SN, TILE_OPC_MAXB_U_SN,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_ADDB_SN, TILEPRO_OPC_ADDH_SN,
+  TILEPRO_OPC_ADD_SN, TILEPRO_OPC_ADIFFB_U_SN, TILEPRO_OPC_ADIFFH_SN,
+  TILEPRO_OPC_AND_SN, TILEPRO_OPC_AVGB_U_SN, TILEPRO_OPC_AVGH_SN,
+  TILEPRO_OPC_CRC32_32_SN, TILEPRO_OPC_CRC32_8_SN, TILEPRO_OPC_INTHB_SN,
+  TILEPRO_OPC_INTHH_SN, TILEPRO_OPC_INTLB_SN, TILEPRO_OPC_INTLH_SN,
+  TILEPRO_OPC_MAXB_U_SN,
   BITFIELD(18, 4) /* index 680 */,
-  TILE_OPC_MAXH_SN, TILE_OPC_MINB_U_SN, TILE_OPC_MINH_SN, TILE_OPC_MNZB_SN,
-  TILE_OPC_MNZH_SN, TILE_OPC_MNZ_SN, TILE_OPC_MULHHA_SS_SN,
-  TILE_OPC_MULHHA_SU_SN, TILE_OPC_MULHHA_UU_SN, TILE_OPC_MULHHSA_UU_SN,
-  TILE_OPC_MULHH_SS_SN, TILE_OPC_MULHH_SU_SN, TILE_OPC_MULHH_UU_SN,
-  TILE_OPC_MULHLA_SS_SN, TILE_OPC_MULHLA_SU_SN, TILE_OPC_MULHLA_US_SN,
+  TILEPRO_OPC_MAXH_SN, TILEPRO_OPC_MINB_U_SN, TILEPRO_OPC_MINH_SN,
+  TILEPRO_OPC_MNZB_SN, TILEPRO_OPC_MNZH_SN, TILEPRO_OPC_MNZ_SN,
+  TILEPRO_OPC_MULHHA_SS_SN, TILEPRO_OPC_MULHHA_SU_SN,
+  TILEPRO_OPC_MULHHA_UU_SN, TILEPRO_OPC_MULHHSA_UU_SN,
+  TILEPRO_OPC_MULHH_SS_SN, TILEPRO_OPC_MULHH_SU_SN, TILEPRO_OPC_MULHH_UU_SN,
+  TILEPRO_OPC_MULHLA_SS_SN, TILEPRO_OPC_MULHLA_SU_SN,
+  TILEPRO_OPC_MULHLA_US_SN,
   BITFIELD(18, 4) /* index 697 */,
-  TILE_OPC_MULHLA_UU_SN, TILE_OPC_MULHLSA_UU_SN, TILE_OPC_MULHL_SS_SN,
-  TILE_OPC_MULHL_SU_SN, TILE_OPC_MULHL_US_SN, TILE_OPC_MULHL_UU_SN,
-  TILE_OPC_MULLLA_SS_SN, TILE_OPC_MULLLA_SU_SN, TILE_OPC_MULLLA_UU_SN,
-  TILE_OPC_MULLLSA_UU_SN, TILE_OPC_MULLL_SS_SN, TILE_OPC_MULLL_SU_SN,
-  TILE_OPC_MULLL_UU_SN, TILE_OPC_MVNZ_SN, TILE_OPC_MVZ_SN, TILE_OPC_MZB_SN,
+  TILEPRO_OPC_MULHLA_UU_SN, TILEPRO_OPC_MULHLSA_UU_SN,
+  TILEPRO_OPC_MULHL_SS_SN, TILEPRO_OPC_MULHL_SU_SN, TILEPRO_OPC_MULHL_US_SN,
+  TILEPRO_OPC_MULHL_UU_SN, TILEPRO_OPC_MULLLA_SS_SN, TILEPRO_OPC_MULLLA_SU_SN,
+  TILEPRO_OPC_MULLLA_UU_SN, TILEPRO_OPC_MULLLSA_UU_SN,
+  TILEPRO_OPC_MULLL_SS_SN, TILEPRO_OPC_MULLL_SU_SN, TILEPRO_OPC_MULLL_UU_SN,
+  TILEPRO_OPC_MVNZ_SN, TILEPRO_OPC_MVZ_SN, TILEPRO_OPC_MZB_SN,
   BITFIELD(18, 4) /* index 714 */,
-  TILE_OPC_MZH_SN, TILE_OPC_MZ_SN, TILE_OPC_NOR_SN, CHILD(731),
-  TILE_OPC_PACKHB_SN, TILE_OPC_PACKLB_SN, TILE_OPC_RL_SN, TILE_OPC_S1A_SN,
-  TILE_OPC_S2A_SN, TILE_OPC_S3A_SN, TILE_OPC_SADAB_U_SN, TILE_OPC_SADAH_SN,
-  TILE_OPC_SADAH_U_SN, TILE_OPC_SADB_U_SN, TILE_OPC_SADH_SN,
-  TILE_OPC_SADH_U_SN,
+  TILEPRO_OPC_MZH_SN, TILEPRO_OPC_MZ_SN, TILEPRO_OPC_NOR_SN, CHILD(731),
+  TILEPRO_OPC_PACKHB_SN, TILEPRO_OPC_PACKLB_SN, TILEPRO_OPC_RL_SN,
+  TILEPRO_OPC_S1A_SN, TILEPRO_OPC_S2A_SN, TILEPRO_OPC_S3A_SN,
+  TILEPRO_OPC_SADAB_U_SN, TILEPRO_OPC_SADAH_SN, TILEPRO_OPC_SADAH_U_SN,
+  TILEPRO_OPC_SADB_U_SN, TILEPRO_OPC_SADH_SN, TILEPRO_OPC_SADH_U_SN,
   BITFIELD(12, 2) /* index 731 */,
-  TILE_OPC_OR_SN, TILE_OPC_OR_SN, TILE_OPC_OR_SN, CHILD(736),
+  TILEPRO_OPC_OR_SN, TILEPRO_OPC_OR_SN, TILEPRO_OPC_OR_SN, CHILD(736),
   BITFIELD(14, 2) /* index 736 */,
-  TILE_OPC_OR_SN, TILE_OPC_OR_SN, TILE_OPC_OR_SN, CHILD(741),
+  TILEPRO_OPC_OR_SN, TILEPRO_OPC_OR_SN, TILEPRO_OPC_OR_SN, CHILD(741),
   BITFIELD(16, 2) /* index 741 */,
-  TILE_OPC_OR_SN, TILE_OPC_OR_SN, TILE_OPC_OR_SN, TILE_OPC_MOVE_SN,
+  TILEPRO_OPC_OR_SN, TILEPRO_OPC_OR_SN, TILEPRO_OPC_OR_SN,
+  TILEPRO_OPC_MOVE_SN,
   BITFIELD(18, 4) /* index 746 */,
-  TILE_OPC_SEQB_SN, TILE_OPC_SEQH_SN, TILE_OPC_SEQ_SN, TILE_OPC_SHLB_SN,
-  TILE_OPC_SHLH_SN, TILE_OPC_SHL_SN, TILE_OPC_SHRB_SN, TILE_OPC_SHRH_SN,
-  TILE_OPC_SHR_SN, TILE_OPC_SLTB_SN, TILE_OPC_SLTB_U_SN, TILE_OPC_SLTEB_SN,
-  TILE_OPC_SLTEB_U_SN, TILE_OPC_SLTEH_SN, TILE_OPC_SLTEH_U_SN,
-  TILE_OPC_SLTE_SN,
+  TILEPRO_OPC_SEQB_SN, TILEPRO_OPC_SEQH_SN, TILEPRO_OPC_SEQ_SN,
+  TILEPRO_OPC_SHLB_SN, TILEPRO_OPC_SHLH_SN, TILEPRO_OPC_SHL_SN,
+  TILEPRO_OPC_SHRB_SN, TILEPRO_OPC_SHRH_SN, TILEPRO_OPC_SHR_SN,
+  TILEPRO_OPC_SLTB_SN, TILEPRO_OPC_SLTB_U_SN, TILEPRO_OPC_SLTEB_SN,
+  TILEPRO_OPC_SLTEB_U_SN, TILEPRO_OPC_SLTEH_SN, TILEPRO_OPC_SLTEH_U_SN,
+  TILEPRO_OPC_SLTE_SN,
   BITFIELD(18, 4) /* index 763 */,
-  TILE_OPC_SLTE_U_SN, TILE_OPC_SLTH_SN, TILE_OPC_SLTH_U_SN, TILE_OPC_SLT_SN,
-  TILE_OPC_SLT_U_SN, TILE_OPC_SNEB_SN, TILE_OPC_SNEH_SN, TILE_OPC_SNE_SN,
-  TILE_OPC_SRAB_SN, TILE_OPC_SRAH_SN, TILE_OPC_SRA_SN, TILE_OPC_SUBB_SN,
-  TILE_OPC_SUBH_SN, TILE_OPC_SUB_SN, TILE_OPC_XOR_SN, TILE_OPC_DWORD_ALIGN_SN,
+  TILEPRO_OPC_SLTE_U_SN, TILEPRO_OPC_SLTH_SN, TILEPRO_OPC_SLTH_U_SN,
+  TILEPRO_OPC_SLT_SN, TILEPRO_OPC_SLT_U_SN, TILEPRO_OPC_SNEB_SN,
+  TILEPRO_OPC_SNEH_SN, TILEPRO_OPC_SNE_SN, TILEPRO_OPC_SRAB_SN,
+  TILEPRO_OPC_SRAH_SN, TILEPRO_OPC_SRA_SN, TILEPRO_OPC_SUBB_SN,
+  TILEPRO_OPC_SUBH_SN, TILEPRO_OPC_SUB_SN, TILEPRO_OPC_XOR_SN,
+  TILEPRO_OPC_DWORD_ALIGN_SN,
   BITFIELD(18, 3) /* index 780 */,
   CHILD(789), CHILD(792), CHILD(795), CHILD(798), CHILD(801), CHILD(804),
   CHILD(807), CHILD(810),
   BITFIELD(21, 1) /* index 789 */,
-  TILE_OPC_ADDS_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_ADDS_SN, TILEPRO_OPC_NONE,
   BITFIELD(21, 1) /* index 792 */,
-  TILE_OPC_SUBS_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_SUBS_SN, TILEPRO_OPC_NONE,
   BITFIELD(21, 1) /* index 795 */,
-  TILE_OPC_ADDBS_U_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_ADDBS_U_SN, TILEPRO_OPC_NONE,
   BITFIELD(21, 1) /* index 798 */,
-  TILE_OPC_ADDHS_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_ADDHS_SN, TILEPRO_OPC_NONE,
   BITFIELD(21, 1) /* index 801 */,
-  TILE_OPC_SUBBS_U_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_SUBBS_U_SN, TILEPRO_OPC_NONE,
   BITFIELD(21, 1) /* index 804 */,
-  TILE_OPC_SUBHS_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_SUBHS_SN, TILEPRO_OPC_NONE,
   BITFIELD(21, 1) /* index 807 */,
-  TILE_OPC_PACKHS_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_PACKHS_SN, TILEPRO_OPC_NONE,
   BITFIELD(21, 1) /* index 810 */,
-  TILE_OPC_PACKBS_U_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_PACKBS_U_SN, TILEPRO_OPC_NONE,
   BITFIELD(6, 2) /* index 813 */,
-  TILE_OPC_ADDLI_SN, TILE_OPC_ADDLI_SN, TILE_OPC_ADDLI_SN, CHILD(818),
+  TILEPRO_OPC_ADDLI_SN, TILEPRO_OPC_ADDLI_SN, TILEPRO_OPC_ADDLI_SN,
+  CHILD(818),
   BITFIELD(8, 2) /* index 818 */,
-  TILE_OPC_ADDLI_SN, TILE_OPC_ADDLI_SN, TILE_OPC_ADDLI_SN, CHILD(823),
+  TILEPRO_OPC_ADDLI_SN, TILEPRO_OPC_ADDLI_SN, TILEPRO_OPC_ADDLI_SN,
+  CHILD(823),
   BITFIELD(10, 2) /* index 823 */,
-  TILE_OPC_ADDLI_SN, TILE_OPC_ADDLI_SN, TILE_OPC_ADDLI_SN, TILE_OPC_MOVELI_SN,
+  TILEPRO_OPC_ADDLI_SN, TILEPRO_OPC_ADDLI_SN, TILEPRO_OPC_ADDLI_SN,
+  TILEPRO_OPC_MOVELI_SN,
   BITFIELD(6, 2) /* index 828 */,
-  TILE_OPC_ADDLI, TILE_OPC_ADDLI, TILE_OPC_ADDLI, CHILD(833),
+  TILEPRO_OPC_ADDLI, TILEPRO_OPC_ADDLI, TILEPRO_OPC_ADDLI, CHILD(833),
   BITFIELD(8, 2) /* index 833 */,
-  TILE_OPC_ADDLI, TILE_OPC_ADDLI, TILE_OPC_ADDLI, CHILD(838),
+  TILEPRO_OPC_ADDLI, TILEPRO_OPC_ADDLI, TILEPRO_OPC_ADDLI, CHILD(838),
   BITFIELD(10, 2) /* index 838 */,
-  TILE_OPC_ADDLI, TILE_OPC_ADDLI, TILE_OPC_ADDLI, TILE_OPC_MOVELI,
+  TILEPRO_OPC_ADDLI, TILEPRO_OPC_ADDLI, TILEPRO_OPC_ADDLI, TILEPRO_OPC_MOVELI,
   BITFIELD(0, 2) /* index 843 */,
-  TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_AULI, CHILD(848),
+  TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, CHILD(848),
   BITFIELD(2, 2) /* index 848 */,
-  TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_AULI, CHILD(853),
+  TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, CHILD(853),
   BITFIELD(4, 2) /* index 853 */,
-  TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_AULI, CHILD(858),
+  TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, CHILD(858),
   BITFIELD(6, 2) /* index 858 */,
-  TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_AULI, CHILD(863),
+  TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, CHILD(863),
   BITFIELD(8, 2) /* index 863 */,
-  TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_AULI, CHILD(868),
+  TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, CHILD(868),
   BITFIELD(10, 2) /* index 868 */,
-  TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_INFOL,
+  TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, TILEPRO_OPC_INFOL,
   BITFIELD(20, 2) /* index 873 */,
-  TILE_OPC_NONE, TILE_OPC_ADDIB, TILE_OPC_ADDIH, TILE_OPC_ADDI,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_ADDIB, TILEPRO_OPC_ADDIH, TILEPRO_OPC_ADDI,
   BITFIELD(20, 2) /* index 878 */,
-  TILE_OPC_MAXIB_U, TILE_OPC_MAXIH, TILE_OPC_MINIB_U, TILE_OPC_MINIH,
+  TILEPRO_OPC_MAXIB_U, TILEPRO_OPC_MAXIH, TILEPRO_OPC_MINIB_U,
+  TILEPRO_OPC_MINIH,
   BITFIELD(20, 2) /* index 883 */,
-  CHILD(888), TILE_OPC_SEQIB, TILE_OPC_SEQIH, TILE_OPC_SEQI,
+  CHILD(888), TILEPRO_OPC_SEQIB, TILEPRO_OPC_SEQIH, TILEPRO_OPC_SEQI,
   BITFIELD(6, 2) /* index 888 */,
-  TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_ORI, CHILD(893),
+  TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, CHILD(893),
   BITFIELD(8, 2) /* index 893 */,
-  TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_ORI, CHILD(898),
+  TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, CHILD(898),
   BITFIELD(10, 2) /* index 898 */,
-  TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_MOVEI,
+  TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, TILEPRO_OPC_MOVEI,
   BITFIELD(20, 2) /* index 903 */,
-  TILE_OPC_SLTIB, TILE_OPC_SLTIB_U, TILE_OPC_SLTIH, TILE_OPC_SLTIH_U,
+  TILEPRO_OPC_SLTIB, TILEPRO_OPC_SLTIB_U, TILEPRO_OPC_SLTIH,
+  TILEPRO_OPC_SLTIH_U,
   BITFIELD(20, 2) /* index 908 */,
-  TILE_OPC_SLTI, TILE_OPC_SLTI_U, TILE_OPC_NONE, TILE_OPC_NONE,
+  TILEPRO_OPC_SLTI, TILEPRO_OPC_SLTI_U, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   BITFIELD(20, 2) /* index 913 */,
-  TILE_OPC_NONE, TILE_OPC_ADDIB_SN, TILE_OPC_ADDIH_SN, TILE_OPC_ADDI_SN,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_ADDIB_SN, TILEPRO_OPC_ADDIH_SN,
+  TILEPRO_OPC_ADDI_SN,
   BITFIELD(20, 2) /* index 918 */,
-  TILE_OPC_MAXIB_U_SN, TILE_OPC_MAXIH_SN, TILE_OPC_MINIB_U_SN,
-  TILE_OPC_MINIH_SN,
+  TILEPRO_OPC_MAXIB_U_SN, TILEPRO_OPC_MAXIH_SN, TILEPRO_OPC_MINIB_U_SN,
+  TILEPRO_OPC_MINIH_SN,
   BITFIELD(20, 2) /* index 923 */,
-  CHILD(928), TILE_OPC_SEQIB_SN, TILE_OPC_SEQIH_SN, TILE_OPC_SEQI_SN,
+  CHILD(928), TILEPRO_OPC_SEQIB_SN, TILEPRO_OPC_SEQIH_SN, TILEPRO_OPC_SEQI_SN,
   BITFIELD(6, 2) /* index 928 */,
-  TILE_OPC_ORI_SN, TILE_OPC_ORI_SN, TILE_OPC_ORI_SN, CHILD(933),
+  TILEPRO_OPC_ORI_SN, TILEPRO_OPC_ORI_SN, TILEPRO_OPC_ORI_SN, CHILD(933),
   BITFIELD(8, 2) /* index 933 */,
-  TILE_OPC_ORI_SN, TILE_OPC_ORI_SN, TILE_OPC_ORI_SN, CHILD(938),
+  TILEPRO_OPC_ORI_SN, TILEPRO_OPC_ORI_SN, TILEPRO_OPC_ORI_SN, CHILD(938),
   BITFIELD(10, 2) /* index 938 */,
-  TILE_OPC_ORI_SN, TILE_OPC_ORI_SN, TILE_OPC_ORI_SN, TILE_OPC_MOVEI_SN,
+  TILEPRO_OPC_ORI_SN, TILEPRO_OPC_ORI_SN, TILEPRO_OPC_ORI_SN,
+  TILEPRO_OPC_MOVEI_SN,
   BITFIELD(20, 2) /* index 943 */,
-  TILE_OPC_SLTIB_SN, TILE_OPC_SLTIB_U_SN, TILE_OPC_SLTIH_SN,
-  TILE_OPC_SLTIH_U_SN,
+  TILEPRO_OPC_SLTIB_SN, TILEPRO_OPC_SLTIB_U_SN, TILEPRO_OPC_SLTIH_SN,
+  TILEPRO_OPC_SLTIH_U_SN,
   BITFIELD(20, 2) /* index 948 */,
-  TILE_OPC_SLTI_SN, TILE_OPC_SLTI_U_SN, TILE_OPC_NONE, TILE_OPC_NONE,
+  TILEPRO_OPC_SLTI_SN, TILEPRO_OPC_SLTI_U_SN, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE,
   BITFIELD(20, 2) /* index 953 */,
-  TILE_OPC_NONE, CHILD(958), TILE_OPC_XORI, TILE_OPC_NONE,
+  TILEPRO_OPC_NONE, CHILD(958), TILEPRO_OPC_XORI, TILEPRO_OPC_NONE,
   BITFIELD(0, 2) /* index 958 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(963),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(963),
   BITFIELD(2, 2) /* index 963 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(968),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(968),
   BITFIELD(4, 2) /* index 968 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(973),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(973),
   BITFIELD(6, 2) /* index 973 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(978),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(978),
   BITFIELD(8, 2) /* index 978 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(983),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(983),
   BITFIELD(10, 2) /* index 983 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_INFO,
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_INFO,
   BITFIELD(20, 2) /* index 988 */,
-  TILE_OPC_NONE, TILE_OPC_ANDI_SN, TILE_OPC_XORI_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_ANDI_SN, TILEPRO_OPC_XORI_SN,
+  TILEPRO_OPC_NONE,
   BITFIELD(17, 5) /* index 993 */,
-  TILE_OPC_NONE, TILE_OPC_RLI, TILE_OPC_SHLIB, TILE_OPC_SHLIH, TILE_OPC_SHLI,
-  TILE_OPC_SHRIB, TILE_OPC_SHRIH, TILE_OPC_SHRI, TILE_OPC_SRAIB,
-  TILE_OPC_SRAIH, TILE_OPC_SRAI, CHILD(1026), TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_RLI, TILEPRO_OPC_SHLIB, TILEPRO_OPC_SHLIH,
+  TILEPRO_OPC_SHLI, TILEPRO_OPC_SHRIB, TILEPRO_OPC_SHRIH, TILEPRO_OPC_SHRI,
+  TILEPRO_OPC_SRAIB, TILEPRO_OPC_SRAIH, TILEPRO_OPC_SRAI, CHILD(1026),
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   BITFIELD(12, 4) /* index 1026 */,
-  TILE_OPC_NONE, CHILD(1043), CHILD(1046), CHILD(1049), CHILD(1052),
+  TILEPRO_OPC_NONE, CHILD(1043), CHILD(1046), CHILD(1049), CHILD(1052),
   CHILD(1055), CHILD(1058), CHILD(1061), CHILD(1064), CHILD(1067),
-  CHILD(1070), CHILD(1073), TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE,
+  CHILD(1070), CHILD(1073), TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1043 */,
-  TILE_OPC_BITX, TILE_OPC_NONE,
+  TILEPRO_OPC_BITX, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1046 */,
-  TILE_OPC_BYTEX, TILE_OPC_NONE,
+  TILEPRO_OPC_BYTEX, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1049 */,
-  TILE_OPC_CLZ, TILE_OPC_NONE,
+  TILEPRO_OPC_CLZ, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1052 */,
-  TILE_OPC_CTZ, TILE_OPC_NONE,
+  TILEPRO_OPC_CTZ, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1055 */,
-  TILE_OPC_FNOP, TILE_OPC_NONE,
+  TILEPRO_OPC_FNOP, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1058 */,
-  TILE_OPC_NOP, TILE_OPC_NONE,
+  TILEPRO_OPC_NOP, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1061 */,
-  TILE_OPC_PCNT, TILE_OPC_NONE,
+  TILEPRO_OPC_PCNT, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1064 */,
-  TILE_OPC_TBLIDXB0, TILE_OPC_NONE,
+  TILEPRO_OPC_TBLIDXB0, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1067 */,
-  TILE_OPC_TBLIDXB1, TILE_OPC_NONE,
+  TILEPRO_OPC_TBLIDXB1, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1070 */,
-  TILE_OPC_TBLIDXB2, TILE_OPC_NONE,
+  TILEPRO_OPC_TBLIDXB2, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1073 */,
-  TILE_OPC_TBLIDXB3, TILE_OPC_NONE,
+  TILEPRO_OPC_TBLIDXB3, TILEPRO_OPC_NONE,
   BITFIELD(17, 5) /* index 1076 */,
-  TILE_OPC_NONE, TILE_OPC_RLI_SN, TILE_OPC_SHLIB_SN, TILE_OPC_SHLIH_SN,
-  TILE_OPC_SHLI_SN, TILE_OPC_SHRIB_SN, TILE_OPC_SHRIH_SN, TILE_OPC_SHRI_SN,
-  TILE_OPC_SRAIB_SN, TILE_OPC_SRAIH_SN, TILE_OPC_SRAI_SN, CHILD(1109),
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_RLI_SN, TILEPRO_OPC_SHLIB_SN,
+  TILEPRO_OPC_SHLIH_SN, TILEPRO_OPC_SHLI_SN, TILEPRO_OPC_SHRIB_SN,
+  TILEPRO_OPC_SHRIH_SN, TILEPRO_OPC_SHRI_SN, TILEPRO_OPC_SRAIB_SN,
+  TILEPRO_OPC_SRAIH_SN, TILEPRO_OPC_SRAI_SN, CHILD(1109), TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   BITFIELD(12, 4) /* index 1109 */,
-  TILE_OPC_NONE, CHILD(1126), CHILD(1129), CHILD(1132), CHILD(1135),
+  TILEPRO_OPC_NONE, CHILD(1126), CHILD(1129), CHILD(1132), CHILD(1135),
   CHILD(1055), CHILD(1058), CHILD(1138), CHILD(1141), CHILD(1144),
-  CHILD(1147), CHILD(1150), TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE,
+  CHILD(1147), CHILD(1150), TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1126 */,
-  TILE_OPC_BITX_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_BITX_SN, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1129 */,
-  TILE_OPC_BYTEX_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_BYTEX_SN, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1132 */,
-  TILE_OPC_CLZ_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_CLZ_SN, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1135 */,
-  TILE_OPC_CTZ_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_CTZ_SN, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1138 */,
-  TILE_OPC_PCNT_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_PCNT_SN, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1141 */,
-  TILE_OPC_TBLIDXB0_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_TBLIDXB0_SN, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1144 */,
-  TILE_OPC_TBLIDXB1_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_TBLIDXB1_SN, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1147 */,
-  TILE_OPC_TBLIDXB2_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_TBLIDXB2_SN, TILEPRO_OPC_NONE,
   BITFIELD(16, 1) /* index 1150 */,
-  TILE_OPC_TBLIDXB3_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_TBLIDXB3_SN, TILEPRO_OPC_NONE,
 };
 
 static const unsigned short decode_X1_fsm[1540] =
 {
   BITFIELD(54, 9) /* index 0 */,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, CHILD(513), CHILD(561), CHILD(594),
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, CHILD(641), CHILD(689),
-  CHILD(722), TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, CHILD(766),
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  CHILD(513), CHILD(561), CHILD(594), TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, CHILD(641),
+  CHILD(689), CHILD(722), TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, CHILD(766),
   CHILD(766), CHILD(766), CHILD(766), CHILD(766), CHILD(766), CHILD(766),
   CHILD(766), CHILD(766), CHILD(766), CHILD(766), CHILD(766), CHILD(766),
   CHILD(766), CHILD(766), CHILD(766), CHILD(766), CHILD(766), CHILD(766),
@@ -1596,594 +1655,641 @@ static const unsigned short decode_X1_fsm[1540] =
   CHILD(826), CHILD(826), CHILD(826), CHILD(843), CHILD(843), CHILD(843),
   CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843),
   CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843), CHILD(843),
-  CHILD(843), CHILD(860), CHILD(899), CHILD(923), CHILD(932), TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, CHILD(941), CHILD(950), CHILD(974), CHILD(983),
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM,
-  TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, TILE_OPC_MM, CHILD(992),
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  CHILD(1334), TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_J, TILE_OPC_J,
-  TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J,
-  TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J,
-  TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J,
-  TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J,
-  TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J,
-  TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J,
-  TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J,
-  TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J,
-  TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J,
-  TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J, TILE_OPC_J,
-  TILE_OPC_J, TILE_OPC_J, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL,
-  TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL,
-  TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL,
-  TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL,
-  TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL,
-  TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL,
-  TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL,
-  TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL,
-  TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL,
-  TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL,
-  TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL,
-  TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL,
-  TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL, TILE_OPC_JAL,
-  TILE_OPC_JAL, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
+  CHILD(843), CHILD(860), CHILD(899), CHILD(923), CHILD(932),
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  CHILD(941), CHILD(950), CHILD(974), CHILD(983), TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM,
+  TILEPRO_OPC_MM, TILEPRO_OPC_MM, TILEPRO_OPC_MM, CHILD(992),
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, CHILD(1334),
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_J,
+  TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J,
+  TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J,
+  TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J,
+  TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J,
+  TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J,
+  TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J,
+  TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J,
+  TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J,
+  TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J,
+  TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J,
+  TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J,
+  TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J,
+  TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_J, TILEPRO_OPC_JAL,
+  TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL,
+  TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL,
+  TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL,
+  TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL,
+  TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL,
+  TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL,
+  TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL,
+  TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL,
+  TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL,
+  TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL,
+  TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL,
+  TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL,
+  TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL,
+  TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL,
+  TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL,
+  TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_JAL, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   BITFIELD(49, 5) /* index 513 */,
-  TILE_OPC_NONE, TILE_OPC_ADDB, TILE_OPC_ADDH, TILE_OPC_ADD, TILE_OPC_AND,
-  TILE_OPC_INTHB, TILE_OPC_INTHH, TILE_OPC_INTLB, TILE_OPC_INTLH,
-  TILE_OPC_JALRP, TILE_OPC_JALR, TILE_OPC_JRP, TILE_OPC_JR, TILE_OPC_LNK,
-  TILE_OPC_MAXB_U, TILE_OPC_MAXH, TILE_OPC_MINB_U, TILE_OPC_MINH,
-  TILE_OPC_MNZB, TILE_OPC_MNZH, TILE_OPC_MNZ, TILE_OPC_MZB, TILE_OPC_MZH,
-  TILE_OPC_MZ, TILE_OPC_NOR, CHILD(546), TILE_OPC_PACKHB, TILE_OPC_PACKLB,
-  TILE_OPC_RL, TILE_OPC_S1A, TILE_OPC_S2A, TILE_OPC_S3A,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_ADDB, TILEPRO_OPC_ADDH, TILEPRO_OPC_ADD,
+  TILEPRO_OPC_AND, TILEPRO_OPC_INTHB, TILEPRO_OPC_INTHH, TILEPRO_OPC_INTLB,
+  TILEPRO_OPC_INTLH, TILEPRO_OPC_JALRP, TILEPRO_OPC_JALR, TILEPRO_OPC_JRP,
+  TILEPRO_OPC_JR, TILEPRO_OPC_LNK, TILEPRO_OPC_MAXB_U, TILEPRO_OPC_MAXH,
+  TILEPRO_OPC_MINB_U, TILEPRO_OPC_MINH, TILEPRO_OPC_MNZB, TILEPRO_OPC_MNZH,
+  TILEPRO_OPC_MNZ, TILEPRO_OPC_MZB, TILEPRO_OPC_MZH, TILEPRO_OPC_MZ,
+  TILEPRO_OPC_NOR, CHILD(546), TILEPRO_OPC_PACKHB, TILEPRO_OPC_PACKLB,
+  TILEPRO_OPC_RL, TILEPRO_OPC_S1A, TILEPRO_OPC_S2A, TILEPRO_OPC_S3A,
   BITFIELD(43, 2) /* index 546 */,
-  TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_OR, CHILD(551),
+  TILEPRO_OPC_OR, TILEPRO_OPC_OR, TILEPRO_OPC_OR, CHILD(551),
   BITFIELD(45, 2) /* index 551 */,
-  TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_OR, CHILD(556),
+  TILEPRO_OPC_OR, TILEPRO_OPC_OR, TILEPRO_OPC_OR, CHILD(556),
   BITFIELD(47, 2) /* index 556 */,
-  TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_MOVE,
+  TILEPRO_OPC_OR, TILEPRO_OPC_OR, TILEPRO_OPC_OR, TILEPRO_OPC_MOVE,
   BITFIELD(49, 5) /* index 561 */,
-  TILE_OPC_SB, TILE_OPC_SEQB, TILE_OPC_SEQH, TILE_OPC_SEQ, TILE_OPC_SHLB,
-  TILE_OPC_SHLH, TILE_OPC_SHL, TILE_OPC_SHRB, TILE_OPC_SHRH, TILE_OPC_SHR,
-  TILE_OPC_SH, TILE_OPC_SLTB, TILE_OPC_SLTB_U, TILE_OPC_SLTEB,
-  TILE_OPC_SLTEB_U, TILE_OPC_SLTEH, TILE_OPC_SLTEH_U, TILE_OPC_SLTE,
-  TILE_OPC_SLTE_U, TILE_OPC_SLTH, TILE_OPC_SLTH_U, TILE_OPC_SLT,
-  TILE_OPC_SLT_U, TILE_OPC_SNEB, TILE_OPC_SNEH, TILE_OPC_SNE, TILE_OPC_SRAB,
-  TILE_OPC_SRAH, TILE_OPC_SRA, TILE_OPC_SUBB, TILE_OPC_SUBH, TILE_OPC_SUB,
+  TILEPRO_OPC_SB, TILEPRO_OPC_SEQB, TILEPRO_OPC_SEQH, TILEPRO_OPC_SEQ,
+  TILEPRO_OPC_SHLB, TILEPRO_OPC_SHLH, TILEPRO_OPC_SHL, TILEPRO_OPC_SHRB,
+  TILEPRO_OPC_SHRH, TILEPRO_OPC_SHR, TILEPRO_OPC_SH, TILEPRO_OPC_SLTB,
+  TILEPRO_OPC_SLTB_U, TILEPRO_OPC_SLTEB, TILEPRO_OPC_SLTEB_U,
+  TILEPRO_OPC_SLTEH, TILEPRO_OPC_SLTEH_U, TILEPRO_OPC_SLTE,
+  TILEPRO_OPC_SLTE_U, TILEPRO_OPC_SLTH, TILEPRO_OPC_SLTH_U, TILEPRO_OPC_SLT,
+  TILEPRO_OPC_SLT_U, TILEPRO_OPC_SNEB, TILEPRO_OPC_SNEH, TILEPRO_OPC_SNE,
+  TILEPRO_OPC_SRAB, TILEPRO_OPC_SRAH, TILEPRO_OPC_SRA, TILEPRO_OPC_SUBB,
+  TILEPRO_OPC_SUBH, TILEPRO_OPC_SUB,
   BITFIELD(49, 4) /* index 594 */,
   CHILD(611), CHILD(614), CHILD(617), CHILD(620), CHILD(623), CHILD(626),
-  CHILD(629), CHILD(632), CHILD(635), CHILD(638), TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
+  CHILD(629), CHILD(632), CHILD(635), CHILD(638), TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 611 */,
-  TILE_OPC_SW, TILE_OPC_NONE,
+  TILEPRO_OPC_SW, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 614 */,
-  TILE_OPC_XOR, TILE_OPC_NONE,
+  TILEPRO_OPC_XOR, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 617 */,
-  TILE_OPC_ADDS, TILE_OPC_NONE,
+  TILEPRO_OPC_ADDS, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 620 */,
-  TILE_OPC_SUBS, TILE_OPC_NONE,
+  TILEPRO_OPC_SUBS, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 623 */,
-  TILE_OPC_ADDBS_U, TILE_OPC_NONE,
+  TILEPRO_OPC_ADDBS_U, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 626 */,
-  TILE_OPC_ADDHS, TILE_OPC_NONE,
+  TILEPRO_OPC_ADDHS, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 629 */,
-  TILE_OPC_SUBBS_U, TILE_OPC_NONE,
+  TILEPRO_OPC_SUBBS_U, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 632 */,
-  TILE_OPC_SUBHS, TILE_OPC_NONE,
+  TILEPRO_OPC_SUBHS, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 635 */,
-  TILE_OPC_PACKHS, TILE_OPC_NONE,
+  TILEPRO_OPC_PACKHS, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 638 */,
-  TILE_OPC_PACKBS_U, TILE_OPC_NONE,
+  TILEPRO_OPC_PACKBS_U, TILEPRO_OPC_NONE,
   BITFIELD(49, 5) /* index 641 */,
-  TILE_OPC_NONE, TILE_OPC_ADDB_SN, TILE_OPC_ADDH_SN, TILE_OPC_ADD_SN,
-  TILE_OPC_AND_SN, TILE_OPC_INTHB_SN, TILE_OPC_INTHH_SN, TILE_OPC_INTLB_SN,
-  TILE_OPC_INTLH_SN, TILE_OPC_JALRP, TILE_OPC_JALR, TILE_OPC_JRP, TILE_OPC_JR,
-  TILE_OPC_LNK_SN, TILE_OPC_MAXB_U_SN, TILE_OPC_MAXH_SN, TILE_OPC_MINB_U_SN,
-  TILE_OPC_MINH_SN, TILE_OPC_MNZB_SN, TILE_OPC_MNZH_SN, TILE_OPC_MNZ_SN,
-  TILE_OPC_MZB_SN, TILE_OPC_MZH_SN, TILE_OPC_MZ_SN, TILE_OPC_NOR_SN,
-  CHILD(674), TILE_OPC_PACKHB_SN, TILE_OPC_PACKLB_SN, TILE_OPC_RL_SN,
-  TILE_OPC_S1A_SN, TILE_OPC_S2A_SN, TILE_OPC_S3A_SN,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_ADDB_SN, TILEPRO_OPC_ADDH_SN,
+  TILEPRO_OPC_ADD_SN, TILEPRO_OPC_AND_SN, TILEPRO_OPC_INTHB_SN,
+  TILEPRO_OPC_INTHH_SN, TILEPRO_OPC_INTLB_SN, TILEPRO_OPC_INTLH_SN,
+  TILEPRO_OPC_JALRP, TILEPRO_OPC_JALR, TILEPRO_OPC_JRP, TILEPRO_OPC_JR,
+  TILEPRO_OPC_LNK_SN, TILEPRO_OPC_MAXB_U_SN, TILEPRO_OPC_MAXH_SN,
+  TILEPRO_OPC_MINB_U_SN, TILEPRO_OPC_MINH_SN, TILEPRO_OPC_MNZB_SN,
+  TILEPRO_OPC_MNZH_SN, TILEPRO_OPC_MNZ_SN, TILEPRO_OPC_MZB_SN,
+  TILEPRO_OPC_MZH_SN, TILEPRO_OPC_MZ_SN, TILEPRO_OPC_NOR_SN, CHILD(674),
+  TILEPRO_OPC_PACKHB_SN, TILEPRO_OPC_PACKLB_SN, TILEPRO_OPC_RL_SN,
+  TILEPRO_OPC_S1A_SN, TILEPRO_OPC_S2A_SN, TILEPRO_OPC_S3A_SN,
   BITFIELD(43, 2) /* index 674 */,
-  TILE_OPC_OR_SN, TILE_OPC_OR_SN, TILE_OPC_OR_SN, CHILD(679),
+  TILEPRO_OPC_OR_SN, TILEPRO_OPC_OR_SN, TILEPRO_OPC_OR_SN, CHILD(679),
   BITFIELD(45, 2) /* index 679 */,
-  TILE_OPC_OR_SN, TILE_OPC_OR_SN, TILE_OPC_OR_SN, CHILD(684),
+  TILEPRO_OPC_OR_SN, TILEPRO_OPC_OR_SN, TILEPRO_OPC_OR_SN, CHILD(684),
   BITFIELD(47, 2) /* index 684 */,
-  TILE_OPC_OR_SN, TILE_OPC_OR_SN, TILE_OPC_OR_SN, TILE_OPC_MOVE_SN,
+  TILEPRO_OPC_OR_SN, TILEPRO_OPC_OR_SN, TILEPRO_OPC_OR_SN,
+  TILEPRO_OPC_MOVE_SN,
   BITFIELD(49, 5) /* index 689 */,
-  TILE_OPC_SB, TILE_OPC_SEQB_SN, TILE_OPC_SEQH_SN, TILE_OPC_SEQ_SN,
-  TILE_OPC_SHLB_SN, TILE_OPC_SHLH_SN, TILE_OPC_SHL_SN, TILE_OPC_SHRB_SN,
-  TILE_OPC_SHRH_SN, TILE_OPC_SHR_SN, TILE_OPC_SH, TILE_OPC_SLTB_SN,
-  TILE_OPC_SLTB_U_SN, TILE_OPC_SLTEB_SN, TILE_OPC_SLTEB_U_SN,
-  TILE_OPC_SLTEH_SN, TILE_OPC_SLTEH_U_SN, TILE_OPC_SLTE_SN,
-  TILE_OPC_SLTE_U_SN, TILE_OPC_SLTH_SN, TILE_OPC_SLTH_U_SN, TILE_OPC_SLT_SN,
-  TILE_OPC_SLT_U_SN, TILE_OPC_SNEB_SN, TILE_OPC_SNEH_SN, TILE_OPC_SNE_SN,
-  TILE_OPC_SRAB_SN, TILE_OPC_SRAH_SN, TILE_OPC_SRA_SN, TILE_OPC_SUBB_SN,
-  TILE_OPC_SUBH_SN, TILE_OPC_SUB_SN,
+  TILEPRO_OPC_SB, TILEPRO_OPC_SEQB_SN, TILEPRO_OPC_SEQH_SN,
+  TILEPRO_OPC_SEQ_SN, TILEPRO_OPC_SHLB_SN, TILEPRO_OPC_SHLH_SN,
+  TILEPRO_OPC_SHL_SN, TILEPRO_OPC_SHRB_SN, TILEPRO_OPC_SHRH_SN,
+  TILEPRO_OPC_SHR_SN, TILEPRO_OPC_SH, TILEPRO_OPC_SLTB_SN,
+  TILEPRO_OPC_SLTB_U_SN, TILEPRO_OPC_SLTEB_SN, TILEPRO_OPC_SLTEB_U_SN,
+  TILEPRO_OPC_SLTEH_SN, TILEPRO_OPC_SLTEH_U_SN, TILEPRO_OPC_SLTE_SN,
+  TILEPRO_OPC_SLTE_U_SN, TILEPRO_OPC_SLTH_SN, TILEPRO_OPC_SLTH_U_SN,
+  TILEPRO_OPC_SLT_SN, TILEPRO_OPC_SLT_U_SN, TILEPRO_OPC_SNEB_SN,
+  TILEPRO_OPC_SNEH_SN, TILEPRO_OPC_SNE_SN, TILEPRO_OPC_SRAB_SN,
+  TILEPRO_OPC_SRAH_SN, TILEPRO_OPC_SRA_SN, TILEPRO_OPC_SUBB_SN,
+  TILEPRO_OPC_SUBH_SN, TILEPRO_OPC_SUB_SN,
   BITFIELD(49, 4) /* index 722 */,
   CHILD(611), CHILD(739), CHILD(742), CHILD(745), CHILD(748), CHILD(751),
-  CHILD(754), CHILD(757), CHILD(760), CHILD(763), TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
+  CHILD(754), CHILD(757), CHILD(760), CHILD(763), TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 739 */,
-  TILE_OPC_XOR_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_XOR_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 742 */,
-  TILE_OPC_ADDS_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_ADDS_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 745 */,
-  TILE_OPC_SUBS_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_SUBS_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 748 */,
-  TILE_OPC_ADDBS_U_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_ADDBS_U_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 751 */,
-  TILE_OPC_ADDHS_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_ADDHS_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 754 */,
-  TILE_OPC_SUBBS_U_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_SUBBS_U_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 757 */,
-  TILE_OPC_SUBHS_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_SUBHS_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 760 */,
-  TILE_OPC_PACKHS_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_PACKHS_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 763 */,
-  TILE_OPC_PACKBS_U_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_PACKBS_U_SN, TILEPRO_OPC_NONE,
   BITFIELD(37, 2) /* index 766 */,
-  TILE_OPC_ADDLI_SN, TILE_OPC_ADDLI_SN, TILE_OPC_ADDLI_SN, CHILD(771),
+  TILEPRO_OPC_ADDLI_SN, TILEPRO_OPC_ADDLI_SN, TILEPRO_OPC_ADDLI_SN,
+  CHILD(771),
   BITFIELD(39, 2) /* index 771 */,
-  TILE_OPC_ADDLI_SN, TILE_OPC_ADDLI_SN, TILE_OPC_ADDLI_SN, CHILD(776),
+  TILEPRO_OPC_ADDLI_SN, TILEPRO_OPC_ADDLI_SN, TILEPRO_OPC_ADDLI_SN,
+  CHILD(776),
   BITFIELD(41, 2) /* index 776 */,
-  TILE_OPC_ADDLI_SN, TILE_OPC_ADDLI_SN, TILE_OPC_ADDLI_SN, TILE_OPC_MOVELI_SN,
+  TILEPRO_OPC_ADDLI_SN, TILEPRO_OPC_ADDLI_SN, TILEPRO_OPC_ADDLI_SN,
+  TILEPRO_OPC_MOVELI_SN,
   BITFIELD(37, 2) /* index 781 */,
-  TILE_OPC_ADDLI, TILE_OPC_ADDLI, TILE_OPC_ADDLI, CHILD(786),
+  TILEPRO_OPC_ADDLI, TILEPRO_OPC_ADDLI, TILEPRO_OPC_ADDLI, CHILD(786),
   BITFIELD(39, 2) /* index 786 */,
-  TILE_OPC_ADDLI, TILE_OPC_ADDLI, TILE_OPC_ADDLI, CHILD(791),
+  TILEPRO_OPC_ADDLI, TILEPRO_OPC_ADDLI, TILEPRO_OPC_ADDLI, CHILD(791),
   BITFIELD(41, 2) /* index 791 */,
-  TILE_OPC_ADDLI, TILE_OPC_ADDLI, TILE_OPC_ADDLI, TILE_OPC_MOVELI,
+  TILEPRO_OPC_ADDLI, TILEPRO_OPC_ADDLI, TILEPRO_OPC_ADDLI, TILEPRO_OPC_MOVELI,
   BITFIELD(31, 2) /* index 796 */,
-  TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_AULI, CHILD(801),
+  TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, CHILD(801),
   BITFIELD(33, 2) /* index 801 */,
-  TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_AULI, CHILD(806),
+  TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, CHILD(806),
   BITFIELD(35, 2) /* index 806 */,
-  TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_AULI, CHILD(811),
+  TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, CHILD(811),
   BITFIELD(37, 2) /* index 811 */,
-  TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_AULI, CHILD(816),
+  TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, CHILD(816),
   BITFIELD(39, 2) /* index 816 */,
-  TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_AULI, CHILD(821),
+  TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, CHILD(821),
   BITFIELD(41, 2) /* index 821 */,
-  TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_AULI, TILE_OPC_INFOL,
+  TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, TILEPRO_OPC_AULI, TILEPRO_OPC_INFOL,
   BITFIELD(31, 4) /* index 826 */,
-  TILE_OPC_BZ, TILE_OPC_BZT, TILE_OPC_BNZ, TILE_OPC_BNZT, TILE_OPC_BGZ,
-  TILE_OPC_BGZT, TILE_OPC_BGEZ, TILE_OPC_BGEZT, TILE_OPC_BLZ, TILE_OPC_BLZT,
-  TILE_OPC_BLEZ, TILE_OPC_BLEZT, TILE_OPC_BBS, TILE_OPC_BBST, TILE_OPC_BBNS,
-  TILE_OPC_BBNST,
+  TILEPRO_OPC_BZ, TILEPRO_OPC_BZT, TILEPRO_OPC_BNZ, TILEPRO_OPC_BNZT,
+  TILEPRO_OPC_BGZ, TILEPRO_OPC_BGZT, TILEPRO_OPC_BGEZ, TILEPRO_OPC_BGEZT,
+  TILEPRO_OPC_BLZ, TILEPRO_OPC_BLZT, TILEPRO_OPC_BLEZ, TILEPRO_OPC_BLEZT,
+  TILEPRO_OPC_BBS, TILEPRO_OPC_BBST, TILEPRO_OPC_BBNS, TILEPRO_OPC_BBNST,
   BITFIELD(31, 4) /* index 843 */,
-  TILE_OPC_BZ_SN, TILE_OPC_BZT_SN, TILE_OPC_BNZ_SN, TILE_OPC_BNZT_SN,
-  TILE_OPC_BGZ_SN, TILE_OPC_BGZT_SN, TILE_OPC_BGEZ_SN, TILE_OPC_BGEZT_SN,
-  TILE_OPC_BLZ_SN, TILE_OPC_BLZT_SN, TILE_OPC_BLEZ_SN, TILE_OPC_BLEZT_SN,
-  TILE_OPC_BBS_SN, TILE_OPC_BBST_SN, TILE_OPC_BBNS_SN, TILE_OPC_BBNST_SN,
+  TILEPRO_OPC_BZ_SN, TILEPRO_OPC_BZT_SN, TILEPRO_OPC_BNZ_SN,
+  TILEPRO_OPC_BNZT_SN, TILEPRO_OPC_BGZ_SN, TILEPRO_OPC_BGZT_SN,
+  TILEPRO_OPC_BGEZ_SN, TILEPRO_OPC_BGEZT_SN, TILEPRO_OPC_BLZ_SN,
+  TILEPRO_OPC_BLZT_SN, TILEPRO_OPC_BLEZ_SN, TILEPRO_OPC_BLEZT_SN,
+  TILEPRO_OPC_BBS_SN, TILEPRO_OPC_BBST_SN, TILEPRO_OPC_BBNS_SN,
+  TILEPRO_OPC_BBNST_SN,
   BITFIELD(51, 3) /* index 860 */,
-  TILE_OPC_NONE, TILE_OPC_ADDIB, TILE_OPC_ADDIH, TILE_OPC_ADDI, CHILD(869),
-  TILE_OPC_MAXIB_U, TILE_OPC_MAXIH, TILE_OPC_MFSPR,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_ADDIB, TILEPRO_OPC_ADDIH, TILEPRO_OPC_ADDI,
+  CHILD(869), TILEPRO_OPC_MAXIB_U, TILEPRO_OPC_MAXIH, TILEPRO_OPC_MFSPR,
   BITFIELD(31, 2) /* index 869 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(874),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(874),
   BITFIELD(33, 2) /* index 874 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(879),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(879),
   BITFIELD(35, 2) /* index 879 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(884),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(884),
   BITFIELD(37, 2) /* index 884 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(889),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(889),
   BITFIELD(39, 2) /* index 889 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(894),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(894),
   BITFIELD(41, 2) /* index 894 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_INFO,
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_INFO,
   BITFIELD(51, 3) /* index 899 */,
-  TILE_OPC_MINIB_U, TILE_OPC_MINIH, TILE_OPC_MTSPR, CHILD(908),
-  TILE_OPC_SEQIB, TILE_OPC_SEQIH, TILE_OPC_SEQI, TILE_OPC_SLTIB,
+  TILEPRO_OPC_MINIB_U, TILEPRO_OPC_MINIH, TILEPRO_OPC_MTSPR, CHILD(908),
+  TILEPRO_OPC_SEQIB, TILEPRO_OPC_SEQIH, TILEPRO_OPC_SEQI, TILEPRO_OPC_SLTIB,
   BITFIELD(37, 2) /* index 908 */,
-  TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_ORI, CHILD(913),
+  TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, CHILD(913),
   BITFIELD(39, 2) /* index 913 */,
-  TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_ORI, CHILD(918),
+  TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, CHILD(918),
   BITFIELD(41, 2) /* index 918 */,
-  TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_MOVEI,
+  TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, TILEPRO_OPC_MOVEI,
   BITFIELD(51, 3) /* index 923 */,
-  TILE_OPC_SLTIB_U, TILE_OPC_SLTIH, TILE_OPC_SLTIH_U, TILE_OPC_SLTI,
-  TILE_OPC_SLTI_U, TILE_OPC_XORI, TILE_OPC_LBADD, TILE_OPC_LBADD_U,
+  TILEPRO_OPC_SLTIB_U, TILEPRO_OPC_SLTIH, TILEPRO_OPC_SLTIH_U,
+  TILEPRO_OPC_SLTI, TILEPRO_OPC_SLTI_U, TILEPRO_OPC_XORI, TILEPRO_OPC_LBADD,
+  TILEPRO_OPC_LBADD_U,
   BITFIELD(51, 3) /* index 932 */,
-  TILE_OPC_LHADD, TILE_OPC_LHADD_U, TILE_OPC_LWADD, TILE_OPC_LWADD_NA,
-  TILE_OPC_SBADD, TILE_OPC_SHADD, TILE_OPC_SWADD, TILE_OPC_NONE,
+  TILEPRO_OPC_LHADD, TILEPRO_OPC_LHADD_U, TILEPRO_OPC_LWADD,
+  TILEPRO_OPC_LWADD_NA, TILEPRO_OPC_SBADD, TILEPRO_OPC_SHADD,
+  TILEPRO_OPC_SWADD, TILEPRO_OPC_NONE,
   BITFIELD(51, 3) /* index 941 */,
-  TILE_OPC_NONE, TILE_OPC_ADDIB_SN, TILE_OPC_ADDIH_SN, TILE_OPC_ADDI_SN,
-  TILE_OPC_ANDI_SN, TILE_OPC_MAXIB_U_SN, TILE_OPC_MAXIH_SN, TILE_OPC_MFSPR,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_ADDIB_SN, TILEPRO_OPC_ADDIH_SN,
+  TILEPRO_OPC_ADDI_SN, TILEPRO_OPC_ANDI_SN, TILEPRO_OPC_MAXIB_U_SN,
+  TILEPRO_OPC_MAXIH_SN, TILEPRO_OPC_MFSPR,
   BITFIELD(51, 3) /* index 950 */,
-  TILE_OPC_MINIB_U_SN, TILE_OPC_MINIH_SN, TILE_OPC_MTSPR, CHILD(959),
-  TILE_OPC_SEQIB_SN, TILE_OPC_SEQIH_SN, TILE_OPC_SEQI_SN, TILE_OPC_SLTIB_SN,
+  TILEPRO_OPC_MINIB_U_SN, TILEPRO_OPC_MINIH_SN, TILEPRO_OPC_MTSPR, CHILD(959),
+  TILEPRO_OPC_SEQIB_SN, TILEPRO_OPC_SEQIH_SN, TILEPRO_OPC_SEQI_SN,
+  TILEPRO_OPC_SLTIB_SN,
   BITFIELD(37, 2) /* index 959 */,
-  TILE_OPC_ORI_SN, TILE_OPC_ORI_SN, TILE_OPC_ORI_SN, CHILD(964),
+  TILEPRO_OPC_ORI_SN, TILEPRO_OPC_ORI_SN, TILEPRO_OPC_ORI_SN, CHILD(964),
   BITFIELD(39, 2) /* index 964 */,
-  TILE_OPC_ORI_SN, TILE_OPC_ORI_SN, TILE_OPC_ORI_SN, CHILD(969),
+  TILEPRO_OPC_ORI_SN, TILEPRO_OPC_ORI_SN, TILEPRO_OPC_ORI_SN, CHILD(969),
   BITFIELD(41, 2) /* index 969 */,
-  TILE_OPC_ORI_SN, TILE_OPC_ORI_SN, TILE_OPC_ORI_SN, TILE_OPC_MOVEI_SN,
+  TILEPRO_OPC_ORI_SN, TILEPRO_OPC_ORI_SN, TILEPRO_OPC_ORI_SN,
+  TILEPRO_OPC_MOVEI_SN,
   BITFIELD(51, 3) /* index 974 */,
-  TILE_OPC_SLTIB_U_SN, TILE_OPC_SLTIH_SN, TILE_OPC_SLTIH_U_SN,
-  TILE_OPC_SLTI_SN, TILE_OPC_SLTI_U_SN, TILE_OPC_XORI_SN, TILE_OPC_LBADD_SN,
-  TILE_OPC_LBADD_U_SN,
+  TILEPRO_OPC_SLTIB_U_SN, TILEPRO_OPC_SLTIH_SN, TILEPRO_OPC_SLTIH_U_SN,
+  TILEPRO_OPC_SLTI_SN, TILEPRO_OPC_SLTI_U_SN, TILEPRO_OPC_XORI_SN,
+  TILEPRO_OPC_LBADD_SN, TILEPRO_OPC_LBADD_U_SN,
   BITFIELD(51, 3) /* index 983 */,
-  TILE_OPC_LHADD_SN, TILE_OPC_LHADD_U_SN, TILE_OPC_LWADD_SN,
-  TILE_OPC_LWADD_NA_SN, TILE_OPC_SBADD, TILE_OPC_SHADD, TILE_OPC_SWADD,
-  TILE_OPC_NONE,
+  TILEPRO_OPC_LHADD_SN, TILEPRO_OPC_LHADD_U_SN, TILEPRO_OPC_LWADD_SN,
+  TILEPRO_OPC_LWADD_NA_SN, TILEPRO_OPC_SBADD, TILEPRO_OPC_SHADD,
+  TILEPRO_OPC_SWADD, TILEPRO_OPC_NONE,
   BITFIELD(46, 7) /* index 992 */,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, CHILD(1121),
-  CHILD(1121), CHILD(1121), CHILD(1121), CHILD(1124), CHILD(1124),
-  CHILD(1124), CHILD(1124), CHILD(1127), CHILD(1127), CHILD(1127),
-  CHILD(1127), CHILD(1130), CHILD(1130), CHILD(1130), CHILD(1130),
-  CHILD(1133), CHILD(1133), CHILD(1133), CHILD(1133), CHILD(1136),
-  CHILD(1136), CHILD(1136), CHILD(1136), CHILD(1139), CHILD(1139),
-  CHILD(1139), CHILD(1139), CHILD(1142), CHILD(1142), CHILD(1142),
-  CHILD(1142), CHILD(1145), CHILD(1145), CHILD(1145), CHILD(1145),
-  CHILD(1148), CHILD(1148), CHILD(1148), CHILD(1148), CHILD(1151),
-  CHILD(1242), CHILD(1290), CHILD(1323), TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  CHILD(1121), CHILD(1121), CHILD(1121), CHILD(1121), CHILD(1124),
+  CHILD(1124), CHILD(1124), CHILD(1124), CHILD(1127), CHILD(1127),
+  CHILD(1127), CHILD(1127), CHILD(1130), CHILD(1130), CHILD(1130),
+  CHILD(1130), CHILD(1133), CHILD(1133), CHILD(1133), CHILD(1133),
+  CHILD(1136), CHILD(1136), CHILD(1136), CHILD(1136), CHILD(1139),
+  CHILD(1139), CHILD(1139), CHILD(1139), CHILD(1142), CHILD(1142),
+  CHILD(1142), CHILD(1142), CHILD(1145), CHILD(1145), CHILD(1145),
+  CHILD(1145), CHILD(1148), CHILD(1148), CHILD(1148), CHILD(1148),
+  CHILD(1151), CHILD(1242), CHILD(1290), CHILD(1323), TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1121 */,
-  TILE_OPC_RLI, TILE_OPC_NONE,
+  TILEPRO_OPC_RLI, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1124 */,
-  TILE_OPC_SHLIB, TILE_OPC_NONE,
+  TILEPRO_OPC_SHLIB, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1127 */,
-  TILE_OPC_SHLIH, TILE_OPC_NONE,
+  TILEPRO_OPC_SHLIH, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1130 */,
-  TILE_OPC_SHLI, TILE_OPC_NONE,
+  TILEPRO_OPC_SHLI, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1133 */,
-  TILE_OPC_SHRIB, TILE_OPC_NONE,
+  TILEPRO_OPC_SHRIB, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1136 */,
-  TILE_OPC_SHRIH, TILE_OPC_NONE,
+  TILEPRO_OPC_SHRIH, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1139 */,
-  TILE_OPC_SHRI, TILE_OPC_NONE,
+  TILEPRO_OPC_SHRI, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1142 */,
-  TILE_OPC_SRAIB, TILE_OPC_NONE,
+  TILEPRO_OPC_SRAIB, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1145 */,
-  TILE_OPC_SRAIH, TILE_OPC_NONE,
+  TILEPRO_OPC_SRAIH, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1148 */,
-  TILE_OPC_SRAI, TILE_OPC_NONE,
+  TILEPRO_OPC_SRAI, TILEPRO_OPC_NONE,
   BITFIELD(43, 3) /* index 1151 */,
-  TILE_OPC_NONE, CHILD(1160), CHILD(1163), CHILD(1166), CHILD(1169),
+  TILEPRO_OPC_NONE, CHILD(1160), CHILD(1163), CHILD(1166), CHILD(1169),
   CHILD(1172), CHILD(1175), CHILD(1178),
   BITFIELD(53, 1) /* index 1160 */,
-  TILE_OPC_DRAIN, TILE_OPC_NONE,
+  TILEPRO_OPC_DRAIN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1163 */,
-  TILE_OPC_DTLBPR, TILE_OPC_NONE,
+  TILEPRO_OPC_DTLBPR, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1166 */,
-  TILE_OPC_FINV, TILE_OPC_NONE,
+  TILEPRO_OPC_FINV, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1169 */,
-  TILE_OPC_FLUSH, TILE_OPC_NONE,
+  TILEPRO_OPC_FLUSH, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1172 */,
-  TILE_OPC_FNOP, TILE_OPC_NONE,
+  TILEPRO_OPC_FNOP, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1175 */,
-  TILE_OPC_ICOH, TILE_OPC_NONE,
+  TILEPRO_OPC_ICOH, TILEPRO_OPC_NONE,
   BITFIELD(31, 2) /* index 1178 */,
   CHILD(1183), CHILD(1211), CHILD(1239), CHILD(1239),
   BITFIELD(53, 1) /* index 1183 */,
-  CHILD(1186), TILE_OPC_NONE,
+  CHILD(1186), TILEPRO_OPC_NONE,
   BITFIELD(33, 2) /* index 1186 */,
-  TILE_OPC_ILL, TILE_OPC_ILL, TILE_OPC_ILL, CHILD(1191),
+  TILEPRO_OPC_ILL, TILEPRO_OPC_ILL, TILEPRO_OPC_ILL, CHILD(1191),
   BITFIELD(35, 2) /* index 1191 */,
-  TILE_OPC_ILL, CHILD(1196), TILE_OPC_ILL, TILE_OPC_ILL,
+  TILEPRO_OPC_ILL, CHILD(1196), TILEPRO_OPC_ILL, TILEPRO_OPC_ILL,
   BITFIELD(37, 2) /* index 1196 */,
-  TILE_OPC_ILL, CHILD(1201), TILE_OPC_ILL, TILE_OPC_ILL,
+  TILEPRO_OPC_ILL, CHILD(1201), TILEPRO_OPC_ILL, TILEPRO_OPC_ILL,
   BITFIELD(39, 2) /* index 1201 */,
-  TILE_OPC_ILL, CHILD(1206), TILE_OPC_ILL, TILE_OPC_ILL,
+  TILEPRO_OPC_ILL, CHILD(1206), TILEPRO_OPC_ILL, TILEPRO_OPC_ILL,
   BITFIELD(41, 2) /* index 1206 */,
-  TILE_OPC_ILL, TILE_OPC_ILL, TILE_OPC_BPT, TILE_OPC_ILL,
+  TILEPRO_OPC_ILL, TILEPRO_OPC_ILL, TILEPRO_OPC_BPT, TILEPRO_OPC_ILL,
   BITFIELD(53, 1) /* index 1211 */,
-  CHILD(1214), TILE_OPC_NONE,
+  CHILD(1214), TILEPRO_OPC_NONE,
   BITFIELD(33, 2) /* index 1214 */,
-  TILE_OPC_ILL, TILE_OPC_ILL, TILE_OPC_ILL, CHILD(1219),
+  TILEPRO_OPC_ILL, TILEPRO_OPC_ILL, TILEPRO_OPC_ILL, CHILD(1219),
   BITFIELD(35, 2) /* index 1219 */,
-  TILE_OPC_ILL, CHILD(1224), TILE_OPC_ILL, TILE_OPC_ILL,
+  TILEPRO_OPC_ILL, CHILD(1224), TILEPRO_OPC_ILL, TILEPRO_OPC_ILL,
   BITFIELD(37, 2) /* index 1224 */,
-  TILE_OPC_ILL, CHILD(1229), TILE_OPC_ILL, TILE_OPC_ILL,
+  TILEPRO_OPC_ILL, CHILD(1229), TILEPRO_OPC_ILL, TILEPRO_OPC_ILL,
   BITFIELD(39, 2) /* index 1229 */,
-  TILE_OPC_ILL, CHILD(1234), TILE_OPC_ILL, TILE_OPC_ILL,
+  TILEPRO_OPC_ILL, CHILD(1234), TILEPRO_OPC_ILL, TILEPRO_OPC_ILL,
   BITFIELD(41, 2) /* index 1234 */,
-  TILE_OPC_ILL, TILE_OPC_ILL, TILE_OPC_RAISE, TILE_OPC_ILL,
+  TILEPRO_OPC_ILL, TILEPRO_OPC_ILL, TILEPRO_OPC_RAISE, TILEPRO_OPC_ILL,
   BITFIELD(53, 1) /* index 1239 */,
-  TILE_OPC_ILL, TILE_OPC_NONE,
+  TILEPRO_OPC_ILL, TILEPRO_OPC_NONE,
   BITFIELD(43, 3) /* index 1242 */,
   CHILD(1251), CHILD(1254), CHILD(1257), CHILD(1275), CHILD(1278),
   CHILD(1281), CHILD(1284), CHILD(1287),
   BITFIELD(53, 1) /* index 1251 */,
-  TILE_OPC_INV, TILE_OPC_NONE,
+  TILEPRO_OPC_INV, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1254 */,
-  TILE_OPC_IRET, TILE_OPC_NONE,
+  TILEPRO_OPC_IRET, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1257 */,
-  CHILD(1260), TILE_OPC_NONE,
+  CHILD(1260), TILEPRO_OPC_NONE,
   BITFIELD(31, 2) /* index 1260 */,
-  TILE_OPC_LB, TILE_OPC_LB, TILE_OPC_LB, CHILD(1265),
+  TILEPRO_OPC_LB, TILEPRO_OPC_LB, TILEPRO_OPC_LB, CHILD(1265),
   BITFIELD(33, 2) /* index 1265 */,
-  TILE_OPC_LB, TILE_OPC_LB, TILE_OPC_LB, CHILD(1270),
+  TILEPRO_OPC_LB, TILEPRO_OPC_LB, TILEPRO_OPC_LB, CHILD(1270),
   BITFIELD(35, 2) /* index 1270 */,
-  TILE_OPC_LB, TILE_OPC_LB, TILE_OPC_LB, TILE_OPC_PREFETCH,
+  TILEPRO_OPC_LB, TILEPRO_OPC_LB, TILEPRO_OPC_LB, TILEPRO_OPC_PREFETCH,
   BITFIELD(53, 1) /* index 1275 */,
-  TILE_OPC_LB_U, TILE_OPC_NONE,
+  TILEPRO_OPC_LB_U, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1278 */,
-  TILE_OPC_LH, TILE_OPC_NONE,
+  TILEPRO_OPC_LH, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1281 */,
-  TILE_OPC_LH_U, TILE_OPC_NONE,
+  TILEPRO_OPC_LH_U, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1284 */,
-  TILE_OPC_LW, TILE_OPC_NONE,
+  TILEPRO_OPC_LW, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1287 */,
-  TILE_OPC_MF, TILE_OPC_NONE,
+  TILEPRO_OPC_MF, TILEPRO_OPC_NONE,
   BITFIELD(43, 3) /* index 1290 */,
   CHILD(1299), CHILD(1302), CHILD(1305), CHILD(1308), CHILD(1311),
   CHILD(1314), CHILD(1317), CHILD(1320),
   BITFIELD(53, 1) /* index 1299 */,
-  TILE_OPC_NAP, TILE_OPC_NONE,
+  TILEPRO_OPC_NAP, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1302 */,
-  TILE_OPC_NOP, TILE_OPC_NONE,
+  TILEPRO_OPC_NOP, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1305 */,
-  TILE_OPC_SWINT0, TILE_OPC_NONE,
+  TILEPRO_OPC_SWINT0, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1308 */,
-  TILE_OPC_SWINT1, TILE_OPC_NONE,
+  TILEPRO_OPC_SWINT1, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1311 */,
-  TILE_OPC_SWINT2, TILE_OPC_NONE,
+  TILEPRO_OPC_SWINT2, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1314 */,
-  TILE_OPC_SWINT3, TILE_OPC_NONE,
+  TILEPRO_OPC_SWINT3, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1317 */,
-  TILE_OPC_TNS, TILE_OPC_NONE,
+  TILEPRO_OPC_TNS, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1320 */,
-  TILE_OPC_WH64, TILE_OPC_NONE,
+  TILEPRO_OPC_WH64, TILEPRO_OPC_NONE,
   BITFIELD(43, 2) /* index 1323 */,
-  CHILD(1328), TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
+  CHILD(1328), TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   BITFIELD(45, 1) /* index 1328 */,
-  CHILD(1331), TILE_OPC_NONE,
+  CHILD(1331), TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1331 */,
-  TILE_OPC_LW_NA, TILE_OPC_NONE,
+  TILEPRO_OPC_LW_NA, TILEPRO_OPC_NONE,
   BITFIELD(46, 7) /* index 1334 */,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, CHILD(1463),
-  CHILD(1463), CHILD(1463), CHILD(1463), CHILD(1466), CHILD(1466),
-  CHILD(1466), CHILD(1466), CHILD(1469), CHILD(1469), CHILD(1469),
-  CHILD(1469), CHILD(1472), CHILD(1472), CHILD(1472), CHILD(1472),
-  CHILD(1475), CHILD(1475), CHILD(1475), CHILD(1475), CHILD(1478),
-  CHILD(1478), CHILD(1478), CHILD(1478), CHILD(1481), CHILD(1481),
-  CHILD(1481), CHILD(1481), CHILD(1484), CHILD(1484), CHILD(1484),
-  CHILD(1484), CHILD(1487), CHILD(1487), CHILD(1487), CHILD(1487),
-  CHILD(1490), CHILD(1490), CHILD(1490), CHILD(1490), CHILD(1151),
-  CHILD(1493), CHILD(1517), CHILD(1529), TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  CHILD(1463), CHILD(1463), CHILD(1463), CHILD(1463), CHILD(1466),
+  CHILD(1466), CHILD(1466), CHILD(1466), CHILD(1469), CHILD(1469),
+  CHILD(1469), CHILD(1469), CHILD(1472), CHILD(1472), CHILD(1472),
+  CHILD(1472), CHILD(1475), CHILD(1475), CHILD(1475), CHILD(1475),
+  CHILD(1478), CHILD(1478), CHILD(1478), CHILD(1478), CHILD(1481),
+  CHILD(1481), CHILD(1481), CHILD(1481), CHILD(1484), CHILD(1484),
+  CHILD(1484), CHILD(1484), CHILD(1487), CHILD(1487), CHILD(1487),
+  CHILD(1487), CHILD(1490), CHILD(1490), CHILD(1490), CHILD(1490),
+  CHILD(1151), CHILD(1493), CHILD(1517), CHILD(1529), TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1463 */,
-  TILE_OPC_RLI_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_RLI_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1466 */,
-  TILE_OPC_SHLIB_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_SHLIB_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1469 */,
-  TILE_OPC_SHLIH_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_SHLIH_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1472 */,
-  TILE_OPC_SHLI_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_SHLI_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1475 */,
-  TILE_OPC_SHRIB_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_SHRIB_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1478 */,
-  TILE_OPC_SHRIH_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_SHRIH_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1481 */,
-  TILE_OPC_SHRI_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_SHRI_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1484 */,
-  TILE_OPC_SRAIB_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_SRAIB_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1487 */,
-  TILE_OPC_SRAIH_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_SRAIH_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1490 */,
-  TILE_OPC_SRAI_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_SRAI_SN, TILEPRO_OPC_NONE,
   BITFIELD(43, 3) /* index 1493 */,
   CHILD(1251), CHILD(1254), CHILD(1502), CHILD(1505), CHILD(1508),
   CHILD(1511), CHILD(1514), CHILD(1287),
   BITFIELD(53, 1) /* index 1502 */,
-  TILE_OPC_LB_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_LB_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1505 */,
-  TILE_OPC_LB_U_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_LB_U_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1508 */,
-  TILE_OPC_LH_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_LH_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1511 */,
-  TILE_OPC_LH_U_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_LH_U_SN, TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1514 */,
-  TILE_OPC_LW_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_LW_SN, TILEPRO_OPC_NONE,
   BITFIELD(43, 3) /* index 1517 */,
   CHILD(1299), CHILD(1302), CHILD(1305), CHILD(1308), CHILD(1311),
   CHILD(1314), CHILD(1526), CHILD(1320),
   BITFIELD(53, 1) /* index 1526 */,
-  TILE_OPC_TNS_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_TNS_SN, TILEPRO_OPC_NONE,
   BITFIELD(43, 2) /* index 1529 */,
-  CHILD(1534), TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
+  CHILD(1534), TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   BITFIELD(45, 1) /* index 1534 */,
-  CHILD(1537), TILE_OPC_NONE,
+  CHILD(1537), TILEPRO_OPC_NONE,
   BITFIELD(53, 1) /* index 1537 */,
-  TILE_OPC_LW_NA_SN, TILE_OPC_NONE,
+  TILEPRO_OPC_LW_NA_SN, TILEPRO_OPC_NONE,
 };
 
 static const unsigned short decode_Y0_fsm[168] =
 {
   BITFIELD(27, 4) /* index 0 */,
-  TILE_OPC_NONE, CHILD(17), CHILD(22), CHILD(27), CHILD(47), CHILD(52),
-  CHILD(57), CHILD(62), CHILD(67), TILE_OPC_ADDI, CHILD(72), CHILD(102),
-  TILE_OPC_SEQI, CHILD(117), TILE_OPC_SLTI, TILE_OPC_SLTI_U,
+  TILEPRO_OPC_NONE, CHILD(17), CHILD(22), CHILD(27), CHILD(47), CHILD(52),
+  CHILD(57), CHILD(62), CHILD(67), TILEPRO_OPC_ADDI, CHILD(72), CHILD(102),
+  TILEPRO_OPC_SEQI, CHILD(117), TILEPRO_OPC_SLTI, TILEPRO_OPC_SLTI_U,
   BITFIELD(18, 2) /* index 17 */,
-  TILE_OPC_ADD, TILE_OPC_S1A, TILE_OPC_S2A, TILE_OPC_SUB,
+  TILEPRO_OPC_ADD, TILEPRO_OPC_S1A, TILEPRO_OPC_S2A, TILEPRO_OPC_SUB,
   BITFIELD(18, 2) /* index 22 */,
-  TILE_OPC_MNZ, TILE_OPC_MVNZ, TILE_OPC_MVZ, TILE_OPC_MZ,
+  TILEPRO_OPC_MNZ, TILEPRO_OPC_MVNZ, TILEPRO_OPC_MVZ, TILEPRO_OPC_MZ,
   BITFIELD(18, 2) /* index 27 */,
-  TILE_OPC_AND, TILE_OPC_NOR, CHILD(32), TILE_OPC_XOR,
+  TILEPRO_OPC_AND, TILEPRO_OPC_NOR, CHILD(32), TILEPRO_OPC_XOR,
   BITFIELD(12, 2) /* index 32 */,
-  TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_OR, CHILD(37),
+  TILEPRO_OPC_OR, TILEPRO_OPC_OR, TILEPRO_OPC_OR, CHILD(37),
   BITFIELD(14, 2) /* index 37 */,
-  TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_OR, CHILD(42),
+  TILEPRO_OPC_OR, TILEPRO_OPC_OR, TILEPRO_OPC_OR, CHILD(42),
   BITFIELD(16, 2) /* index 42 */,
-  TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_MOVE,
+  TILEPRO_OPC_OR, TILEPRO_OPC_OR, TILEPRO_OPC_OR, TILEPRO_OPC_MOVE,
   BITFIELD(18, 2) /* index 47 */,
-  TILE_OPC_RL, TILE_OPC_SHL, TILE_OPC_SHR, TILE_OPC_SRA,
+  TILEPRO_OPC_RL, TILEPRO_OPC_SHL, TILEPRO_OPC_SHR, TILEPRO_OPC_SRA,
   BITFIELD(18, 2) /* index 52 */,
-  TILE_OPC_SLTE, TILE_OPC_SLTE_U, TILE_OPC_SLT, TILE_OPC_SLT_U,
+  TILEPRO_OPC_SLTE, TILEPRO_OPC_SLTE_U, TILEPRO_OPC_SLT, TILEPRO_OPC_SLT_U,
   BITFIELD(18, 2) /* index 57 */,
-  TILE_OPC_MULHLSA_UU, TILE_OPC_S3A, TILE_OPC_SEQ, TILE_OPC_SNE,
+  TILEPRO_OPC_MULHLSA_UU, TILEPRO_OPC_S3A, TILEPRO_OPC_SEQ, TILEPRO_OPC_SNE,
   BITFIELD(18, 2) /* index 62 */,
-  TILE_OPC_MULHH_SS, TILE_OPC_MULHH_UU, TILE_OPC_MULLL_SS, TILE_OPC_MULLL_UU,
+  TILEPRO_OPC_MULHH_SS, TILEPRO_OPC_MULHH_UU, TILEPRO_OPC_MULLL_SS,
+  TILEPRO_OPC_MULLL_UU,
   BITFIELD(18, 2) /* index 67 */,
-  TILE_OPC_MULHHA_SS, TILE_OPC_MULHHA_UU, TILE_OPC_MULLLA_SS,
-  TILE_OPC_MULLLA_UU,
+  TILEPRO_OPC_MULHHA_SS, TILEPRO_OPC_MULHHA_UU, TILEPRO_OPC_MULLLA_SS,
+  TILEPRO_OPC_MULLLA_UU,
   BITFIELD(0, 2) /* index 72 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(77),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(77),
   BITFIELD(2, 2) /* index 77 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(82),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(82),
   BITFIELD(4, 2) /* index 82 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(87),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(87),
   BITFIELD(6, 2) /* index 87 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(92),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(92),
   BITFIELD(8, 2) /* index 92 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(97),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(97),
   BITFIELD(10, 2) /* index 97 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_INFO,
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_INFO,
   BITFIELD(6, 2) /* index 102 */,
-  TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_ORI, CHILD(107),
+  TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, CHILD(107),
   BITFIELD(8, 2) /* index 107 */,
-  TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_ORI, CHILD(112),
+  TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, CHILD(112),
   BITFIELD(10, 2) /* index 112 */,
-  TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_MOVEI,
+  TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, TILEPRO_OPC_MOVEI,
   BITFIELD(15, 5) /* index 117 */,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_RLI,
-  TILE_OPC_RLI, TILE_OPC_RLI, TILE_OPC_RLI, TILE_OPC_SHLI, TILE_OPC_SHLI,
-  TILE_OPC_SHLI, TILE_OPC_SHLI, TILE_OPC_SHRI, TILE_OPC_SHRI, TILE_OPC_SHRI,
-  TILE_OPC_SHRI, TILE_OPC_SRAI, TILE_OPC_SRAI, TILE_OPC_SRAI, TILE_OPC_SRAI,
-  CHILD(150), CHILD(159), TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_RLI, TILEPRO_OPC_RLI, TILEPRO_OPC_RLI, TILEPRO_OPC_RLI,
+  TILEPRO_OPC_SHLI, TILEPRO_OPC_SHLI, TILEPRO_OPC_SHLI, TILEPRO_OPC_SHLI,
+  TILEPRO_OPC_SHRI, TILEPRO_OPC_SHRI, TILEPRO_OPC_SHRI, TILEPRO_OPC_SHRI,
+  TILEPRO_OPC_SRAI, TILEPRO_OPC_SRAI, TILEPRO_OPC_SRAI, TILEPRO_OPC_SRAI,
+  CHILD(150), CHILD(159), TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   BITFIELD(12, 3) /* index 150 */,
-  TILE_OPC_NONE, TILE_OPC_BITX, TILE_OPC_BYTEX, TILE_OPC_CLZ, TILE_OPC_CTZ,
-  TILE_OPC_FNOP, TILE_OPC_NOP, TILE_OPC_PCNT,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_BITX, TILEPRO_OPC_BYTEX, TILEPRO_OPC_CLZ,
+  TILEPRO_OPC_CTZ, TILEPRO_OPC_FNOP, TILEPRO_OPC_NOP, TILEPRO_OPC_PCNT,
   BITFIELD(12, 3) /* index 159 */,
-  TILE_OPC_TBLIDXB0, TILE_OPC_TBLIDXB1, TILE_OPC_TBLIDXB2, TILE_OPC_TBLIDXB3,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
+  TILEPRO_OPC_TBLIDXB0, TILEPRO_OPC_TBLIDXB1, TILEPRO_OPC_TBLIDXB2,
+  TILEPRO_OPC_TBLIDXB3, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE,
 };
 
 static const unsigned short decode_Y1_fsm[140] =
 {
   BITFIELD(59, 4) /* index 0 */,
-  TILE_OPC_NONE, CHILD(17), CHILD(22), CHILD(27), CHILD(47), CHILD(52),
-  CHILD(57), TILE_OPC_ADDI, CHILD(62), CHILD(92), TILE_OPC_SEQI, CHILD(107),
-  TILE_OPC_SLTI, TILE_OPC_SLTI_U, TILE_OPC_NONE, TILE_OPC_NONE,
+  TILEPRO_OPC_NONE, CHILD(17), CHILD(22), CHILD(27), CHILD(47), CHILD(52),
+  CHILD(57), TILEPRO_OPC_ADDI, CHILD(62), CHILD(92), TILEPRO_OPC_SEQI,
+  CHILD(107), TILEPRO_OPC_SLTI, TILEPRO_OPC_SLTI_U, TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE,
   BITFIELD(49, 2) /* index 17 */,
-  TILE_OPC_ADD, TILE_OPC_S1A, TILE_OPC_S2A, TILE_OPC_SUB,
+  TILEPRO_OPC_ADD, TILEPRO_OPC_S1A, TILEPRO_OPC_S2A, TILEPRO_OPC_SUB,
   BITFIELD(49, 2) /* index 22 */,
-  TILE_OPC_NONE, TILE_OPC_MNZ, TILE_OPC_MZ, TILE_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_MNZ, TILEPRO_OPC_MZ, TILEPRO_OPC_NONE,
   BITFIELD(49, 2) /* index 27 */,
-  TILE_OPC_AND, TILE_OPC_NOR, CHILD(32), TILE_OPC_XOR,
+  TILEPRO_OPC_AND, TILEPRO_OPC_NOR, CHILD(32), TILEPRO_OPC_XOR,
   BITFIELD(43, 2) /* index 32 */,
-  TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_OR, CHILD(37),
+  TILEPRO_OPC_OR, TILEPRO_OPC_OR, TILEPRO_OPC_OR, CHILD(37),
   BITFIELD(45, 2) /* index 37 */,
-  TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_OR, CHILD(42),
+  TILEPRO_OPC_OR, TILEPRO_OPC_OR, TILEPRO_OPC_OR, CHILD(42),
   BITFIELD(47, 2) /* index 42 */,
-  TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_OR, TILE_OPC_MOVE,
+  TILEPRO_OPC_OR, TILEPRO_OPC_OR, TILEPRO_OPC_OR, TILEPRO_OPC_MOVE,
   BITFIELD(49, 2) /* index 47 */,
-  TILE_OPC_RL, TILE_OPC_SHL, TILE_OPC_SHR, TILE_OPC_SRA,
+  TILEPRO_OPC_RL, TILEPRO_OPC_SHL, TILEPRO_OPC_SHR, TILEPRO_OPC_SRA,
   BITFIELD(49, 2) /* index 52 */,
-  TILE_OPC_SLTE, TILE_OPC_SLTE_U, TILE_OPC_SLT, TILE_OPC_SLT_U,
+  TILEPRO_OPC_SLTE, TILEPRO_OPC_SLTE_U, TILEPRO_OPC_SLT, TILEPRO_OPC_SLT_U,
   BITFIELD(49, 2) /* index 57 */,
-  TILE_OPC_NONE, TILE_OPC_S3A, TILE_OPC_SEQ, TILE_OPC_SNE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_S3A, TILEPRO_OPC_SEQ, TILEPRO_OPC_SNE,
   BITFIELD(31, 2) /* index 62 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(67),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(67),
   BITFIELD(33, 2) /* index 67 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(72),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(72),
   BITFIELD(35, 2) /* index 72 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(77),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(77),
   BITFIELD(37, 2) /* index 77 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(82),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(82),
   BITFIELD(39, 2) /* index 82 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, CHILD(87),
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, CHILD(87),
   BITFIELD(41, 2) /* index 87 */,
-  TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_ANDI, TILE_OPC_INFO,
+  TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_ANDI, TILEPRO_OPC_INFO,
   BITFIELD(37, 2) /* index 92 */,
-  TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_ORI, CHILD(97),
+  TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, CHILD(97),
   BITFIELD(39, 2) /* index 97 */,
-  TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_ORI, CHILD(102),
+  TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, CHILD(102),
   BITFIELD(41, 2) /* index 102 */,
-  TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_ORI, TILE_OPC_MOVEI,
+  TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, TILEPRO_OPC_ORI, TILEPRO_OPC_MOVEI,
   BITFIELD(48, 3) /* index 107 */,
-  TILE_OPC_NONE, TILE_OPC_RLI, TILE_OPC_SHLI, TILE_OPC_SHRI, TILE_OPC_SRAI,
-  CHILD(116), TILE_OPC_NONE, TILE_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_RLI, TILEPRO_OPC_SHLI, TILEPRO_OPC_SHRI,
+  TILEPRO_OPC_SRAI, CHILD(116), TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   BITFIELD(43, 3) /* index 116 */,
-  TILE_OPC_NONE, CHILD(125), CHILD(130), CHILD(135), TILE_OPC_NONE,
-  TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
+  TILEPRO_OPC_NONE, CHILD(125), CHILD(130), CHILD(135), TILEPRO_OPC_NONE,
+  TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   BITFIELD(46, 2) /* index 125 */,
-  TILE_OPC_FNOP, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
+  TILEPRO_OPC_FNOP, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   BITFIELD(46, 2) /* index 130 */,
-  TILE_OPC_ILL, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
+  TILEPRO_OPC_ILL, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
   BITFIELD(46, 2) /* index 135 */,
-  TILE_OPC_NOP, TILE_OPC_NONE, TILE_OPC_NONE, TILE_OPC_NONE,
+  TILEPRO_OPC_NOP, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE, TILEPRO_OPC_NONE,
 };
 
 static const unsigned short decode_Y2_fsm[24] =
 {
   BITFIELD(56, 3) /* index 0 */,
-  CHILD(9), TILE_OPC_LB_U, TILE_OPC_LH, TILE_OPC_LH_U, TILE_OPC_LW,
-  TILE_OPC_SB, TILE_OPC_SH, TILE_OPC_SW,
+  CHILD(9), TILEPRO_OPC_LB_U, TILEPRO_OPC_LH, TILEPRO_OPC_LH_U,
+  TILEPRO_OPC_LW, TILEPRO_OPC_SB, TILEPRO_OPC_SH, TILEPRO_OPC_SW,
   BITFIELD(20, 2) /* index 9 */,
-  TILE_OPC_LB, TILE_OPC_LB, TILE_OPC_LB, CHILD(14),
+  TILEPRO_OPC_LB, TILEPRO_OPC_LB, TILEPRO_OPC_LB, CHILD(14),
   BITFIELD(22, 2) /* index 14 */,
-  TILE_OPC_LB, TILE_OPC_LB, TILE_OPC_LB, CHILD(19),
+  TILEPRO_OPC_LB, TILEPRO_OPC_LB, TILEPRO_OPC_LB, CHILD(19),
   BITFIELD(24, 2) /* index 19 */,
-  TILE_OPC_LB, TILE_OPC_LB, TILE_OPC_LB, TILE_OPC_PREFETCH,
+  TILEPRO_OPC_LB, TILEPRO_OPC_LB, TILEPRO_OPC_LB, TILEPRO_OPC_PREFETCH,
 };
 
 #undef BITFIELD
 #undef CHILD
 const unsigned short * const
-tile_bundle_decoder_fsms[TILE_NUM_PIPELINE_ENCODINGS] =
+tilepro_bundle_decoder_fsms[TILEPRO_NUM_PIPELINE_ENCODINGS] =
 {
   decode_X0_fsm,
   decode_X1_fsm,
@@ -2191,220 +2297,220 @@ tile_bundle_decoder_fsms[TILE_NUM_PIPELINE_ENCODINGS] =
   decode_Y1_fsm,
   decode_Y2_fsm
 };
-const struct tile_operand tile_operands[43] =
+const struct tilepro_operand tilepro_operands[43] =
 {
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(TILE_IMM8_X0),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEPRO_IMM8_X0),
     8, 1, 0, 0, 0, 0,
     create_Imm8_X0, get_Imm8_X0
   },
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(TILE_IMM8_X1),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEPRO_IMM8_X1),
     8, 1, 0, 0, 0, 0,
     create_Imm8_X1, get_Imm8_X1
   },
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(TILE_IMM8_Y0),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEPRO_IMM8_Y0),
     8, 1, 0, 0, 0, 0,
     create_Imm8_Y0, get_Imm8_Y0
   },
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(TILE_IMM8_Y1),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEPRO_IMM8_Y1),
     8, 1, 0, 0, 0, 0,
     create_Imm8_Y1, get_Imm8_Y1
   },
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(TILE_IMM16_X0),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEPRO_IMM16_X0),
     16, 1, 0, 0, 0, 0,
     create_Imm16_X0, get_Imm16_X0
   },
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(TILE_IMM16_X1),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEPRO_IMM16_X1),
     16, 1, 0, 0, 0, 0,
     create_Imm16_X1, get_Imm16_X1
   },
   {
-    TILE_OP_TYPE_ADDRESS, BFD_RELOC(TILE_JOFFLONG_X1),
-    29, 1, 0, 0, 1, TILE_LOG2_BUNDLE_ALIGNMENT_IN_BYTES,
+    TILEPRO_OP_TYPE_ADDRESS, BFD_RELOC(TILEPRO_JOFFLONG_X1),
+    29, 1, 0, 0, 1, TILEPRO_LOG2_BUNDLE_ALIGNMENT_IN_BYTES,
     create_JOffLong_X1, get_JOffLong_X1
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 0, 1, 0, 0,
     create_Dest_X0, get_Dest_X0
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 1, 0, 0, 0,
     create_SrcA_X0, get_SrcA_X0
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 0, 1, 0, 0,
     create_Dest_X1, get_Dest_X1
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 1, 0, 0, 0,
     create_SrcA_X1, get_SrcA_X1
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 0, 1, 0, 0,
     create_Dest_Y0, get_Dest_Y0
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 1, 0, 0, 0,
     create_SrcA_Y0, get_SrcA_Y0
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 0, 1, 0, 0,
     create_Dest_Y1, get_Dest_Y1
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 1, 0, 0, 0,
     create_SrcA_Y1, get_SrcA_Y1
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 1, 0, 0, 0,
     create_SrcA_Y2, get_SrcA_Y2
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 1, 0, 0, 0,
     create_SrcB_X0, get_SrcB_X0
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 1, 0, 0, 0,
     create_SrcB_X1, get_SrcB_X1
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 1, 0, 0, 0,
     create_SrcB_Y0, get_SrcB_Y0
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 1, 0, 0, 0,
     create_SrcB_Y1, get_SrcB_Y1
   },
   {
-    TILE_OP_TYPE_ADDRESS, BFD_RELOC(TILE_BROFF_X1),
-    17, 1, 0, 0, 1, TILE_LOG2_BUNDLE_ALIGNMENT_IN_BYTES,
+    TILEPRO_OP_TYPE_ADDRESS, BFD_RELOC(TILEPRO_BROFF_X1),
+    17, 1, 0, 0, 1, TILEPRO_LOG2_BUNDLE_ALIGNMENT_IN_BYTES,
     create_BrOff_X1, get_BrOff_X1
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 1, 1, 0, 0,
     create_Dest_X0, get_Dest_X0
   },
   {
-    TILE_OP_TYPE_ADDRESS, BFD_RELOC(NONE),
-    28, 1, 0, 0, 1, TILE_LOG2_BUNDLE_ALIGNMENT_IN_BYTES,
+    TILEPRO_OP_TYPE_ADDRESS, BFD_RELOC(NONE),
+    28, 1, 0, 0, 1, TILEPRO_LOG2_BUNDLE_ALIGNMENT_IN_BYTES,
     create_JOff_X1, get_JOff_X1
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 0, 1, 0, 0,
     create_SrcBDest_Y2, get_SrcBDest_Y2
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 1, 1, 0, 0,
     create_SrcA_X1, get_SrcA_X1
   },
   {
-    TILE_OP_TYPE_SPR, BFD_RELOC(TILE_MF_IMM15_X1),
+    TILEPRO_OP_TYPE_SPR, BFD_RELOC(TILEPRO_MF_IMM15_X1),
     15, 0, 0, 0, 0, 0,
     create_MF_Imm15_X1, get_MF_Imm15_X1
   },
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(TILE_MMSTART_X0),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEPRO_MMSTART_X0),
     5, 0, 0, 0, 0, 0,
     create_MMStart_X0, get_MMStart_X0
   },
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(TILE_MMEND_X0),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEPRO_MMEND_X0),
     5, 0, 0, 0, 0, 0,
     create_MMEnd_X0, get_MMEnd_X0
   },
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(TILE_MMSTART_X1),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEPRO_MMSTART_X1),
     5, 0, 0, 0, 0, 0,
     create_MMStart_X1, get_MMStart_X1
   },
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(TILE_MMEND_X1),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEPRO_MMEND_X1),
     5, 0, 0, 0, 0, 0,
     create_MMEnd_X1, get_MMEnd_X1
   },
   {
-    TILE_OP_TYPE_SPR, BFD_RELOC(TILE_MT_IMM15_X1),
+    TILEPRO_OP_TYPE_SPR, BFD_RELOC(TILEPRO_MT_IMM15_X1),
     15, 0, 0, 0, 0, 0,
     create_MT_Imm15_X1, get_MT_Imm15_X1
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 1, 1, 0, 0,
     create_Dest_Y0, get_Dest_Y0
   },
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(TILE_SHAMT_X0),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEPRO_SHAMT_X0),
     5, 0, 0, 0, 0, 0,
     create_ShAmt_X0, get_ShAmt_X0
   },
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(TILE_SHAMT_X1),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEPRO_SHAMT_X1),
     5, 0, 0, 0, 0, 0,
     create_ShAmt_X1, get_ShAmt_X1
   },
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(TILE_SHAMT_Y0),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEPRO_SHAMT_Y0),
     5, 0, 0, 0, 0, 0,
     create_ShAmt_Y0, get_ShAmt_Y0
   },
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(TILE_SHAMT_Y1),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEPRO_SHAMT_Y1),
     5, 0, 0, 0, 0, 0,
     create_ShAmt_Y1, get_ShAmt_Y1
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     6, 0, 1, 0, 0, 0,
     create_SrcBDest_Y2, get_SrcBDest_Y2
   },
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEPRO_DEST_IMM8_X1),
     8, 1, 0, 0, 0, 0,
     create_Dest_Imm8_X1, get_Dest_Imm8_X1
   },
   {
-    TILE_OP_TYPE_ADDRESS, BFD_RELOC(TILE_SN_BROFF),
-    10, 1, 0, 0, 1, TILE_LOG2_SN_INSTRUCTION_SIZE_IN_BYTES,
+    TILEPRO_OP_TYPE_ADDRESS, BFD_RELOC(NONE),
+    10, 1, 0, 0, 1, TILEPRO_LOG2_SN_INSTRUCTION_SIZE_IN_BYTES,
     create_BrOff_SN, get_BrOff_SN
   },
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(TILE_SN_UIMM8),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(NONE),
     8, 0, 0, 0, 0, 0,
     create_Imm8_SN, get_Imm8_SN
   },
   {
-    TILE_OP_TYPE_IMMEDIATE, BFD_RELOC(TILE_SN_IMM8),
+    TILEPRO_OP_TYPE_IMMEDIATE, BFD_RELOC(NONE),
     8, 1, 0, 0, 0, 0,
     create_Imm8_SN, get_Imm8_SN
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     2, 0, 0, 1, 0, 0,
     create_Dest_SN, get_Dest_SN
   },
   {
-    TILE_OP_TYPE_REGISTER, BFD_RELOC(NONE),
+    TILEPRO_OP_TYPE_REGISTER, BFD_RELOC(NONE),
     2, 0, 1, 0, 0, 0,
     create_Src_SN, get_Src_SN
   }
@@ -2416,10 +2522,10 @@ const struct tile_operand tile_operands[43] =
 /* Given a set of bundle bits and a specific pipe, returns which
  * instruction the bundle contains in that pipe.
  */
-const struct tile_opcode *
-find_opcode(tile_bundle_bits bits, tile_pipeline pipe)
+const struct tilepro_opcode *
+find_opcode(tilepro_bundle_bits bits, tilepro_pipeline pipe)
 {
-  const unsigned short *table = tile_bundle_decoder_fsms[pipe];
+  const unsigned short *table = tilepro_bundle_decoder_fsms[pipe];
   int index = 0;
 
   while (1)
@@ -2429,51 +2535,51 @@ find_opcode(tile_bundle_bits bits, tile_pipeline pipe)
       ((unsigned int)(bits >> (bitspec & 63))) & (bitspec >> 6);
 
     unsigned short next = table[index + 1 + bitfield];
-    if (next <= TILE_OPC_NONE)
-      return &tile_opcodes[next];
+    if (next <= TILEPRO_OPC_NONE)
+      return &tilepro_opcodes[next];
 
-    index = next - TILE_OPC_NONE;
+    index = next - TILEPRO_OPC_NONE;
   }
 }
 
 
 int
-parse_insn_tile(tile_bundle_bits bits,
-                unsigned int pc,
-                struct tile_decoded_instruction
-                decoded[TILE_MAX_INSTRUCTIONS_PER_BUNDLE])
+parse_insn_tilepro(tilepro_bundle_bits bits,
+                   unsigned int pc,
+                   struct tilepro_decoded_instruction
+                   decoded[TILEPRO_MAX_INSTRUCTIONS_PER_BUNDLE])
 {
   int num_instructions = 0;
   int pipe;
 
   int min_pipe, max_pipe;
-  if ((bits & TILE_BUNDLE_Y_ENCODING_MASK) == 0)
+  if ((bits & TILEPRO_BUNDLE_Y_ENCODING_MASK) == 0)
   {
-    min_pipe = TILE_PIPELINE_X0;
-    max_pipe = TILE_PIPELINE_X1;
+    min_pipe = TILEPRO_PIPELINE_X0;
+    max_pipe = TILEPRO_PIPELINE_X1;
   }
   else
   {
-    min_pipe = TILE_PIPELINE_Y0;
-    max_pipe = TILE_PIPELINE_Y2;
+    min_pipe = TILEPRO_PIPELINE_Y0;
+    max_pipe = TILEPRO_PIPELINE_Y2;
   }
 
   /* For each pipe, find an instruction that fits. */
   for (pipe = min_pipe; pipe <= max_pipe; pipe++)
   {
-    const struct tile_opcode *opc;
-    struct tile_decoded_instruction *d;
+    const struct tilepro_opcode *opc;
+    struct tilepro_decoded_instruction *d;
     int i;
 
     d = &decoded[num_instructions++];
-    opc = find_opcode (bits, (tile_pipeline)pipe);
+    opc = find_opcode (bits, (tilepro_pipeline)pipe);
     d->opcode = opc;
 
     /* Decode each operand, sign extending, etc. as appropriate. */
     for (i = 0; i < opc->num_operands; i++)
     {
-      const struct tile_operand *op =
-        &tile_operands[opc->operands[pipe][i]];
+      const struct tilepro_operand *op =
+        &tilepro_operands[opc->operands[pipe][i]];
       int opval = op->extract (bits);
       if (op->is_signed)
       {
@@ -2483,9 +2589,9 @@ parse_insn_tile(tile_bundle_bits bits,
       }
 
       /* Adjust PC-relative scaled branch offsets. */
-      if (op->type == TILE_OP_TYPE_ADDRESS)
+      if (op->type == TILEPRO_OP_TYPE_ADDRESS)
       {
-        opval *= TILE_BUNDLE_SIZE_IN_BYTES;
+        opval *= TILEPRO_BUNDLE_SIZE_IN_BYTES;
         opval += (int)pc;
       }
 
index d57007b..65b5f8a 100644 (file)
@@ -1,3 +1,23 @@
+/* TILE-Gx opcode information.
+ *
+ * Copyright 2011 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ *
+ *
+ *
+ *
+ *
+ */
+
 /* This define is BFD_RELOC_##x for real bfd, or -1 for everyone else. */
 #define BFD_RELOC(x) -1
 
@@ -6,10 +26,8 @@
 #define TREG_SN 56
 #define TREG_ZERO 63
 
-/* FIXME: Rename this. */
-#include <asm/opcode-tile_64.h>
-
 #include <linux/stddef.h>
+#include <asm/tile-desc.h>
 
 const struct tilegx_opcode tilegx_opcodes[334] =
 {
@@ -2040,12 +2058,12 @@ const struct tilegx_operand tilegx_operands[35] =
     create_BrOff_X1, get_BrOff_X1
   },
   {
-    TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(NONE),
+    TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_MMSTART_X0),
     6, 0, 0, 0, 0, 0,
     create_BFStart_X0, get_BFStart_X0
   },
   {
-    TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(NONE),
+    TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_MMEND_X0),
     6, 0, 0, 0, 0, 0,
     create_BFEnd_X0, get_BFEnd_X0
   },
index f9803df..4f47b8a 100644 (file)
 #include <linux/reboot.h>
 #include <linux/uaccess.h>
 #include <linux/ptrace.h>
-#include <asm/opcode-tile.h>
-#include <asm/opcode_constants.h>
 #include <asm/stack.h>
 #include <asm/traps.h>
 
 #include <arch/interrupts.h>
 #include <arch/spr_def.h>
+#include <arch/opcode.h>
 
 void __init trap_init(void)
 {
@@ -135,7 +134,7 @@ static int special_ill(bundle_bits bundle, int *sigp, int *codep)
        if (get_UnaryOpcodeExtension_X1(bundle) != ILL_UNARY_OPCODE_X1)
                return 0;
 #else
-       if (bundle & TILE_BUNDLE_Y_ENCODING_MASK)
+       if (bundle & TILEPRO_BUNDLE_Y_ENCODING_MASK)
                return 0;
        if (get_Opcode_X1(bundle) != SHUN_0_OPCODE_X1)
                return 0;
index 49284fa..a87d2a8 100644 (file)
@@ -79,8 +79,6 @@ EXPORT_SYMBOL(__umoddi3);
 int64_t __moddi3(int64_t dividend, int64_t divisor);
 EXPORT_SYMBOL(__moddi3);
 #ifndef __tilegx__
-uint64_t __ll_mul(uint64_t n0, uint64_t n1);
-EXPORT_SYMBOL(__ll_mul);
 int64_t __muldi3(int64_t, int64_t);
 EXPORT_SYMBOL(__muldi3);
 uint64_t __lshrdi3(uint64_t, unsigned int);
index b596e54..8f630ce 100644 (file)
@@ -768,25 +768,14 @@ static uint64_t blkio_get_stat(struct blkio_group *blkg,
        return disk_total;
 }
 
-static int blkio_check_dev_num(dev_t dev)
-{
-       int part = 0;
-       struct gendisk *disk;
-
-       disk = get_gendisk(dev, &part);
-       if (!disk || part)
-               return -ENODEV;
-
-       return 0;
-}
-
 static int blkio_policy_parse_and_set(char *buf,
        struct blkio_policy_node *newpn, enum blkio_policy_id plid, int fileid)
 {
+       struct gendisk *disk = NULL;
        char *s[4], *p, *major_s = NULL, *minor_s = NULL;
-       int ret;
        unsigned long major, minor;
-       int i = 0;
+       int i = 0, ret = -EINVAL;
+       int part;
        dev_t dev;
        u64 temp;
 
@@ -804,37 +793,36 @@ static int blkio_policy_parse_and_set(char *buf,
        }
 
        if (i != 2)
-               return -EINVAL;
+               goto out;
 
        p = strsep(&s[0], ":");
        if (p != NULL)
                major_s = p;
        else
-               return -EINVAL;
+               goto out;
 
        minor_s = s[0];
        if (!minor_s)
-               return -EINVAL;
+               goto out;
 
-       ret = strict_strtoul(major_s, 10, &major);
-       if (ret)
-               return -EINVAL;
+       if (strict_strtoul(major_s, 10, &major))
+               goto out;
 
-       ret = strict_strtoul(minor_s, 10, &minor);
-       if (ret)
-               return -EINVAL;
+       if (strict_strtoul(minor_s, 10, &minor))
+               goto out;
 
        dev = MKDEV(major, minor);
 
-       ret = strict_strtoull(s[1], 10, &temp);
-       if (ret)
-               return -EINVAL;
+       if (strict_strtoull(s[1], 10, &temp))
+               goto out;
 
        /* For rule removal, do not check for device presence. */
        if (temp) {
-               ret = blkio_check_dev_num(dev);
-               if (ret)
-                       return ret;
+               disk = get_gendisk(dev, &part);
+               if (!disk || part) {
+                       ret = -ENODEV;
+                       goto out;
+               }
        }
 
        newpn->dev = dev;
@@ -843,7 +831,7 @@ static int blkio_policy_parse_and_set(char *buf,
        case BLKIO_POLICY_PROP:
                if ((temp < BLKIO_WEIGHT_MIN && temp > 0) ||
                     temp > BLKIO_WEIGHT_MAX)
-                       return -EINVAL;
+                       goto out;
 
                newpn->plid = plid;
                newpn->fileid = fileid;
@@ -860,7 +848,7 @@ static int blkio_policy_parse_and_set(char *buf,
                case BLKIO_THROTL_read_iops_device:
                case BLKIO_THROTL_write_iops_device:
                        if (temp > THROTL_IOPS_MAX)
-                               return -EINVAL;
+                               goto out;
 
                        newpn->plid = plid;
                        newpn->fileid = fileid;
@@ -871,68 +859,96 @@ static int blkio_policy_parse_and_set(char *buf,
        default:
                BUG();
        }
-
-       return 0;
+       ret = 0;
+out:
+       put_disk(disk);
+       return ret;
 }
 
 unsigned int blkcg_get_weight(struct blkio_cgroup *blkcg,
                              dev_t dev)
 {
        struct blkio_policy_node *pn;
+       unsigned long flags;
+       unsigned int weight;
+
+       spin_lock_irqsave(&blkcg->lock, flags);
 
        pn = blkio_policy_search_node(blkcg, dev, BLKIO_POLICY_PROP,
                                BLKIO_PROP_weight_device);
        if (pn)
-               return pn->val.weight;
+               weight = pn->val.weight;
        else
-               return blkcg->weight;
+               weight = blkcg->weight;
+
+       spin_unlock_irqrestore(&blkcg->lock, flags);
+
+       return weight;
 }
 EXPORT_SYMBOL_GPL(blkcg_get_weight);
 
 uint64_t blkcg_get_read_bps(struct blkio_cgroup *blkcg, dev_t dev)
 {
        struct blkio_policy_node *pn;
+       unsigned long flags;
+       uint64_t bps = -1;
 
+       spin_lock_irqsave(&blkcg->lock, flags);
        pn = blkio_policy_search_node(blkcg, dev, BLKIO_POLICY_THROTL,
                                BLKIO_THROTL_read_bps_device);
        if (pn)
-               return pn->val.bps;
-       else
-               return -1;
+               bps = pn->val.bps;
+       spin_unlock_irqrestore(&blkcg->lock, flags);
+
+       return bps;
 }
 
 uint64_t blkcg_get_write_bps(struct blkio_cgroup *blkcg, dev_t dev)
 {
        struct blkio_policy_node *pn;
+       unsigned long flags;
+       uint64_t bps = -1;
+
+       spin_lock_irqsave(&blkcg->lock, flags);
        pn = blkio_policy_search_node(blkcg, dev, BLKIO_POLICY_THROTL,
                                BLKIO_THROTL_write_bps_device);
        if (pn)
-               return pn->val.bps;
-       else
-               return -1;
+               bps = pn->val.bps;
+       spin_unlock_irqrestore(&blkcg->lock, flags);
+
+       return bps;
 }
 
 unsigned int blkcg_get_read_iops(struct blkio_cgroup *blkcg, dev_t dev)
 {
        struct blkio_policy_node *pn;
+       unsigned long flags;
+       unsigned int iops = -1;
 
+       spin_lock_irqsave(&blkcg->lock, flags);
        pn = blkio_policy_search_node(blkcg, dev, BLKIO_POLICY_THROTL,
                                BLKIO_THROTL_read_iops_device);
        if (pn)
-               return pn->val.iops;
-       else
-               return -1;
+               iops = pn->val.iops;
+       spin_unlock_irqrestore(&blkcg->lock, flags);
+
+       return iops;
 }
 
 unsigned int blkcg_get_write_iops(struct blkio_cgroup *blkcg, dev_t dev)
 {
        struct blkio_policy_node *pn;
+       unsigned long flags;
+       unsigned int iops = -1;
+
+       spin_lock_irqsave(&blkcg->lock, flags);
        pn = blkio_policy_search_node(blkcg, dev, BLKIO_POLICY_THROTL,
                                BLKIO_THROTL_write_iops_device);
        if (pn)
-               return pn->val.iops;
-       else
-               return -1;
+               iops = pn->val.iops;
+       spin_unlock_irqrestore(&blkcg->lock, flags);
+
+       return iops;
 }
 
 /* Checks whether user asked for deleting a policy rule */
@@ -1085,6 +1101,7 @@ static int blkiocg_file_write(struct cgroup *cgrp, struct cftype *cft,
 
        if (blkio_delete_rule_command(newpn)) {
                blkio_policy_delete_node(pn);
+               kfree(pn);
                spin_unlock_irq(&blkcg->lock);
                goto update_io_group;
        }
index a71d290..6f3ace7 100644 (file)
@@ -188,7 +188,7 @@ struct blkio_policy_node {
        union {
                unsigned int weight;
                /*
-                * Rate read/write in terms of byptes per second
+                * Rate read/write in terms of bytes per second
                 * Whether this rate represents read or write is determined
                 * by file type "fileid".
                 */
index d34433a..f43c8a5 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/task_io_accounting_ops.h>
 #include <linux/fault-inject.h>
 #include <linux/list_sort.h>
+#include <linux/delay.h>
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/block.h>
@@ -38,8 +39,6 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(block_bio_remap);
 EXPORT_TRACEPOINT_SYMBOL_GPL(block_rq_remap);
 EXPORT_TRACEPOINT_SYMBOL_GPL(block_bio_complete);
 
-static int __make_request(struct request_queue *q, struct bio *bio);
-
 /*
  * For the allocated request tables
  */
@@ -347,30 +346,80 @@ void blk_put_queue(struct request_queue *q)
 }
 EXPORT_SYMBOL(blk_put_queue);
 
-/*
- * Note: If a driver supplied the queue lock, it is disconnected
- * by this function. The actual state of the lock doesn't matter
- * here as the request_queue isn't accessible after this point
- * (QUEUE_FLAG_DEAD is set) and no other requests will be queued.
+/**
+ * blk_drain_queue - drain requests from request_queue
+ * @q: queue to drain
+ * @drain_all: whether to drain all requests or only the ones w/ ELVPRIV
+ *
+ * Drain requests from @q.  If @drain_all is set, all requests are drained.
+ * If not, only ELVPRIV requests are drained.  The caller is responsible
+ * for ensuring that no new requests which need to be drained are queued.
+ */
+void blk_drain_queue(struct request_queue *q, bool drain_all)
+{
+       while (true) {
+               int nr_rqs;
+
+               spin_lock_irq(q->queue_lock);
+
+               elv_drain_elevator(q);
+               if (drain_all)
+                       blk_throtl_drain(q);
+
+               __blk_run_queue(q);
+
+               if (drain_all)
+                       nr_rqs = q->rq.count[0] + q->rq.count[1];
+               else
+                       nr_rqs = q->rq.elvpriv;
+
+               spin_unlock_irq(q->queue_lock);
+
+               if (!nr_rqs)
+                       break;
+               msleep(10);
+       }
+}
+
+/**
+ * blk_cleanup_queue - shutdown a request queue
+ * @q: request queue to shutdown
+ *
+ * Mark @q DEAD, drain all pending requests, destroy and put it.  All
+ * future requests will be failed immediately with -ENODEV.
  */
 void blk_cleanup_queue(struct request_queue *q)
 {
-       /*
-        * We know we have process context here, so we can be a little
-        * cautious and ensure that pending block actions on this device
-        * are done before moving on. Going into this function, we should
-        * not have processes doing IO to this device.
-        */
-       blk_sync_queue(q);
+       spinlock_t *lock = q->queue_lock;
 
-       del_timer_sync(&q->backing_dev_info.laptop_mode_wb_timer);
+       /* mark @q DEAD, no new request or merges will be allowed afterwards */
        mutex_lock(&q->sysfs_lock);
        queue_flag_set_unlocked(QUEUE_FLAG_DEAD, q);
-       mutex_unlock(&q->sysfs_lock);
+
+       spin_lock_irq(lock);
+       queue_flag_set(QUEUE_FLAG_NOMERGES, q);
+       queue_flag_set(QUEUE_FLAG_NOXMERGES, q);
+       queue_flag_set(QUEUE_FLAG_DEAD, q);
 
        if (q->queue_lock != &q->__queue_lock)
                q->queue_lock = &q->__queue_lock;
 
+       spin_unlock_irq(lock);
+       mutex_unlock(&q->sysfs_lock);
+
+       /*
+        * Drain all requests queued before DEAD marking.  The caller might
+        * be trying to tear down @q before its elevator is initialized, in
+        * which case we don't want to call into draining.
+        */
+       if (q->elevator)
+               blk_drain_queue(q, true);
+
+       /* @q won't process any more request, flush async actions */
+       del_timer_sync(&q->backing_dev_info.laptop_mode_wb_timer);
+       blk_sync_queue(q);
+
+       /* @q is and will stay empty, shutdown and put */
        blk_put_queue(q);
 }
 EXPORT_SYMBOL(blk_cleanup_queue);
@@ -541,7 +590,7 @@ blk_init_allocated_queue_node(struct request_queue *q, request_fn_proc *rfn,
        /*
         * This also sets hw/phys segments, boundary and size
         */
-       blk_queue_make_request(q, __make_request);
+       blk_queue_make_request(q, blk_queue_bio);
 
        q->sg_reserved_size = INT_MAX;
 
@@ -576,7 +625,7 @@ static inline void blk_free_request(struct request_queue *q, struct request *rq)
 }
 
 static struct request *
-blk_alloc_request(struct request_queue *q, int flags, int priv, gfp_t gfp_mask)
+blk_alloc_request(struct request_queue *q, unsigned int flags, gfp_t gfp_mask)
 {
        struct request *rq = mempool_alloc(q->rq.rq_pool, gfp_mask);
 
@@ -587,12 +636,10 @@ blk_alloc_request(struct request_queue *q, int flags, int priv, gfp_t gfp_mask)
 
        rq->cmd_flags = flags | REQ_ALLOCED;
 
-       if (priv) {
-               if (unlikely(elv_set_request(q, rq, gfp_mask))) {
-                       mempool_free(rq, q->rq.rq_pool);
-                       return NULL;
-               }
-               rq->cmd_flags |= REQ_ELVPRIV;
+       if ((flags & REQ_ELVPRIV) &&
+           unlikely(elv_set_request(q, rq, gfp_mask))) {
+               mempool_free(rq, q->rq.rq_pool);
+               return NULL;
        }
 
        return rq;
@@ -651,12 +698,13 @@ static void __freed_request(struct request_queue *q, int sync)
  * A request has just been released.  Account for it, update the full and
  * congestion status, wake up any waiters.   Called under q->queue_lock.
  */
-static void freed_request(struct request_queue *q, int sync, int priv)
+static void freed_request(struct request_queue *q, unsigned int flags)
 {
        struct request_list *rl = &q->rq;
+       int sync = rw_is_sync(flags);
 
        rl->count[sync]--;
-       if (priv)
+       if (flags & REQ_ELVPRIV)
                rl->elvpriv--;
 
        __freed_request(q, sync);
@@ -684,10 +732,19 @@ static bool blk_rq_should_init_elevator(struct bio *bio)
        return true;
 }
 
-/*
- * Get a free request, queue_lock must be held.
- * Returns NULL on failure, with queue_lock held.
- * Returns !NULL on success, with queue_lock *not held*.
+/**
+ * get_request - get a free request
+ * @q: request_queue to allocate request from
+ * @rw_flags: RW and SYNC flags
+ * @bio: bio to allocate request for (can be %NULL)
+ * @gfp_mask: allocation mask
+ *
+ * Get a free request from @q.  This function may fail under memory
+ * pressure or if @q is dead.
+ *
+ * Must be callled with @q->queue_lock held and,
+ * Returns %NULL on failure, with @q->queue_lock held.
+ * Returns !%NULL on success, with @q->queue_lock *not held*.
  */
 static struct request *get_request(struct request_queue *q, int rw_flags,
                                   struct bio *bio, gfp_t gfp_mask)
@@ -696,7 +753,10 @@ static struct request *get_request(struct request_queue *q, int rw_flags,
        struct request_list *rl = &q->rq;
        struct io_context *ioc = NULL;
        const bool is_sync = rw_is_sync(rw_flags) != 0;
-       int may_queue, priv = 0;
+       int may_queue;
+
+       if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)))
+               return NULL;
 
        may_queue = elv_may_queue(q, rw_flags);
        if (may_queue == ELV_MQUEUE_NO)
@@ -740,17 +800,17 @@ static struct request *get_request(struct request_queue *q, int rw_flags,
        rl->count[is_sync]++;
        rl->starved[is_sync] = 0;
 
-       if (blk_rq_should_init_elevator(bio)) {
-               priv = !test_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
-               if (priv)
-                       rl->elvpriv++;
+       if (blk_rq_should_init_elevator(bio) &&
+           !test_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags)) {
+               rw_flags |= REQ_ELVPRIV;
+               rl->elvpriv++;
        }
 
        if (blk_queue_io_stat(q))
                rw_flags |= REQ_IO_STAT;
        spin_unlock_irq(q->queue_lock);
 
-       rq = blk_alloc_request(q, rw_flags, priv, gfp_mask);
+       rq = blk_alloc_request(q, rw_flags, gfp_mask);
        if (unlikely(!rq)) {
                /*
                 * Allocation failed presumably due to memory. Undo anything
@@ -760,7 +820,7 @@ static struct request *get_request(struct request_queue *q, int rw_flags,
                 * wait queue, but this is pretty rare.
                 */
                spin_lock_irq(q->queue_lock);
-               freed_request(q, is_sync, priv);
+               freed_request(q, rw_flags);
 
                /*
                 * in the very unlikely event that allocation failed and no
@@ -790,11 +850,18 @@ out:
        return rq;
 }
 
-/*
- * No available requests for this queue, wait for some requests to become
- * available.
+/**
+ * get_request_wait - get a free request with retry
+ * @q: request_queue to allocate request from
+ * @rw_flags: RW and SYNC flags
+ * @bio: bio to allocate request for (can be %NULL)
+ *
+ * Get a free request from @q.  This function keeps retrying under memory
+ * pressure and fails iff @q is dead.
  *
- * Called with q->queue_lock held, and returns with it unlocked.
+ * Must be callled with @q->queue_lock held and,
+ * Returns %NULL on failure, with @q->queue_lock held.
+ * Returns !%NULL on success, with @q->queue_lock *not held*.
  */
 static struct request *get_request_wait(struct request_queue *q, int rw_flags,
                                        struct bio *bio)
@@ -808,6 +875,9 @@ static struct request *get_request_wait(struct request_queue *q, int rw_flags,
                struct io_context *ioc;
                struct request_list *rl = &q->rq;
 
+               if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)))
+                       return NULL;
+
                prepare_to_wait_exclusive(&rl->wait[is_sync], &wait,
                                TASK_UNINTERRUPTIBLE);
 
@@ -838,19 +908,15 @@ struct request *blk_get_request(struct request_queue *q, int rw, gfp_t gfp_mask)
 {
        struct request *rq;
 
-       if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)))
-               return NULL;
-
        BUG_ON(rw != READ && rw != WRITE);
 
        spin_lock_irq(q->queue_lock);
-       if (gfp_mask & __GFP_WAIT) {
+       if (gfp_mask & __GFP_WAIT)
                rq = get_request_wait(q, rw, NULL);
-       } else {
+       else
                rq = get_request(q, rw, NULL, gfp_mask);
-               if (!rq)
-                       spin_unlock_irq(q->queue_lock);
-       }
+       if (!rq)
+               spin_unlock_irq(q->queue_lock);
        /* q->queue_lock is unlocked at this point */
 
        return rq;
@@ -1052,14 +1118,13 @@ void __blk_put_request(struct request_queue *q, struct request *req)
         * it didn't come out of our reserved rq pools
         */
        if (req->cmd_flags & REQ_ALLOCED) {
-               int is_sync = rq_is_sync(req) != 0;
-               int priv = req->cmd_flags & REQ_ELVPRIV;
+               unsigned int flags = req->cmd_flags;
 
                BUG_ON(!list_empty(&req->queuelist));
                BUG_ON(!hlist_unhashed(&req->hash));
 
                blk_free_request(q, req);
-               freed_request(q, is_sync, priv);
+               freed_request(q, flags);
        }
 }
 EXPORT_SYMBOL_GPL(__blk_put_request);
@@ -1161,18 +1226,32 @@ static bool bio_attempt_front_merge(struct request_queue *q,
        return true;
 }
 
-/*
- * Attempts to merge with the plugged list in the current process. Returns
- * true if merge was successful, otherwise false.
+/**
+ * attempt_plug_merge - try to merge with %current's plugged list
+ * @q: request_queue new bio is being queued at
+ * @bio: new bio being queued
+ * @request_count: out parameter for number of traversed plugged requests
+ *
+ * Determine whether @bio being queued on @q can be merged with a request
+ * on %current's plugged list.  Returns %true if merge was successful,
+ * otherwise %false.
+ *
+ * This function is called without @q->queue_lock; however, elevator is
+ * accessed iff there already are requests on the plugged list which in
+ * turn guarantees validity of the elevator.
+ *
+ * Note that, on successful merge, elevator operation
+ * elevator_bio_merged_fn() will be called without queue lock.  Elevator
+ * must be ready for this.
  */
-static bool attempt_plug_merge(struct task_struct *tsk, struct request_queue *q,
-                              struct bio *bio, unsigned int *request_count)
+static bool attempt_plug_merge(struct request_queue *q, struct bio *bio,
+                              unsigned int *request_count)
 {
        struct blk_plug *plug;
        struct request *rq;
        bool ret = false;
 
-       plug = tsk->plug;
+       plug = current->plug;
        if (!plug)
                goto out;
        *request_count = 0;
@@ -1202,7 +1281,6 @@ out:
 
 void init_request_from_bio(struct request *req, struct bio *bio)
 {
-       req->cpu = bio->bi_comp_cpu;
        req->cmd_type = REQ_TYPE_FS;
 
        req->cmd_flags |= bio->bi_rw & REQ_COMMON_MASK;
@@ -1215,7 +1293,7 @@ void init_request_from_bio(struct request *req, struct bio *bio)
        blk_rq_bio_prep(req->q, req, bio);
 }
 
-static int __make_request(struct request_queue *q, struct bio *bio)
+void blk_queue_bio(struct request_queue *q, struct bio *bio)
 {
        const bool sync = !!(bio->bi_rw & REQ_SYNC);
        struct blk_plug *plug;
@@ -1240,8 +1318,8 @@ static int __make_request(struct request_queue *q, struct bio *bio)
         * Check if we can merge with the plugged list before grabbing
         * any locks.
         */
-       if (attempt_plug_merge(current, q, bio, &request_count))
-               goto out;
+       if (attempt_plug_merge(q, bio, &request_count))
+               return;
 
        spin_lock_irq(q->queue_lock);
 
@@ -1275,6 +1353,10 @@ get_rq:
         * Returns with the queue unlocked.
         */
        req = get_request_wait(q, rw_flags, bio);
+       if (unlikely(!req)) {
+               bio_endio(bio, -ENODEV);        /* @q is dead */
+               goto out_unlock;
+       }
 
        /*
         * After dropping the lock and possibly sleeping here, our request
@@ -1284,8 +1366,7 @@ get_rq:
         */
        init_request_from_bio(req, bio);
 
-       if (test_bit(QUEUE_FLAG_SAME_COMP, &q->queue_flags) ||
-           bio_flagged(bio, BIO_CPU_AFFINE))
+       if (test_bit(QUEUE_FLAG_SAME_COMP, &q->queue_flags))
                req->cpu = raw_smp_processor_id();
 
        plug = current->plug;
@@ -1316,9 +1397,8 @@ get_rq:
 out_unlock:
                spin_unlock_irq(q->queue_lock);
        }
-out:
-       return 0;
 }
+EXPORT_SYMBOL_GPL(blk_queue_bio);      /* for device mapper only */
 
 /*
  * If bio->bi_dev is a partition, remap the location
@@ -1417,165 +1497,135 @@ static inline int bio_check_eod(struct bio *bio, unsigned int nr_sectors)
        return 0;
 }
 
-/**
- * generic_make_request - hand a buffer to its device driver for I/O
- * @bio:  The bio describing the location in memory and on the device.
- *
- * generic_make_request() is used to make I/O requests of block
- * devices. It is passed a &struct bio, which describes the I/O that needs
- * to be done.
- *
- * generic_make_request() does not return any status.  The
- * success/failure status of the request, along with notification of
- * completion, is delivered asynchronously through the bio->bi_end_io
- * function described (one day) else where.
- *
- * The caller of generic_make_request must make sure that bi_io_vec
- * are set to describe the memory buffer, and that bi_dev and bi_sector are
- * set to describe the device address, and the
- * bi_end_io and optionally bi_private are set to describe how
- * completion notification should be signaled.
- *
- * generic_make_request and the drivers it calls may use bi_next if this
- * bio happens to be merged with someone else, and may change bi_dev and
- * bi_sector for remaps as it sees fit.  So the values of these fields
- * should NOT be depended on after the call to generic_make_request.
- */
-static inline void __generic_make_request(struct bio *bio)
+static noinline_for_stack bool
+generic_make_request_checks(struct bio *bio)
 {
        struct request_queue *q;
-       sector_t old_sector;
-       int ret, nr_sectors = bio_sectors(bio);
-       dev_t old_dev;
+       int nr_sectors = bio_sectors(bio);
        int err = -EIO;
+       char b[BDEVNAME_SIZE];
+       struct hd_struct *part;
 
        might_sleep();
 
        if (bio_check_eod(bio, nr_sectors))
                goto end_io;
 
-       /*
-        * Resolve the mapping until finished. (drivers are
-        * still free to implement/resolve their own stacking
-        * by explicitly returning 0)
-        *
-        * NOTE: we don't repeat the blk_size check for each new device.
-        * Stacking drivers are expected to know what they are doing.
-        */
-       old_sector = -1;
-       old_dev = 0;
-       do {
-               char b[BDEVNAME_SIZE];
-               struct hd_struct *part;
-
-               q = bdev_get_queue(bio->bi_bdev);
-               if (unlikely(!q)) {
-                       printk(KERN_ERR
-                              "generic_make_request: Trying to access "
-                               "nonexistent block-device %s (%Lu)\n",
-                               bdevname(bio->bi_bdev, b),
-                               (long long) bio->bi_sector);
-                       goto end_io;
-               }
-
-               if (unlikely(!(bio->bi_rw & REQ_DISCARD) &&
-                            nr_sectors > queue_max_hw_sectors(q))) {
-                       printk(KERN_ERR "bio too big device %s (%u > %u)\n",
-                              bdevname(bio->bi_bdev, b),
-                              bio_sectors(bio),
-                              queue_max_hw_sectors(q));
-                       goto end_io;
-               }
-
-               if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)))
-                       goto end_io;
-
-               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;
-
-               /*
-                * If this device has partitions, remap block n
-                * of partition p to block n+start(p) of the disk.
-                */
-               blk_partition_remap(bio);
+       q = bdev_get_queue(bio->bi_bdev);
+       if (unlikely(!q)) {
+               printk(KERN_ERR
+                      "generic_make_request: Trying to access "
+                       "nonexistent block-device %s (%Lu)\n",
+                       bdevname(bio->bi_bdev, b),
+                       (long long) bio->bi_sector);
+               goto end_io;
+       }
 
-               if (bio_integrity_enabled(bio) && bio_integrity_prep(bio))
-                       goto end_io;
+       if (unlikely(!(bio->bi_rw & REQ_DISCARD) &&
+                    nr_sectors > queue_max_hw_sectors(q))) {
+               printk(KERN_ERR "bio too big device %s (%u > %u)\n",
+                      bdevname(bio->bi_bdev, b),
+                      bio_sectors(bio),
+                      queue_max_hw_sectors(q));
+               goto end_io;
+       }
 
-               if (old_sector != -1)
-                       trace_block_bio_remap(q, bio, old_dev, old_sector);
+       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;
 
-               old_sector = bio->bi_sector;
-               old_dev = bio->bi_bdev->bd_dev;
+       /*
+        * If this device has partitions, remap block n
+        * of partition p to block n+start(p) of the disk.
+        */
+       blk_partition_remap(bio);
 
-               if (bio_check_eod(bio, nr_sectors))
-                       goto end_io;
+       if (bio_integrity_enabled(bio) && bio_integrity_prep(bio))
+               goto end_io;
 
-               /*
-                * Filter flush bio's early so that make_request based
-                * drivers without flush support don't have to worry
-                * about them.
-                */
-               if ((bio->bi_rw & (REQ_FLUSH | REQ_FUA)) && !q->flush_flags) {
-                       bio->bi_rw &= ~(REQ_FLUSH | REQ_FUA);
-                       if (!nr_sectors) {
-                               err = 0;
-                               goto end_io;
-                       }
-               }
+       if (bio_check_eod(bio, nr_sectors))
+               goto end_io;
 
-               if ((bio->bi_rw & REQ_DISCARD) &&
-                   (!blk_queue_discard(q) ||
-                    ((bio->bi_rw & REQ_SECURE) &&
-                     !blk_queue_secdiscard(q)))) {
-                       err = -EOPNOTSUPP;
+       /*
+        * Filter flush bio's early so that make_request based
+        * drivers without flush support don't have to worry
+        * about them.
+        */
+       if ((bio->bi_rw & (REQ_FLUSH | REQ_FUA)) && !q->flush_flags) {
+               bio->bi_rw &= ~(REQ_FLUSH | REQ_FUA);
+               if (!nr_sectors) {
+                       err = 0;
                        goto end_io;
                }
+       }
 
-               if (blk_throtl_bio(q, &bio))
-                       goto end_io;
-
-               /*
-                * If bio = NULL, bio has been throttled and will be submitted
-                * later.
-                */
-               if (!bio)
-                       break;
-
-               trace_block_bio_queue(q, bio);
+       if ((bio->bi_rw & REQ_DISCARD) &&
+           (!blk_queue_discard(q) ||
+            ((bio->bi_rw & REQ_SECURE) &&
+             !blk_queue_secdiscard(q)))) {
+               err = -EOPNOTSUPP;
+               goto end_io;
+       }
 
-               ret = q->make_request_fn(q, bio);
-       } while (ret);
+       if (blk_throtl_bio(q, bio))
+               return false;   /* throttled, will be resubmitted later */
 
-       return;
+       trace_block_bio_queue(q, bio);
+       return true;
 
 end_io:
        bio_endio(bio, err);
+       return false;
 }
 
-/*
- * We only want one ->make_request_fn to be active at a time,
- * else stack usage with stacked devices could be a problem.
- * So use current->bio_list to keep a list of requests
- * submited by a make_request_fn function.
- * current->bio_list is also used as a flag to say if
- * generic_make_request is currently active in this task or not.
- * If it is NULL, then no make_request is active.  If it is non-NULL,
- * then a make_request is active, and new requests should be added
- * at the tail
+/**
+ * generic_make_request - hand a buffer to its device driver for I/O
+ * @bio:  The bio describing the location in memory and on the device.
+ *
+ * generic_make_request() is used to make I/O requests of block
+ * devices. It is passed a &struct bio, which describes the I/O that needs
+ * to be done.
+ *
+ * generic_make_request() does not return any status.  The
+ * success/failure status of the request, along with notification of
+ * completion, is delivered asynchronously through the bio->bi_end_io
+ * function described (one day) else where.
+ *
+ * The caller of generic_make_request must make sure that bi_io_vec
+ * are set to describe the memory buffer, and that bi_dev and bi_sector are
+ * set to describe the device address, and the
+ * bi_end_io and optionally bi_private are set to describe how
+ * completion notification should be signaled.
+ *
+ * generic_make_request and the drivers it calls may use bi_next if this
+ * bio happens to be merged with someone else, and may resubmit the bio to
+ * a lower device by calling into generic_make_request recursively, which
+ * means the bio should NOT be touched after the call to ->make_request_fn.
  */
 void generic_make_request(struct bio *bio)
 {
        struct bio_list bio_list_on_stack;
 
+       if (!generic_make_request_checks(bio))
+               return;
+
+       /*
+        * We only want one ->make_request_fn to be active at a time, else
+        * stack usage with stacked devices could be a problem.  So use
+        * current->bio_list to keep a list of requests submited by a
+        * make_request_fn function.  current->bio_list is also used as a
+        * flag to say if generic_make_request is currently active in this
+        * task or not.  If it is NULL, then no make_request is active.  If
+        * it is non-NULL, then a make_request is active, and new requests
+        * should be added at the tail
+        */
        if (current->bio_list) {
-               /* make_request is active */
                bio_list_add(current->bio_list, bio);
                return;
        }
+
        /* following loop may be a bit non-obvious, and so deserves some
         * explanation.
         * Before entering the loop, bio->bi_next is NULL (as all callers
@@ -1583,22 +1633,21 @@ void generic_make_request(struct bio *bio)
         * We pretend that we have just taken it off a longer list, so
         * we assign bio_list to a pointer to the bio_list_on_stack,
         * thus initialising the bio_list of new bios to be
-        * added.  __generic_make_request may indeed add some more bios
+        * added.  ->make_request() may indeed add some more bios
         * through a recursive call to generic_make_request.  If it
         * did, we find a non-NULL value in bio_list and re-enter the loop
         * from the top.  In this case we really did just take the bio
         * of the top of the list (no pretending) and so remove it from
-        * bio_list, and call into __generic_make_request again.
-        *
-        * The loop was structured like this to make only one call to
-        * __generic_make_request (which is important as it is large and
-        * inlined) and to keep the structure simple.
+        * bio_list, and call into ->make_request() again.
         */
        BUG_ON(bio->bi_next);
        bio_list_init(&bio_list_on_stack);
        current->bio_list = &bio_list_on_stack;
        do {
-               __generic_make_request(bio);
+               struct request_queue *q = bdev_get_queue(bio->bi_bdev);
+
+               q->make_request_fn(q, bio);
+
                bio = bio_list_pop(current->bio_list);
        } while (bio);
        current->bio_list = NULL; /* deactivate */
@@ -1725,6 +1774,8 @@ int blk_insert_cloned_request(struct request_queue *q, struct request *rq)
                where = ELEVATOR_INSERT_FLUSH;
 
        add_acct_request(q, rq, where);
+       if (where == ELEVATOR_INSERT_FLUSH)
+               __blk_run_queue(q);
        spin_unlock_irqrestore(q->queue_lock, flags);
 
        return 0;
@@ -2628,6 +2679,20 @@ EXPORT_SYMBOL(kblockd_schedule_delayed_work);
 
 #define PLUG_MAGIC     0x91827364
 
+/**
+ * blk_start_plug - initialize blk_plug and track it inside the task_struct
+ * @plug:      The &struct blk_plug that needs to be initialized
+ *
+ * Description:
+ *   Tracking blk_plug inside the task_struct will help with auto-flushing the
+ *   pending I/O should the task end up blocking between blk_start_plug() and
+ *   blk_finish_plug(). This is important from a performance perspective, but
+ *   also ensures that we don't deadlock. For instance, if the task is blocking
+ *   for a memory allocation, memory reclaim could end up wanting to free a
+ *   page belonging to that request that is currently residing in our private
+ *   plug. By flushing the pending I/O when the process goes to sleep, we avoid
+ *   this kind of deadlock.
+ */
 void blk_start_plug(struct blk_plug *plug)
 {
        struct task_struct *tsk = current;
index 491eb30..720ad60 100644 (file)
@@ -320,7 +320,7 @@ void blk_insert_flush(struct request *rq)
                return;
        }
 
-       BUG_ON(!rq->bio || rq->bio != rq->biotail);
+       BUG_ON(rq->bio != rq->biotail); /*assumes zero or single bio rq */
 
        /*
         * If there's data but flush is not necessary, the request can be
@@ -330,7 +330,6 @@ void blk_insert_flush(struct request *rq)
        if ((policy & REQ_FSEQ_DATA) &&
            !(policy & (REQ_FSEQ_PREFLUSH | REQ_FSEQ_POSTFLUSH))) {
                list_add_tail(&rq->queuelist, &q->queue_head);
-               blk_run_queue_async(q);
                return;
        }
 
index 60fda88..e7f9f65 100644 (file)
@@ -457,11 +457,11 @@ queue_attr_store(struct kobject *kobj, struct attribute *attr,
 }
 
 /**
- * blk_cleanup_queue: - release a &struct request_queue when it is no longer needed
- * @kobj:    the kobj belonging of the request queue to be released
+ * blk_release_queue: - release a &struct request_queue when it is no longer needed
+ * @kobj:    the kobj belonging to the request queue to be released
  *
  * Description:
- *     blk_cleanup_queue is the pair to blk_init_queue() or
+ *     blk_release_queue is the pair to blk_init_queue() or
  *     blk_queue_make_request().  It should be called when a request queue is
  *     being released; typically when a block device is being de-registered.
  *     Currently, its primary task it to free all the &struct request
@@ -490,6 +490,7 @@ static void blk_release_queue(struct kobject *kobj)
        if (q->queue_tags)
                __blk_queue_free_tags(q);
 
+       blk_throtl_release(q);
        blk_trace_shutdown(q);
 
        bdi_destroy(&q->backing_dev_info);
index ece65fc..e74d6d1 100644 (file)
@@ -286,12 +286,14 @@ void blk_queue_end_tag(struct request_queue *q, struct request *rq)
 
        BUG_ON(tag == -1);
 
-       if (unlikely(tag >= bqt->real_max_depth))
+       if (unlikely(tag >= bqt->max_depth)) {
                /*
                 * This can happen after tag depth has been reduced.
-                * FIXME: how about a warning or info message here?
+                * But tag shouldn't be larger than real_max_depth.
                 */
+               WARN_ON(tag >= bqt->real_max_depth);
                return;
+       }
 
        list_del_init(&rq->queuelist);
        rq->cmd_flags &= ~REQ_QUEUED;
index a19f58c..4553245 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/bio.h>
 #include <linux/blktrace_api.h>
 #include "blk-cgroup.h"
+#include "blk.h"
 
 /* Max dispatch from a group in 1 round */
 static int throtl_grp_quantum = 8;
@@ -302,16 +303,16 @@ throtl_grp *throtl_find_tg(struct throtl_data *td, struct blkio_cgroup *blkcg)
        return tg;
 }
 
-/*
- * This function returns with queue lock unlocked in case of error, like
- * request queue is no more
- */
 static struct throtl_grp * throtl_get_tg(struct throtl_data *td)
 {
        struct throtl_grp *tg = NULL, *__tg = NULL;
        struct blkio_cgroup *blkcg;
        struct request_queue *q = td->queue;
 
+       /* no throttling for dead queue */
+       if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)))
+               return NULL;
+
        rcu_read_lock();
        blkcg = task_blkio_cgroup(current);
        tg = throtl_find_tg(td, blkcg);
@@ -323,32 +324,22 @@ static struct throtl_grp * throtl_get_tg(struct throtl_data *td)
        /*
         * Need to allocate a group. Allocation of group also needs allocation
         * of per cpu stats which in-turn takes a mutex() and can block. Hence
-        * we need to drop rcu lock and queue_lock before we call alloc
-        *
-        * Take the request queue reference to make sure queue does not
-        * go away once we return from allocation.
+        * we need to drop rcu lock and queue_lock before we call alloc.
         */
-       blk_get_queue(q);
        rcu_read_unlock();
        spin_unlock_irq(q->queue_lock);
 
        tg = throtl_alloc_tg(td);
-       /*
-        * We might have slept in group allocation. Make sure queue is not
-        * dead
-        */
-       if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags))) {
-               blk_put_queue(q);
-               if (tg)
-                       kfree(tg);
-
-               return ERR_PTR(-ENODEV);
-       }
-       blk_put_queue(q);
 
        /* Group allocated and queue is still alive. take the lock */
        spin_lock_irq(q->queue_lock);
 
+       /* Make sure @q is still alive */
+       if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags))) {
+               kfree(tg);
+               return NULL;
+       }
+
        /*
         * Initialize the new group. After sleeping, read the blkcg again.
         */
@@ -1014,11 +1005,6 @@ static void throtl_release_tgs(struct throtl_data *td)
        }
 }
 
-static void throtl_td_free(struct throtl_data *td)
-{
-       kfree(td);
-}
-
 /*
  * Blk cgroup controller notification saying that blkio_group object is being
  * delinked as associated cgroup object is going away. That also means that
@@ -1123,17 +1109,17 @@ static struct blkio_policy_type blkio_policy_throtl = {
        .plid = BLKIO_POLICY_THROTL,
 };
 
-int blk_throtl_bio(struct request_queue *q, struct bio **biop)
+bool blk_throtl_bio(struct request_queue *q, struct bio *bio)
 {
        struct throtl_data *td = q->td;
        struct throtl_grp *tg;
-       struct bio *bio = *biop;
        bool rw = bio_data_dir(bio), update_disptime = true;
        struct blkio_cgroup *blkcg;
+       bool throttled = false;
 
        if (bio->bi_rw & REQ_THROTTLED) {
                bio->bi_rw &= ~REQ_THROTTLED;
-               return 0;
+               goto out;
        }
 
        /*
@@ -1152,7 +1138,7 @@ int blk_throtl_bio(struct request_queue *q, struct bio **biop)
                        blkiocg_update_dispatch_stats(&tg->blkg, bio->bi_size,
                                        rw, rw_is_sync(bio->bi_rw));
                        rcu_read_unlock();
-                       return 0;
+                       goto out;
                }
        }
        rcu_read_unlock();
@@ -1161,18 +1147,10 @@ int blk_throtl_bio(struct request_queue *q, struct bio **biop)
         * Either group has not been allocated yet or it is not an unlimited
         * IO group
         */
-
        spin_lock_irq(q->queue_lock);
        tg = throtl_get_tg(td);
-
-       if (IS_ERR(tg)) {
-               if (PTR_ERR(tg) == -ENODEV) {
-                       /*
-                        * Queue is gone. No queue lock held here.
-                        */
-                       return -ENODEV;
-               }
-       }
+       if (unlikely(!tg))
+               goto out_unlock;
 
        if (tg->nr_queued[rw]) {
                /*
@@ -1200,7 +1178,7 @@ int blk_throtl_bio(struct request_queue *q, struct bio **biop)
                 * So keep on trimming slice even if bio is not queued.
                 */
                throtl_trim_slice(td, tg, rw);
-               goto out;
+               goto out_unlock;
        }
 
 queue_bio:
@@ -1212,16 +1190,52 @@ queue_bio:
                        tg->nr_queued[READ], tg->nr_queued[WRITE]);
 
        throtl_add_bio_tg(q->td, tg, bio);
-       *biop = NULL;
+       throttled = true;
 
        if (update_disptime) {
                tg_update_disptime(td, tg);
                throtl_schedule_next_dispatch(td);
        }
 
+out_unlock:
+       spin_unlock_irq(q->queue_lock);
 out:
+       return throttled;
+}
+
+/**
+ * blk_throtl_drain - drain throttled bios
+ * @q: request_queue to drain throttled bios for
+ *
+ * Dispatch all currently throttled bios on @q through ->make_request_fn().
+ */
+void blk_throtl_drain(struct request_queue *q)
+       __releases(q->queue_lock) __acquires(q->queue_lock)
+{
+       struct throtl_data *td = q->td;
+       struct throtl_rb_root *st = &td->tg_service_tree;
+       struct throtl_grp *tg;
+       struct bio_list bl;
+       struct bio *bio;
+
+       WARN_ON_ONCE(!queue_is_locked(q));
+
+       bio_list_init(&bl);
+
+       while ((tg = throtl_rb_first(st))) {
+               throtl_dequeue_tg(td, tg);
+
+               while ((bio = bio_list_peek(&tg->bio_lists[READ])))
+                       tg_dispatch_one_bio(td, tg, bio_data_dir(bio), &bl);
+               while ((bio = bio_list_peek(&tg->bio_lists[WRITE])))
+                       tg_dispatch_one_bio(td, tg, bio_data_dir(bio), &bl);
+       }
        spin_unlock_irq(q->queue_lock);
-       return 0;
+
+       while ((bio = bio_list_pop(&bl)))
+               generic_make_request(bio);
+
+       spin_lock_irq(q->queue_lock);
 }
 
 int blk_throtl_init(struct request_queue *q)
@@ -1296,7 +1310,11 @@ void blk_throtl_exit(struct request_queue *q)
         * it.
         */
        throtl_shutdown_wq(q);
-       throtl_td_free(td);
+}
+
+void blk_throtl_release(struct request_queue *q)
+{
+       kfree(q->td);
 }
 
 static int __init throtl_init(void)
index 20b900a..3f6551b 100644 (file)
@@ -15,6 +15,7 @@ void blk_rq_bio_prep(struct request_queue *q, struct request *rq,
                        struct bio *bio);
 int blk_rq_append_bio(struct request_queue *q, struct request *rq,
                      struct bio *bio);
+void blk_drain_queue(struct request_queue *q, bool drain_all);
 void blk_dequeue_request(struct request *rq);
 void __blk_queue_free_tags(struct request_queue *q);
 bool __blk_end_bidi_request(struct request *rq, int error,
@@ -188,4 +189,21 @@ static inline int blk_do_io_stat(struct request *rq)
                (rq->cmd_flags & REQ_DISCARD));
 }
 
-#endif
+#ifdef CONFIG_BLK_DEV_THROTTLING
+extern bool blk_throtl_bio(struct request_queue *q, struct bio *bio);
+extern void blk_throtl_drain(struct request_queue *q);
+extern int blk_throtl_init(struct request_queue *q);
+extern void blk_throtl_exit(struct request_queue *q);
+extern void blk_throtl_release(struct request_queue *q);
+#else /* CONFIG_BLK_DEV_THROTTLING */
+static inline bool blk_throtl_bio(struct request_queue *q, struct bio *bio)
+{
+       return false;
+}
+static inline void blk_throtl_drain(struct request_queue *q) { }
+static inline int blk_throtl_init(struct request_queue *q) { return 0; }
+static inline void blk_throtl_exit(struct request_queue *q) { }
+static inline void blk_throtl_release(struct request_queue *q) { }
+#endif /* CONFIG_BLK_DEV_THROTTLING */
+
+#endif /* BLK_INTERNAL_H */
index a3b64bc..66343d6 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/compiler.h>
-#include <linux/delay.h>
 #include <linux/blktrace_api.h>
 #include <linux/hash.h>
 #include <linux/uaccess.h>
@@ -182,7 +181,7 @@ static void elevator_attach(struct request_queue *q, struct elevator_queue *eq,
        eq->elevator_data = data;
 }
 
-static char chosen_elevator[16];
+static char chosen_elevator[ELV_NAME_MAX];
 
 static int __init elevator_setup(char *str)
 {
@@ -606,43 +605,35 @@ void elv_requeue_request(struct request_queue *q, struct request *rq)
 void elv_drain_elevator(struct request_queue *q)
 {
        static int printed;
+
+       lockdep_assert_held(q->queue_lock);
+
        while (q->elevator->ops->elevator_dispatch_fn(q, 1))
                ;
-       if (q->nr_sorted == 0)
-               return;
-       if (printed++ < 10) {
+       if (q->nr_sorted && printed++ < 10) {
                printk(KERN_ERR "%s: forced dispatching is broken "
                       "(nr_sorted=%u), please report this\n",
                       q->elevator->elevator_type->elevator_name, q->nr_sorted);
        }
 }
 
-/*
- * Call with queue lock held, interrupts disabled
- */
 void elv_quiesce_start(struct request_queue *q)
 {
        if (!q->elevator)
                return;
 
+       spin_lock_irq(q->queue_lock);
        queue_flag_set(QUEUE_FLAG_ELVSWITCH, q);
+       spin_unlock_irq(q->queue_lock);
 
-       /*
-        * make sure we don't have any requests in flight
-        */
-       elv_drain_elevator(q);
-       while (q->rq.elvpriv) {
-               __blk_run_queue(q);
-               spin_unlock_irq(q->queue_lock);
-               msleep(10);
-               spin_lock_irq(q->queue_lock);
-               elv_drain_elevator(q);
-       }
+       blk_drain_queue(q, false);
 }
 
 void elv_quiesce_end(struct request_queue *q)
 {
+       spin_lock_irq(q->queue_lock);
        queue_flag_clear(QUEUE_FLAG_ELVSWITCH, q);
+       spin_unlock_irq(q->queue_lock);
 }
 
 void __elv_add_request(struct request_queue *q, struct request *rq, int where)
@@ -972,7 +963,6 @@ static int elevator_switch(struct request_queue *q, struct elevator_type *new_e)
        /*
         * Turn on BYPASS and drain all requests w/ elevator private data
         */
-       spin_lock_irq(q->queue_lock);
        elv_quiesce_start(q);
 
        /*
@@ -983,8 +973,8 @@ static int elevator_switch(struct request_queue *q, struct elevator_type *new_e)
        /*
         * attach and start new elevator
         */
+       spin_lock_irq(q->queue_lock);
        elevator_attach(q, e, data);
-
        spin_unlock_irq(q->queue_lock);
 
        if (old_elevator->registered) {
@@ -999,9 +989,7 @@ static int elevator_switch(struct request_queue *q, struct elevator_type *new_e)
         * finally exit old elevator and turn off BYPASS.
         */
        elevator_exit(old_elevator);
-       spin_lock_irq(q->queue_lock);
        elv_quiesce_end(q);
-       spin_unlock_irq(q->queue_lock);
 
        blk_add_trace_msg(q, "elv switch: %s", e->elevator_type->elevator_name);
 
@@ -1015,10 +1003,7 @@ fail_register:
        elevator_exit(e);
        q->elevator = old_elevator;
        elv_register_queue(q);
-
-       spin_lock_irq(q->queue_lock);
-       queue_flag_clear(QUEUE_FLAG_ELVSWITCH, q);
-       spin_unlock_irq(q->queue_lock);
+       elv_quiesce_end(q);
 
        return err;
 }
index 94855a9..9253839 100644 (file)
@@ -537,7 +537,7 @@ void register_disk(struct gendisk *disk)
        disk->slave_dir = kobject_create_and_add("slaves", &ddev->kobj);
 
        /* No minors to use for partitions */
-       if (!disk_partitionable(disk))
+       if (!disk_part_scan_enabled(disk))
                goto exit;
 
        /* No such device (e.g., media were just removed) */
@@ -612,6 +612,12 @@ void add_disk(struct gendisk *disk)
        register_disk(disk);
        blk_register_queue(disk);
 
+       /*
+        * Take an extra ref on queue which will be put on disk_release()
+        * so that it sticks around as long as @disk is there.
+        */
+       WARN_ON_ONCE(blk_get_queue(disk->queue));
+
        retval = sysfs_create_link(&disk_to_dev(disk)->kobj, &bdi->dev->kobj,
                                   "bdi");
        WARN_ON(retval);
@@ -842,7 +848,7 @@ static int show_partition(struct seq_file *seqf, void *v)
        char buf[BDEVNAME_SIZE];
 
        /* Don't show non-partitionable removeable devices or empty devices */
-       if (!get_capacity(sgp) || (!disk_partitionable(sgp) &&
+       if (!get_capacity(sgp) || (!disk_max_parts(sgp) &&
                                   (sgp->flags & GENHD_FL_REMOVABLE)))
                return 0;
        if (sgp->flags & GENHD_FL_SUPPRESS_PARTITION_INFO)
@@ -1166,6 +1172,8 @@ static void disk_release(struct device *dev)
        disk_replace_part_tbl(disk, NULL);
        free_part_stats(&disk->part0);
        free_part_info(&disk->part0);
+       if (disk->queue)
+               blk_put_queue(disk->queue);
        kfree(disk);
 }
 struct class block_class = {
index 1124cd2..5c74efc 100644 (file)
@@ -101,7 +101,7 @@ static int blkdev_reread_part(struct block_device *bdev)
        struct gendisk *disk = bdev->bd_disk;
        int res;
 
-       if (!disk_partitionable(disk) || bdev != bdev->bd_contains)
+       if (!disk_part_scan_enabled(disk) || bdev != bdev->bd_contains)
                return -EINVAL;
        if (!capable(CAP_SYS_ADMIN))
                return -EACCES;
index 4f4230b..fbdf0d8 100644 (file)
@@ -565,7 +565,7 @@ int scsi_cmd_ioctl(struct request_queue *q, struct gendisk *bd_disk, fmode_t mod
 {
        int err;
 
-       if (!q || blk_get_queue(q))
+       if (!q)
                return -ENXIO;
 
        switch (cmd) {
@@ -686,7 +686,6 @@ int scsi_cmd_ioctl(struct request_queue *q, struct gendisk *bd_disk, fmode_t mod
                        err = -ENOTTY;
        }
 
-       blk_put_queue(q);
        return err;
 }
 EXPORT_SYMBOL(scsi_cmd_ioctl);
index 0e46fae..6d9a3ab 100644 (file)
@@ -398,6 +398,14 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
        },
        {
        .callback = init_nvs_nosave,
+       .ident = "Sony Vaio VPCEB17FX",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB17FX"),
+               },
+       },
+       {
+       .callback = init_nvs_nosave,
        .ident = "Sony Vaio VGN-SR11M",
        .matches = {
                DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
index c03277d..004f2ce 100644 (file)
@@ -202,11 +202,18 @@ static int __devexit ahci_remove(struct platform_device *pdev)
        return 0;
 }
 
+static const struct of_device_id ahci_of_match[] = {
+       { .compatible = "calxeda,hb-ahci", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, ahci_of_match);
+
 static struct platform_driver ahci_driver = {
        .remove = __devexit_p(ahci_remove),
        .driver = {
                .name = "ahci",
                .owner = THIS_MODULE,
+               .of_match_table = ahci_of_match,
        },
        .id_table       = ahci_devtype,
 };
index 6bb3aaf..124dbf6 100644 (file)
@@ -29,13 +29,10 @@ static int rpm_suspend(struct device *dev, int rpmflags);
 void update_pm_runtime_accounting(struct device *dev)
 {
        unsigned long now = jiffies;
-       int delta;
+       unsigned long delta;
 
        delta = now - dev->power.accounting_timestamp;
 
-       if (delta < 0)
-               delta = 0;
-
        dev->power.accounting_timestamp = now;
 
        if (dev->power.disable_depth > 0)
@@ -296,6 +293,9 @@ static int rpm_callback(int (*cb)(struct device *), struct device *dev)
  * the callback was running then carry it out, otherwise send an idle
  * notification for its parent (if the suspend succeeded and both
  * ignore_children of parent->power and irq_safe of dev->power are not set).
+ * If ->runtime_suspend failed with -EAGAIN or -EBUSY, and if the RPM_AUTO
+ * flag is set and the next autosuspend-delay expiration time is in the
+ * future, schedule another autosuspend attempt.
  *
  * This function must be called under dev->power.lock with interrupts disabled.
  */
@@ -416,10 +416,21 @@ static int rpm_suspend(struct device *dev, int rpmflags)
        if (retval) {
                __update_runtime_status(dev, RPM_ACTIVE);
                dev->power.deferred_resume = false;
-               if (retval == -EAGAIN || retval == -EBUSY)
+               if (retval == -EAGAIN || retval == -EBUSY) {
                        dev->power.runtime_error = 0;
-               else
+
+                       /*
+                        * If the callback routine failed an autosuspend, and
+                        * if the last_busy time has been updated so that there
+                        * is a new autosuspend expiration time, automatically
+                        * reschedule another autosuspend.
+                        */
+                       if ((rpmflags & RPM_AUTO) &&
+                           pm_runtime_autosuspend_expiration(dev) != 0)
+                               goto repeat;
+               } else {
                        pm_runtime_cancel_pending(dev);
+               }
                wake_up_all(&dev->power.wait_queue);
                goto out;
        }
index 528f631..167ba0a 100644 (file)
@@ -159,7 +159,7 @@ aoeblk_release(struct gendisk *disk, fmode_t mode)
        return 0;
 }
 
-static int
+static void
 aoeblk_make_request(struct request_queue *q, struct bio *bio)
 {
        struct sk_buff_head queue;
@@ -172,25 +172,25 @@ aoeblk_make_request(struct request_queue *q, struct bio *bio)
        if (bio == NULL) {
                printk(KERN_ERR "aoe: bio is NULL\n");
                BUG();
-               return 0;
+               return;
        }
        d = bio->bi_bdev->bd_disk->private_data;
        if (d == NULL) {
                printk(KERN_ERR "aoe: bd_disk->private_data is NULL\n");
                BUG();
                bio_endio(bio, -ENXIO);
-               return 0;
+               return;
        } else if (bio->bi_io_vec == NULL) {
                printk(KERN_ERR "aoe: bi_io_vec is NULL\n");
                BUG();
                bio_endio(bio, -ENXIO);
-               return 0;
+               return;
        }
        buf = mempool_alloc(d->bufpool, GFP_NOIO);
        if (buf == NULL) {
                printk(KERN_INFO "aoe: buf allocation failure\n");
                bio_endio(bio, -ENOMEM);
-               return 0;
+               return;
        }
        memset(buf, 0, sizeof(*buf));
        INIT_LIST_HEAD(&buf->bufs);
@@ -211,7 +211,7 @@ aoeblk_make_request(struct request_queue *q, struct bio *bio)
                spin_unlock_irqrestore(&d->lock, flags);
                mempool_free(buf, d->bufpool);
                bio_endio(bio, -ENXIO);
-               return 0;
+               return;
        }
 
        list_add_tail(&buf->bufs, &d->bufq);
@@ -222,8 +222,6 @@ aoeblk_make_request(struct request_queue *q, struct bio *bio)
 
        spin_unlock_irqrestore(&d->lock, flags);
        aoenet_xmit(&queue);
-
-       return 0;
 }
 
 static int
index dba1c32..d22119d 100644 (file)
@@ -323,7 +323,7 @@ out:
        return err;
 }
 
-static int brd_make_request(struct request_queue *q, struct bio *bio)
+static void brd_make_request(struct request_queue *q, struct bio *bio)
 {
        struct block_device *bdev = bio->bi_bdev;
        struct brd_device *brd = bdev->bd_disk->private_data;
@@ -359,8 +359,6 @@ static int brd_make_request(struct request_queue *q, struct bio *bio)
 
 out:
        bio_endio(bio, err);
-
-       return 0;
 }
 
 #ifdef CONFIG_BLK_DEV_XIP
index 8f4ef65..486f94e 100644 (file)
@@ -68,6 +68,10 @@ static int cciss_tape_cmds = 6;
 module_param(cciss_tape_cmds, int, 0644);
 MODULE_PARM_DESC(cciss_tape_cmds,
        "number of commands to allocate for tape devices (default: 6)");
+static int cciss_simple_mode;
+module_param(cciss_simple_mode, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(cciss_simple_mode,
+       "Use 'simple mode' rather than 'performant mode'");
 
 static DEFINE_MUTEX(cciss_mutex);
 static struct proc_dir_entry *proc_cciss;
@@ -176,6 +180,7 @@ static void cciss_geometry_inquiry(ctlr_info_t *h, int logvol,
                        unsigned int block_size, InquiryData_struct *inq_buff,
                                   drive_info_struct *drv);
 static void __devinit cciss_interrupt_mode(ctlr_info_t *);
+static int __devinit cciss_enter_simple_mode(struct ctlr_info *h);
 static void start_io(ctlr_info_t *h);
 static int sendcmd_withirq(ctlr_info_t *h, __u8 cmd, void *buff, size_t size,
                        __u8 page_code, unsigned char scsi3addr[],
@@ -388,7 +393,7 @@ static void cciss_seq_show_header(struct seq_file *seq)
                h->product_name,
                (unsigned long)h->board_id,
                h->firm_ver[0], h->firm_ver[1], h->firm_ver[2],
-               h->firm_ver[3], (unsigned int)h->intr[PERF_MODE_INT],
+               h->firm_ver[3], (unsigned int)h->intr[h->intr_mode],
                h->num_luns,
                h->Qdepth, h->commands_outstanding,
                h->maxQsinceinit, h->max_outstanding, h->maxSG);
@@ -636,6 +641,18 @@ static ssize_t host_store_rescan(struct device *dev,
 }
 static DEVICE_ATTR(rescan, S_IWUSR, NULL, host_store_rescan);
 
+static ssize_t host_show_transport_mode(struct device *dev,
+                                struct device_attribute *attr,
+                                char *buf)
+{
+       struct ctlr_info *h = to_hba(dev);
+
+       return snprintf(buf, 20, "%s\n",
+               h->transMethod & CFGTBL_Trans_Performant ?
+                       "performant" : "simple");
+}
+static DEVICE_ATTR(transport_mode, S_IRUGO, host_show_transport_mode, NULL);
+
 static ssize_t dev_show_unique_id(struct device *dev,
                                 struct device_attribute *attr,
                                 char *buf)
@@ -808,6 +825,7 @@ static DEVICE_ATTR(usage_count, S_IRUGO, cciss_show_usage_count, NULL);
 static struct attribute *cciss_host_attrs[] = {
        &dev_attr_rescan.attr,
        &dev_attr_resettable.attr,
+       &dev_attr_transport_mode.attr,
        NULL
 };
 
@@ -3984,6 +4002,9 @@ static void __devinit cciss_put_controller_into_performant_mode(ctlr_info_t *h)
 {
        __u32 trans_support;
 
+       if (cciss_simple_mode)
+               return;
+
        dev_dbg(&h->pdev->dev, "Trying to put board into Performant mode\n");
        /* Attempt to put controller into performant mode if supported */
        /* Does board support performant mode? */
@@ -4081,7 +4102,7 @@ static void __devinit cciss_interrupt_mode(ctlr_info_t *h)
 default_int_mode:
 #endif                         /* CONFIG_PCI_MSI */
        /* if we get here we're going to use the default interrupt mode */
-       h->intr[PERF_MODE_INT] = h->pdev->irq;
+       h->intr[h->intr_mode] = h->pdev->irq;
        return;
 }
 
@@ -4341,6 +4362,9 @@ static int __devinit cciss_pci_init(ctlr_info_t *h)
        }
        cciss_enable_scsi_prefetch(h);
        cciss_p600_dma_prefetch_quirk(h);
+       err = cciss_enter_simple_mode(h);
+       if (err)
+               goto err_out_free_res;
        cciss_put_controller_into_performant_mode(h);
        return 0;
 
@@ -4533,6 +4557,13 @@ static int cciss_controller_hard_reset(struct pci_dev *pdev,
                pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
                pmcsr |= PCI_D0;
                pci_write_config_word(pdev, pos + PCI_PM_CTRL, pmcsr);
+
+               /*
+                * The P600 requires a small delay when changing states.
+                * Otherwise we may think the board did not reset and we bail.
+                * This for kdump only and is particular to the P600.
+                */
+               msleep(500);
        }
        return 0;
 }
@@ -4843,20 +4874,20 @@ static int cciss_request_irq(ctlr_info_t *h,
        irqreturn_t (*intxhandler)(int, void *))
 {
        if (h->msix_vector || h->msi_vector) {
-               if (!request_irq(h->intr[PERF_MODE_INT], msixhandler,
+               if (!request_irq(h->intr[h->intr_mode], msixhandler,
                                IRQF_DISABLED, h->devname, h))
                        return 0;
                dev_err(&h->pdev->dev, "Unable to get msi irq %d"
-                       " for %s\n", h->intr[PERF_MODE_INT],
+                       " for %s\n", h->intr[h->intr_mode],
                        h->devname);
                return -1;
        }
 
-       if (!request_irq(h->intr[PERF_MODE_INT], intxhandler,
+       if (!request_irq(h->intr[h->intr_mode], intxhandler,
                        IRQF_DISABLED, h->devname, h))
                return 0;
        dev_err(&h->pdev->dev, "Unable to get irq %d for %s\n",
-               h->intr[PERF_MODE_INT], h->devname);
+               h->intr[h->intr_mode], h->devname);
        return -1;
 }
 
@@ -4887,7 +4918,7 @@ static void cciss_undo_allocations_after_kdump_soft_reset(ctlr_info_t *h)
 {
        int ctlr = h->ctlr;
 
-       free_irq(h->intr[PERF_MODE_INT], h);
+       free_irq(h->intr[h->intr_mode], h);
 #ifdef CONFIG_PCI_MSI
        if (h->msix_vector)
                pci_disable_msix(h->pdev);
@@ -4953,6 +4984,7 @@ reinit_after_soft_reset:
        h = hba[i];
        h->pdev = pdev;
        h->busy_initializing = 1;
+       h->intr_mode = cciss_simple_mode ? SIMPLE_MODE_INT : PERF_MODE_INT;
        INIT_LIST_HEAD(&h->cmpQ);
        INIT_LIST_HEAD(&h->reqQ);
        mutex_init(&h->busy_shutting_down);
@@ -5009,7 +5041,7 @@ reinit_after_soft_reset:
 
        dev_info(&h->pdev->dev, "%s: <0x%x> at PCI %s IRQ %d%s using DAC\n",
               h->devname, pdev->device, pci_name(pdev),
-              h->intr[PERF_MODE_INT], dac ? "" : " not");
+              h->intr[h->intr_mode], dac ? "" : " not");
 
        if (cciss_allocate_cmd_pool(h))
                goto clean4;
@@ -5056,7 +5088,7 @@ reinit_after_soft_reset:
                spin_lock_irqsave(&h->lock, flags);
                h->access.set_intr_mask(h, CCISS_INTR_OFF);
                spin_unlock_irqrestore(&h->lock, flags);
-               free_irq(h->intr[PERF_MODE_INT], h);
+               free_irq(h->intr[h->intr_mode], h);
                rc = cciss_request_irq(h, cciss_msix_discard_completions,
                                        cciss_intx_discard_completions);
                if (rc) {
@@ -5133,7 +5165,7 @@ clean4:
        cciss_free_cmd_pool(h);
        cciss_free_scatterlists(h);
        cciss_free_sg_chain_blocks(h->cmd_sg_list, h->nr_cmds);
-       free_irq(h->intr[PERF_MODE_INT], h);
+       free_irq(h->intr[h->intr_mode], h);
 clean2:
        unregister_blkdev(h->major, h->devname);
 clean1:
@@ -5172,9 +5204,31 @@ static void cciss_shutdown(struct pci_dev *pdev)
        if (return_code != IO_OK)
                dev_warn(&h->pdev->dev, "Error flushing cache\n");
        h->access.set_intr_mask(h, CCISS_INTR_OFF);
-       free_irq(h->intr[PERF_MODE_INT], h);
+       free_irq(h->intr[h->intr_mode], h);
+}
+
+static int __devinit cciss_enter_simple_mode(struct ctlr_info *h)
+{
+       u32 trans_support;
+
+       trans_support = readl(&(h->cfgtable->TransportSupport));
+       if (!(trans_support & SIMPLE_MODE))
+               return -ENOTSUPP;
+
+       h->max_commands = readl(&(h->cfgtable->CmdsOutMax));
+       writel(CFGTBL_Trans_Simple, &(h->cfgtable->HostWrite.TransportRequest));
+       writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL);
+       cciss_wait_for_mode_change_ack(h);
+       print_cfg_table(h);
+       if (!(readl(&(h->cfgtable->TransportActive)) & CFGTBL_Trans_Simple)) {
+               dev_warn(&h->pdev->dev, "unable to get board into simple mode\n");
+               return -ENODEV;
+       }
+       h->transMethod = CFGTBL_Trans_Simple;
+       return 0;
 }
 
+
 static void __devexit cciss_remove_one(struct pci_dev *pdev)
 {
        ctlr_info_t *h;
index c049548..7fda30e 100644 (file)
@@ -92,6 +92,7 @@ struct ctlr_info
        unsigned int intr[4];
        unsigned int msix_vector;
        unsigned int msi_vector;
+       int     intr_mode;
        int     cciss_max_sectors;
        BYTE    cciss_read;
        BYTE    cciss_write;
index b2fceb5..9125bbe 100644 (file)
@@ -620,6 +620,7 @@ static int cpqarray_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
        }
        vendor_id = pdev->vendor;
        device_id = pdev->device;
+       revision  = pdev->revision;
        irq = pdev->irq;
 
        for(i=0; i<6; i++)
@@ -632,7 +633,6 @@ static int cpqarray_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
        }
 
        pci_read_config_word(pdev, PCI_COMMAND, &command);
-       pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
        pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &cache_line_size);
        pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &latency_timer);
 
index 1706d60..9cf2035 100644 (file)
@@ -1506,7 +1506,7 @@ extern void drbd_free_mdev(struct drbd_conf *mdev);
 extern int proc_details;
 
 /* drbd_req */
-extern int drbd_make_request(struct request_queue *q, struct bio *bio);
+extern void drbd_make_request(struct request_queue *q, struct bio *bio);
 extern int drbd_read_remote(struct drbd_conf *mdev, struct drbd_request *req);
 extern int drbd_merge_bvec(struct request_queue *q, struct bvec_merge_data *bvm, struct bio_vec *bvec);
 extern int is_valid_ar_handle(struct drbd_request *, sector_t);
index 3424d67..4a0f314 100644 (file)
@@ -1073,7 +1073,7 @@ static int drbd_fail_request_early(struct drbd_conf *mdev, int is_write)
        return 0;
 }
 
-int drbd_make_request(struct request_queue *q, struct bio *bio)
+void drbd_make_request(struct request_queue *q, struct bio *bio)
 {
        unsigned int s_enr, e_enr;
        struct drbd_conf *mdev = (struct drbd_conf *) q->queuedata;
@@ -1081,7 +1081,7 @@ int drbd_make_request(struct request_queue *q, struct bio *bio)
 
        if (drbd_fail_request_early(mdev, bio_data_dir(bio) & WRITE)) {
                bio_endio(bio, -EPERM);
-               return 0;
+               return;
        }
 
        start_time = jiffies;
@@ -1100,7 +1100,8 @@ int drbd_make_request(struct request_queue *q, struct bio *bio)
 
        if (likely(s_enr == e_enr)) {
                inc_ap_bio(mdev, 1);
-               return drbd_make_request_common(mdev, bio, start_time);
+               drbd_make_request_common(mdev, bio, start_time);
+               return;
        }
 
        /* can this bio be split generically?
@@ -1148,7 +1149,6 @@ int drbd_make_request(struct request_queue *q, struct bio *bio)
 
                bio_pair_release(bp);
        }
-       return 0;
 }
 
 /* This is called by bio_add_page().  With this function we reduce
index 4720c7a..3d80682 100644 (file)
@@ -76,6 +76,8 @@
 #include <linux/splice.h>
 #include <linux/sysfs.h>
 #include <linux/miscdevice.h>
+#include <linux/falloc.h>
+
 #include <asm/uaccess.h>
 
 static DEFINE_IDR(loop_index_idr);
@@ -203,74 +205,6 @@ lo_do_transfer(struct loop_device *lo, int cmd,
 }
 
 /**
- * do_lo_send_aops - helper for writing data to a loop device
- *
- * This is the fast version for backing filesystems which implement the address
- * space operations write_begin and write_end.
- */
-static int do_lo_send_aops(struct loop_device *lo, struct bio_vec *bvec,
-               loff_t pos, struct page *unused)
-{
-       struct file *file = lo->lo_backing_file; /* kudos to NFsckingS */
-       struct address_space *mapping = file->f_mapping;
-       pgoff_t index;
-       unsigned offset, bv_offs;
-       int len, ret;
-
-       mutex_lock(&mapping->host->i_mutex);
-       index = pos >> PAGE_CACHE_SHIFT;
-       offset = pos & ((pgoff_t)PAGE_CACHE_SIZE - 1);
-       bv_offs = bvec->bv_offset;
-       len = bvec->bv_len;
-       while (len > 0) {
-               sector_t IV;
-               unsigned size, copied;
-               int transfer_result;
-               struct page *page;
-               void *fsdata;
-
-               IV = ((sector_t)index << (PAGE_CACHE_SHIFT - 9))+(offset >> 9);
-               size = PAGE_CACHE_SIZE - offset;
-               if (size > len)
-                       size = len;
-
-               ret = pagecache_write_begin(file, mapping, pos, size, 0,
-                                                       &page, &fsdata);
-               if (ret)
-                       goto fail;
-
-               file_update_time(file);
-
-               transfer_result = lo_do_transfer(lo, WRITE, page, offset,
-                               bvec->bv_page, bv_offs, size, IV);
-               copied = size;
-               if (unlikely(transfer_result))
-                       copied = 0;
-
-               ret = pagecache_write_end(file, mapping, pos, size, copied,
-                                                       page, fsdata);
-               if (ret < 0 || ret != copied)
-                       goto fail;
-
-               if (unlikely(transfer_result))
-                       goto fail;
-
-               bv_offs += copied;
-               len -= copied;
-               offset = 0;
-               index++;
-               pos += copied;
-       }
-       ret = 0;
-out:
-       mutex_unlock(&mapping->host->i_mutex);
-       return ret;
-fail:
-       ret = -1;
-       goto out;
-}
-
-/**
  * __do_lo_send_write - helper for writing data to a loop device
  *
  * This helper just factors out common code between do_lo_send_direct_write()
@@ -297,10 +231,8 @@ static int __do_lo_send_write(struct file *file,
 /**
  * do_lo_send_direct_write - helper for writing data to a loop device
  *
- * This is the fast, non-transforming version for backing filesystems which do
- * not implement the address space operations write_begin and write_end.
- * It uses the write file operation which should be present on all writeable
- * filesystems.
+ * This is the fast, non-transforming version that does not need double
+ * buffering.
  */
 static int do_lo_send_direct_write(struct loop_device *lo,
                struct bio_vec *bvec, loff_t pos, struct page *page)
@@ -316,15 +248,9 @@ static int do_lo_send_direct_write(struct loop_device *lo,
 /**
  * do_lo_send_write - helper for writing data to a loop device
  *
- * This is the slow, transforming version for filesystems which do not
- * implement the address space operations write_begin and write_end.  It
- * uses the write file operation which should be present on all writeable
- * filesystems.
- *
- * Using fops->write is slower than using aops->{prepare,commit}_write in the
- * transforming case because we need to double buffer the data as we cannot do
- * the transformations in place as we do not have direct access to the
- * destination pages of the backing file.
+ * This is the slow, transforming version that needs to double buffer the
+ * data as it cannot do the transformations in place without having direct
+ * access to the destination pages of the backing file.
  */
 static int do_lo_send_write(struct loop_device *lo, struct bio_vec *bvec,
                loff_t pos, struct page *page)
@@ -350,17 +276,16 @@ static int lo_send(struct loop_device *lo, struct bio *bio, loff_t pos)
        struct page *page = NULL;
        int i, ret = 0;
 
-       do_lo_send = do_lo_send_aops;
-       if (!(lo->lo_flags & LO_FLAGS_USE_AOPS)) {
+       if (lo->transfer != transfer_none) {
+               page = alloc_page(GFP_NOIO | __GFP_HIGHMEM);
+               if (unlikely(!page))
+                       goto fail;
+               kmap(page);
+               do_lo_send = do_lo_send_write;
+       } else {
                do_lo_send = do_lo_send_direct_write;
-               if (lo->transfer != transfer_none) {
-                       page = alloc_page(GFP_NOIO | __GFP_HIGHMEM);
-                       if (unlikely(!page))
-                               goto fail;
-                       kmap(page);
-                       do_lo_send = do_lo_send_write;
-               }
        }
+
        bio_for_each_segment(bvec, bio, i) {
                ret = do_lo_send(lo, bvec, pos, page);
                if (ret < 0)
@@ -484,6 +409,29 @@ static int do_bio_filebacked(struct loop_device *lo, struct bio *bio)
                        }
                }
 
+               /*
+                * We use punch hole to reclaim the free space used by the
+                * image a.k.a. discard. However we do support discard if
+                * encryption is enabled, because it may give an attacker
+                * useful information.
+                */
+               if (bio->bi_rw & REQ_DISCARD) {
+                       struct file *file = lo->lo_backing_file;
+                       int mode = FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE;
+
+                       if ((!file->f_op->fallocate) ||
+                           lo->lo_encrypt_key_size) {
+                               ret = -EOPNOTSUPP;
+                               goto out;
+                       }
+                       ret = file->f_op->fallocate(file, mode, pos,
+                                                   bio->bi_size);
+                       if (unlikely(ret && ret != -EINVAL &&
+                                    ret != -EOPNOTSUPP))
+                               ret = -EIO;
+                       goto out;
+               }
+
                ret = lo_send(lo, bio, pos);
 
                if ((bio->bi_rw & REQ_FUA) && !ret) {
@@ -514,7 +462,7 @@ static struct bio *loop_get_bio(struct loop_device *lo)
        return bio_list_pop(&lo->lo_bio_list);
 }
 
-static int loop_make_request(struct request_queue *q, struct bio *old_bio)
+static void loop_make_request(struct request_queue *q, struct bio *old_bio)
 {
        struct loop_device *lo = q->queuedata;
        int rw = bio_rw(old_bio);
@@ -532,12 +480,11 @@ static int loop_make_request(struct request_queue *q, struct bio *old_bio)
        loop_add_bio(lo, old_bio);
        wake_up(&lo->lo_event);
        spin_unlock_irq(&lo->lo_lock);
-       return 0;
+       return;
 
 out:
        spin_unlock_irq(&lo->lo_lock);
        bio_io_error(old_bio);
-       return 0;
 }
 
 struct switch_request {
@@ -700,7 +647,7 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
                goto out_putf;
 
        fput(old_file);
-       if (max_part > 0)
+       if (lo->lo_flags & LO_FLAGS_PARTSCAN)
                ioctl_by_bdev(bdev, BLKRRPART, 0);
        return 0;
 
@@ -777,16 +724,25 @@ static ssize_t loop_attr_autoclear_show(struct loop_device *lo, char *buf)
        return sprintf(buf, "%s\n", autoclear ? "1" : "0");
 }
 
+static ssize_t loop_attr_partscan_show(struct loop_device *lo, char *buf)
+{
+       int partscan = (lo->lo_flags & LO_FLAGS_PARTSCAN);
+
+       return sprintf(buf, "%s\n", partscan ? "1" : "0");
+}
+
 LOOP_ATTR_RO(backing_file);
 LOOP_ATTR_RO(offset);
 LOOP_ATTR_RO(sizelimit);
 LOOP_ATTR_RO(autoclear);
+LOOP_ATTR_RO(partscan);
 
 static struct attribute *loop_attrs[] = {
        &loop_attr_backing_file.attr,
        &loop_attr_offset.attr,
        &loop_attr_sizelimit.attr,
        &loop_attr_autoclear.attr,
+       &loop_attr_partscan.attr,
        NULL,
 };
 
@@ -807,6 +763,35 @@ static void loop_sysfs_exit(struct loop_device *lo)
                           &loop_attribute_group);
 }
 
+static void loop_config_discard(struct loop_device *lo)
+{
+       struct file *file = lo->lo_backing_file;
+       struct inode *inode = file->f_mapping->host;
+       struct request_queue *q = lo->lo_queue;
+
+       /*
+        * We use punch hole to reclaim the free space used by the
+        * image a.k.a. discard. However we do support discard if
+        * encryption is enabled, because it may give an attacker
+        * useful information.
+        */
+       if ((!file->f_op->fallocate) ||
+           lo->lo_encrypt_key_size) {
+               q->limits.discard_granularity = 0;
+               q->limits.discard_alignment = 0;
+               q->limits.max_discard_sectors = 0;
+               q->limits.discard_zeroes_data = 0;
+               queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, q);
+               return;
+       }
+
+       q->limits.discard_granularity = inode->i_sb->s_blocksize;
+       q->limits.discard_alignment = inode->i_sb->s_blocksize;
+       q->limits.max_discard_sectors = UINT_MAX >> 9;
+       q->limits.discard_zeroes_data = 1;
+       queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q);
+}
+
 static int loop_set_fd(struct loop_device *lo, fmode_t mode,
                       struct block_device *bdev, unsigned int arg)
 {
@@ -849,35 +834,23 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
        mapping = file->f_mapping;
        inode = mapping->host;
 
-       if (!(file->f_mode & FMODE_WRITE))
-               lo_flags |= LO_FLAGS_READ_ONLY;
-
        error = -EINVAL;
-       if (S_ISREG(inode->i_mode) || S_ISBLK(inode->i_mode)) {
-               const struct address_space_operations *aops = mapping->a_ops;
-
-               if (aops->write_begin)
-                       lo_flags |= LO_FLAGS_USE_AOPS;
-               if (!(lo_flags & LO_FLAGS_USE_AOPS) && !file->f_op->write)
-                       lo_flags |= LO_FLAGS_READ_ONLY;
+       if (!S_ISREG(inode->i_mode) && !S_ISBLK(inode->i_mode))
+               goto out_putf;
 
-               lo_blocksize = S_ISBLK(inode->i_mode) ?
-                       inode->i_bdev->bd_block_size : PAGE_SIZE;
+       if (!(file->f_mode & FMODE_WRITE) || !(mode & FMODE_WRITE) ||
+           !file->f_op->write)
+               lo_flags |= LO_FLAGS_READ_ONLY;
 
-               error = 0;
-       } else {
-               goto out_putf;
-       }
+       lo_blocksize = S_ISBLK(inode->i_mode) ?
+               inode->i_bdev->bd_block_size : PAGE_SIZE;
 
+       error = -EFBIG;
        size = get_loop_size(lo, file);
-
-       if ((loff_t)(sector_t)size != size) {
-               error = -EFBIG;
+       if ((loff_t)(sector_t)size != size)
                goto out_putf;
-       }
 
-       if (!(mode & FMODE_WRITE))
-               lo_flags |= LO_FLAGS_READ_ONLY;
+       error = 0;
 
        set_device_ro(bdev, (lo_flags & LO_FLAGS_READ_ONLY) != 0);
 
@@ -919,7 +892,9 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
        }
        lo->lo_state = Lo_bound;
        wake_up_process(lo->lo_thread);
-       if (max_part > 0)
+       if (part_shift)
+               lo->lo_flags |= LO_FLAGS_PARTSCAN;
+       if (lo->lo_flags & LO_FLAGS_PARTSCAN)
                ioctl_by_bdev(bdev, BLKRRPART, 0);
        return 0;
 
@@ -980,10 +955,11 @@ loop_init_xfer(struct loop_device *lo, struct loop_func_table *xfer,
        return err;
 }
 
-static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)
+static int loop_clr_fd(struct loop_device *lo)
 {
        struct file *filp = lo->lo_backing_file;
        gfp_t gfp = lo->old_gfp_mask;
+       struct block_device *bdev = lo->lo_device;
 
        if (lo->lo_state != Lo_bound)
                return -ENXIO;
@@ -1012,7 +988,6 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)
        lo->lo_offset = 0;
        lo->lo_sizelimit = 0;
        lo->lo_encrypt_key_size = 0;
-       lo->lo_flags = 0;
        lo->lo_thread = NULL;
        memset(lo->lo_encrypt_key, 0, LO_KEY_SIZE);
        memset(lo->lo_crypt_name, 0, LO_NAME_SIZE);
@@ -1030,8 +1005,11 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)
        lo->lo_state = Lo_unbound;
        /* This is safe: open() is still holding a reference. */
        module_put(THIS_MODULE);
-       if (max_part > 0 && bdev)
+       if (lo->lo_flags & LO_FLAGS_PARTSCAN && bdev)
                ioctl_by_bdev(bdev, BLKRRPART, 0);
+       lo->lo_flags = 0;
+       if (!part_shift)
+               lo->lo_disk->flags |= GENHD_FL_NO_PART_SCAN;
        mutex_unlock(&lo->lo_ctl_mutex);
        /*
         * Need not hold lo_ctl_mutex to fput backing file.
@@ -1085,6 +1063,7 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
                if (figure_loop_size(lo))
                        return -EFBIG;
        }
+       loop_config_discard(lo);
 
        memcpy(lo->lo_file_name, info->lo_file_name, LO_NAME_SIZE);
        memcpy(lo->lo_crypt_name, info->lo_crypt_name, LO_NAME_SIZE);
@@ -1100,6 +1079,13 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
             (info->lo_flags & LO_FLAGS_AUTOCLEAR))
                lo->lo_flags ^= LO_FLAGS_AUTOCLEAR;
 
+       if ((info->lo_flags & LO_FLAGS_PARTSCAN) &&
+            !(lo->lo_flags & LO_FLAGS_PARTSCAN)) {
+               lo->lo_flags |= LO_FLAGS_PARTSCAN;
+               lo->lo_disk->flags &= ~GENHD_FL_NO_PART_SCAN;
+               ioctl_by_bdev(lo->lo_device, BLKRRPART, 0);
+       }
+
        lo->lo_encrypt_key_size = info->lo_encrypt_key_size;
        lo->lo_init[0] = info->lo_init[0];
        lo->lo_init[1] = info->lo_init[1];
@@ -1293,7 +1279,7 @@ static int lo_ioctl(struct block_device *bdev, fmode_t mode,
                break;
        case LOOP_CLR_FD:
                /* loop_clr_fd would have unlocked lo_ctl_mutex on success */
-               err = loop_clr_fd(lo, bdev);
+               err = loop_clr_fd(lo);
                if (!err)
                        goto out_unlocked;
                break;
@@ -1513,7 +1499,7 @@ static int lo_release(struct gendisk *disk, fmode_t mode)
                 * In autoclear mode, stop the loop thread
                 * and remove configuration after last close.
                 */
-               err = loop_clr_fd(lo, NULL);
+               err = loop_clr_fd(lo);
                if (!err)
                        goto out_unlocked;
        } else {
@@ -1635,6 +1621,27 @@ static int loop_add(struct loop_device **l, int i)
        if (!disk)
                goto out_free_queue;
 
+       /*
+        * Disable partition scanning by default. The in-kernel partition
+        * scanning can be requested individually per-device during its
+        * setup. Userspace can always add and remove partitions from all
+        * devices. The needed partition minors are allocated from the
+        * extended minor space, the main loop device numbers will continue
+        * to match the loop minors, regardless of the number of partitions
+        * used.
+        *
+        * If max_part is given, partition scanning is globally enabled for
+        * all loop devices. The minors for the main loop devices will be
+        * multiples of max_part.
+        *
+        * Note: Global-for-all-devices, set-only-at-init, read-only module
+        * parameteters like 'max_loop' and 'max_part' make things needlessly
+        * complicated, are too static, inflexible and may surprise
+        * userspace tools. Parameters like this in general should be avoided.
+        */
+       if (!part_shift)
+               disk->flags |= GENHD_FL_NO_PART_SCAN;
+       disk->flags |= GENHD_FL_EXT_DEVT;
        mutex_init(&lo->lo_ctl_mutex);
        lo->lo_number           = i;
        lo->lo_thread           = NULL;
index f533f33..c3f0ee1 100644 (file)
@@ -127,8 +127,7 @@ static void sock_shutdown(struct nbd_device *lo, int lock)
        if (lock)
                mutex_lock(&lo->tx_lock);
        if (lo->sock) {
-               printk(KERN_WARNING "%s: shutting down socket\n",
-                       lo->disk->disk_name);
+               dev_warn(disk_to_dev(lo->disk), "shutting down socket\n");
                kernel_sock_shutdown(lo->sock, SHUT_RDWR);
                lo->sock = NULL;
        }
@@ -158,8 +157,9 @@ static int sock_xmit(struct nbd_device *lo, int send, void *buf, int size,
        sigset_t blocked, oldset;
 
        if (unlikely(!sock)) {
-               printk(KERN_ERR "%s: Attempted %s on closed socket in sock_xmit\n",
-                      lo->disk->disk_name, (send ? "send" : "recv"));
+               dev_err(disk_to_dev(lo->disk),
+                       "Attempted %s on closed socket in sock_xmit\n",
+                       (send ? "send" : "recv"));
                return -EINVAL;
        }
 
@@ -250,8 +250,8 @@ static int nbd_send_req(struct nbd_device *lo, struct request *req)
        result = sock_xmit(lo, 1, &request, sizeof(request),
                        (nbd_cmd(req) == NBD_CMD_WRITE) ? MSG_MORE : 0);
        if (result <= 0) {
-               printk(KERN_ERR "%s: Send control failed (result %d)\n",
-                               lo->disk->disk_name, result);
+               dev_err(disk_to_dev(lo->disk),
+                       "Send control failed (result %d)\n", result);
                goto error_out;
        }
 
@@ -270,8 +270,9 @@ static int nbd_send_req(struct nbd_device *lo, struct request *req)
                                        lo->disk->disk_name, req, bvec->bv_len);
                        result = sock_send_bvec(lo, bvec, flags);
                        if (result <= 0) {
-                               printk(KERN_ERR "%s: Send data failed (result %d)\n",
-                                               lo->disk->disk_name, result);
+                               dev_err(disk_to_dev(lo->disk),
+                                       "Send data failed (result %d)\n",
+                                       result);
                                goto error_out;
                        }
                }
@@ -328,14 +329,13 @@ static struct request *nbd_read_stat(struct nbd_device *lo)
        reply.magic = 0;
        result = sock_xmit(lo, 0, &reply, sizeof(reply), MSG_WAITALL);
        if (result <= 0) {
-               printk(KERN_ERR "%s: Receive control failed (result %d)\n",
-                               lo->disk->disk_name, result);
+               dev_err(disk_to_dev(lo->disk),
+                       "Receive control failed (result %d)\n", result);
                goto harderror;
        }
 
        if (ntohl(reply.magic) != NBD_REPLY_MAGIC) {
-               printk(KERN_ERR "%s: Wrong magic (0x%lx)\n",
-                               lo->disk->disk_name,
+               dev_err(disk_to_dev(lo->disk), "Wrong magic (0x%lx)\n",
                                (unsigned long)ntohl(reply.magic));
                result = -EPROTO;
                goto harderror;
@@ -347,15 +347,15 @@ static struct request *nbd_read_stat(struct nbd_device *lo)
                if (result != -ENOENT)
                        goto harderror;
 
-               printk(KERN_ERR "%s: Unexpected reply (%p)\n",
-                               lo->disk->disk_name, reply.handle);
+               dev_err(disk_to_dev(lo->disk), "Unexpected reply (%p)\n",
+                       reply.handle);
                result = -EBADR;
                goto harderror;
        }
 
        if (ntohl(reply.error)) {
-               printk(KERN_ERR "%s: Other side returned error (%d)\n",
-                               lo->disk->disk_name, ntohl(reply.error));
+               dev_err(disk_to_dev(lo->disk), "Other side returned error (%d)\n",
+                       ntohl(reply.error));
                req->errors++;
                return req;
        }
@@ -369,8 +369,8 @@ static struct request *nbd_read_stat(struct nbd_device *lo)
                rq_for_each_segment(bvec, req, iter) {
                        result = sock_recv_bvec(lo, bvec);
                        if (result <= 0) {
-                               printk(KERN_ERR "%s: Receive data failed (result %d)\n",
-                                               lo->disk->disk_name, result);
+                               dev_err(disk_to_dev(lo->disk), "Receive data failed (result %d)\n",
+                                       result);
                                req->errors++;
                                return req;
                        }
@@ -405,10 +405,10 @@ static int nbd_do_it(struct nbd_device *lo)
 
        BUG_ON(lo->magic != LO_MAGIC);
 
-       lo->pid = current->pid;
-       ret = sysfs_create_file(&disk_to_dev(lo->disk)->kobj, &pid_attr.attr);
+       lo->pid = task_pid_nr(current);
+       ret = device_create_file(disk_to_dev(lo->disk), &pid_attr);
        if (ret) {
-               printk(KERN_ERR "nbd: sysfs_create_file failed!");
+               dev_err(disk_to_dev(lo->disk), "device_create_file failed!\n");
                lo->pid = 0;
                return ret;
        }
@@ -416,7 +416,7 @@ static int nbd_do_it(struct nbd_device *lo)
        while ((req = nbd_read_stat(lo)) != NULL)
                nbd_end_request(req);
 
-       sysfs_remove_file(&disk_to_dev(lo->disk)->kobj, &pid_attr.attr);
+       device_remove_file(disk_to_dev(lo->disk), &pid_attr);
        lo->pid = 0;
        return 0;
 }
@@ -457,8 +457,8 @@ static void nbd_handle_req(struct nbd_device *lo, struct request *req)
        if (rq_data_dir(req) == WRITE) {
                nbd_cmd(req) = NBD_CMD_WRITE;
                if (lo->flags & NBD_READ_ONLY) {
-                       printk(KERN_ERR "%s: Write on read-only\n",
-                                       lo->disk->disk_name);
+                       dev_err(disk_to_dev(lo->disk),
+                               "Write on read-only\n");
                        goto error_out;
                }
        }
@@ -468,16 +468,15 @@ static void nbd_handle_req(struct nbd_device *lo, struct request *req)
        mutex_lock(&lo->tx_lock);
        if (unlikely(!lo->sock)) {
                mutex_unlock(&lo->tx_lock);
-               printk(KERN_ERR "%s: Attempted send on closed socket\n",
-                      lo->disk->disk_name);
+               dev_err(disk_to_dev(lo->disk),
+                       "Attempted send on closed socket\n");
                goto error_out;
        }
 
        lo->active_req = req;
 
        if (nbd_send_req(lo, req) != 0) {
-               printk(KERN_ERR "%s: Request send failed\n",
-                               lo->disk->disk_name);
+               dev_err(disk_to_dev(lo->disk), "Request send failed\n");
                req->errors++;
                nbd_end_request(req);
        } else {
@@ -549,8 +548,8 @@ static void do_nbd_request(struct request_queue *q)
                BUG_ON(lo->magic != LO_MAGIC);
 
                if (unlikely(!lo->sock)) {
-                       printk(KERN_ERR "%s: Attempted send on closed socket\n",
-                               lo->disk->disk_name);
+                       dev_err(disk_to_dev(lo->disk),
+                               "Attempted send on closed socket\n");
                        req->errors++;
                        nbd_end_request(req);
                        spin_lock_irq(q->queue_lock);
@@ -576,7 +575,7 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *lo,
        case NBD_DISCONNECT: {
                struct request sreq;
 
-               printk(KERN_INFO "%s: NBD_DISCONNECT\n", lo->disk->disk_name);
+               dev_info(disk_to_dev(lo->disk), "NBD_DISCONNECT\n");
 
                blk_rq_init(NULL, &sreq);
                sreq.cmd_type = REQ_TYPE_SPECIAL;
@@ -674,7 +673,7 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *lo,
                file = lo->file;
                lo->file = NULL;
                nbd_clear_que(lo);
-               printk(KERN_WARNING "%s: queue cleared\n", lo->disk->disk_name);
+               dev_warn(disk_to_dev(lo->disk), "queue cleared\n");
                if (file)
                        fput(file);
                lo->bytesize = 0;
@@ -694,8 +693,8 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *lo,
                return 0;
 
        case NBD_PRINT_DEBUG:
-               printk(KERN_INFO "%s: next = %p, prev = %p, head = %p\n",
-                       bdev->bd_disk->disk_name,
+               dev_info(disk_to_dev(lo->disk),
+                       "next = %p, prev = %p, head = %p\n",
                        lo->queue_head.next, lo->queue_head.prev,
                        &lo->queue_head);
                return 0;
@@ -745,7 +744,7 @@ static int __init nbd_init(void)
        BUILD_BUG_ON(sizeof(struct nbd_request) != 28);
 
        if (max_part < 0) {
-               printk(KERN_CRIT "nbd: max_part must be >= 0\n");
+               printk(KERN_ERR "nbd: max_part must be >= 0\n");
                return -EINVAL;
        }
 
index e133f09..a63b0a2 100644 (file)
@@ -2444,7 +2444,7 @@ static void pkt_end_io_read_cloned(struct bio *bio, int err)
        pkt_bio_finished(pd);
 }
 
-static int pkt_make_request(struct request_queue *q, struct bio *bio)
+static void pkt_make_request(struct request_queue *q, struct bio *bio)
 {
        struct pktcdvd_device *pd;
        char b[BDEVNAME_SIZE];
@@ -2473,7 +2473,7 @@ static int pkt_make_request(struct request_queue *q, struct bio *bio)
                cloned_bio->bi_end_io = pkt_end_io_read_cloned;
                pd->stats.secs_r += bio->bi_size >> 9;
                pkt_queue_bio(pd, cloned_bio);
-               return 0;
+               return;
        }
 
        if (!test_bit(PACKET_WRITABLE, &pd->flags)) {
@@ -2509,7 +2509,7 @@ static int pkt_make_request(struct request_queue *q, struct bio *bio)
                        pkt_make_request(q, &bp->bio1);
                        pkt_make_request(q, &bp->bio2);
                        bio_pair_release(bp);
-                       return 0;
+                       return;
                }
        }
 
@@ -2533,7 +2533,7 @@ static int pkt_make_request(struct request_queue *q, struct bio *bio)
                                }
                                spin_unlock(&pkt->lock);
                                spin_unlock(&pd->cdrw.active_list_lock);
-                               return 0;
+                               return;
                        } else {
                                blocked_bio = 1;
                        }
@@ -2584,10 +2584,9 @@ static int pkt_make_request(struct request_queue *q, struct bio *bio)
                 */
                wake_up(&pd->wqueue);
        }
-       return 0;
+       return;
 end_io:
        bio_io_error(bio);
-       return 0;
 }
 
 
index b3bdb8a..7fad7af 100644 (file)
@@ -596,7 +596,7 @@ out:
        return next;
 }
 
-static int ps3vram_make_request(struct request_queue *q, struct bio *bio)
+static void ps3vram_make_request(struct request_queue *q, struct bio *bio)
 {
        struct ps3_system_bus_device *dev = q->queuedata;
        struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
@@ -610,13 +610,11 @@ static int ps3vram_make_request(struct request_queue *q, struct bio *bio)
        spin_unlock_irq(&priv->lock);
 
        if (busy)
-               return 0;
+               return;
 
        do {
                bio = ps3vram_do_bio(dev, bio);
        } while (bio);
-
-       return 0;
 }
 
 static int __devinit ps3vram_probe(struct ps3_system_bus_device *dev)
index 031ca72..aa27120 100644 (file)
@@ -513,7 +513,7 @@ static void process_page(unsigned long data)
        }
 }
 
-static int mm_make_request(struct request_queue *q, struct bio *bio)
+static void mm_make_request(struct request_queue *q, struct bio *bio)
 {
        struct cardinfo *card = q->queuedata;
        pr_debug("mm_make_request %llu %u\n",
@@ -525,7 +525,7 @@ static int mm_make_request(struct request_queue *q, struct bio *bio)
        card->biotail = &bio->bi_next;
        spin_unlock_irq(&card->lock);
 
-       return 0;
+       return;
 }
 
 static irqreturn_t mm_interrupt(int irq, void *__card)
index 1540792..15ec4db 100644 (file)
@@ -39,6 +39,9 @@
 #include <linux/list.h>
 #include <linux/delay.h>
 #include <linux/freezer.h>
+#include <linux/loop.h>
+#include <linux/falloc.h>
+#include <linux/fs.h>
 
 #include <xen/events.h>
 #include <xen/page.h>
@@ -258,13 +261,16 @@ irqreturn_t xen_blkif_be_int(int irq, void *dev_id)
 
 static void print_stats(struct xen_blkif *blkif)
 {
-       pr_info("xen-blkback (%s): oo %3d  |  rd %4d  |  wr %4d  |  f %4d\n",
+       pr_info("xen-blkback (%s): oo %3d  |  rd %4d  |  wr %4d  |  f %4d"
+                "  |  ds %4d\n",
                 current->comm, blkif->st_oo_req,
-                blkif->st_rd_req, blkif->st_wr_req, blkif->st_f_req);
+                blkif->st_rd_req, blkif->st_wr_req,
+                blkif->st_f_req, blkif->st_ds_req);
        blkif->st_print = jiffies + msecs_to_jiffies(10 * 1000);
        blkif->st_rd_req = 0;
        blkif->st_wr_req = 0;
        blkif->st_oo_req = 0;
+       blkif->st_ds_req = 0;
 }
 
 int xen_blkif_schedule(void *arg)
@@ -410,6 +416,59 @@ static int xen_blkbk_map(struct blkif_request *req,
        return ret;
 }
 
+static void xen_blk_discard(struct xen_blkif *blkif, struct blkif_request *req)
+{
+       int err = 0;
+       int status = BLKIF_RSP_OKAY;
+       struct block_device *bdev = blkif->vbd.bdev;
+
+       if (blkif->blk_backend_type == BLKIF_BACKEND_PHY)
+               /* just forward the discard request */
+               err = blkdev_issue_discard(bdev,
+                               req->u.discard.sector_number,
+                               req->u.discard.nr_sectors,
+                               GFP_KERNEL, 0);
+       else if (blkif->blk_backend_type == BLKIF_BACKEND_FILE) {
+               /* punch a hole in the backing file */
+               struct loop_device *lo = bdev->bd_disk->private_data;
+               struct file *file = lo->lo_backing_file;
+
+               if (file->f_op->fallocate)
+                       err = file->f_op->fallocate(file,
+                               FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE,
+                               req->u.discard.sector_number << 9,
+                               req->u.discard.nr_sectors << 9);
+               else
+                       err = -EOPNOTSUPP;
+       } else
+               err = -EOPNOTSUPP;
+
+       if (err == -EOPNOTSUPP) {
+               pr_debug(DRV_PFX "discard op failed, not supported\n");
+               status = BLKIF_RSP_EOPNOTSUPP;
+       } else if (err)
+               status = BLKIF_RSP_ERROR;
+
+       make_response(blkif, req->id, req->operation, status);
+}
+
+static void xen_blk_drain_io(struct xen_blkif *blkif)
+{
+       atomic_set(&blkif->drain, 1);
+       do {
+               /* The initial value is one, and one refcnt taken at the
+                * start of the xen_blkif_schedule thread. */
+               if (atomic_read(&blkif->refcnt) <= 2)
+                       break;
+               wait_for_completion_interruptible_timeout(
+                               &blkif->drain_complete, HZ);
+
+               if (!atomic_read(&blkif->drain))
+                       break;
+       } while (!kthread_should_stop());
+       atomic_set(&blkif->drain, 0);
+}
+
 /*
  * Completion callback on the bio's. Called as bh->b_end_io()
  */
@@ -422,6 +481,11 @@ static void __end_block_io_op(struct pending_req *pending_req, int error)
                pr_debug(DRV_PFX "flush diskcache op failed, not supported\n");
                xen_blkbk_flush_diskcache(XBT_NIL, pending_req->blkif->be, 0);
                pending_req->status = BLKIF_RSP_EOPNOTSUPP;
+       } else if ((pending_req->operation == BLKIF_OP_WRITE_BARRIER) &&
+                   (error == -EOPNOTSUPP)) {
+               pr_debug(DRV_PFX "write barrier op failed, not supported\n");
+               xen_blkbk_barrier(XBT_NIL, pending_req->blkif->be, 0);
+               pending_req->status = BLKIF_RSP_EOPNOTSUPP;
        } else if (error) {
                pr_debug(DRV_PFX "Buffer not up-to-date at end of operation,"
                         " error=%d\n", error);
@@ -438,6 +502,10 @@ static void __end_block_io_op(struct pending_req *pending_req, int error)
                make_response(pending_req->blkif, pending_req->id,
                              pending_req->operation, pending_req->status);
                xen_blkif_put(pending_req->blkif);
+               if (atomic_read(&pending_req->blkif->refcnt) <= 2) {
+                       if (atomic_read(&pending_req->blkif->drain))
+                               complete(&pending_req->blkif->drain_complete);
+               }
                free_req(pending_req);
        }
 }
@@ -532,7 +600,6 @@ do_block_io_op(struct xen_blkif *blkif)
 
        return more_to_do;
 }
-
 /*
  * Transmutation of the 'struct blkif_request' to a proper 'struct bio'
  * and call the 'submit_bio' to pass it to the underlying storage.
@@ -549,6 +616,7 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif,
        int i, nbio = 0;
        int operation;
        struct blk_plug plug;
+       bool drain = false;
 
        switch (req->operation) {
        case BLKIF_OP_READ:
@@ -559,11 +627,16 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif,
                blkif->st_wr_req++;
                operation = WRITE_ODIRECT;
                break;
+       case BLKIF_OP_WRITE_BARRIER:
+               drain = true;
        case BLKIF_OP_FLUSH_DISKCACHE:
                blkif->st_f_req++;
                operation = WRITE_FLUSH;
                break;
-       case BLKIF_OP_WRITE_BARRIER:
+       case BLKIF_OP_DISCARD:
+               blkif->st_ds_req++;
+               operation = REQ_DISCARD;
+               break;
        default:
                operation = 0; /* make gcc happy */
                goto fail_response;
@@ -572,7 +645,8 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif,
 
        /* Check that the number of segments is sane. */
        nseg = req->nr_segments;
-       if (unlikely(nseg == 0 && operation != WRITE_FLUSH) ||
+       if (unlikely(nseg == 0 && operation != WRITE_FLUSH &&
+                               operation != REQ_DISCARD) ||
            unlikely(nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST)) {
                pr_debug(DRV_PFX "Bad number of segments in request (%d)\n",
                         nseg);
@@ -621,16 +695,25 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif,
                }
        }
 
+       /* Wait on all outstanding I/O's and once that has been completed
+        * issue the WRITE_FLUSH.
+        */
+       if (drain)
+               xen_blk_drain_io(pending_req->blkif);
+
        /*
         * If we have failed at this point, we need to undo the M2P override,
         * set gnttab_set_unmap_op on all of the grant references and perform
         * the hypercall to unmap the grants - that is all done in
         * xen_blkbk_unmap.
         */
-       if (xen_blkbk_map(req, pending_req, seg))
+       if (operation != REQ_DISCARD && xen_blkbk_map(req, pending_req, seg))
                goto fail_flush;
 
-       /* This corresponding xen_blkif_put is done in __end_block_io_op */
+       /*
+        * This corresponding xen_blkif_put is done in __end_block_io_op, or
+        * below (in "!bio") if we are handling a BLKIF_OP_DISCARD.
+        */
        xen_blkif_get(blkif);
 
        for (i = 0; i < nseg; i++) {
@@ -654,18 +737,25 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif,
                preq.sector_number += seg[i].nsec;
        }
 
-       /* This will be hit if the operation was a flush. */
+       /* This will be hit if the operation was a flush or discard. */
        if (!bio) {
-               BUG_ON(operation != WRITE_FLUSH);
+               BUG_ON(operation != WRITE_FLUSH && operation != REQ_DISCARD);
 
-               bio = bio_alloc(GFP_KERNEL, 0);
-               if (unlikely(bio == NULL))
-                       goto fail_put_bio;
+               if (operation == WRITE_FLUSH) {
+                       bio = bio_alloc(GFP_KERNEL, 0);
+                       if (unlikely(bio == NULL))
+                               goto fail_put_bio;
 
-               biolist[nbio++] = bio;
-               bio->bi_bdev    = preq.bdev;
-               bio->bi_private = pending_req;
-               bio->bi_end_io  = end_block_io_op;
+                       biolist[nbio++] = bio;
+                       bio->bi_bdev    = preq.bdev;
+                       bio->bi_private = pending_req;
+                       bio->bi_end_io  = end_block_io_op;
+               } else if (operation == REQ_DISCARD) {
+                       xen_blk_discard(blkif, req);
+                       xen_blkif_put(blkif);
+                       free_req(pending_req);
+                       return 0;
+               }
        }
 
        /*
@@ -685,7 +775,7 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif,
 
        if (operation == READ)
                blkif->st_rd_sect += preq.nr_sects;
-       else if (operation == WRITE || operation == WRITE_FLUSH)
+       else if (operation & WRITE)
                blkif->st_wr_sect += preq.nr_sects;
 
        return 0;
@@ -765,9 +855,9 @@ static int __init xen_blkif_init(void)
 
        mmap_pages = xen_blkif_reqs * BLKIF_MAX_SEGMENTS_PER_REQUEST;
 
-       blkbk->pending_reqs          = kmalloc(sizeof(blkbk->pending_reqs[0]) *
+       blkbk->pending_reqs          = kzalloc(sizeof(blkbk->pending_reqs[0]) *
                                        xen_blkif_reqs, GFP_KERNEL);
-       blkbk->pending_grant_handles = kzalloc(sizeof(blkbk->pending_grant_handles[0]) *
+       blkbk->pending_grant_handles = kmalloc(sizeof(blkbk->pending_grant_handles[0]) *
                                        mmap_pages, GFP_KERNEL);
        blkbk->pending_pages         = kzalloc(sizeof(blkbk->pending_pages[0]) *
                                        mmap_pages, GFP_KERNEL);
@@ -790,8 +880,6 @@ static int __init xen_blkif_init(void)
        if (rc)
                goto failed_init;
 
-       memset(blkbk->pending_reqs, 0, sizeof(blkbk->pending_reqs));
-
        INIT_LIST_HEAD(&blkbk->pending_free);
        spin_lock_init(&blkbk->pending_free_lock);
        init_waitqueue_head(&blkbk->pending_free_wq);
index c4bd340..de09f52 100644 (file)
@@ -62,13 +62,26 @@ struct blkif_common_response {
 
 /* i386 protocol version */
 #pragma pack(push, 4)
+
+struct blkif_x86_32_request_rw {
+       blkif_sector_t sector_number;/* start sector idx on disk (r/w only)  */
+       struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+};
+
+struct blkif_x86_32_request_discard {
+       blkif_sector_t sector_number;/* start sector idx on disk (r/w only)  */
+       uint64_t nr_sectors;
+};
+
 struct blkif_x86_32_request {
        uint8_t        operation;    /* BLKIF_OP_???                         */
        uint8_t        nr_segments;  /* number of segments                   */
        blkif_vdev_t   handle;       /* only for read/write requests         */
        uint64_t       id;           /* private guest value, echoed in resp  */
-       blkif_sector_t sector_number;/* start sector idx on disk (r/w only)  */
-       struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+       union {
+               struct blkif_x86_32_request_rw rw;
+               struct blkif_x86_32_request_discard discard;
+       } u;
 };
 struct blkif_x86_32_response {
        uint64_t        id;              /* copied from request */
@@ -78,13 +91,26 @@ struct blkif_x86_32_response {
 #pragma pack(pop)
 
 /* x86_64 protocol version */
+
+struct blkif_x86_64_request_rw {
+       blkif_sector_t sector_number;/* start sector idx on disk (r/w only)  */
+       struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+};
+
+struct blkif_x86_64_request_discard {
+       blkif_sector_t sector_number;/* start sector idx on disk (r/w only)  */
+       uint64_t nr_sectors;
+};
+
 struct blkif_x86_64_request {
        uint8_t        operation;    /* BLKIF_OP_???                         */
        uint8_t        nr_segments;  /* number of segments                   */
        blkif_vdev_t   handle;       /* only for read/write requests         */
        uint64_t       __attribute__((__aligned__(8))) id;
-       blkif_sector_t sector_number;/* start sector idx on disk (r/w only)  */
-       struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+       union {
+               struct blkif_x86_64_request_rw rw;
+               struct blkif_x86_64_request_discard discard;
+       } u;
 };
 struct blkif_x86_64_response {
        uint64_t       __attribute__((__aligned__(8))) id;
@@ -112,6 +138,11 @@ enum blkif_protocol {
        BLKIF_PROTOCOL_X86_64 = 3,
 };
 
+enum blkif_backend_type {
+       BLKIF_BACKEND_PHY  = 1,
+       BLKIF_BACKEND_FILE = 2,
+};
+
 struct xen_vbd {
        /* What the domain refers to this vbd as. */
        blkif_vdev_t            handle;
@@ -137,6 +168,7 @@ struct xen_blkif {
        unsigned int            irq;
        /* Comms information. */
        enum blkif_protocol     blk_protocol;
+       enum blkif_backend_type blk_backend_type;
        union blkif_back_rings  blk_rings;
        struct vm_struct        *blk_ring_area;
        /* The VBD attached to this interface. */
@@ -148,6 +180,9 @@ struct xen_blkif {
        atomic_t                refcnt;
 
        wait_queue_head_t       wq;
+       /* for barrier (drain) requests */
+       struct completion       drain_complete;
+       atomic_t                drain;
        /* One thread per one blkif. */
        struct task_struct      *xenblkd;
        unsigned int            waiting_reqs;
@@ -158,6 +193,7 @@ struct xen_blkif {
        int                     st_wr_req;
        int                     st_oo_req;
        int                     st_f_req;
+       int                     st_ds_req;
        int                     st_rd_sect;
        int                     st_wr_sect;
 
@@ -181,7 +217,7 @@ struct xen_blkif {
 
 struct phys_req {
        unsigned short          dev;
-       unsigned short          nr_sects;
+       blkif_sector_t          nr_sects;
        struct block_device     *bdev;
        blkif_sector_t          sector_number;
 };
@@ -195,6 +231,8 @@ int xen_blkif_schedule(void *arg);
 int xen_blkbk_flush_diskcache(struct xenbus_transaction xbt,
                              struct backend_info *be, int state);
 
+int xen_blkbk_barrier(struct xenbus_transaction xbt,
+                     struct backend_info *be, int state);
 struct xenbus_device *xen_blkbk_xenbus(struct backend_info *be);
 
 static inline void blkif_get_x86_32_req(struct blkif_request *dst,
@@ -205,12 +243,25 @@ static inline void blkif_get_x86_32_req(struct blkif_request *dst,
        dst->nr_segments = src->nr_segments;
        dst->handle = src->handle;
        dst->id = src->id;
-       dst->u.rw.sector_number = src->sector_number;
-       barrier();
-       if (n > dst->nr_segments)
-               n = dst->nr_segments;
-       for (i = 0; i < n; i++)
-               dst->u.rw.seg[i] = src->seg[i];
+       switch (src->operation) {
+       case BLKIF_OP_READ:
+       case BLKIF_OP_WRITE:
+       case BLKIF_OP_WRITE_BARRIER:
+       case BLKIF_OP_FLUSH_DISKCACHE:
+               dst->u.rw.sector_number = src->u.rw.sector_number;
+               barrier();
+               if (n > dst->nr_segments)
+                       n = dst->nr_segments;
+               for (i = 0; i < n; i++)
+                       dst->u.rw.seg[i] = src->u.rw.seg[i];
+               break;
+       case BLKIF_OP_DISCARD:
+               dst->u.discard.sector_number = src->u.discard.sector_number;
+               dst->u.discard.nr_sectors = src->u.discard.nr_sectors;
+               break;
+       default:
+               break;
+       }
 }
 
 static inline void blkif_get_x86_64_req(struct blkif_request *dst,
@@ -221,12 +272,25 @@ static inline void blkif_get_x86_64_req(struct blkif_request *dst,
        dst->nr_segments = src->nr_segments;
        dst->handle = src->handle;
        dst->id = src->id;
-       dst->u.rw.sector_number = src->sector_number;
-       barrier();
-       if (n > dst->nr_segments)
-               n = dst->nr_segments;
-       for (i = 0; i < n; i++)
-               dst->u.rw.seg[i] = src->seg[i];
+       switch (src->operation) {
+       case BLKIF_OP_READ:
+       case BLKIF_OP_WRITE:
+       case BLKIF_OP_WRITE_BARRIER:
+       case BLKIF_OP_FLUSH_DISKCACHE:
+               dst->u.rw.sector_number = src->u.rw.sector_number;
+               barrier();
+               if (n > dst->nr_segments)
+                       n = dst->nr_segments;
+               for (i = 0; i < n; i++)
+                       dst->u.rw.seg[i] = src->u.rw.seg[i];
+               break;
+       case BLKIF_OP_DISCARD:
+               dst->u.discard.sector_number = src->u.discard.sector_number;
+               dst->u.discard.nr_sectors = src->u.discard.nr_sectors;
+               break;
+       default:
+               break;
+       }
 }
 
 #endif /* __XEN_BLKIF__BACKEND__COMMON_H__ */
index 5fd2010..2c008af 100644 (file)
@@ -114,6 +114,8 @@ static struct xen_blkif *xen_blkif_alloc(domid_t domid)
        spin_lock_init(&blkif->blk_ring_lock);
        atomic_set(&blkif->refcnt, 1);
        init_waitqueue_head(&blkif->wq);
+       init_completion(&blkif->drain_complete);
+       atomic_set(&blkif->drain, 0);
        blkif->st_print = jiffies;
        init_waitqueue_head(&blkif->waiting_to_free);
 
@@ -272,6 +274,7 @@ VBD_SHOW(oo_req,  "%d\n", be->blkif->st_oo_req);
 VBD_SHOW(rd_req,  "%d\n", be->blkif->st_rd_req);
 VBD_SHOW(wr_req,  "%d\n", be->blkif->st_wr_req);
 VBD_SHOW(f_req,  "%d\n", be->blkif->st_f_req);
+VBD_SHOW(ds_req,  "%d\n", be->blkif->st_ds_req);
 VBD_SHOW(rd_sect, "%d\n", be->blkif->st_rd_sect);
 VBD_SHOW(wr_sect, "%d\n", be->blkif->st_wr_sect);
 
@@ -280,6 +283,7 @@ static struct attribute *xen_vbdstat_attrs[] = {
        &dev_attr_rd_req.attr,
        &dev_attr_wr_req.attr,
        &dev_attr_f_req.attr,
+       &dev_attr_ds_req.attr,
        &dev_attr_rd_sect.attr,
        &dev_attr_wr_sect.attr,
        NULL
@@ -419,6 +423,73 @@ int xen_blkbk_flush_diskcache(struct xenbus_transaction xbt,
        return err;
 }
 
+int xen_blkbk_discard(struct xenbus_transaction xbt, struct backend_info *be)
+{
+       struct xenbus_device *dev = be->dev;
+       struct xen_blkif *blkif = be->blkif;
+       char *type;
+       int err;
+       int state = 0;
+
+       type = xenbus_read(XBT_NIL, dev->nodename, "type", NULL);
+       if (!IS_ERR(type)) {
+               if (strncmp(type, "file", 4) == 0) {
+                       state = 1;
+                       blkif->blk_backend_type = BLKIF_BACKEND_FILE;
+               }
+               if (strncmp(type, "phy", 3) == 0) {
+                       struct block_device *bdev = be->blkif->vbd.bdev;
+                       struct request_queue *q = bdev_get_queue(bdev);
+                       if (blk_queue_discard(q)) {
+                               err = xenbus_printf(xbt, dev->nodename,
+                                       "discard-granularity", "%u",
+                                       q->limits.discard_granularity);
+                               if (err) {
+                                       xenbus_dev_fatal(dev, err,
+                                               "writing discard-granularity");
+                                       goto kfree;
+                               }
+                               err = xenbus_printf(xbt, dev->nodename,
+                                       "discard-alignment", "%u",
+                                       q->limits.discard_alignment);
+                               if (err) {
+                                       xenbus_dev_fatal(dev, err,
+                                               "writing discard-alignment");
+                                       goto kfree;
+                               }
+                               state = 1;
+                               blkif->blk_backend_type = BLKIF_BACKEND_PHY;
+                       }
+               }
+       } else {
+               err = PTR_ERR(type);
+               xenbus_dev_fatal(dev, err, "reading type");
+               goto out;
+       }
+
+       err = xenbus_printf(xbt, dev->nodename, "feature-discard",
+                           "%d", state);
+       if (err)
+               xenbus_dev_fatal(dev, err, "writing feature-discard");
+kfree:
+       kfree(type);
+out:
+       return err;
+}
+int xen_blkbk_barrier(struct xenbus_transaction xbt,
+                     struct backend_info *be, int state)
+{
+       struct xenbus_device *dev = be->dev;
+       int err;
+
+       err = xenbus_printf(xbt, dev->nodename, "feature-barrier",
+                           "%d", state);
+       if (err)
+               xenbus_dev_fatal(dev, err, "writing feature-barrier");
+
+       return err;
+}
+
 /*
  * Entry point to this code when a new device is created.  Allocate the basic
  * structures, and watch the store waiting for the hotplug scripts to tell us
@@ -650,6 +721,11 @@ again:
        if (err)
                goto abort;
 
+       err = xen_blkbk_discard(xbt, be);
+
+       /* If we can't advertise it is OK. */
+       err = xen_blkbk_barrier(xbt, be, be->blkif->vbd.flush_support);
+
        err = xenbus_printf(xbt, dev->nodename, "sectors", "%llu",
                            (unsigned long long)vbd_sz(&be->blkif->vbd));
        if (err) {
index 9ea8c25..7b2ec59 100644 (file)
@@ -98,6 +98,9 @@ struct blkfront_info
        unsigned long shadow_free;
        unsigned int feature_flush;
        unsigned int flush_op;
+       unsigned int feature_discard;
+       unsigned int discard_granularity;
+       unsigned int discard_alignment;
        int is_ready;
 };
 
@@ -302,29 +305,36 @@ static int blkif_queue_request(struct request *req)
                ring_req->operation = info->flush_op;
        }
 
-       ring_req->nr_segments = blk_rq_map_sg(req->q, req, info->sg);
-       BUG_ON(ring_req->nr_segments > BLKIF_MAX_SEGMENTS_PER_REQUEST);
+       if (unlikely(req->cmd_flags & REQ_DISCARD)) {
+               /* id, sector_number and handle are set above. */
+               ring_req->operation = BLKIF_OP_DISCARD;
+               ring_req->nr_segments = 0;
+               ring_req->u.discard.nr_sectors = blk_rq_sectors(req);
+       } else {
+               ring_req->nr_segments = blk_rq_map_sg(req->q, req, info->sg);
+               BUG_ON(ring_req->nr_segments > BLKIF_MAX_SEGMENTS_PER_REQUEST);
 
-       for_each_sg(info->sg, sg, ring_req->nr_segments, i) {
-               buffer_mfn = pfn_to_mfn(page_to_pfn(sg_page(sg)));
-               fsect = sg->offset >> 9;
-               lsect = fsect + (sg->length >> 9) - 1;
-               /* install a grant reference. */
-               ref = gnttab_claim_grant_reference(&gref_head);
-               BUG_ON(ref == -ENOSPC);
+               for_each_sg(info->sg, sg, ring_req->nr_segments, i) {
+                       buffer_mfn = pfn_to_mfn(page_to_pfn(sg_page(sg)));
+                       fsect = sg->offset >> 9;
+                       lsect = fsect + (sg->length >> 9) - 1;
+                       /* install a grant reference. */
+                       ref = gnttab_claim_grant_reference(&gref_head);
+                       BUG_ON(ref == -ENOSPC);
 
-               gnttab_grant_foreign_access_ref(
-                               ref,
-                               info->xbdev->otherend_id,
-                               buffer_mfn,
-                               rq_data_dir(req) );
-
-               info->shadow[id].frame[i] = mfn_to_pfn(buffer_mfn);
-               ring_req->u.rw.seg[i] =
-                               (struct blkif_request_segment) {
-                                       .gref       = ref,
-                                       .first_sect = fsect,
-                                       .last_sect  = lsect };
+                       gnttab_grant_foreign_access_ref(
+                                       ref,
+                                       info->xbdev->otherend_id,
+                                       buffer_mfn,
+                                       rq_data_dir(req));
+
+                       info->shadow[id].frame[i] = mfn_to_pfn(buffer_mfn);
+                       ring_req->u.rw.seg[i] =
+                                       (struct blkif_request_segment) {
+                                               .gref       = ref,
+                                               .first_sect = fsect,
+                                               .last_sect  = lsect };
+               }
        }
 
        info->ring.req_prod_pvt++;
@@ -370,7 +380,9 @@ static void do_blkif_request(struct request_queue *rq)
 
                blk_start_request(req);
 
-               if (req->cmd_type != REQ_TYPE_FS) {
+               if ((req->cmd_type != REQ_TYPE_FS) ||
+                   ((req->cmd_flags & (REQ_FLUSH | REQ_FUA)) &&
+                   !info->flush_op)) {
                        __blk_end_request_all(req, -EIO);
                        continue;
                }
@@ -399,6 +411,7 @@ wait:
 static int xlvbd_init_blk_queue(struct gendisk *gd, u16 sector_size)
 {
        struct request_queue *rq;
+       struct blkfront_info *info = gd->private_data;
 
        rq = blk_init_queue(do_blkif_request, &blkif_io_lock);
        if (rq == NULL)
@@ -406,6 +419,13 @@ static int xlvbd_init_blk_queue(struct gendisk *gd, u16 sector_size)
 
        queue_flag_set_unlocked(QUEUE_FLAG_VIRT, rq);
 
+       if (info->feature_discard) {
+               queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, rq);
+               blk_queue_max_discard_sectors(rq, get_capacity(gd));
+               rq->limits.discard_granularity = info->discard_granularity;
+               rq->limits.discard_alignment = info->discard_alignment;
+       }
+
        /* Hard sector size and max sectors impersonate the equiv. hardware. */
        blk_queue_logical_block_size(rq, sector_size);
        blk_queue_max_hw_sectors(rq, 512);
@@ -722,6 +742,17 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
 
                error = (bret->status == BLKIF_RSP_OKAY) ? 0 : -EIO;
                switch (bret->operation) {
+               case BLKIF_OP_DISCARD:
+                       if (unlikely(bret->status == BLKIF_RSP_EOPNOTSUPP)) {
+                               struct request_queue *rq = info->rq;
+                               printk(KERN_WARNING "blkfront: %s: discard op failed\n",
+                                          info->gd->disk_name);
+                               error = -EOPNOTSUPP;
+                               info->feature_discard = 0;
+                               queue_flag_clear(QUEUE_FLAG_DISCARD, rq);
+                       }
+                       __blk_end_request_all(req, error);
+                       break;
                case BLKIF_OP_FLUSH_DISKCACHE:
                case BLKIF_OP_WRITE_BARRIER:
                        if (unlikely(bret->status == BLKIF_RSP_EOPNOTSUPP)) {
@@ -1098,6 +1129,33 @@ blkfront_closing(struct blkfront_info *info)
        bdput(bdev);
 }
 
+static void blkfront_setup_discard(struct blkfront_info *info)
+{
+       int err;
+       char *type;
+       unsigned int discard_granularity;
+       unsigned int discard_alignment;
+
+       type = xenbus_read(XBT_NIL, info->xbdev->otherend, "type", NULL);
+       if (IS_ERR(type))
+               return;
+
+       if (strncmp(type, "phy", 3) == 0) {
+               err = xenbus_gather(XBT_NIL, info->xbdev->otherend,
+                       "discard-granularity", "%u", &discard_granularity,
+                       "discard-alignment", "%u", &discard_alignment,
+                       NULL);
+               if (!err) {
+                       info->feature_discard = 1;
+                       info->discard_granularity = discard_granularity;
+                       info->discard_alignment = discard_alignment;
+               }
+       } else if (strncmp(type, "file", 4) == 0)
+               info->feature_discard = 1;
+
+       kfree(type);
+}
+
 /*
  * Invoked when the backend is finally 'ready' (and has told produced
  * the details about the physical device - #sectors, size, etc).
@@ -1108,7 +1166,7 @@ static void blkfront_connect(struct blkfront_info *info)
        unsigned long sector_size;
        unsigned int binfo;
        int err;
-       int barrier, flush;
+       int barrier, flush, discard;
 
        switch (info->connected) {
        case BLKIF_STATE_CONNECTED:
@@ -1178,7 +1236,14 @@ static void blkfront_connect(struct blkfront_info *info)
                info->feature_flush = REQ_FLUSH;
                info->flush_op = BLKIF_OP_FLUSH_DISKCACHE;
        }
-               
+
+       err = xenbus_gather(XBT_NIL, info->xbdev->otherend,
+                           "feature-discard", "%d", &discard,
+                           NULL);
+
+       if (!err && discard)
+               blkfront_setup_discard(info);
+
        err = xlvbd_alloc_gendisk(sectors, info, binfo, sector_size);
        if (err) {
                xenbus_dev_fatal(info->xbdev, err, "xlvbd_add at %s",
@@ -1385,6 +1450,8 @@ static struct xenbus_driver blkfront = {
 
 static int __init xlblk_init(void)
 {
+       int ret;
+
        if (!xen_domain())
                return -ENODEV;
 
@@ -1394,7 +1461,13 @@ static int __init xlblk_init(void)
                return -ENODEV;
        }
 
-       return xenbus_register_frontend(&blkfront);
+       ret = xenbus_register_frontend(&blkfront);
+       if (ret) {
+               unregister_blkdev(XENVBD_MAJOR, DEV_NAME);
+               return ret;
+       }
+
+       return 0;
 }
 module_init(xlblk_init);
 
index 2e3b3d3..ab8f469 100644 (file)
@@ -193,7 +193,8 @@ config ARCH_HAS_ASYNC_TX_FIND_CHANNEL
 config PL330_DMA
        tristate "DMA API Driver for PL330"
        select DMA_ENGINE
-       depends on PL330
+       depends on ARM_AMBA
+       select PL330
        help
          Select if your platform has one or more PL330 DMACs.
          You need to provide platform specific settings via
index be21e3f..b7cbd1a 100644 (file)
  *    after the final transfer signalled by LBREQ or LSREQ.  The DMAC
  *    will then move to the next LLI entry.
  *
- * Only the former works sanely with scatter lists, so we only implement
- * the DMAC flow control method.  However, peripherals which use the LBREQ
- * and LSREQ signals (eg, MMCI) are unable to use this mode, which through
- * these hardware restrictions prevents them from using scatter DMA.
- *
  * Global TODO:
  * - Break out common code from arch/arm/mach-s3c64xx and share
  */
-#include <linux/device.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
-#include <linux/dmapool.h>
-#include <linux/dmaengine.h>
 #include <linux/amba/bus.h>
 #include <linux/amba/pl08x.h>
 #include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dmaengine.h>
+#include <linux/dmapool.h>
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
 #include <linux/seq_file.h>
-
+#include <linux/slab.h>
 #include <asm/hardware/pl080.h>
 
 #define DRIVER_NAME    "pl08xdmac"
 
+static struct amba_driver pl08x_amba_driver;
+
 /**
  * struct vendor_data - vendor-specific config parameters for PL08x derivatives
  * @channels: the number of channels available in this variant
@@ -126,7 +123,8 @@ struct pl08x_lli {
  * @phy_chans: array of data for the physical channels
  * @pool: a pool for the LLI descriptors
  * @pool_ctr: counter of LLIs in the pool
- * @lli_buses: bitmask to or in to LLI pointer selecting AHB port for LLI fetches
+ * @lli_buses: bitmask to or in to LLI pointer selecting AHB port for LLI
+ * fetches
  * @mem_buses: set to indicate memory transfers on AHB2.
  * @lock: a spinlock for this struct
  */
@@ -149,14 +147,6 @@ struct pl08x_driver_data {
  * PL08X specific defines
  */
 
-/*
- * Memory boundaries: the manual for PL08x says that the controller
- * cannot read past a 1KiB boundary, so these defines are used to
- * create transfer LLIs that do not cross such boundaries.
- */
-#define PL08X_BOUNDARY_SHIFT           (10)    /* 1KB 0x400 */
-#define PL08X_BOUNDARY_SIZE            (1 << PL08X_BOUNDARY_SHIFT)
-
 /* Size (bytes) of each LLI buffer allocated for one transfer */
 # define PL08X_LLI_TSFR_SIZE   0x2000
 
@@ -272,7 +262,6 @@ static void pl08x_resume_phy_chan(struct pl08x_phy_chan *ch)
        writel(val, ch->base + PL080_CH_CONFIG);
 }
 
-
 /*
  * pl08x_terminate_phy_chan() stops the channel, clears the FIFO and
  * clears any pending interrupt status.  This should not be used for
@@ -363,7 +352,9 @@ static u32 pl08x_getbytes_chan(struct pl08x_dma_chan *plchan)
        if (!list_empty(&plchan->pend_list)) {
                struct pl08x_txd *txdi;
                list_for_each_entry(txdi, &plchan->pend_list, node) {
-                       bytes += txdi->len;
+                       struct pl08x_sg *dsg;
+                       list_for_each_entry(dsg, &txd->dsg_list, node)
+                               bytes += dsg->len;
                }
        }
 
@@ -407,6 +398,7 @@ pl08x_get_phy_channel(struct pl08x_driver_data *pl08x,
                return NULL;
        }
 
+       pm_runtime_get_sync(&pl08x->adev->dev);
        return ch;
 }
 
@@ -420,6 +412,8 @@ static inline void pl08x_put_phy_channel(struct pl08x_driver_data *pl08x,
        /* Stop the channel and clear its interrupts */
        pl08x_terminate_phy_chan(pl08x, ch);
 
+       pm_runtime_put(&pl08x->adev->dev);
+
        /* Mark it as free */
        ch->serving = NULL;
        spin_unlock_irqrestore(&ch->lock, flags);
@@ -499,36 +493,30 @@ struct pl08x_lli_build_data {
 };
 
 /*
- * Autoselect a master bus to use for the transfer this prefers the
- * destination bus if both available if fixed address on one bus the
- * other will be chosen
+ * Autoselect a master bus to use for the transfer. Slave will be the chosen as
+ * victim in case src & dest are not similarly aligned. i.e. If after aligning
+ * masters address with width requirements of transfer (by sending few byte by
+ * byte data), slave is still not aligned, then its width will be reduced to
+ * BYTE.
+ * - prefers the destination bus if both available
+ * - prefers bus with fixed address (i.e. peripheral)
  */
 static void pl08x_choose_master_bus(struct pl08x_lli_build_data *bd,
        struct pl08x_bus_data **mbus, struct pl08x_bus_data **sbus, u32 cctl)
 {
        if (!(cctl & PL080_CONTROL_DST_INCR)) {
-               *mbus = &bd->srcbus;
-               *sbus = &bd->dstbus;
-       } else if (!(cctl & PL080_CONTROL_SRC_INCR)) {
                *mbus = &bd->dstbus;
                *sbus = &bd->srcbus;
+       } else if (!(cctl & PL080_CONTROL_SRC_INCR)) {
+               *mbus = &bd->srcbus;
+               *sbus = &bd->dstbus;
        } else {
-               if (bd->dstbus.buswidth == 4) {
+               if (bd->dstbus.buswidth >= bd->srcbus.buswidth) {
                        *mbus = &bd->dstbus;
                        *sbus = &bd->srcbus;
-               } else if (bd->srcbus.buswidth == 4) {
-                       *mbus = &bd->srcbus;
-                       *sbus = &bd->dstbus;
-               } else if (bd->dstbus.buswidth == 2) {
-                       *mbus = &bd->dstbus;
-                       *sbus = &bd->srcbus;
-               } else if (bd->srcbus.buswidth == 2) {
+               } else {
                        *mbus = &bd->srcbus;
                        *sbus = &bd->dstbus;
-               } else {
-                       /* bd->srcbus.buswidth == 1 */
-                       *mbus = &bd->dstbus;
-                       *sbus = &bd->srcbus;
                }
        }
 }
@@ -547,7 +535,8 @@ static void pl08x_fill_lli_for_desc(struct pl08x_lli_build_data *bd,
        llis_va[num_llis].cctl = cctl;
        llis_va[num_llis].src = bd->srcbus.addr;
        llis_va[num_llis].dst = bd->dstbus.addr;
-       llis_va[num_llis].lli = llis_bus + (num_llis + 1) * sizeof(struct pl08x_lli);
+       llis_va[num_llis].lli = llis_bus + (num_llis + 1) *
+               sizeof(struct pl08x_lli);
        llis_va[num_llis].lli |= bd->lli_bus;
 
        if (cctl & PL080_CONTROL_SRC_INCR)
@@ -560,16 +549,12 @@ static void pl08x_fill_lli_for_desc(struct pl08x_lli_build_data *bd,
        bd->remainder -= len;
 }
 
-/*
- * Return number of bytes to fill to boundary, or len.
- * This calculation works for any value of addr.
- */
-static inline size_t pl08x_pre_boundary(u32 addr, size_t len)
+static inline void prep_byte_width_lli(struct pl08x_lli_build_data *bd,
+               u32 *cctl, u32 len, int num_llis, size_t *total_bytes)
 {
-       size_t boundary_len = PL08X_BOUNDARY_SIZE -
-                       (addr & (PL08X_BOUNDARY_SIZE - 1));
-
-       return min(boundary_len, len);
+       *cctl = pl08x_cctl_bits(*cctl, 1, 1, len);
+       pl08x_fill_lli_for_desc(bd, num_llis, len, *cctl);
+       (*total_bytes) += len;
 }
 
 /*
@@ -583,13 +568,12 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
        struct pl08x_bus_data *mbus, *sbus;
        struct pl08x_lli_build_data bd;
        int num_llis = 0;
-       u32 cctl;
-       size_t max_bytes_per_lli;
-       size_t total_bytes = 0;
+       u32 cctl, early_bytes = 0;
+       size_t max_bytes_per_lli, total_bytes;
        struct pl08x_lli *llis_va;
+       struct pl08x_sg *dsg;
 
-       txd->llis_va = dma_pool_alloc(pl08x->pool, GFP_NOWAIT,
-                                     &txd->llis_bus);
+       txd->llis_va = dma_pool_alloc(pl08x->pool, GFP_NOWAIT, &txd->llis_bus);
        if (!txd->llis_va) {
                dev_err(&pl08x->adev->dev, "%s no memory for llis\n", __func__);
                return 0;
@@ -597,13 +581,9 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
 
        pl08x->pool_ctr++;
 
-       /* Get the default CCTL */
-       cctl = txd->cctl;
-
        bd.txd = txd;
-       bd.srcbus.addr = txd->src_addr;
-       bd.dstbus.addr = txd->dst_addr;
        bd.lli_bus = (pl08x->lli_buses & PL08X_AHB2) ? PL080_LLI_LM_AHB2 : 0;
+       cctl = txd->cctl;
 
        /* Find maximum width of the source bus */
        bd.srcbus.maxwidth =
@@ -615,215 +595,179 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
                pl08x_get_bytes_for_cctl((cctl & PL080_CONTROL_DWIDTH_MASK) >>
                                       PL080_CONTROL_DWIDTH_SHIFT);
 
-       /* Set up the bus widths to the maximum */
-       bd.srcbus.buswidth = bd.srcbus.maxwidth;
-       bd.dstbus.buswidth = bd.dstbus.maxwidth;
+       list_for_each_entry(dsg, &txd->dsg_list, node) {
+               total_bytes = 0;
+               cctl = txd->cctl;
 
-       /*
-        * Bytes transferred == tsize * MIN(buswidths), not max(buswidths)
-        */
-       max_bytes_per_lli = min(bd.srcbus.buswidth, bd.dstbus.buswidth) *
-               PL080_CONTROL_TRANSFER_SIZE_MASK;
+               bd.srcbus.addr = dsg->src_addr;
+               bd.dstbus.addr = dsg->dst_addr;
+               bd.remainder = dsg->len;
+               bd.srcbus.buswidth = bd.srcbus.maxwidth;
+               bd.dstbus.buswidth = bd.dstbus.maxwidth;
 
-       /* We need to count this down to zero */
-       bd.remainder = txd->len;
+               pl08x_choose_master_bus(&bd, &mbus, &sbus, cctl);
 
-       /*
-        * Choose bus to align to
-        * - prefers destination bus if both available
-        * - if fixed address on one bus chooses other
-        */
-       pl08x_choose_master_bus(&bd, &mbus, &sbus, cctl);
-
-       dev_vdbg(&pl08x->adev->dev, "src=0x%08x%s/%u dst=0x%08x%s/%u len=%zu llimax=%zu\n",
-                bd.srcbus.addr, cctl & PL080_CONTROL_SRC_INCR ? "+" : "",
-                bd.srcbus.buswidth,
-                bd.dstbus.addr, cctl & PL080_CONTROL_DST_INCR ? "+" : "",
-                bd.dstbus.buswidth,
-                bd.remainder, max_bytes_per_lli);
-       dev_vdbg(&pl08x->adev->dev, "mbus=%s sbus=%s\n",
-                mbus == &bd.srcbus ? "src" : "dst",
-                sbus == &bd.srcbus ? "src" : "dst");
-
-       if (txd->len < mbus->buswidth) {
-               /* Less than a bus width available - send as single bytes */
-               while (bd.remainder) {
-                       dev_vdbg(&pl08x->adev->dev,
-                                "%s single byte LLIs for a transfer of "
-                                "less than a bus width (remain 0x%08x)\n",
-                                __func__, bd.remainder);
-                       cctl = pl08x_cctl_bits(cctl, 1, 1, 1);
-                       pl08x_fill_lli_for_desc(&bd, num_llis++, 1, cctl);
-                       total_bytes++;
-               }
-       } else {
-               /* Make one byte LLIs until master bus is aligned */
-               while ((mbus->addr) % (mbus->buswidth)) {
-                       dev_vdbg(&pl08x->adev->dev,
-                               "%s adjustment lli for less than bus width "
-                                "(remain 0x%08x)\n",
-                                __func__, bd.remainder);
-                       cctl = pl08x_cctl_bits(cctl, 1, 1, 1);
-                       pl08x_fill_lli_for_desc(&bd, num_llis++, 1, cctl);
-                       total_bytes++;
-               }
+               dev_vdbg(&pl08x->adev->dev, "src=0x%08x%s/%u dst=0x%08x%s/%u len=%zu\n",
+                       bd.srcbus.addr, cctl & PL080_CONTROL_SRC_INCR ? "+" : "",
+                       bd.srcbus.buswidth,
+                       bd.dstbus.addr, cctl & PL080_CONTROL_DST_INCR ? "+" : "",
+                       bd.dstbus.buswidth,
+                       bd.remainder);
+               dev_vdbg(&pl08x->adev->dev, "mbus=%s sbus=%s\n",
+                       mbus == &bd.srcbus ? "src" : "dst",
+                       sbus == &bd.srcbus ? "src" : "dst");
 
                /*
-                * Master now aligned
-                * - if slave is not then we must set its width down
+                * Zero length is only allowed if all these requirements are
+                * met:
+                * - flow controller is peripheral.
+                * - src.addr is aligned to src.width
+                * - dst.addr is aligned to dst.width
+                *
+                * sg_len == 1 should be true, as there can be two cases here:
+                *
+                * - Memory addresses are contiguous and are not scattered.
+                *   Here, Only one sg will be passed by user driver, with
+                *   memory address and zero length. We pass this to controller
+                *   and after the transfer it will receive the last burst
+                *   request from peripheral and so transfer finishes.
+                *
+                * - Memory addresses are scattered and are not contiguous.
+                *   Here, Obviously as DMA controller doesn't know when a lli's
+                *   transfer gets over, it can't load next lli. So in this
+                *   case, there has to be an assumption that only one lli is
+                *   supported. Thus, we can't have scattered addresses.
                 */
-               if (sbus->addr % sbus->buswidth) {
-                       dev_dbg(&pl08x->adev->dev,
-                               "%s set down bus width to one byte\n",
-                                __func__);
+               if (!bd.remainder) {
+                       u32 fc = (txd->ccfg & PL080_CONFIG_FLOW_CONTROL_MASK) >>
+                               PL080_CONFIG_FLOW_CONTROL_SHIFT;
+                       if (!((fc >= PL080_FLOW_SRC2DST_DST) &&
+                                       (fc <= PL080_FLOW_SRC2DST_SRC))) {
+                               dev_err(&pl08x->adev->dev, "%s sg len can't be zero",
+                                       __func__);
+                               return 0;
+                       }
+
+                       if ((bd.srcbus.addr % bd.srcbus.buswidth) ||
+                                       (bd.srcbus.addr % bd.srcbus.buswidth)) {
+                               dev_err(&pl08x->adev->dev,
+                                       "%s src & dst address must be aligned to src"
+                                       " & dst width if peripheral is flow controller",
+                                       __func__);
+                               return 0;
+                       }
 
-                       sbus->buswidth = 1;
+                       cctl = pl08x_cctl_bits(cctl, bd.srcbus.buswidth,
+                                       bd.dstbus.buswidth, 0);
+                       pl08x_fill_lli_for_desc(&bd, num_llis++, 0, cctl);
+                       break;
                }
 
                /*
-                * Make largest possible LLIs until less than one bus
-                * width left
+                * Send byte by byte for following cases
+                * - Less than a bus width available
+                * - until master bus is aligned
                 */
-               while (bd.remainder > (mbus->buswidth - 1)) {
-                       size_t lli_len, target_len, tsize, odd_bytes;
+               if (bd.remainder < mbus->buswidth)
+                       early_bytes = bd.remainder;
+               else if ((mbus->addr) % (mbus->buswidth)) {
+                       early_bytes = mbus->buswidth - (mbus->addr) %
+                               (mbus->buswidth);
+                       if ((bd.remainder - early_bytes) < mbus->buswidth)
+                               early_bytes = bd.remainder;
+               }
 
+               if (early_bytes) {
+                       dev_vdbg(&pl08x->adev->dev,
+                               "%s byte width LLIs (remain 0x%08x)\n",
+                               __func__, bd.remainder);
+                       prep_byte_width_lli(&bd, &cctl, early_bytes, num_llis++,
+                               &total_bytes);
+               }
+
+               if (bd.remainder) {
                        /*
-                        * If enough left try to send max possible,
-                        * otherwise try to send the remainder
+                        * Master now aligned
+                        * - if slave is not then we must set its width down
                         */
-                       target_len = min(bd.remainder, max_bytes_per_lli);
+                       if (sbus->addr % sbus->buswidth) {
+                               dev_dbg(&pl08x->adev->dev,
+                                       "%s set down bus width to one byte\n",
+                                       __func__);
+
+                               sbus->buswidth = 1;
+                       }
 
                        /*
-                        * Set bus lengths for incrementing buses to the
-                        * number of bytes which fill to next memory boundary,
-                        * limiting on the target length calculated above.
+                        * Bytes transferred = tsize * src width, not
+                        * MIN(buswidths)
                         */
-                       if (cctl & PL080_CONTROL_SRC_INCR)
-                               bd.srcbus.fill_bytes =
-                                       pl08x_pre_boundary(bd.srcbus.addr,
-                                               target_len);
-                       else
-                               bd.srcbus.fill_bytes = target_len;
-
-                       if (cctl & PL080_CONTROL_DST_INCR)
-                               bd.dstbus.fill_bytes =
-                                       pl08x_pre_boundary(bd.dstbus.addr,
-                                               target_len);
-                       else
-                               bd.dstbus.fill_bytes = target_len;
-
-                       /* Find the nearest */
-                       lli_len = min(bd.srcbus.fill_bytes,
-                                     bd.dstbus.fill_bytes);
-
-                       BUG_ON(lli_len > bd.remainder);
-
-                       if (lli_len <= 0) {
-                               dev_err(&pl08x->adev->dev,
-                                       "%s lli_len is %zu, <= 0\n",
-                                               __func__, lli_len);
-                               return 0;
-                       }
+                       max_bytes_per_lli = bd.srcbus.buswidth *
+                               PL080_CONTROL_TRANSFER_SIZE_MASK;
+                       dev_vdbg(&pl08x->adev->dev,
+                               "%s max bytes per lli = %zu\n",
+                               __func__, max_bytes_per_lli);
+
+                       /*
+                        * Make largest possible LLIs until less than one bus
+                        * width left
+                        */
+                       while (bd.remainder > (mbus->buswidth - 1)) {
+                               size_t lli_len, tsize, width;
 
-                       if (lli_len == target_len) {
-                               /*
-                                * Can send what we wanted.
-                                * Maintain alignment
-                                */
-                               lli_len = (lli_len/mbus->buswidth) *
-                                                       mbus->buswidth;
-                               odd_bytes = 0;
-                       } else {
                                /*
-                                * So now we know how many bytes to transfer
-                                * to get to the nearest boundary.  The next
-                                * LLI will past the boundary.  However, we
-                                * may be working to a boundary on the slave
-                                * bus.  We need to ensure the master stays
-                                * aligned, and that we are working in
-                                * multiples of the bus widths.
+                                * If enough left try to send max possible,
+                                * otherwise try to send the remainder
                                 */
-                               odd_bytes = lli_len % mbus->buswidth;
-                               lli_len -= odd_bytes;
-
-                       }
+                               lli_len = min(bd.remainder, max_bytes_per_lli);
 
-                       if (lli_len) {
                                /*
-                                * Check against minimum bus alignment:
-                                * Calculate actual transfer size in relation
-                                * to bus width an get a maximum remainder of
-                                * the smallest bus width - 1
+                                * Check against maximum bus alignment:
+                                * Calculate actual transfer size in relation to
+                                * bus width an get a maximum remainder of the
+                                * highest bus width - 1
                                 */
-                               /* FIXME: use round_down()? */
-                               tsize = lli_len / min(mbus->buswidth,
-                                                     sbus->buswidth);
-                               lli_len = tsize * min(mbus->buswidth,
-                                                     sbus->buswidth);
-
-                               if (target_len != lli_len) {
-                                       dev_vdbg(&pl08x->adev->dev,
-                                       "%s can't send what we want. Desired 0x%08zx, lli of 0x%08zx bytes in txd of 0x%08zx\n",
-                                       __func__, target_len, lli_len, txd->len);
-                               }
-
-                               cctl = pl08x_cctl_bits(cctl,
-                                                      bd.srcbus.buswidth,
-                                                      bd.dstbus.buswidth,
-                                                      tsize);
+                               width = max(mbus->buswidth, sbus->buswidth);
+                               lli_len = (lli_len / width) * width;
+                               tsize = lli_len / bd.srcbus.buswidth;
 
                                dev_vdbg(&pl08x->adev->dev,
-                                       "%s fill lli with single lli chunk of size 0x%08zx (remainder 0x%08zx)\n",
+                                       "%s fill lli with single lli chunk of "
+                                       "size 0x%08zx (remainder 0x%08zx)\n",
                                        __func__, lli_len, bd.remainder);
+
+                               cctl = pl08x_cctl_bits(cctl, bd.srcbus.buswidth,
+                                       bd.dstbus.buswidth, tsize);
                                pl08x_fill_lli_for_desc(&bd, num_llis++,
-                                       lli_len, cctl);
+                                               lli_len, cctl);
                                total_bytes += lli_len;
                        }
 
-
-                       if (odd_bytes) {
-                               /*
-                                * Creep past the boundary, maintaining
-                                * master alignment
-                                */
-                               int j;
-                               for (j = 0; (j < mbus->buswidth)
-                                               && (bd.remainder); j++) {
-                                       cctl = pl08x_cctl_bits(cctl, 1, 1, 1);
-                                       dev_vdbg(&pl08x->adev->dev,
-                                               "%s align with boundary, single byte (remain 0x%08zx)\n",
-                                               __func__, bd.remainder);
-                                       pl08x_fill_lli_for_desc(&bd,
-                                               num_llis++, 1, cctl);
-                                       total_bytes++;
-                               }
+                       /*
+                        * Send any odd bytes
+                        */
+                       if (bd.remainder) {
+                               dev_vdbg(&pl08x->adev->dev,
+                                       "%s align with boundary, send odd bytes (remain %zu)\n",
+                                       __func__, bd.remainder);
+                               prep_byte_width_lli(&bd, &cctl, bd.remainder,
+                                               num_llis++, &total_bytes);
                        }
                }
 
-               /*
-                * Send any odd bytes
-                */
-               while (bd.remainder) {
-                       cctl = pl08x_cctl_bits(cctl, 1, 1, 1);
-                       dev_vdbg(&pl08x->adev->dev,
-                               "%s align with boundary, single odd byte (remain %zu)\n",
-                               __func__, bd.remainder);
-                       pl08x_fill_lli_for_desc(&bd, num_llis++, 1, cctl);
-                       total_bytes++;
+               if (total_bytes != dsg->len) {
+                       dev_err(&pl08x->adev->dev,
+                               "%s size of encoded lli:s don't match total txd, transferred 0x%08zx from size 0x%08zx\n",
+                               __func__, total_bytes, dsg->len);
+                       return 0;
                }
-       }
-       if (total_bytes != txd->len) {
-               dev_err(&pl08x->adev->dev,
-                       "%s size of encoded lli:s don't match total txd, transferred 0x%08zx from size 0x%08zx\n",
-                       __func__, total_bytes, txd->len);
-               return 0;
-       }
 
-       if (num_llis >= MAX_NUM_TSFR_LLIS) {
-               dev_err(&pl08x->adev->dev,
-                       "%s need to increase MAX_NUM_TSFR_LLIS from 0x%08x\n",
-                       __func__, (u32) MAX_NUM_TSFR_LLIS);
-               return 0;
+               if (num_llis >= MAX_NUM_TSFR_LLIS) {
+                       dev_err(&pl08x->adev->dev,
+                               "%s need to increase MAX_NUM_TSFR_LLIS from 0x%08x\n",
+                               __func__, (u32) MAX_NUM_TSFR_LLIS);
+                       return 0;
+               }
        }
 
        llis_va = txd->llis_va;
@@ -856,11 +800,19 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
 static void pl08x_free_txd(struct pl08x_driver_data *pl08x,
                           struct pl08x_txd *txd)
 {
+       struct pl08x_sg *dsg, *_dsg;
+
        /* Free the LLI */
-       dma_pool_free(pl08x->pool, txd->llis_va, txd->llis_bus);
+       if (txd->llis_va)
+               dma_pool_free(pl08x->pool, txd->llis_va, txd->llis_bus);
 
        pl08x->pool_ctr--;
 
+       list_for_each_entry_safe(dsg, _dsg, &txd->dsg_list, node) {
+               list_del(&dsg->node);
+               kfree(dsg);
+       }
+
        kfree(txd);
 }
 
@@ -917,9 +869,7 @@ static int prep_phy_channel(struct pl08x_dma_chan *plchan,
         * need, but for slaves the physical signals may be muxed!
         * Can the platform allow us to use this channel?
         */
-       if (plchan->slave &&
-           ch->signal < 0 &&
-           pl08x->pd->get_signal) {
+       if (plchan->slave && pl08x->pd->get_signal) {
                ret = pl08x->pd->get_signal(plchan);
                if (ret < 0) {
                        dev_dbg(&pl08x->adev->dev,
@@ -1008,10 +958,8 @@ static struct dma_async_tx_descriptor *pl08x_prep_dma_interrupt(
  * If slaves are relying on interrupts to signal completion this function
  * must not be called with interrupts disabled.
  */
-static enum dma_status
-pl08x_dma_tx_status(struct dma_chan *chan,
-                   dma_cookie_t cookie,
-                   struct dma_tx_state *txstate)
+static enum dma_status pl08x_dma_tx_status(struct dma_chan *chan,
+               dma_cookie_t cookie, struct dma_tx_state *txstate)
 {
        struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
        dma_cookie_t last_used;
@@ -1253,7 +1201,9 @@ static int pl08x_prep_channel_resources(struct pl08x_dma_chan *plchan,
 
        num_llis = pl08x_fill_llis_for_desc(pl08x, txd);
        if (!num_llis) {
-               kfree(txd);
+               spin_lock_irqsave(&plchan->lock, flags);
+               pl08x_free_txd(pl08x, txd);
+               spin_unlock_irqrestore(&plchan->lock, flags);
                return -EINVAL;
        }
 
@@ -1301,13 +1251,14 @@ static int pl08x_prep_channel_resources(struct pl08x_dma_chan *plchan,
 static struct pl08x_txd *pl08x_get_txd(struct pl08x_dma_chan *plchan,
        unsigned long flags)
 {
-       struct pl08x_txd *txd = kzalloc(sizeof(struct pl08x_txd), GFP_NOWAIT);
+       struct pl08x_txd *txd = kzalloc(sizeof(*txd), GFP_NOWAIT);
 
        if (txd) {
                dma_async_tx_descriptor_init(&txd->tx, &plchan->chan);
                txd->tx.flags = flags;
                txd->tx.tx_submit = pl08x_tx_submit;
                INIT_LIST_HEAD(&txd->node);
+               INIT_LIST_HEAD(&txd->dsg_list);
 
                /* Always enable error and terminal interrupts */
                txd->ccfg = PL080_CONFIG_ERR_IRQ_MASK |
@@ -1326,6 +1277,7 @@ static struct dma_async_tx_descriptor *pl08x_prep_dma_memcpy(
        struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
        struct pl08x_driver_data *pl08x = plchan->host;
        struct pl08x_txd *txd;
+       struct pl08x_sg *dsg;
        int ret;
 
        txd = pl08x_get_txd(plchan, flags);
@@ -1335,10 +1287,19 @@ static struct dma_async_tx_descriptor *pl08x_prep_dma_memcpy(
                return NULL;
        }
 
+       dsg = kzalloc(sizeof(struct pl08x_sg), GFP_NOWAIT);
+       if (!dsg) {
+               pl08x_free_txd(pl08x, txd);
+               dev_err(&pl08x->adev->dev, "%s no memory for pl080 sg\n",
+                               __func__);
+               return NULL;
+       }
+       list_add_tail(&dsg->node, &txd->dsg_list);
+
        txd->direction = DMA_NONE;
-       txd->src_addr = src;
-       txd->dst_addr = dest;
-       txd->len = len;
+       dsg->src_addr = src;
+       dsg->dst_addr = dest;
+       dsg->len = len;
 
        /* Set platform data for m2m */
        txd->ccfg |= PL080_FLOW_MEM2MEM << PL080_CONFIG_FLOW_CONTROL_SHIFT;
@@ -1367,19 +1328,13 @@ static struct dma_async_tx_descriptor *pl08x_prep_slave_sg(
        struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
        struct pl08x_driver_data *pl08x = plchan->host;
        struct pl08x_txd *txd;
-       int ret;
-
-       /*
-        * Current implementation ASSUMES only one sg
-        */
-       if (sg_len != 1) {
-               dev_err(&pl08x->adev->dev, "%s prepared too long sglist\n",
-                       __func__);
-               BUG();
-       }
+       struct pl08x_sg *dsg;
+       struct scatterlist *sg;
+       dma_addr_t slave_addr;
+       int ret, tmp;
 
        dev_dbg(&pl08x->adev->dev, "%s prepare transaction of %d bytes from %s\n",
-               __func__, sgl->length, plchan->name);
+                       __func__, sgl->length, plchan->name);
 
        txd = pl08x_get_txd(plchan, flags);
        if (!txd) {
@@ -1398,24 +1353,49 @@ static struct dma_async_tx_descriptor *pl08x_prep_slave_sg(
         * channel target address dynamically at runtime.
         */
        txd->direction = direction;
-       txd->len = sgl->length;
 
        if (direction == DMA_TO_DEVICE) {
-               txd->ccfg |= PL080_FLOW_MEM2PER << PL080_CONFIG_FLOW_CONTROL_SHIFT;
                txd->cctl = plchan->dst_cctl;
-               txd->src_addr = sgl->dma_address;
-               txd->dst_addr = plchan->dst_addr;
+               slave_addr = plchan->dst_addr;
        } else if (direction == DMA_FROM_DEVICE) {
-               txd->ccfg |= PL080_FLOW_PER2MEM << PL080_CONFIG_FLOW_CONTROL_SHIFT;
                txd->cctl = plchan->src_cctl;
-               txd->src_addr = plchan->src_addr;
-               txd->dst_addr = sgl->dma_address;
+               slave_addr = plchan->src_addr;
        } else {
+               pl08x_free_txd(pl08x, txd);
                dev_err(&pl08x->adev->dev,
                        "%s direction unsupported\n", __func__);
                return NULL;
        }
 
+       if (plchan->cd->device_fc)
+               tmp = (direction == DMA_TO_DEVICE) ? PL080_FLOW_MEM2PER_PER :
+                       PL080_FLOW_PER2MEM_PER;
+       else
+               tmp = (direction == DMA_TO_DEVICE) ? PL080_FLOW_MEM2PER :
+                       PL080_FLOW_PER2MEM;
+
+       txd->ccfg |= tmp << PL080_CONFIG_FLOW_CONTROL_SHIFT;
+
+       for_each_sg(sgl, sg, sg_len, tmp) {
+               dsg = kzalloc(sizeof(struct pl08x_sg), GFP_NOWAIT);
+               if (!dsg) {
+                       pl08x_free_txd(pl08x, txd);
+                       dev_err(&pl08x->adev->dev, "%s no mem for pl080 sg\n",
+                                       __func__);
+                       return NULL;
+               }
+               list_add_tail(&dsg->node, &txd->dsg_list);
+
+               dsg->len = sg_dma_len(sg);
+               if (direction == DMA_TO_DEVICE) {
+                       dsg->src_addr = sg_phys(sg);
+                       dsg->dst_addr = slave_addr;
+               } else {
+                       dsg->src_addr = slave_addr;
+                       dsg->dst_addr = sg_phys(sg);
+               }
+       }
+
        ret = pl08x_prep_channel_resources(plchan, txd);
        if (ret)
                return NULL;
@@ -1489,9 +1469,15 @@ static int pl08x_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
 
 bool pl08x_filter_id(struct dma_chan *chan, void *chan_id)
 {
-       struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
+       struct pl08x_dma_chan *plchan;
        char *name = chan_id;
 
+       /* Reject channels for devices not bound to this driver */
+       if (chan->device->dev->driver != &pl08x_amba_driver.drv)
+               return false;
+
+       plchan = to_pl08x_chan(chan);
+
        /* Check that the channel is not taken! */
        if (!strcmp(plchan->name, name))
                return true;
@@ -1507,34 +1493,34 @@ bool pl08x_filter_id(struct dma_chan *chan, void *chan_id)
  */
 static void pl08x_ensure_on(struct pl08x_driver_data *pl08x)
 {
-       u32 val;
-
-       val = readl(pl08x->base + PL080_CONFIG);
-       val &= ~(PL080_CONFIG_M2_BE | PL080_CONFIG_M1_BE | PL080_CONFIG_ENABLE);
-       /* We implicitly clear bit 1 and that means little-endian mode */
-       val |= PL080_CONFIG_ENABLE;
-       writel(val, pl08x->base + PL080_CONFIG);
+       writel(PL080_CONFIG_ENABLE, pl08x->base + PL080_CONFIG);
 }
 
 static void pl08x_unmap_buffers(struct pl08x_txd *txd)
 {
        struct device *dev = txd->tx.chan->device->dev;
+       struct pl08x_sg *dsg;
 
        if (!(txd->tx.flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
                if (txd->tx.flags & DMA_COMPL_SRC_UNMAP_SINGLE)
-                       dma_unmap_single(dev, txd->src_addr, txd->len,
-                               DMA_TO_DEVICE);
-               else
-                       dma_unmap_page(dev, txd->src_addr, txd->len,
-                               DMA_TO_DEVICE);
+                       list_for_each_entry(dsg, &txd->dsg_list, node)
+                               dma_unmap_single(dev, dsg->src_addr, dsg->len,
+                                               DMA_TO_DEVICE);
+               else {
+                       list_for_each_entry(dsg, &txd->dsg_list, node)
+                               dma_unmap_page(dev, dsg->src_addr, dsg->len,
+                                               DMA_TO_DEVICE);
+               }
        }
        if (!(txd->tx.flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
                if (txd->tx.flags & DMA_COMPL_DEST_UNMAP_SINGLE)
-                       dma_unmap_single(dev, txd->dst_addr, txd->len,
-                               DMA_FROM_DEVICE);
+                       list_for_each_entry(dsg, &txd->dsg_list, node)
+                               dma_unmap_single(dev, dsg->dst_addr, dsg->len,
+                                               DMA_FROM_DEVICE);
                else
-                       dma_unmap_page(dev, txd->dst_addr, txd->len,
-                               DMA_FROM_DEVICE);
+                       list_for_each_entry(dsg, &txd->dsg_list, node)
+                               dma_unmap_page(dev, dsg->dst_addr, dsg->len,
+                                               DMA_FROM_DEVICE);
        }
 }
 
@@ -1589,8 +1575,8 @@ static void pl08x_tasklet(unsigned long data)
                 */
                list_for_each_entry(waiting, &pl08x->memcpy.channels,
                                    chan.device_node) {
-                 if (waiting->state == PL08X_CHAN_WAITING &&
-                           waiting->waiting != NULL) {
+                       if (waiting->state == PL08X_CHAN_WAITING &&
+                               waiting->waiting != NULL) {
                                int ret;
 
                                /* This should REALLY not fail now */
@@ -1630,38 +1616,40 @@ static void pl08x_tasklet(unsigned long data)
 static irqreturn_t pl08x_irq(int irq, void *dev)
 {
        struct pl08x_driver_data *pl08x = dev;
-       u32 mask = 0;
-       u32 val;
-       int i;
-
-       val = readl(pl08x->base + PL080_ERR_STATUS);
-       if (val) {
-               /* An error interrupt (on one or more channels) */
-               dev_err(&pl08x->adev->dev,
-                       "%s error interrupt, register value 0x%08x\n",
-                               __func__, val);
-               /*
-                * Simply clear ALL PL08X error interrupts,
-                * regardless of channel and cause
-                * FIXME: should be 0x00000003 on PL081 really.
-                */
-               writel(0x000000FF, pl08x->base + PL080_ERR_CLEAR);
+       u32 mask = 0, err, tc, i;
+
+       /* check & clear - ERR & TC interrupts */
+       err = readl(pl08x->base + PL080_ERR_STATUS);
+       if (err) {
+               dev_err(&pl08x->adev->dev, "%s error interrupt, register value 0x%08x\n",
+                       __func__, err);
+               writel(err, pl08x->base + PL080_ERR_CLEAR);
        }
-       val = readl(pl08x->base + PL080_INT_STATUS);
+       tc = readl(pl08x->base + PL080_INT_STATUS);
+       if (tc)
+               writel(tc, pl08x->base + PL080_TC_CLEAR);
+
+       if (!err && !tc)
+               return IRQ_NONE;
+
        for (i = 0; i < pl08x->vd->channels; i++) {
-               if ((1 << i) & val) {
+               if (((1 << i) & err) || ((1 << i) & tc)) {
                        /* Locate physical channel */
                        struct pl08x_phy_chan *phychan = &pl08x->phy_chans[i];
                        struct pl08x_dma_chan *plchan = phychan->serving;
 
+                       if (!plchan) {
+                               dev_err(&pl08x->adev->dev,
+                                       "%s Error TC interrupt on unused channel: 0x%08x\n",
+                                       __func__, i);
+                               continue;
+                       }
+
                        /* Schedule tasklet on this channel */
                        tasklet_schedule(&plchan->tasklet);
-
                        mask |= (1 << i);
                }
        }
-       /* Clear only the terminal interrupts on channels we processed */
-       writel(mask, pl08x->base + PL080_TC_CLEAR);
 
        return mask ? IRQ_HANDLED : IRQ_NONE;
 }
@@ -1685,9 +1673,7 @@ static void pl08x_dma_slave_init(struct pl08x_dma_chan *chan)
  * Make a local wrapper to hold required data
  */
 static int pl08x_dma_init_virtual_channels(struct pl08x_driver_data *pl08x,
-                                          struct dma_device *dmadev,
-                                          unsigned int channels,
-                                          bool slave)
+               struct dma_device *dmadev, unsigned int channels, bool slave)
 {
        struct pl08x_dma_chan *chan;
        int i;
@@ -1700,7 +1686,7 @@ static int pl08x_dma_init_virtual_channels(struct pl08x_driver_data *pl08x,
         * to cope with that situation.
         */
        for (i = 0; i < channels; i++) {
-               chan = kzalloc(sizeof(struct pl08x_dma_chan), GFP_KERNEL);
+               chan = kzalloc(sizeof(*chan), GFP_KERNEL);
                if (!chan) {
                        dev_err(&pl08x->adev->dev,
                                "%s no memory for channel\n", __func__);
@@ -1728,7 +1714,7 @@ static int pl08x_dma_init_virtual_channels(struct pl08x_driver_data *pl08x,
                        kfree(chan);
                        continue;
                }
-               dev_info(&pl08x->adev->dev,
+               dev_dbg(&pl08x->adev->dev,
                         "initialize virtual channel \"%s\"\n",
                         chan->name);
 
@@ -1837,9 +1823,9 @@ static const struct file_operations pl08x_debugfs_operations = {
 static void init_pl08x_debugfs(struct pl08x_driver_data *pl08x)
 {
        /* Expose a simple debugfs interface to view all clocks */
-       (void) debugfs_create_file(dev_name(&pl08x->adev->dev), S_IFREG | S_IRUGO,
-                                  NULL, pl08x,
-                                  &pl08x_debugfs_operations);
+       (void) debugfs_create_file(dev_name(&pl08x->adev->dev),
+                       S_IFREG | S_IRUGO, NULL, pl08x,
+                       &pl08x_debugfs_operations);
 }
 
 #else
@@ -1860,12 +1846,15 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
                return ret;
 
        /* Create the driver state holder */
-       pl08x = kzalloc(sizeof(struct pl08x_driver_data), GFP_KERNEL);
+       pl08x = kzalloc(sizeof(*pl08x), GFP_KERNEL);
        if (!pl08x) {
                ret = -ENOMEM;
                goto out_no_pl08x;
        }
 
+       pm_runtime_set_active(&adev->dev);
+       pm_runtime_enable(&adev->dev);
+
        /* Initialize memcpy engine */
        dma_cap_set(DMA_MEMCPY, pl08x->memcpy.cap_mask);
        pl08x->memcpy.dev = &adev->dev;
@@ -1939,7 +1928,7 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
        }
 
        /* Initialize physical channels */
-       pl08x->phy_chans = kmalloc((vd->channels * sizeof(struct pl08x_phy_chan)),
+       pl08x->phy_chans = kmalloc((vd->channels * sizeof(*pl08x->phy_chans)),
                        GFP_KERNEL);
        if (!pl08x->phy_chans) {
                dev_err(&adev->dev, "%s failed to allocate "
@@ -1956,9 +1945,8 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
                spin_lock_init(&ch->lock);
                ch->serving = NULL;
                ch->signal = -1;
-               dev_info(&adev->dev,
-                        "physical channel %d is %s\n", i,
-                        pl08x_phy_channel_busy(ch) ? "BUSY" : "FREE");
+               dev_dbg(&adev->dev, "physical channel %d is %s\n",
+                       i, pl08x_phy_channel_busy(ch) ? "BUSY" : "FREE");
        }
 
        /* Register as many memcpy channels as there are physical channels */
@@ -1974,8 +1962,7 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
 
        /* Register slave channels */
        ret = pl08x_dma_init_virtual_channels(pl08x, &pl08x->slave,
-                                             pl08x->pd->num_slave_channels,
-                                             true);
+                       pl08x->pd->num_slave_channels, true);
        if (ret <= 0) {
                dev_warn(&pl08x->adev->dev,
                        "%s failed to enumerate slave channels - %d\n",
@@ -2005,6 +1992,8 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
        dev_info(&pl08x->adev->dev, "DMA: PL%03x rev%u at 0x%08llx irq %d\n",
                 amba_part(adev), amba_rev(adev),
                 (unsigned long long)adev->res.start, adev->irq[0]);
+
+       pm_runtime_put(&adev->dev);
        return 0;
 
 out_no_slave_reg:
@@ -2023,6 +2012,9 @@ out_no_ioremap:
        dma_pool_destroy(pl08x->pool);
 out_no_lli_pool:
 out_no_platdata:
+       pm_runtime_put(&adev->dev);
+       pm_runtime_disable(&adev->dev);
+
        kfree(pl08x);
 out_no_pl08x:
        amba_release_regions(adev);
index 6a483ea..fcfa0a8 100644 (file)
@@ -107,10 +107,11 @@ static struct at_desc *atc_desc_get(struct at_dma_chan *atchan)
 {
        struct at_desc *desc, *_desc;
        struct at_desc *ret = NULL;
+       unsigned long flags;
        unsigned int i = 0;
        LIST_HEAD(tmp_list);
 
-       spin_lock_bh(&atchan->lock);
+       spin_lock_irqsave(&atchan->lock, flags);
        list_for_each_entry_safe(desc, _desc, &atchan->free_list, desc_node) {
                i++;
                if (async_tx_test_ack(&desc->txd)) {
@@ -121,7 +122,7 @@ static struct at_desc *atc_desc_get(struct at_dma_chan *atchan)
                dev_dbg(chan2dev(&atchan->chan_common),
                                "desc %p not ACKed\n", desc);
        }
-       spin_unlock_bh(&atchan->lock);
+       spin_unlock_irqrestore(&atchan->lock, flags);
        dev_vdbg(chan2dev(&atchan->chan_common),
                "scanned %u descriptors on freelist\n", i);
 
@@ -129,9 +130,9 @@ static struct at_desc *atc_desc_get(struct at_dma_chan *atchan)
        if (!ret) {
                ret = atc_alloc_descriptor(&atchan->chan_common, GFP_ATOMIC);
                if (ret) {
-                       spin_lock_bh(&atchan->lock);
+                       spin_lock_irqsave(&atchan->lock, flags);
                        atchan->descs_allocated++;
-                       spin_unlock_bh(&atchan->lock);
+                       spin_unlock_irqrestore(&atchan->lock, flags);
                } else {
                        dev_err(chan2dev(&atchan->chan_common),
                                        "not enough descriptors available\n");
@@ -150,8 +151,9 @@ static void atc_desc_put(struct at_dma_chan *atchan, struct at_desc *desc)
 {
        if (desc) {
                struct at_desc *child;
+               unsigned long flags;
 
-               spin_lock_bh(&atchan->lock);
+               spin_lock_irqsave(&atchan->lock, flags);
                list_for_each_entry(child, &desc->tx_list, desc_node)
                        dev_vdbg(chan2dev(&atchan->chan_common),
                                        "moving child desc %p to freelist\n",
@@ -160,7 +162,7 @@ static void atc_desc_put(struct at_dma_chan *atchan, struct at_desc *desc)
                dev_vdbg(chan2dev(&atchan->chan_common),
                         "moving desc %p to freelist\n", desc);
                list_add(&desc->desc_node, &atchan->free_list);
-               spin_unlock_bh(&atchan->lock);
+               spin_unlock_irqrestore(&atchan->lock, flags);
        }
 }
 
@@ -299,7 +301,7 @@ atc_chain_complete(struct at_dma_chan *atchan, struct at_desc *desc)
 
        /* for cyclic transfers,
         * no need to replay callback function while stopping */
-       if (!test_bit(ATC_IS_CYCLIC, &atchan->status)) {
+       if (!atc_chan_is_cyclic(atchan)) {
                dma_async_tx_callback   callback = txd->callback;
                void                    *param = txd->callback_param;
 
@@ -471,16 +473,17 @@ static void atc_handle_cyclic(struct at_dma_chan *atchan)
 static void atc_tasklet(unsigned long data)
 {
        struct at_dma_chan *atchan = (struct at_dma_chan *)data;
+       unsigned long flags;
 
-       spin_lock(&atchan->lock);
+       spin_lock_irqsave(&atchan->lock, flags);
        if (test_and_clear_bit(ATC_IS_ERROR, &atchan->status))
                atc_handle_error(atchan);
-       else if (test_bit(ATC_IS_CYCLIC, &atchan->status))
+       else if (atc_chan_is_cyclic(atchan))
                atc_handle_cyclic(atchan);
        else
                atc_advance_work(atchan);
 
-       spin_unlock(&atchan->lock);
+       spin_unlock_irqrestore(&atchan->lock, flags);
 }
 
 static irqreturn_t at_dma_interrupt(int irq, void *dev_id)
@@ -539,8 +542,9 @@ static dma_cookie_t atc_tx_submit(struct dma_async_tx_descriptor *tx)
        struct at_desc          *desc = txd_to_at_desc(tx);
        struct at_dma_chan      *atchan = to_at_dma_chan(tx->chan);
        dma_cookie_t            cookie;
+       unsigned long           flags;
 
-       spin_lock_bh(&atchan->lock);
+       spin_lock_irqsave(&atchan->lock, flags);
        cookie = atc_assign_cookie(atchan, desc);
 
        if (list_empty(&atchan->active_list)) {
@@ -554,7 +558,7 @@ static dma_cookie_t atc_tx_submit(struct dma_async_tx_descriptor *tx)
                list_add_tail(&desc->desc_node, &atchan->queue);
        }
 
-       spin_unlock_bh(&atchan->lock);
+       spin_unlock_irqrestore(&atchan->lock, flags);
 
        return cookie;
 }
@@ -927,28 +931,29 @@ static int atc_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
        struct at_dma_chan      *atchan = to_at_dma_chan(chan);
        struct at_dma           *atdma = to_at_dma(chan->device);
        int                     chan_id = atchan->chan_common.chan_id;
+       unsigned long           flags;
 
        LIST_HEAD(list);
 
        dev_vdbg(chan2dev(chan), "atc_control (%d)\n", cmd);
 
        if (cmd == DMA_PAUSE) {
-               spin_lock_bh(&atchan->lock);
+               spin_lock_irqsave(&atchan->lock, flags);
 
                dma_writel(atdma, CHER, AT_DMA_SUSP(chan_id));
                set_bit(ATC_IS_PAUSED, &atchan->status);
 
-               spin_unlock_bh(&atchan->lock);
+               spin_unlock_irqrestore(&atchan->lock, flags);
        } else if (cmd == DMA_RESUME) {
-               if (!test_bit(ATC_IS_PAUSED, &atchan->status))
+               if (!atc_chan_is_paused(atchan))
                        return 0;
 
-               spin_lock_bh(&atchan->lock);
+               spin_lock_irqsave(&atchan->lock, flags);
 
                dma_writel(atdma, CHDR, AT_DMA_RES(chan_id));
                clear_bit(ATC_IS_PAUSED, &atchan->status);
 
-               spin_unlock_bh(&atchan->lock);
+               spin_unlock_irqrestore(&atchan->lock, flags);
        } else if (cmd == DMA_TERMINATE_ALL) {
                struct at_desc  *desc, *_desc;
                /*
@@ -957,7 +962,7 @@ static int atc_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
                 * channel. We still have to poll the channel enable bit due
                 * to AHB/HSB limitations.
                 */
-               spin_lock_bh(&atchan->lock);
+               spin_lock_irqsave(&atchan->lock, flags);
 
                /* disabling channel: must also remove suspend state */
                dma_writel(atdma, CHDR, AT_DMA_RES(chan_id) | atchan->mask);
@@ -978,7 +983,7 @@ static int atc_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
                /* if channel dedicated to cyclic operations, free it */
                clear_bit(ATC_IS_CYCLIC, &atchan->status);
 
-               spin_unlock_bh(&atchan->lock);
+               spin_unlock_irqrestore(&atchan->lock, flags);
        } else {
                return -ENXIO;
        }
@@ -1004,9 +1009,10 @@ atc_tx_status(struct dma_chan *chan,
        struct at_dma_chan      *atchan = to_at_dma_chan(chan);
        dma_cookie_t            last_used;
        dma_cookie_t            last_complete;
+       unsigned long           flags;
        enum dma_status         ret;
 
-       spin_lock_bh(&atchan->lock);
+       spin_lock_irqsave(&atchan->lock, flags);
 
        last_complete = atchan->completed_cookie;
        last_used = chan->cookie;
@@ -1021,7 +1027,7 @@ atc_tx_status(struct dma_chan *chan,
                ret = dma_async_is_complete(cookie, last_complete, last_used);
        }
 
-       spin_unlock_bh(&atchan->lock);
+       spin_unlock_irqrestore(&atchan->lock, flags);
 
        if (ret != DMA_SUCCESS)
                dma_set_tx_state(txstate, last_complete, last_used,
@@ -1029,7 +1035,7 @@ atc_tx_status(struct dma_chan *chan,
        else
                dma_set_tx_state(txstate, last_complete, last_used, 0);
 
-       if (test_bit(ATC_IS_PAUSED, &atchan->status))
+       if (atc_chan_is_paused(atchan))
                ret = DMA_PAUSED;
 
        dev_vdbg(chan2dev(chan), "tx_status %d: cookie = %d (d%d, u%d)\n",
@@ -1046,18 +1052,19 @@ atc_tx_status(struct dma_chan *chan,
 static void atc_issue_pending(struct dma_chan *chan)
 {
        struct at_dma_chan      *atchan = to_at_dma_chan(chan);
+       unsigned long           flags;
 
        dev_vdbg(chan2dev(chan), "issue_pending\n");
 
        /* Not needed for cyclic transfers */
-       if (test_bit(ATC_IS_CYCLIC, &atchan->status))
+       if (atc_chan_is_cyclic(atchan))
                return;
 
-       spin_lock_bh(&atchan->lock);
+       spin_lock_irqsave(&atchan->lock, flags);
        if (!atc_chan_is_enabled(atchan)) {
                atc_advance_work(atchan);
        }
-       spin_unlock_bh(&atchan->lock);
+       spin_unlock_irqrestore(&atchan->lock, flags);
 }
 
 /**
@@ -1073,6 +1080,7 @@ static int atc_alloc_chan_resources(struct dma_chan *chan)
        struct at_dma           *atdma = to_at_dma(chan->device);
        struct at_desc          *desc;
        struct at_dma_slave     *atslave;
+       unsigned long           flags;
        int                     i;
        u32                     cfg;
        LIST_HEAD(tmp_list);
@@ -1116,11 +1124,11 @@ static int atc_alloc_chan_resources(struct dma_chan *chan)
                list_add_tail(&desc->desc_node, &tmp_list);
        }
 
-       spin_lock_bh(&atchan->lock);
+       spin_lock_irqsave(&atchan->lock, flags);
        atchan->descs_allocated = i;
        list_splice(&tmp_list, &atchan->free_list);
        atchan->completed_cookie = chan->cookie = 1;
-       spin_unlock_bh(&atchan->lock);
+       spin_unlock_irqrestore(&atchan->lock, flags);
 
        /* channel parameters */
        channel_writel(atchan, CFG, cfg);
@@ -1260,12 +1268,11 @@ static int __init at_dma_probe(struct platform_device *pdev)
 
        /* initialize channels related values */
        INIT_LIST_HEAD(&atdma->dma_common.channels);
-       for (i = 0; i < pdata->nr_channels; i++, atdma->dma_common.chancnt++) {
+       for (i = 0; i < pdata->nr_channels; i++) {
                struct at_dma_chan      *atchan = &atdma->chan[i];
 
                atchan->chan_common.device = &atdma->dma_common;
                atchan->chan_common.cookie = atchan->completed_cookie = 1;
-               atchan->chan_common.chan_id = i;
                list_add_tail(&atchan->chan_common.device_node,
                                &atdma->dma_common.channels);
 
@@ -1293,22 +1300,20 @@ static int __init at_dma_probe(struct platform_device *pdev)
        if (dma_has_cap(DMA_MEMCPY, atdma->dma_common.cap_mask))
                atdma->dma_common.device_prep_dma_memcpy = atc_prep_dma_memcpy;
 
-       if (dma_has_cap(DMA_SLAVE, atdma->dma_common.cap_mask))
+       if (dma_has_cap(DMA_SLAVE, atdma->dma_common.cap_mask)) {
                atdma->dma_common.device_prep_slave_sg = atc_prep_slave_sg;
-
-       if (dma_has_cap(DMA_CYCLIC, atdma->dma_common.cap_mask))
+               /* controller can do slave DMA: can trigger cyclic transfers */
+               dma_cap_set(DMA_CYCLIC, atdma->dma_common.cap_mask);
                atdma->dma_common.device_prep_dma_cyclic = atc_prep_dma_cyclic;
-
-       if (dma_has_cap(DMA_SLAVE, atdma->dma_common.cap_mask) ||
-           dma_has_cap(DMA_CYCLIC, atdma->dma_common.cap_mask))
                atdma->dma_common.device_control = atc_control;
+       }
 
        dma_writel(atdma, EN, AT_DMA_ENABLE);
 
        dev_info(&pdev->dev, "Atmel AHB DMA Controller ( %s%s), %d channels\n",
          dma_has_cap(DMA_MEMCPY, atdma->dma_common.cap_mask) ? "cpy " : "",
          dma_has_cap(DMA_SLAVE, atdma->dma_common.cap_mask)  ? "slave " : "",
-         atdma->dma_common.chancnt);
+         pdata->nr_channels);
 
        dma_async_device_register(&atdma->dma_common);
 
@@ -1377,27 +1382,112 @@ static void at_dma_shutdown(struct platform_device *pdev)
        clk_disable(atdma->clk);
 }
 
+static int at_dma_prepare(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct at_dma *atdma = platform_get_drvdata(pdev);
+       struct dma_chan *chan, *_chan;
+
+       list_for_each_entry_safe(chan, _chan, &atdma->dma_common.channels,
+                       device_node) {
+               struct at_dma_chan *atchan = to_at_dma_chan(chan);
+               /* wait for transaction completion (except in cyclic case) */
+               if (atc_chan_is_enabled(atchan) && !atc_chan_is_cyclic(atchan))
+                       return -EAGAIN;
+       }
+       return 0;
+}
+
+static void atc_suspend_cyclic(struct at_dma_chan *atchan)
+{
+       struct dma_chan *chan = &atchan->chan_common;
+
+       /* Channel should be paused by user
+        * do it anyway even if it is not done already */
+       if (!atc_chan_is_paused(atchan)) {
+               dev_warn(chan2dev(chan),
+               "cyclic channel not paused, should be done by channel user\n");
+               atc_control(chan, DMA_PAUSE, 0);
+       }
+
+       /* now preserve additional data for cyclic operations */
+       /* next descriptor address in the cyclic list */
+       atchan->save_dscr = channel_readl(atchan, DSCR);
+
+       vdbg_dump_regs(atchan);
+}
+
 static int at_dma_suspend_noirq(struct device *dev)
 {
        struct platform_device *pdev = to_platform_device(dev);
        struct at_dma *atdma = platform_get_drvdata(pdev);
+       struct dma_chan *chan, *_chan;
 
-       at_dma_off(platform_get_drvdata(pdev));
+       /* preserve data */
+       list_for_each_entry_safe(chan, _chan, &atdma->dma_common.channels,
+                       device_node) {
+               struct at_dma_chan *atchan = to_at_dma_chan(chan);
+
+               if (atc_chan_is_cyclic(atchan))
+                       atc_suspend_cyclic(atchan);
+               atchan->save_cfg = channel_readl(atchan, CFG);
+       }
+       atdma->save_imr = dma_readl(atdma, EBCIMR);
+
+       /* disable DMA controller */
+       at_dma_off(atdma);
        clk_disable(atdma->clk);
        return 0;
 }
 
+static void atc_resume_cyclic(struct at_dma_chan *atchan)
+{
+       struct at_dma   *atdma = to_at_dma(atchan->chan_common.device);
+
+       /* restore channel status for cyclic descriptors list:
+        * next descriptor in the cyclic list at the time of suspend */
+       channel_writel(atchan, SADDR, 0);
+       channel_writel(atchan, DADDR, 0);
+       channel_writel(atchan, CTRLA, 0);
+       channel_writel(atchan, CTRLB, 0);
+       channel_writel(atchan, DSCR, atchan->save_dscr);
+       dma_writel(atdma, CHER, atchan->mask);
+
+       /* channel pause status should be removed by channel user
+        * We cannot take the initiative to do it here */
+
+       vdbg_dump_regs(atchan);
+}
+
 static int at_dma_resume_noirq(struct device *dev)
 {
        struct platform_device *pdev = to_platform_device(dev);
        struct at_dma *atdma = platform_get_drvdata(pdev);
+       struct dma_chan *chan, *_chan;
 
+       /* bring back DMA controller */
        clk_enable(atdma->clk);
        dma_writel(atdma, EN, AT_DMA_ENABLE);
+
+       /* clear any pending interrupt */
+       while (dma_readl(atdma, EBCISR))
+               cpu_relax();
+
+       /* restore saved data */
+       dma_writel(atdma, EBCIER, atdma->save_imr);
+       list_for_each_entry_safe(chan, _chan, &atdma->dma_common.channels,
+                       device_node) {
+               struct at_dma_chan *atchan = to_at_dma_chan(chan);
+
+               channel_writel(atchan, CFG, atchan->save_cfg);
+               if (atc_chan_is_cyclic(atchan))
+                       atc_resume_cyclic(atchan);
+       }
        return 0;
 }
 
 static const struct dev_pm_ops at_dma_dev_pm_ops = {
+       .prepare = at_dma_prepare,
        .suspend_noirq = at_dma_suspend_noirq,
        .resume_noirq = at_dma_resume_noirq,
 };
index 087dbf1..aa4c9ae 100644 (file)
@@ -204,6 +204,9 @@ enum atc_status {
  * @status: transmit status information from irq/prep* functions
  *                to tasklet (use atomic operations)
  * @tasklet: bottom half to finish transaction work
+ * @save_cfg: configuration register that is saved on suspend/resume cycle
+ * @save_dscr: for cyclic operations, preserve next descriptor address in
+ *             the cyclic list on suspend/resume cycle
  * @lock: serializes enqueue/dequeue operations to descriptors lists
  * @completed_cookie: identifier for the most recently completed operation
  * @active_list: list of descriptors dmaengine is being running on
@@ -218,6 +221,8 @@ struct at_dma_chan {
        u8                      mask;
        unsigned long           status;
        struct tasklet_struct   tasklet;
+       u32                     save_cfg;
+       u32                     save_dscr;
 
        spinlock_t              lock;
 
@@ -248,6 +253,7 @@ static inline struct at_dma_chan *to_at_dma_chan(struct dma_chan *dchan)
  * @chan_common: common dmaengine dma_device object members
  * @ch_regs: memory mapped register base
  * @clk: dma controller clock
+ * @save_imr: interrupt mask register that is saved on suspend/resume cycle
  * @all_chan_mask: all channels availlable in a mask
  * @dma_desc_pool: base of DMA descriptor region (DMA address)
  * @chan: channels table to store at_dma_chan structures
@@ -256,6 +262,7 @@ struct at_dma {
        struct dma_device       dma_common;
        void __iomem            *regs;
        struct clk              *clk;
+       u32                     save_imr;
 
        u8                      all_chan_mask;
 
@@ -355,6 +362,23 @@ static inline int atc_chan_is_enabled(struct at_dma_chan *atchan)
        return !!(dma_readl(atdma, CHSR) & atchan->mask);
 }
 
+/**
+ * atc_chan_is_paused - test channel pause/resume status
+ * @atchan: channel we want to test status
+ */
+static inline int atc_chan_is_paused(struct at_dma_chan *atchan)
+{
+       return test_bit(ATC_IS_PAUSED, &atchan->status);
+}
+
+/**
+ * atc_chan_is_cyclic - test if given channel has cyclic property set
+ * @atchan: channel we want to test status
+ */
+static inline int atc_chan_is_cyclic(struct at_dma_chan *atchan)
+{
+       return test_bit(ATC_IS_CYCLIC, &atchan->status);
+}
 
 /**
  * set_desc_eol - set end-of-link to descriptor so it will end transfer
index 765f5ff..eb1d864 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
 #include <linux/dmaengine.h>
+#include <linux/freezer.h>
 #include <linux/init.h>
 #include <linux/kthread.h>
 #include <linux/module.h>
@@ -251,6 +252,7 @@ static int dmatest_func(void *data)
        int                     i;
 
        thread_name = current->comm;
+       set_freezable_with_signal();
 
        ret = -ENOMEM;
 
@@ -305,7 +307,8 @@ static int dmatest_func(void *data)
                dma_addr_t dma_srcs[src_cnt];
                dma_addr_t dma_dsts[dst_cnt];
                struct completion cmp;
-               unsigned long tmo = msecs_to_jiffies(timeout);
+               unsigned long start, tmo, end = 0 /* compiler... */;
+               bool reload = true;
                u8 align = 0;
 
                total_tests++;
@@ -404,7 +407,17 @@ static int dmatest_func(void *data)
                }
                dma_async_issue_pending(chan);
 
-               tmo = wait_for_completion_timeout(&cmp, tmo);
+               do {
+                       start = jiffies;
+                       if (reload)
+                               end = start + msecs_to_jiffies(timeout);
+                       else if (end <= start)
+                               end = start + 1;
+                       tmo = wait_for_completion_interruptible_timeout(&cmp,
+                                                               end - start);
+                       reload = try_to_freeze();
+               } while (tmo == -ERESTARTSYS);
+
                status = dma_async_is_tx_complete(chan, cookie, NULL, NULL);
 
                if (tmo == 0) {
@@ -477,6 +490,8 @@ err_srcs:
        pr_notice("%s: terminating after %u tests, %u failures (status %d)\n",
                        thread_name, total_tests, failed_tests, ret);
 
+       /* terminate all transfers on specified channels */
+       chan->device->device_control(chan, DMA_TERMINATE_ALL, 0);
        if (iterations > 0)
                while (!kthread_should_stop()) {
                        DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wait_dmatest_exit);
@@ -499,6 +514,10 @@ static void dmatest_cleanup_channel(struct dmatest_chan *dtc)
                list_del(&thread->node);
                kfree(thread);
        }
+
+       /* terminate all transfers on specified channels */
+       dtc->chan->device->device_control(dtc->chan, DMA_TERMINATE_ALL, 0);
+
        kfree(dtc);
 }
 
index 4d180ca..9bfd6d3 100644 (file)
@@ -1407,12 +1407,11 @@ static int __init dw_probe(struct platform_device *pdev)
        dw->all_chan_mask = (1 << pdata->nr_channels) - 1;
 
        INIT_LIST_HEAD(&dw->dma.channels);
-       for (i = 0; i < pdata->nr_channels; i++, dw->dma.chancnt++) {
+       for (i = 0; i < pdata->nr_channels; i++) {
                struct dw_dma_chan      *dwc = &dw->chan[i];
 
                dwc->chan.device = &dw->dma;
                dwc->chan.cookie = dwc->completed = 1;
-               dwc->chan.chan_id = i;
                if (pdata->chan_allocation_order == CHAN_ALLOCATION_ASCENDING)
                        list_add_tail(&dwc->chan.device_node,
                                        &dw->dma.channels);
@@ -1468,7 +1467,7 @@ static int __init dw_probe(struct platform_device *pdev)
        dma_writel(dw, CFG, DW_CFG_DMA_EN);
 
        printk(KERN_INFO "%s: DesignWare DMA Controller, %d channels\n",
-                       dev_name(&pdev->dev), dw->dma.chancnt);
+                       dev_name(&pdev->dev), pdata->nr_channels);
 
        dma_async_device_register(&dw->dma);
 
index 5d7a49b..b47e2b8 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/dmaengine.h>
+#include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 
index d99f71c..d746899 100644 (file)
@@ -14,6 +14,7 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
 #include <linux/init.h>
+#include <linux/module.h>
 #include <linux/types.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index 7bd7e98..eab1fe7 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/module.h>
 #include <linux/types.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
@@ -318,6 +319,7 @@ struct sdma_engine {
        dma_addr_t                      context_phys;
        struct dma_device               dma_device;
        struct clk                      *clk;
+       struct mutex                    channel_0_lock;
        struct sdma_script_start_addrs  *script_addrs;
 };
 
@@ -415,11 +417,15 @@ static int sdma_load_script(struct sdma_engine *sdma, void *buf, int size,
        dma_addr_t buf_phys;
        int ret;
 
+       mutex_lock(&sdma->channel_0_lock);
+
        buf_virt = dma_alloc_coherent(NULL,
                        size,
                        &buf_phys, GFP_KERNEL);
-       if (!buf_virt)
-               return -ENOMEM;
+       if (!buf_virt) {
+               ret = -ENOMEM;
+               goto err_out;
+       }
 
        bd0->mode.command = C0_SETPM;
        bd0->mode.status = BD_DONE | BD_INTR | BD_WRAP | BD_EXTD;
@@ -433,6 +439,9 @@ static int sdma_load_script(struct sdma_engine *sdma, void *buf, int size,
 
        dma_free_coherent(NULL, size, buf_virt, buf_phys);
 
+err_out:
+       mutex_unlock(&sdma->channel_0_lock);
+
        return ret;
 }
 
@@ -656,6 +665,8 @@ static int sdma_load_context(struct sdma_channel *sdmac)
        dev_dbg(sdma->dev, "event_mask0 = 0x%08x\n", sdmac->event_mask0);
        dev_dbg(sdma->dev, "event_mask1 = 0x%08x\n", sdmac->event_mask1);
 
+       mutex_lock(&sdma->channel_0_lock);
+
        memset(context, 0, sizeof(*context));
        context->channel_state.pc = load_address;
 
@@ -676,6 +687,8 @@ static int sdma_load_context(struct sdma_channel *sdmac)
 
        ret = sdma_run_channel(&sdma->channel[0]);
 
+       mutex_unlock(&sdma->channel_0_lock);
+
        return ret;
 }
 
@@ -1131,18 +1144,17 @@ static void sdma_add_scripts(struct sdma_engine *sdma,
                        saddr_arr[i] = addr_arr[i];
 }
 
-static int __init sdma_get_firmware(struct sdma_engine *sdma,
-               const char *fw_name)
+static void sdma_load_firmware(const struct firmware *fw, void *context)
 {
-       const struct firmware *fw;
+       struct sdma_engine *sdma = context;
        const struct sdma_firmware_header *header;
-       int ret;
        const struct sdma_script_start_addrs *addr;
        unsigned short *ram_code;
 
-       ret = request_firmware(&fw, fw_name, sdma->dev);
-       if (ret)
-               return ret;
+       if (!fw) {
+               dev_err(sdma->dev, "firmware not found\n");
+               return;
+       }
 
        if (fw->size < sizeof(*header))
                goto err_firmware;
@@ -1172,6 +1184,16 @@ static int __init sdma_get_firmware(struct sdma_engine *sdma,
 
 err_firmware:
        release_firmware(fw);
+}
+
+static int __init sdma_get_firmware(struct sdma_engine *sdma,
+               const char *fw_name)
+{
+       int ret;
+
+       ret = request_firmware_nowait(THIS_MODULE,
+                       FW_ACTION_HOTPLUG, fw_name, sdma->dev,
+                       GFP_KERNEL, sdma, sdma_load_firmware);
 
        return ret;
 }
@@ -1269,11 +1291,14 @@ static int __init sdma_probe(struct platform_device *pdev)
        struct sdma_platform_data *pdata = pdev->dev.platform_data;
        int i;
        struct sdma_engine *sdma;
+       s32 *saddr_arr;
 
        sdma = kzalloc(sizeof(*sdma), GFP_KERNEL);
        if (!sdma)
                return -ENOMEM;
 
+       mutex_init(&sdma->channel_0_lock);
+
        sdma->dev = &pdev->dev;
 
        iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1310,6 +1335,11 @@ static int __init sdma_probe(struct platform_device *pdev)
                goto err_alloc;
        }
 
+       /* initially no scripts available */
+       saddr_arr = (s32 *)sdma->script_addrs;
+       for (i = 0; i < SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1; i++)
+               saddr_arr[i] = -EINVAL;
+
        if (of_id)
                pdev->id_entry = of_id->data;
        sdma->devtype = pdev->id_entry->driver_data;
index 8a3fdd8..9e96c43 100644 (file)
@@ -115,16 +115,15 @@ DMAC1 interrupt Functions*/
 
 /**
  * dmac1_mask_periphral_intr - mask the periphral interrupt
- * @midc: dma channel for which masking is required
+ * @mid: dma device for which masking is required
  *
  * Masks the DMA periphral interrupt
  * this is valid for DMAC1 family controllers only
  * This controller should have periphral mask registers already mapped
  */
-static void dmac1_mask_periphral_intr(struct intel_mid_dma_chan *midc)
+static void dmac1_mask_periphral_intr(struct middma_device *mid)
 {
        u32 pimr;
-       struct middma_device *mid = to_middma_device(midc->chan.device);
 
        if (mid->pimr_mask) {
                pimr = readl(mid->mask_reg + LNW_PERIPHRAL_MASK);
@@ -184,7 +183,6 @@ static void enable_dma_interrupt(struct intel_mid_dma_chan *midc)
 static void disable_dma_interrupt(struct intel_mid_dma_chan *midc)
 {
        /*Check LPE PISR, make sure fwd is disabled*/
-       dmac1_mask_periphral_intr(midc);
        iowrite32(MASK_INTR_REG(midc->ch_id), midc->dma_base + MASK_BLOCK);
        iowrite32(MASK_INTR_REG(midc->ch_id), midc->dma_base + MASK_TFR);
        iowrite32(MASK_INTR_REG(midc->ch_id), midc->dma_base + MASK_ERR);
@@ -1114,7 +1112,6 @@ static int mid_setup_dma(struct pci_dev *pdev)
 
                midch->chan.device = &dma->common;
                midch->chan.cookie =  1;
-               midch->chan.chan_id = i;
                midch->ch_id = dma->chan_base + i;
                pr_debug("MDMA:Init CH %d, ID %d\n", i, midch->ch_id);
 
@@ -1150,7 +1147,6 @@ static int mid_setup_dma(struct pci_dev *pdev)
        dma_cap_set(DMA_SLAVE, dma->common.cap_mask);
        dma_cap_set(DMA_PRIVATE, dma->common.cap_mask);
        dma->common.dev = &pdev->dev;
-       dma->common.chancnt = dma->max_chan;
 
        dma->common.device_alloc_chan_resources =
                                        intel_mid_dma_alloc_chan_resources;
@@ -1350,6 +1346,7 @@ int dma_suspend(struct pci_dev *pci, pm_message_t state)
                if (device->ch[i].in_use)
                        return -EAGAIN;
        }
+       dmac1_mask_periphral_intr(device);
        device->state = SUSPENDED;
        pci_save_state(pci);
        pci_disable_device(pci);
index 6815905..ddc2a13 100644 (file)
@@ -1307,6 +1307,7 @@ static irqreturn_t idmac_interrupt(int irq, void *dev_id)
            ipu_submit_buffer(ichan, descnew, sgnew, ichan->active_buffer) < 0) {
                callback = descnew->txd.callback;
                callback_param = descnew->txd.callback_param;
+               list_del_init(&descnew->list);
                spin_unlock(&ichan->lock);
                if (callback)
                        callback(callback_param);
@@ -1428,39 +1429,58 @@ static int __idmac_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
 {
        struct idmac_channel *ichan = to_idmac_chan(chan);
        struct idmac *idmac = to_idmac(chan->device);
+       struct ipu *ipu = to_ipu(idmac);
+       struct list_head *list, *tmp;
        unsigned long flags;
        int i;
 
-       /* Only supports DMA_TERMINATE_ALL */
-       if (cmd != DMA_TERMINATE_ALL)
-               return -ENXIO;
+       switch (cmd) {
+       case DMA_PAUSE:
+               spin_lock_irqsave(&ipu->lock, flags);
+               ipu_ic_disable_task(ipu, chan->chan_id);
 
-       ipu_disable_channel(idmac, ichan,
-                           ichan->status >= IPU_CHANNEL_ENABLED);
+               /* Return all descriptors into "prepared" state */
+               list_for_each_safe(list, tmp, &ichan->queue)
+                       list_del_init(list);
 
-       tasklet_disable(&to_ipu(idmac)->tasklet);
+               ichan->sg[0] = NULL;
+               ichan->sg[1] = NULL;
 
-       /* ichan->queue is modified in ISR, have to spinlock */
-       spin_lock_irqsave(&ichan->lock, flags);
-       list_splice_init(&ichan->queue, &ichan->free_list);
+               spin_unlock_irqrestore(&ipu->lock, flags);
 
-       if (ichan->desc)
-               for (i = 0; i < ichan->n_tx_desc; i++) {
-                       struct idmac_tx_desc *desc = ichan->desc + i;
-                       if (list_empty(&desc->list))
-                               /* Descriptor was prepared, but not submitted */
-                               list_add(&desc->list, &ichan->free_list);
+               ichan->status = IPU_CHANNEL_INITIALIZED;
+               break;
+       case DMA_TERMINATE_ALL:
+               ipu_disable_channel(idmac, ichan,
+                                   ichan->status >= IPU_CHANNEL_ENABLED);
 
-                       async_tx_clear_ack(&desc->txd);
-               }
+               tasklet_disable(&ipu->tasklet);
 
-       ichan->sg[0] = NULL;
-       ichan->sg[1] = NULL;
-       spin_unlock_irqrestore(&ichan->lock, flags);
+               /* ichan->queue is modified in ISR, have to spinlock */
+               spin_lock_irqsave(&ichan->lock, flags);
+               list_splice_init(&ichan->queue, &ichan->free_list);
 
-       tasklet_enable(&to_ipu(idmac)->tasklet);
+               if (ichan->desc)
+                       for (i = 0; i < ichan->n_tx_desc; i++) {
+                               struct idmac_tx_desc *desc = ichan->desc + i;
+                               if (list_empty(&desc->list))
+                                       /* Descriptor was prepared, but not submitted */
+                                       list_add(&desc->list, &ichan->free_list);
 
-       ichan->status = IPU_CHANNEL_INITIALIZED;
+                               async_tx_clear_ack(&desc->txd);
+                       }
+
+               ichan->sg[0] = NULL;
+               ichan->sg[1] = NULL;
+               spin_unlock_irqrestore(&ichan->lock, flags);
+
+               tasklet_enable(&ipu->tasklet);
+
+               ichan->status = IPU_CHANNEL_INITIALIZED;
+               break;
+       default:
+               return -ENOSYS;
+       }
 
        return 0;
 }
@@ -1663,7 +1683,6 @@ static void __exit ipu_idmac_exit(struct ipu *ipu)
                struct idmac_channel *ichan = ipu->channel + i;
 
                idmac_control(&ichan->dma_chan, DMA_TERMINATE_ALL, 0);
-               idmac_prep_slave_sg(&ichan->dma_chan, NULL, 0, DMA_NONE, 0);
        }
 
        dma_async_device_unregister(&idmac->dma);
index b9bae94..8ba4edc 100644 (file)
@@ -741,7 +741,6 @@ static int __devinit mpc_dma_probe(struct platform_device *op)
                mchan = &mdma->channels[i];
 
                mchan->chan.device = dma;
-               mchan->chan.chan_id = i;
                mchan->chan.cookie = 1;
                mchan->completed_cookie = mchan->chan.cookie;
 
index be641cb..b4588bd 100644 (file)
@@ -130,6 +130,23 @@ struct mxs_dma_engine {
        struct mxs_dma_chan             mxs_chans[MXS_DMA_CHANNELS];
 };
 
+static inline void mxs_dma_clkgate(struct mxs_dma_chan *mxs_chan, int enable)
+{
+       struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
+       int chan_id = mxs_chan->chan.chan_id;
+       int set_clr = enable ? MXS_CLR_ADDR : MXS_SET_ADDR;
+
+       /* enable apbh channel clock */
+       if (dma_is_apbh()) {
+               if (apbh_is_old())
+                       writel(1 << (chan_id + BP_APBH_CTRL0_CLKGATE_CHANNEL),
+                               mxs_dma->base + HW_APBHX_CTRL0 + set_clr);
+               else
+                       writel(1 << chan_id,
+                               mxs_dma->base + HW_APBHX_CTRL0 + set_clr);
+       }
+}
+
 static void mxs_dma_reset_chan(struct mxs_dma_chan *mxs_chan)
 {
        struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
@@ -148,38 +165,21 @@ static void mxs_dma_enable_chan(struct mxs_dma_chan *mxs_chan)
        struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
        int chan_id = mxs_chan->chan.chan_id;
 
+       /* clkgate needs to be enabled before writing other registers */
+       mxs_dma_clkgate(mxs_chan, 1);
+
        /* set cmd_addr up */
        writel(mxs_chan->ccw_phys,
                mxs_dma->base + HW_APBHX_CHn_NXTCMDAR(chan_id));
 
-       /* enable apbh channel clock */
-       if (dma_is_apbh()) {
-               if (apbh_is_old())
-                       writel(1 << (chan_id + BP_APBH_CTRL0_CLKGATE_CHANNEL),
-                               mxs_dma->base + HW_APBHX_CTRL0 + MXS_CLR_ADDR);
-               else
-                       writel(1 << chan_id,
-                               mxs_dma->base + HW_APBHX_CTRL0 + MXS_CLR_ADDR);
-       }
-
        /* write 1 to SEMA to kick off the channel */
        writel(1, mxs_dma->base + HW_APBHX_CHn_SEMA(chan_id));
 }
 
 static void mxs_dma_disable_chan(struct mxs_dma_chan *mxs_chan)
 {
-       struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
-       int chan_id = mxs_chan->chan.chan_id;
-
        /* disable apbh channel clock */
-       if (dma_is_apbh()) {
-               if (apbh_is_old())
-                       writel(1 << (chan_id + BP_APBH_CTRL0_CLKGATE_CHANNEL),
-                               mxs_dma->base + HW_APBHX_CTRL0 + MXS_SET_ADDR);
-               else
-                       writel(1 << chan_id,
-                               mxs_dma->base + HW_APBHX_CTRL0 + MXS_SET_ADDR);
-       }
+       mxs_dma_clkgate(mxs_chan, 0);
 
        mxs_chan->status = DMA_SUCCESS;
 }
@@ -338,7 +338,10 @@ static int mxs_dma_alloc_chan_resources(struct dma_chan *chan)
        if (ret)
                goto err_clk;
 
+       /* clkgate needs to be enabled for reset to finish */
+       mxs_dma_clkgate(mxs_chan, 1);
        mxs_dma_reset_chan(mxs_chan);
+       mxs_dma_clkgate(mxs_chan, 0);
 
        dma_async_tx_descriptor_init(&mxs_chan->desc, chan);
        mxs_chan->desc.tx_submit = mxs_dma_tx_submit;
index 1ac8d4b..a6d0e3d 100644 (file)
@@ -60,7 +60,7 @@
 #define DMA_DESC_FOLLOW_WITHOUT_IRQ    0x2
 #define DMA_DESC_FOLLOW_WITH_IRQ       0x3
 
-#define MAX_CHAN_NR                    8
+#define MAX_CHAN_NR                    12
 
 #define DMA_MASK_CTL0_MODE     0x33333333
 #define DMA_MASK_CTL2_MODE     0x00003333
@@ -872,8 +872,7 @@ static int __devinit pch_dma_probe(struct pci_dev *pdev,
        int i;
 
        nr_channels = id->driver_data;
-       pd = kzalloc(sizeof(struct pch_dma)+
-               sizeof(struct pch_dma_chan) * nr_channels, GFP_KERNEL);
+       pd = kzalloc(sizeof(*pd), GFP_KERNEL);
        if (!pd)
                return -ENOMEM;
 
@@ -926,7 +925,6 @@ static int __devinit pch_dma_probe(struct pci_dev *pdev,
        }
 
        pd->dma.dev = &pdev->dev;
-       pd->dma.chancnt = nr_channels;
 
        INIT_LIST_HEAD(&pd->dma.channels);
 
@@ -935,7 +933,6 @@ static int __devinit pch_dma_probe(struct pci_dev *pdev,
 
                pd_chan->chan.device = &pd->dma;
                pd_chan->chan.cookie = 1;
-               pd_chan->chan.chan_id = i;
 
                pd_chan->membase = &regs->desc[i];
 
index 00eee59..5710414 100644 (file)
@@ -17,6 +17,8 @@
 #include <linux/interrupt.h>
 #include <linux/amba/bus.h>
 #include <linux/amba/pl330.h>
+#include <linux/pm_runtime.h>
+#include <linux/scatterlist.h>
 
 #define NR_DEFAULT_DESC        16
 
@@ -68,6 +70,14 @@ struct dma_pl330_chan {
         * NULL if the channel is available to be acquired.
         */
        void *pl330_chid;
+
+       /* For D-to-M and M-to-D channels */
+       int burst_sz; /* the peripheral fifo width */
+       int burst_len; /* the number of burst */
+       dma_addr_t fifo_addr;
+
+       /* for cyclic capability */
+       bool cyclic;
 };
 
 struct dma_pl330_dmac {
@@ -83,6 +93,8 @@ struct dma_pl330_dmac {
 
        /* Peripheral channels connected to this DMAC */
        struct dma_pl330_chan *peripherals; /* keep at end */
+
+       struct clk *clk;
 };
 
 struct dma_pl330_desc {
@@ -152,6 +164,31 @@ static inline void free_desc_list(struct list_head *list)
        spin_unlock_irqrestore(&pdmac->pool_lock, flags);
 }
 
+static inline void handle_cyclic_desc_list(struct list_head *list)
+{
+       struct dma_pl330_desc *desc;
+       struct dma_pl330_chan *pch;
+       unsigned long flags;
+
+       if (list_empty(list))
+               return;
+
+       list_for_each_entry(desc, list, node) {
+               dma_async_tx_callback callback;
+
+               /* Change status to reload it */
+               desc->status = PREP;
+               pch = desc->pchan;
+               callback = desc->txd.callback;
+               if (callback)
+                       callback(desc->txd.callback_param);
+       }
+
+       spin_lock_irqsave(&pch->lock, flags);
+       list_splice_tail_init(list, &pch->work_list);
+       spin_unlock_irqrestore(&pch->lock, flags);
+}
+
 static inline void fill_queue(struct dma_pl330_chan *pch)
 {
        struct dma_pl330_desc *desc;
@@ -205,7 +242,10 @@ static void pl330_tasklet(unsigned long data)
 
        spin_unlock_irqrestore(&pch->lock, flags);
 
-       free_desc_list(&list);
+       if (pch->cyclic)
+               handle_cyclic_desc_list(&list);
+       else
+               free_desc_list(&list);
 }
 
 static void dma_pl330_rqcb(void *token, enum pl330_op_err err)
@@ -236,6 +276,7 @@ static int pl330_alloc_chan_resources(struct dma_chan *chan)
        spin_lock_irqsave(&pch->lock, flags);
 
        pch->completed = chan->cookie = 1;
+       pch->cyclic = false;
 
        pch->pl330_chid = pl330_request_channel(&pdmac->pif);
        if (!pch->pl330_chid) {
@@ -253,25 +294,52 @@ static int pl330_alloc_chan_resources(struct dma_chan *chan)
 static int pl330_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned long arg)
 {
        struct dma_pl330_chan *pch = to_pchan(chan);
-       struct dma_pl330_desc *desc;
+       struct dma_pl330_desc *desc, *_dt;
        unsigned long flags;
+       struct dma_pl330_dmac *pdmac = pch->dmac;
+       struct dma_slave_config *slave_config;
+       LIST_HEAD(list);
 
-       /* Only supports DMA_TERMINATE_ALL */
-       if (cmd != DMA_TERMINATE_ALL)
-               return -ENXIO;
-
-       spin_lock_irqsave(&pch->lock, flags);
-
-       /* FLUSH the PL330 Channel thread */
-       pl330_chan_ctrl(pch->pl330_chid, PL330_OP_FLUSH);
+       switch (cmd) {
+       case DMA_TERMINATE_ALL:
+               spin_lock_irqsave(&pch->lock, flags);
 
-       /* Mark all desc done */
-       list_for_each_entry(desc, &pch->work_list, node)
-               desc->status = DONE;
+               /* FLUSH the PL330 Channel thread */
+               pl330_chan_ctrl(pch->pl330_chid, PL330_OP_FLUSH);
 
-       spin_unlock_irqrestore(&pch->lock, flags);
+               /* Mark all desc done */
+               list_for_each_entry_safe(desc, _dt, &pch->work_list , node) {
+                       desc->status = DONE;
+                       pch->completed = desc->txd.cookie;
+                       list_move_tail(&desc->node, &list);
+               }
 
-       pl330_tasklet((unsigned long) pch);
+               list_splice_tail_init(&list, &pdmac->desc_pool);
+               spin_unlock_irqrestore(&pch->lock, flags);
+               break;
+       case DMA_SLAVE_CONFIG:
+               slave_config = (struct dma_slave_config *)arg;
+
+               if (slave_config->direction == DMA_TO_DEVICE) {
+                       if (slave_config->dst_addr)
+                               pch->fifo_addr = slave_config->dst_addr;
+                       if (slave_config->dst_addr_width)
+                               pch->burst_sz = __ffs(slave_config->dst_addr_width);
+                       if (slave_config->dst_maxburst)
+                               pch->burst_len = slave_config->dst_maxburst;
+               } else if (slave_config->direction == DMA_FROM_DEVICE) {
+                       if (slave_config->src_addr)
+                               pch->fifo_addr = slave_config->src_addr;
+                       if (slave_config->src_addr_width)
+                               pch->burst_sz = __ffs(slave_config->src_addr_width);
+                       if (slave_config->src_maxburst)
+                               pch->burst_len = slave_config->src_maxburst;
+               }
+               break;
+       default:
+               dev_err(pch->dmac->pif.dev, "Not supported command.\n");
+               return -ENXIO;
+       }
 
        return 0;
 }
@@ -288,6 +356,9 @@ static void pl330_free_chan_resources(struct dma_chan *chan)
        pl330_release_channel(pch->pl330_chid);
        pch->pl330_chid = NULL;
 
+       if (pch->cyclic)
+               list_splice_tail_init(&pch->work_list, &pch->dmac->desc_pool);
+
        spin_unlock_irqrestore(&pch->lock, flags);
 }
 
@@ -453,7 +524,7 @@ static struct dma_pl330_desc *pl330_get_desc(struct dma_pl330_chan *pch)
 
        if (peri) {
                desc->req.rqtype = peri->rqtype;
-               desc->req.peri = peri->peri_id;
+               desc->req.peri = pch->chan.chan_id;
        } else {
                desc->req.rqtype = MEMTOMEM;
                desc->req.peri = 0;
@@ -524,6 +595,51 @@ static inline int get_burst_len(struct dma_pl330_desc *desc, size_t len)
        return burst_len;
 }
 
+static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic(
+               struct dma_chan *chan, dma_addr_t dma_addr, size_t len,
+               size_t period_len, enum dma_data_direction direction)
+{
+       struct dma_pl330_desc *desc;
+       struct dma_pl330_chan *pch = to_pchan(chan);
+       dma_addr_t dst;
+       dma_addr_t src;
+
+       desc = pl330_get_desc(pch);
+       if (!desc) {
+               dev_err(pch->dmac->pif.dev, "%s:%d Unable to fetch desc\n",
+                       __func__, __LINE__);
+               return NULL;
+       }
+
+       switch (direction) {
+       case DMA_TO_DEVICE:
+               desc->rqcfg.src_inc = 1;
+               desc->rqcfg.dst_inc = 0;
+               src = dma_addr;
+               dst = pch->fifo_addr;
+               break;
+       case DMA_FROM_DEVICE:
+               desc->rqcfg.src_inc = 0;
+               desc->rqcfg.dst_inc = 1;
+               src = pch->fifo_addr;
+               dst = dma_addr;
+               break;
+       default:
+               dev_err(pch->dmac->pif.dev, "%s:%d Invalid dma direction\n",
+               __func__, __LINE__);
+               return NULL;
+       }
+
+       desc->rqcfg.brst_size = pch->burst_sz;
+       desc->rqcfg.brst_len = 1;
+
+       pch->cyclic = true;
+
+       fill_px(&desc->px, dst, src, period_len);
+
+       return &desc->txd;
+}
+
 static struct dma_async_tx_descriptor *
 pl330_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dst,
                dma_addr_t src, size_t len, unsigned long flags)
@@ -579,7 +695,7 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
        struct dma_pl330_peri *peri = chan->private;
        struct scatterlist *sg;
        unsigned long flags;
-       int i, burst_size;
+       int i;
        dma_addr_t addr;
 
        if (unlikely(!pch || !sgl || !sg_len || !peri))
@@ -595,8 +711,7 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
                return NULL;
        }
 
-       addr = peri->fifo_addr;
-       burst_size = peri->burst_sz;
+       addr = pch->fifo_addr;
 
        first = NULL;
 
@@ -644,7 +759,7 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
                                sg_dma_address(sg), addr, sg_dma_len(sg));
                }
 
-               desc->rqcfg.brst_size = burst_size;
+               desc->rqcfg.brst_size = pch->burst_sz;
                desc->rqcfg.brst_len = 1;
        }
 
@@ -696,6 +811,30 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
                goto probe_err1;
        }
 
+       pdmac->clk = clk_get(&adev->dev, "dma");
+       if (IS_ERR(pdmac->clk)) {
+               dev_err(&adev->dev, "Cannot get operation clock.\n");
+               ret = -EINVAL;
+               goto probe_err1;
+       }
+
+       amba_set_drvdata(adev, pdmac);
+
+#ifdef CONFIG_PM_RUNTIME
+       /* to use the runtime PM helper functions */
+       pm_runtime_enable(&adev->dev);
+
+       /* enable the power domain */
+       if (pm_runtime_get_sync(&adev->dev)) {
+               dev_err(&adev->dev, "failed to get runtime pm\n");
+               ret = -ENODEV;
+               goto probe_err1;
+       }
+#else
+       /* enable dma clk */
+       clk_enable(pdmac->clk);
+#endif
+
        irq = adev->irq[0];
        ret = request_irq(irq, pl330_irq_handler, 0,
                        dev_name(&adev->dev), pi);
@@ -732,6 +871,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
                        case MEMTODEV:
                        case DEVTOMEM:
                                dma_cap_set(DMA_SLAVE, pd->cap_mask);
+                               dma_cap_set(DMA_CYCLIC, pd->cap_mask);
                                break;
                        default:
                                dev_err(&adev->dev, "DEVTODEV Not Supported\n");
@@ -747,11 +887,9 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
                spin_lock_init(&pch->lock);
                pch->pl330_chid = NULL;
                pch->chan.device = pd;
-               pch->chan.chan_id = i;
                pch->dmac = pdmac;
 
                /* Add the channel to the DMAC list */
-               pd->chancnt++;
                list_add_tail(&pch->chan.device_node, &pd->channels);
        }
 
@@ -760,6 +898,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
        pd->device_alloc_chan_resources = pl330_alloc_chan_resources;
        pd->device_free_chan_resources = pl330_free_chan_resources;
        pd->device_prep_dma_memcpy = pl330_prep_dma_memcpy;
+       pd->device_prep_dma_cyclic = pl330_prep_dma_cyclic;
        pd->device_tx_status = pl330_tx_status;
        pd->device_prep_slave_sg = pl330_prep_slave_sg;
        pd->device_control = pl330_control;
@@ -771,8 +910,6 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
                goto probe_err4;
        }
 
-       amba_set_drvdata(adev, pdmac);
-
        dev_info(&adev->dev,
                "Loaded driver for PL330 DMAC-%d\n", adev->periphid);
        dev_info(&adev->dev,
@@ -833,6 +970,13 @@ static int __devexit pl330_remove(struct amba_device *adev)
        res = &adev->res;
        release_mem_region(res->start, resource_size(res));
 
+#ifdef CONFIG_PM_RUNTIME
+       pm_runtime_put(&adev->dev);
+       pm_runtime_disable(&adev->dev);
+#else
+       clk_disable(pdmac->clk);
+#endif
+
        kfree(pdmac);
 
        return 0;
@@ -846,10 +990,49 @@ static struct amba_id pl330_ids[] = {
        { 0, 0 },
 };
 
+#ifdef CONFIG_PM_RUNTIME
+static int pl330_runtime_suspend(struct device *dev)
+{
+       struct dma_pl330_dmac *pdmac = dev_get_drvdata(dev);
+
+       if (!pdmac) {
+               dev_err(dev, "failed to get dmac\n");
+               return -ENODEV;
+       }
+
+       clk_disable(pdmac->clk);
+
+       return 0;
+}
+
+static int pl330_runtime_resume(struct device *dev)
+{
+       struct dma_pl330_dmac *pdmac = dev_get_drvdata(dev);
+
+       if (!pdmac) {
+               dev_err(dev, "failed to get dmac\n");
+               return -ENODEV;
+       }
+
+       clk_enable(pdmac->clk);
+
+       return 0;
+}
+#else
+#define pl330_runtime_suspend  NULL
+#define pl330_runtime_resume   NULL
+#endif /* CONFIG_PM_RUNTIME */
+
+static const struct dev_pm_ops pl330_pm_ops = {
+       .runtime_suspend = pl330_runtime_suspend,
+       .runtime_resume = pl330_runtime_resume,
+};
+
 static struct amba_driver pl330_driver = {
        .drv = {
                .owner = THIS_MODULE,
                .name = "dma-pl330",
+               .pm = &pl330_pm_ops,
        },
        .id_table = pl330_ids,
        .probe = pl330_probe,
index 7f49235..81809c2 100644 (file)
@@ -259,14 +259,23 @@ static int dmae_set_dmars(struct sh_dmae_chan *sh_chan, u16 val)
        return 0;
 }
 
+static void sh_chan_xfer_ld_queue(struct sh_dmae_chan *sh_chan);
+
 static dma_cookie_t sh_dmae_tx_submit(struct dma_async_tx_descriptor *tx)
 {
        struct sh_desc *desc = tx_to_sh_desc(tx), *chunk, *last = desc, *c;
        struct sh_dmae_chan *sh_chan = to_sh_chan(tx->chan);
+       struct sh_dmae_slave *param = tx->chan->private;
        dma_async_tx_callback callback = tx->callback;
        dma_cookie_t cookie;
+       bool power_up;
+
+       spin_lock_irq(&sh_chan->desc_lock);
 
-       spin_lock_bh(&sh_chan->desc_lock);
+       if (list_empty(&sh_chan->ld_queue))
+               power_up = true;
+       else
+               power_up = false;
 
        cookie = sh_chan->common.cookie;
        cookie++;
@@ -302,7 +311,38 @@ static dma_cookie_t sh_dmae_tx_submit(struct dma_async_tx_descriptor *tx)
                tx->cookie, &last->async_tx, sh_chan->id,
                desc->hw.sar, desc->hw.tcr, desc->hw.dar);
 
-       spin_unlock_bh(&sh_chan->desc_lock);
+       if (power_up) {
+               sh_chan->pm_state = DMAE_PM_BUSY;
+
+               pm_runtime_get(sh_chan->dev);
+
+               spin_unlock_irq(&sh_chan->desc_lock);
+
+               pm_runtime_barrier(sh_chan->dev);
+
+               spin_lock_irq(&sh_chan->desc_lock);
+
+               /* Have we been reset, while waiting? */
+               if (sh_chan->pm_state != DMAE_PM_ESTABLISHED) {
+                       dev_dbg(sh_chan->dev, "Bring up channel %d\n",
+                               sh_chan->id);
+                       if (param) {
+                               const struct sh_dmae_slave_config *cfg =
+                                       param->config;
+
+                               dmae_set_dmars(sh_chan, cfg->mid_rid);
+                               dmae_set_chcr(sh_chan, cfg->chcr);
+                       } else {
+                               dmae_init(sh_chan);
+                       }
+
+                       if (sh_chan->pm_state == DMAE_PM_PENDING)
+                               sh_chan_xfer_ld_queue(sh_chan);
+                       sh_chan->pm_state = DMAE_PM_ESTABLISHED;
+               }
+       }
+
+       spin_unlock_irq(&sh_chan->desc_lock);
 
        return cookie;
 }
@@ -346,8 +386,6 @@ static int sh_dmae_alloc_chan_resources(struct dma_chan *chan)
        struct sh_dmae_slave *param = chan->private;
        int ret;
 
-       pm_runtime_get_sync(sh_chan->dev);
-
        /*
         * This relies on the guarantee from dmaengine that alloc_chan_resources
         * never runs concurrently with itself or free_chan_resources.
@@ -367,31 +405,20 @@ static int sh_dmae_alloc_chan_resources(struct dma_chan *chan)
                }
 
                param->config = cfg;
-
-               dmae_set_dmars(sh_chan, cfg->mid_rid);
-               dmae_set_chcr(sh_chan, cfg->chcr);
-       } else {
-               dmae_init(sh_chan);
        }
 
-       spin_lock_bh(&sh_chan->desc_lock);
        while (sh_chan->descs_allocated < NR_DESCS_PER_CHANNEL) {
-               spin_unlock_bh(&sh_chan->desc_lock);
                desc = kzalloc(sizeof(struct sh_desc), GFP_KERNEL);
-               if (!desc) {
-                       spin_lock_bh(&sh_chan->desc_lock);
+               if (!desc)
                        break;
-               }
                dma_async_tx_descriptor_init(&desc->async_tx,
                                        &sh_chan->common);
                desc->async_tx.tx_submit = sh_dmae_tx_submit;
                desc->mark = DESC_IDLE;
 
-               spin_lock_bh(&sh_chan->desc_lock);
                list_add(&desc->node, &sh_chan->ld_free);
                sh_chan->descs_allocated++;
        }
-       spin_unlock_bh(&sh_chan->desc_lock);
 
        if (!sh_chan->descs_allocated) {
                ret = -ENOMEM;
@@ -405,7 +432,7 @@ edescalloc:
                clear_bit(param->slave_id, sh_dmae_slave_used);
 etestused:
 efindslave:
-       pm_runtime_put(sh_chan->dev);
+       chan->private = NULL;
        return ret;
 }
 
@@ -417,7 +444,6 @@ static void sh_dmae_free_chan_resources(struct dma_chan *chan)
        struct sh_dmae_chan *sh_chan = to_sh_chan(chan);
        struct sh_desc *desc, *_desc;
        LIST_HEAD(list);
-       int descs = sh_chan->descs_allocated;
 
        /* Protect against ISR */
        spin_lock_irq(&sh_chan->desc_lock);
@@ -437,15 +463,12 @@ static void sh_dmae_free_chan_resources(struct dma_chan *chan)
                chan->private = NULL;
        }
 
-       spin_lock_bh(&sh_chan->desc_lock);
+       spin_lock_irq(&sh_chan->desc_lock);
 
        list_splice_init(&sh_chan->ld_free, &list);
        sh_chan->descs_allocated = 0;
 
-       spin_unlock_bh(&sh_chan->desc_lock);
-
-       if (descs > 0)
-               pm_runtime_put(sh_chan->dev);
+       spin_unlock_irq(&sh_chan->desc_lock);
 
        list_for_each_entry_safe(desc, _desc, &list, node)
                kfree(desc);
@@ -534,6 +557,7 @@ static struct dma_async_tx_descriptor *sh_dmae_prep_sg(struct sh_dmae_chan *sh_c
        struct sh_desc *first = NULL, *new = NULL /* compiler... */;
        LIST_HEAD(tx_list);
        int chunks = 0;
+       unsigned long irq_flags;
        int i;
 
        if (!sg_len)
@@ -544,7 +568,7 @@ static struct dma_async_tx_descriptor *sh_dmae_prep_sg(struct sh_dmae_chan *sh_c
                        (SH_DMA_TCR_MAX + 1);
 
        /* Have to lock the whole loop to protect against concurrent release */
-       spin_lock_bh(&sh_chan->desc_lock);
+       spin_lock_irqsave(&sh_chan->desc_lock, irq_flags);
 
        /*
         * Chaining:
@@ -590,7 +614,7 @@ static struct dma_async_tx_descriptor *sh_dmae_prep_sg(struct sh_dmae_chan *sh_c
        /* Put them back on the free list, so, they don't get lost */
        list_splice_tail(&tx_list, &sh_chan->ld_free);
 
-       spin_unlock_bh(&sh_chan->desc_lock);
+       spin_unlock_irqrestore(&sh_chan->desc_lock, irq_flags);
 
        return &first->async_tx;
 
@@ -599,7 +623,7 @@ err_get_desc:
                new->mark = DESC_IDLE;
        list_splice(&tx_list, &sh_chan->ld_free);
 
-       spin_unlock_bh(&sh_chan->desc_lock);
+       spin_unlock_irqrestore(&sh_chan->desc_lock, irq_flags);
 
        return NULL;
 }
@@ -661,6 +685,7 @@ static int sh_dmae_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
                           unsigned long arg)
 {
        struct sh_dmae_chan *sh_chan = to_sh_chan(chan);
+       unsigned long flags;
 
        /* Only supports DMA_TERMINATE_ALL */
        if (cmd != DMA_TERMINATE_ALL)
@@ -669,7 +694,7 @@ static int sh_dmae_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
        if (!chan)
                return -EINVAL;
 
-       spin_lock_bh(&sh_chan->desc_lock);
+       spin_lock_irqsave(&sh_chan->desc_lock, flags);
        dmae_halt(sh_chan);
 
        if (!list_empty(&sh_chan->ld_queue)) {
@@ -678,9 +703,8 @@ static int sh_dmae_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
                                                  struct sh_desc, node);
                desc->partial = (desc->hw.tcr - sh_dmae_readl(sh_chan, TCR)) <<
                        sh_chan->xmit_shift;
-
        }
-       spin_unlock_bh(&sh_chan->desc_lock);
+       spin_unlock_irqrestore(&sh_chan->desc_lock, flags);
 
        sh_dmae_chan_ld_cleanup(sh_chan, true);
 
@@ -695,8 +719,9 @@ static dma_async_tx_callback __ld_cleanup(struct sh_dmae_chan *sh_chan, bool all
        dma_cookie_t cookie = 0;
        dma_async_tx_callback callback = NULL;
        void *param = NULL;
+       unsigned long flags;
 
-       spin_lock_bh(&sh_chan->desc_lock);
+       spin_lock_irqsave(&sh_chan->desc_lock, flags);
        list_for_each_entry_safe(desc, _desc, &sh_chan->ld_queue, node) {
                struct dma_async_tx_descriptor *tx = &desc->async_tx;
 
@@ -762,7 +787,13 @@ static dma_async_tx_callback __ld_cleanup(struct sh_dmae_chan *sh_chan, bool all
                     async_tx_test_ack(&desc->async_tx)) || all) {
                        /* Remove from ld_queue list */
                        desc->mark = DESC_IDLE;
+
                        list_move(&desc->node, &sh_chan->ld_free);
+
+                       if (list_empty(&sh_chan->ld_queue)) {
+                               dev_dbg(sh_chan->dev, "Bring down channel %d\n", sh_chan->id);
+                               pm_runtime_put(sh_chan->dev);
+                       }
                }
        }
 
@@ -773,7 +804,7 @@ static dma_async_tx_callback __ld_cleanup(struct sh_dmae_chan *sh_chan, bool all
                 */
                sh_chan->completed_cookie = sh_chan->common.cookie;
 
-       spin_unlock_bh(&sh_chan->desc_lock);
+       spin_unlock_irqrestore(&sh_chan->desc_lock, flags);
 
        if (callback)
                callback(param);
@@ -792,14 +823,14 @@ static void sh_dmae_chan_ld_cleanup(struct sh_dmae_chan *sh_chan, bool all)
                ;
 }
 
+/* Called under spin_lock_irq(&sh_chan->desc_lock) */
 static void sh_chan_xfer_ld_queue(struct sh_dmae_chan *sh_chan)
 {
        struct sh_desc *desc;
 
-       spin_lock_bh(&sh_chan->desc_lock);
        /* DMA work check */
        if (dmae_is_busy(sh_chan))
-               goto sh_chan_xfer_ld_queue_end;
+               return;
 
        /* Find the first not transferred descriptor */
        list_for_each_entry(desc, &sh_chan->ld_queue, node)
@@ -812,15 +843,18 @@ static void sh_chan_xfer_ld_queue(struct sh_dmae_chan *sh_chan)
                        dmae_start(sh_chan);
                        break;
                }
-
-sh_chan_xfer_ld_queue_end:
-       spin_unlock_bh(&sh_chan->desc_lock);
 }
 
 static void sh_dmae_memcpy_issue_pending(struct dma_chan *chan)
 {
        struct sh_dmae_chan *sh_chan = to_sh_chan(chan);
-       sh_chan_xfer_ld_queue(sh_chan);
+
+       spin_lock_irq(&sh_chan->desc_lock);
+       if (sh_chan->pm_state == DMAE_PM_ESTABLISHED)
+               sh_chan_xfer_ld_queue(sh_chan);
+       else
+               sh_chan->pm_state = DMAE_PM_PENDING;
+       spin_unlock_irq(&sh_chan->desc_lock);
 }
 
 static enum dma_status sh_dmae_tx_status(struct dma_chan *chan,
@@ -831,6 +865,7 @@ static enum dma_status sh_dmae_tx_status(struct dma_chan *chan,
        dma_cookie_t last_used;
        dma_cookie_t last_complete;
        enum dma_status status;
+       unsigned long flags;
 
        sh_dmae_chan_ld_cleanup(sh_chan, false);
 
@@ -841,7 +876,7 @@ static enum dma_status sh_dmae_tx_status(struct dma_chan *chan,
        BUG_ON(last_complete < 0);
        dma_set_tx_state(txstate, last_complete, last_used, 0);
 
-       spin_lock_bh(&sh_chan->desc_lock);
+       spin_lock_irqsave(&sh_chan->desc_lock, flags);
 
        status = dma_async_is_complete(cookie, last_complete, last_used);
 
@@ -859,7 +894,7 @@ static enum dma_status sh_dmae_tx_status(struct dma_chan *chan,
                        }
        }
 
-       spin_unlock_bh(&sh_chan->desc_lock);
+       spin_unlock_irqrestore(&sh_chan->desc_lock, flags);
 
        return status;
 }
@@ -912,6 +947,12 @@ static bool sh_dmae_reset(struct sh_dmae_device *shdev)
 
                list_splice_init(&sh_chan->ld_queue, &dl);
 
+               if (!list_empty(&dl)) {
+                       dev_dbg(sh_chan->dev, "Bring down channel %d\n", sh_chan->id);
+                       pm_runtime_put(sh_chan->dev);
+               }
+               sh_chan->pm_state = DMAE_PM_ESTABLISHED;
+
                spin_unlock(&sh_chan->desc_lock);
 
                /* Complete all  */
@@ -952,7 +993,7 @@ static void dmae_do_tasklet(unsigned long data)
        u32 sar_buf = sh_dmae_readl(sh_chan, SAR);
        u32 dar_buf = sh_dmae_readl(sh_chan, DAR);
 
-       spin_lock(&sh_chan->desc_lock);
+       spin_lock_irq(&sh_chan->desc_lock);
        list_for_each_entry(desc, &sh_chan->ld_queue, node) {
                if (desc->mark == DESC_SUBMITTED &&
                    ((desc->direction == DMA_FROM_DEVICE &&
@@ -965,10 +1006,10 @@ static void dmae_do_tasklet(unsigned long data)
                        break;
                }
        }
-       spin_unlock(&sh_chan->desc_lock);
-
        /* Next desc */
        sh_chan_xfer_ld_queue(sh_chan);
+       spin_unlock_irq(&sh_chan->desc_lock);
+
        sh_dmae_chan_ld_cleanup(sh_chan, false);
 }
 
@@ -1036,7 +1077,9 @@ static int __devinit sh_dmae_chan_probe(struct sh_dmae_device *shdev, int id,
                return -ENOMEM;
        }
 
-       /* copy struct dma_device */
+       new_sh_chan->pm_state = DMAE_PM_ESTABLISHED;
+
+       /* reference struct dma_device */
        new_sh_chan->common.device = &shdev->common;
 
        new_sh_chan->dev = shdev->common.dev;
index dc56576..2b55a27 100644 (file)
 
 struct device;
 
+enum dmae_pm_state {
+       DMAE_PM_ESTABLISHED,
+       DMAE_PM_BUSY,
+       DMAE_PM_PENDING,
+};
+
 struct sh_dmae_chan {
        dma_cookie_t completed_cookie;  /* The maximum cookie completed */
        spinlock_t desc_lock;           /* Descriptor operation lock */
@@ -38,6 +44,7 @@ struct sh_dmae_chan {
        u32 __iomem *base;
        char dev_id[16];                /* unique name per DMAC of channel */
        int pm_error;
+       enum dmae_pm_state pm_state;
 };
 
 struct sh_dmae_device {
index f69f90a..a4a398f 100644 (file)
@@ -753,7 +753,7 @@ static int __devinit td_probe(struct platform_device *pdev)
 
        INIT_LIST_HEAD(&td->dma.channels);
 
-       for (i = 0; i < pdata->nr_channels; i++, td->dma.chancnt++) {
+       for (i = 0; i < pdata->nr_channels; i++) {
                struct timb_dma_chan *td_chan = &td->channels[i];
                struct timb_dma_platform_data_channel *pchan =
                        pdata->channels + i;
@@ -762,12 +762,11 @@ static int __devinit td_probe(struct platform_device *pdev)
                if ((i % 2) == pchan->rx) {
                        dev_err(&pdev->dev, "Wrong channel configuration\n");
                        err = -EINVAL;
-                       goto err_tasklet_kill;
+                       goto err_free_irq;
                }
 
                td_chan->chan.device = &td->dma;
                td_chan->chan.cookie = 1;
-               td_chan->chan.chan_id = i;
                spin_lock_init(&td_chan->lock);
                INIT_LIST_HEAD(&td_chan->active_list);
                INIT_LIST_HEAD(&td_chan->queue);
index a687a0d..a774c0d 100644 (file)
@@ -90,6 +90,7 @@ enum apimask_bits {
        ECC_MASK_ENABLE = (APIMASK_ECC_UE_H | APIMASK_ECC_CE_H |
                           APIMASK_ECC_UE_L | APIMASK_ECC_CE_L),
 };
+#define APIMASK_ADI(n)         CPC925_BIT(((n)+1))
 
 /************************************************************
  *     Processor Interface Exception Register (APIEXCP)
@@ -581,16 +582,73 @@ static void cpc925_mc_check(struct mem_ctl_info *mci)
 }
 
 /******************** CPU err device********************************/
+static u32 cpc925_cpu_mask_disabled(void)
+{
+       struct device_node *cpus;
+       struct device_node *cpunode = NULL;
+       static u32 mask = 0;
+
+       /* use cached value if available */
+       if (mask != 0)
+               return mask;
+
+       mask = APIMASK_ADI0 | APIMASK_ADI1;
+
+       cpus = of_find_node_by_path("/cpus");
+       if (cpus == NULL) {
+               cpc925_printk(KERN_DEBUG, "No /cpus node !\n");
+               return 0;
+       }
+
+       while ((cpunode = of_get_next_child(cpus, cpunode)) != NULL) {
+               const u32 *reg = of_get_property(cpunode, "reg", NULL);
+
+               if (strcmp(cpunode->type, "cpu")) {
+                       cpc925_printk(KERN_ERR, "Not a cpu node in /cpus: %s\n", cpunode->name);
+                       continue;
+               }
+
+               if (reg == NULL || *reg > 2) {
+                       cpc925_printk(KERN_ERR, "Bad reg value at %s\n", cpunode->full_name);
+                       continue;
+               }
+
+               mask &= ~APIMASK_ADI(*reg);
+       }
+
+       if (mask != (APIMASK_ADI0 | APIMASK_ADI1)) {
+               /* We assume that each CPU sits on it's own PI and that
+                * for present CPUs the reg property equals to the PI
+                * interface id */
+               cpc925_printk(KERN_WARNING,
+                               "Assuming PI id is equal to CPU MPIC id!\n");
+       }
+
+       of_node_put(cpunode);
+       of_node_put(cpus);
+
+       return mask;
+}
+
 /* Enable CPU Errors detection */
 static void cpc925_cpu_init(struct cpc925_dev_info *dev_info)
 {
        u32 apimask;
+       u32 cpumask;
 
        apimask = __raw_readl(dev_info->vbase + REG_APIMASK_OFFSET);
-       if ((apimask & CPU_MASK_ENABLE) == 0) {
-               apimask |= CPU_MASK_ENABLE;
-               __raw_writel(apimask, dev_info->vbase + REG_APIMASK_OFFSET);
+
+       cpumask = cpc925_cpu_mask_disabled();
+       if (apimask & cpumask) {
+               cpc925_printk(KERN_WARNING, "CPU(s) not present, "
+                               "but enabled in APIMASK, disabling\n");
+               apimask &= ~cpumask;
        }
+
+       if ((apimask & CPU_MASK_ENABLE) == 0)
+               apimask |= CPU_MASK_ENABLE;
+
+       __raw_writel(apimask, dev_info->vbase + REG_APIMASK_OFFSET);
 }
 
 /* Disable CPU Errors detection */
@@ -622,6 +680,9 @@ static void cpc925_cpu_check(struct edac_device_ctl_info *edac_dev)
        if ((apiexcp & CPU_EXCP_DETECTED) == 0)
                return;
 
+       if ((apiexcp & ~cpc925_cpu_mask_disabled()) == 0)
+               return;
+
        apimask = __raw_readl(dev_info->vbase + REG_APIMASK_OFFSET);
        cpc925_printk(KERN_INFO, "Processor Interface Fault\n"
                                 "Processor Interface register dump:\n");
index 0de7d87..3840096 100644 (file)
@@ -205,7 +205,7 @@ static struct platform_driver ppc4xx_edac_driver = {
        .remove                 = ppc4xx_edac_remove,
        .driver = {
                .owner = THIS_MODULE,
-               .name = PPC4XX_EDAC_MODULE_NAME
+               .name = PPC4XX_EDAC_MODULE_NAME,
                .of_match_table = ppc4xx_edac_match,
        },
 };
index f1b7f65..e229576 100644 (file)
@@ -151,7 +151,8 @@ edd_show_host_bus(struct edd_device *edev, char *buf)
                p += scnprintf(p, left, "\tbase_address: %x\n",
                             info->params.interface_path.isa.base_address);
        } else if (!strncmp(info->params.host_bus_type, "PCIX", 4) ||
-                  !strncmp(info->params.host_bus_type, "PCI", 3)) {
+                  !strncmp(info->params.host_bus_type, "PCI", 3) ||
+                  !strncmp(info->params.host_bus_type, "XPRS", 4)) {
                p += scnprintf(p, left,
                             "\t%02x:%02x.%d  channel: %u\n",
                             info->params.interface_path.pci.bus,
@@ -159,7 +160,6 @@ edd_show_host_bus(struct edd_device *edev, char *buf)
                             info->params.interface_path.pci.function,
                             info->params.interface_path.pci.channel);
        } else if (!strncmp(info->params.host_bus_type, "IBND", 4) ||
-                  !strncmp(info->params.host_bus_type, "XPRS", 4) ||
                   !strncmp(info->params.host_bus_type, "HTPT", 4)) {
                p += scnprintf(p, left,
                             "\tTBD: %llx\n",
@@ -668,7 +668,7 @@ edd_get_pci_dev(struct edd_device *edev)
 {
        struct edd_info *info = edd_dev_get_info(edev);
 
-       if (edd_dev_is_type(edev, "PCI")) {
+       if (edd_dev_is_type(edev, "PCI") || edd_dev_is_type(edev, "XPRS")) {
                return pci_get_bus_and_slot(info->params.interface_path.pci.bus,
                                     PCI_DEVFN(info->params.interface_path.pci.slot,
                                               info->params.interface_path.pci.
index 8b3c745..8482a23 100644 (file)
@@ -95,14 +95,18 @@ config GPIO_EP93XX
        depends on ARCH_EP93XX
        select GPIO_GENERIC
 
-config GPIO_EXYNOS4
-       def_bool y
-       depends on CPU_EXYNOS4210
-
 config GPIO_MPC5200
        def_bool y
        depends on PPC_MPC52xx
 
+config GPIO_MPC8XXX
+       bool "MPC512x/MPC8xxx GPIO support"
+       depends on PPC_MPC512x || PPC_MPC831x || PPC_MPC834x || PPC_MPC837x || \
+                  FSL_SOC_BOOKE || PPC_86xx
+       help
+         Say Y here if you're going to use hardware that connects to the
+         MPC512x/831x/834x/837x/8572/8610 GPIOs.
+
 config GPIO_MSM_V1
        tristate "Qualcomm MSM GPIO v1"
        depends on GPIOLIB && ARCH_MSM
@@ -131,18 +135,6 @@ config GPIO_MXS
        select GPIO_GENERIC
        select GENERIC_IRQ_CHIP
 
-config GPIO_PLAT_SAMSUNG
-       def_bool y
-       depends on SAMSUNG_GPIOLIB_4BIT
-
-config GPIO_S5PC100
-       def_bool y
-       depends on CPU_S5PC100
-
-config GPIO_S5PV210
-       def_bool y
-       depends on CPU_S5PV210
-
 config GPIO_PL061
        bool "PrimeCell PL061 GPIO support"
        depends on ARM_AMBA
index 19c5d27..dbcb0bc 100644 (file)
@@ -16,7 +16,6 @@ obj-$(CONFIG_GPIO_CS5535)     += gpio-cs5535.o
 obj-$(CONFIG_GPIO_DA9052)      += gpio-da9052.o
 obj-$(CONFIG_ARCH_DAVINCI)     += gpio-davinci.o
 obj-$(CONFIG_GPIO_EP93XX)      += gpio-ep93xx.o
-obj-$(CONFIG_GPIO_EXYNOS4)     += gpio-exynos4.o
 obj-$(CONFIG_GPIO_IT8761E)     += gpio-it8761e.o
 obj-$(CONFIG_GPIO_JANZ_TTL)    += gpio-janz-ttl.o
 obj-$(CONFIG_MACH_KS8695)      += gpio-ks8695.o
@@ -30,6 +29,7 @@ obj-$(CONFIG_GPIO_MC33880)    += gpio-mc33880.o
 obj-$(CONFIG_GPIO_MCP23S08)    += gpio-mcp23s08.o
 obj-$(CONFIG_GPIO_ML_IOH)      += gpio-ml-ioh.o
 obj-$(CONFIG_GPIO_MPC5200)     += gpio-mpc5200.o
+obj-$(CONFIG_GPIO_MPC8XXX)     += gpio-mpc8xxx.o
 obj-$(CONFIG_GPIO_MSM_V1)      += gpio-msm-v1.o
 obj-$(CONFIG_GPIO_MSM_V2)      += gpio-msm-v2.o
 obj-$(CONFIG_GPIO_MXC)         += gpio-mxc.o
@@ -42,10 +42,7 @@ obj-$(CONFIG_GPIO_PCH)               += gpio-pch.o
 obj-$(CONFIG_GPIO_PL061)       += gpio-pl061.o
 obj-$(CONFIG_PLAT_PXA)         += gpio-pxa.o
 obj-$(CONFIG_GPIO_RDC321X)     += gpio-rdc321x.o
-
-obj-$(CONFIG_GPIO_PLAT_SAMSUNG)        += gpio-plat-samsung.o
-obj-$(CONFIG_GPIO_S5PC100)     += gpio-s5pc100.o
-obj-$(CONFIG_GPIO_S5PV210)     += gpio-s5pv210.o
+obj-$(CONFIG_PLAT_SAMSUNG)     += gpio-samsung.o
 obj-$(CONFIG_ARCH_SA1100)      += gpio-sa1100.o
 obj-$(CONFIG_GPIO_SCH)         += gpio-sch.o
 obj-$(CONFIG_GPIO_STMPE)       += gpio-stmpe.o
diff --git a/drivers/gpio/gpio-exynos4.c b/drivers/gpio/gpio-exynos4.c
deleted file mode 100644 (file)
index d24b337..0000000
+++ /dev/null
@@ -1,385 +0,0 @@
-/*
- * EXYNOS4 - GPIOlib support
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-
-#include <mach/map.h>
-
-#include <plat/gpio-core.h>
-#include <plat/gpio-cfg.h>
-#include <plat/gpio-cfg-helpers.h>
-
-int s3c_gpio_setpull_exynos4(struct s3c_gpio_chip *chip,
-                               unsigned int off, s3c_gpio_pull_t pull)
-{
-       if (pull == S3C_GPIO_PULL_UP)
-               pull = 3;
-
-       return s3c_gpio_setpull_updown(chip, off, pull);
-}
-
-s3c_gpio_pull_t s3c_gpio_getpull_exynos4(struct s3c_gpio_chip *chip,
-                                               unsigned int off)
-{
-       s3c_gpio_pull_t pull;
-
-       pull = s3c_gpio_getpull_updown(chip, off);
-       if (pull == 3)
-               pull = S3C_GPIO_PULL_UP;
-
-       return pull;
-}
-
-static struct s3c_gpio_cfg gpio_cfg = {
-       .set_config     = s3c_gpio_setcfg_s3c64xx_4bit,
-       .set_pull       = s3c_gpio_setpull_exynos4,
-       .get_pull       = s3c_gpio_getpull_exynos4,
-};
-
-static struct s3c_gpio_cfg gpio_cfg_noint = {
-       .set_config     = s3c_gpio_setcfg_s3c64xx_4bit,
-       .set_pull       = s3c_gpio_setpull_exynos4,
-       .get_pull       = s3c_gpio_getpull_exynos4,
-};
-
-/*
- * Following are the gpio banks in v310.
- *
- * The 'config' member when left to NULL, is initialized to the default
- * structure gpio_cfg in the init function below.
- *
- * The 'base' member is also initialized in the init function below.
- * Note: The initialization of 'base' member of s3c_gpio_chip structure
- * uses the above macro and depends on the banks being listed in order here.
- */
-static struct s3c_gpio_chip exynos4_gpio_part1_4bit[] = {
-       {
-               .chip   = {
-                       .base   = EXYNOS4_GPA0(0),
-                       .ngpio  = EXYNOS4_GPIO_A0_NR,
-                       .label  = "GPA0",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPA1(0),
-                       .ngpio  = EXYNOS4_GPIO_A1_NR,
-                       .label  = "GPA1",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPB(0),
-                       .ngpio  = EXYNOS4_GPIO_B_NR,
-                       .label  = "GPB",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPC0(0),
-                       .ngpio  = EXYNOS4_GPIO_C0_NR,
-                       .label  = "GPC0",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPC1(0),
-                       .ngpio  = EXYNOS4_GPIO_C1_NR,
-                       .label  = "GPC1",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPD0(0),
-                       .ngpio  = EXYNOS4_GPIO_D0_NR,
-                       .label  = "GPD0",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPD1(0),
-                       .ngpio  = EXYNOS4_GPIO_D1_NR,
-                       .label  = "GPD1",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPE0(0),
-                       .ngpio  = EXYNOS4_GPIO_E0_NR,
-                       .label  = "GPE0",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPE1(0),
-                       .ngpio  = EXYNOS4_GPIO_E1_NR,
-                       .label  = "GPE1",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPE2(0),
-                       .ngpio  = EXYNOS4_GPIO_E2_NR,
-                       .label  = "GPE2",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPE3(0),
-                       .ngpio  = EXYNOS4_GPIO_E3_NR,
-                       .label  = "GPE3",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPE4(0),
-                       .ngpio  = EXYNOS4_GPIO_E4_NR,
-                       .label  = "GPE4",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPF0(0),
-                       .ngpio  = EXYNOS4_GPIO_F0_NR,
-                       .label  = "GPF0",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPF1(0),
-                       .ngpio  = EXYNOS4_GPIO_F1_NR,
-                       .label  = "GPF1",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPF2(0),
-                       .ngpio  = EXYNOS4_GPIO_F2_NR,
-                       .label  = "GPF2",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPF3(0),
-                       .ngpio  = EXYNOS4_GPIO_F3_NR,
-                       .label  = "GPF3",
-               },
-       },
-};
-
-static struct s3c_gpio_chip exynos4_gpio_part2_4bit[] = {
-       {
-               .chip   = {
-                       .base   = EXYNOS4_GPJ0(0),
-                       .ngpio  = EXYNOS4_GPIO_J0_NR,
-                       .label  = "GPJ0",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPJ1(0),
-                       .ngpio  = EXYNOS4_GPIO_J1_NR,
-                       .label  = "GPJ1",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPK0(0),
-                       .ngpio  = EXYNOS4_GPIO_K0_NR,
-                       .label  = "GPK0",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPK1(0),
-                       .ngpio  = EXYNOS4_GPIO_K1_NR,
-                       .label  = "GPK1",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPK2(0),
-                       .ngpio  = EXYNOS4_GPIO_K2_NR,
-                       .label  = "GPK2",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPK3(0),
-                       .ngpio  = EXYNOS4_GPIO_K3_NR,
-                       .label  = "GPK3",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPL0(0),
-                       .ngpio  = EXYNOS4_GPIO_L0_NR,
-                       .label  = "GPL0",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPL1(0),
-                       .ngpio  = EXYNOS4_GPIO_L1_NR,
-                       .label  = "GPL1",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPL2(0),
-                       .ngpio  = EXYNOS4_GPIO_L2_NR,
-                       .label  = "GPL2",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = EXYNOS4_GPY0(0),
-                       .ngpio  = EXYNOS4_GPIO_Y0_NR,
-                       .label  = "GPY0",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = EXYNOS4_GPY1(0),
-                       .ngpio  = EXYNOS4_GPIO_Y1_NR,
-                       .label  = "GPY1",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = EXYNOS4_GPY2(0),
-                       .ngpio  = EXYNOS4_GPIO_Y2_NR,
-                       .label  = "GPY2",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = EXYNOS4_GPY3(0),
-                       .ngpio  = EXYNOS4_GPIO_Y3_NR,
-                       .label  = "GPY3",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = EXYNOS4_GPY4(0),
-                       .ngpio  = EXYNOS4_GPIO_Y4_NR,
-                       .label  = "GPY4",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = EXYNOS4_GPY5(0),
-                       .ngpio  = EXYNOS4_GPIO_Y5_NR,
-                       .label  = "GPY5",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = EXYNOS4_GPY6(0),
-                       .ngpio  = EXYNOS4_GPIO_Y6_NR,
-                       .label  = "GPY6",
-               },
-       }, {
-               .base   = (S5P_VA_GPIO2 + 0xC00),
-               .config = &gpio_cfg_noint,
-               .irq_base = IRQ_EINT(0),
-               .chip   = {
-                       .base   = EXYNOS4_GPX0(0),
-                       .ngpio  = EXYNOS4_GPIO_X0_NR,
-                       .label  = "GPX0",
-                       .to_irq = samsung_gpiolib_to_irq,
-               },
-       }, {
-               .base   = (S5P_VA_GPIO2 + 0xC20),
-               .config = &gpio_cfg_noint,
-               .irq_base = IRQ_EINT(8),
-               .chip   = {
-                       .base   = EXYNOS4_GPX1(0),
-                       .ngpio  = EXYNOS4_GPIO_X1_NR,
-                       .label  = "GPX1",
-                       .to_irq = samsung_gpiolib_to_irq,
-               },
-       }, {
-               .base   = (S5P_VA_GPIO2 + 0xC40),
-               .config = &gpio_cfg_noint,
-               .irq_base = IRQ_EINT(16),
-               .chip   = {
-                       .base   = EXYNOS4_GPX2(0),
-                       .ngpio  = EXYNOS4_GPIO_X2_NR,
-                       .label  = "GPX2",
-                       .to_irq = samsung_gpiolib_to_irq,
-               },
-       }, {
-               .base   = (S5P_VA_GPIO2 + 0xC60),
-               .config = &gpio_cfg_noint,
-               .irq_base = IRQ_EINT(24),
-               .chip   = {
-                       .base   = EXYNOS4_GPX3(0),
-                       .ngpio  = EXYNOS4_GPIO_X3_NR,
-                       .label  = "GPX3",
-                       .to_irq = samsung_gpiolib_to_irq,
-               },
-       },
-};
-
-static struct s3c_gpio_chip exynos4_gpio_part3_4bit[] = {
-       {
-               .chip   = {
-                       .base   = EXYNOS4_GPZ(0),
-                       .ngpio  = EXYNOS4_GPIO_Z_NR,
-                       .label  = "GPZ",
-               },
-       },
-};
-
-static __init int exynos4_gpiolib_init(void)
-{
-       struct s3c_gpio_chip *chip;
-       int i;
-       int group = 0;
-       int nr_chips;
-
-       /* GPIO part 1 */
-
-       chip = exynos4_gpio_part1_4bit;
-       nr_chips = ARRAY_SIZE(exynos4_gpio_part1_4bit);
-
-       for (i = 0; i < nr_chips; i++, chip++) {
-               if (chip->config == NULL) {
-                       chip->config = &gpio_cfg;
-                       /* Assign the GPIO interrupt group */
-                       chip->group = group++;
-               }
-               if (chip->base == NULL)
-                       chip->base = S5P_VA_GPIO1 + (i) * 0x20;
-       }
-
-       samsung_gpiolib_add_4bit_chips(exynos4_gpio_part1_4bit, nr_chips);
-
-       /* GPIO part 2 */
-
-       chip = exynos4_gpio_part2_4bit;
-       nr_chips = ARRAY_SIZE(exynos4_gpio_part2_4bit);
-
-       for (i = 0; i < nr_chips; i++, chip++) {
-               if (chip->config == NULL) {
-                       chip->config = &gpio_cfg;
-                       /* Assign the GPIO interrupt group */
-                       chip->group = group++;
-               }
-               if (chip->base == NULL)
-                       chip->base = S5P_VA_GPIO2 + (i) * 0x20;
-       }
-
-       samsung_gpiolib_add_4bit_chips(exynos4_gpio_part2_4bit, nr_chips);
-
-       /* GPIO part 3 */
-
-       chip = exynos4_gpio_part3_4bit;
-       nr_chips = ARRAY_SIZE(exynos4_gpio_part3_4bit);
-
-       for (i = 0; i < nr_chips; i++, chip++) {
-               if (chip->config == NULL) {
-                       chip->config = &gpio_cfg;
-                       /* Assign the GPIO interrupt group */
-                       chip->group = group++;
-               }
-               if (chip->base == NULL)
-                       chip->base = S5P_VA_GPIO3 + (i) * 0x20;
-       }
-
-       samsung_gpiolib_add_4bit_chips(exynos4_gpio_part3_4bit, nr_chips);
-       s5p_register_gpioint_bank(IRQ_GPIO_XA, 0, IRQ_GPIO1_NR_GROUPS);
-       s5p_register_gpioint_bank(IRQ_GPIO_XB, IRQ_GPIO1_NR_GROUPS, IRQ_GPIO2_NR_GROUPS);
-
-       return 0;
-}
-core_initcall(exynos4_gpiolib_init);
similarity index 98%
rename from arch/powerpc/sysdev/mpc8xxx_gpio.c
rename to drivers/gpio/gpio-mpc8xxx.c
index fb4963a..ec3fcf0 100644 (file)
@@ -146,6 +146,7 @@ static int mpc8xxx_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
 static void mpc8xxx_gpio_irq_cascade(unsigned int irq, struct irq_desc *desc)
 {
        struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_desc_get_handler_data(desc);
+       struct irq_chip *chip = irq_desc_get_chip(desc);
        struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
        unsigned int mask;
 
@@ -153,6 +154,7 @@ static void mpc8xxx_gpio_irq_cascade(unsigned int irq, struct irq_desc *desc)
        if (mask)
                generic_handle_irq(irq_linear_revmap(mpc8xxx_gc->irq,
                                                     32 - ffs(mask)));
+       chip->irq_eoi(&desc->irq_data);
 }
 
 static void mpc8xxx_irq_unmask(struct irq_data *d)
@@ -310,6 +312,7 @@ static struct of_device_id mpc8xxx_gpio_ids[] __initdata = {
        { .compatible = "fsl,mpc8572-gpio", },
        { .compatible = "fsl,mpc8610-gpio", },
        { .compatible = "fsl,mpc5121-gpio", .data = mpc512x_irq_set_type, },
+       { .compatible = "fsl,pq3-gpio",     },
        { .compatible = "fsl,qoriq-gpio",   },
        {}
 };
diff --git a/drivers/gpio/gpio-plat-samsung.c b/drivers/gpio/gpio-plat-samsung.c
deleted file mode 100644 (file)
index ef67f19..0000000
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *      Ben Dooks <ben@simtec.co.uk>
- *      http://armlinux.simtec.co.uk/
- *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * SAMSUNG - GPIOlib 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/kernel.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <plat/gpio-core.h>
-#include <plat/gpio-cfg.h>
-#include <plat/gpio-cfg-helpers.h>
-
-#ifndef DEBUG_GPIO
-#define gpio_dbg(x...) do { } while (0)
-#else
-#define gpio_dbg(x...) printk(KERN_DEBUG x)
-#endif
-
-/* The samsung_gpiolib_4bit routines are to control the gpio banks where
- * the gpio configuration register (GPxCON) has 4 bits per GPIO, as the
- * following example:
- *
- * base + 0x00: Control register, 4 bits per gpio
- *             gpio n: 4 bits starting at (4*n)
- *             0000 = input, 0001 = output, others mean special-function
- * base + 0x04: Data register, 1 bit per gpio
- *             bit n: data bit n
- *
- * Note, since the data register is one bit per gpio and is at base + 0x4
- * we can use s3c_gpiolib_get and s3c_gpiolib_set to change the state of
- * the output.
-*/
-
-static int samsung_gpiolib_4bit_input(struct gpio_chip *chip,
-                                     unsigned int offset)
-{
-       struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-       void __iomem *base = ourchip->base;
-       unsigned long con;
-
-       con = __raw_readl(base + GPIOCON_OFF);
-       con &= ~(0xf << con_4bit_shift(offset));
-       __raw_writel(con, base + GPIOCON_OFF);
-
-       gpio_dbg("%s: %p: CON now %08lx\n", __func__, base, con);
-
-       return 0;
-}
-
-static int samsung_gpiolib_4bit_output(struct gpio_chip *chip,
-                                      unsigned int offset, int value)
-{
-       struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-       void __iomem *base = ourchip->base;
-       unsigned long con;
-       unsigned long dat;
-
-       con = __raw_readl(base + GPIOCON_OFF);
-       con &= ~(0xf << con_4bit_shift(offset));
-       con |= 0x1 << con_4bit_shift(offset);
-
-       dat = __raw_readl(base + GPIODAT_OFF);
-
-       if (value)
-               dat |= 1 << offset;
-       else
-               dat &= ~(1 << offset);
-
-       __raw_writel(dat, base + GPIODAT_OFF);
-       __raw_writel(con, base + GPIOCON_OFF);
-       __raw_writel(dat, base + GPIODAT_OFF);
-
-       gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
-
-       return 0;
-}
-
-/* The next set of routines are for the case where the GPIO configuration
- * registers are 4 bits per GPIO but there is more than one register (the
- * bank has more than 8 GPIOs.
- *
- * This case is the similar to the 4 bit case, but the registers are as
- * follows:
- *
- * base + 0x00: Control register, 4 bits per gpio (lower 8 GPIOs)
- *             gpio n: 4 bits starting at (4*n)
- *             0000 = input, 0001 = output, others mean special-function
- * base + 0x04: Control register, 4 bits per gpio (up to 8 additions GPIOs)
- *             gpio n: 4 bits starting at (4*n)
- *             0000 = input, 0001 = output, others mean special-function
- * base + 0x08: Data register, 1 bit per gpio
- *             bit n: data bit n
- *
- * To allow us to use the s3c_gpiolib_get and s3c_gpiolib_set routines we
- * store the 'base + 0x4' address so that these routines see the data
- * register at ourchip->base + 0x04.
- */
-
-static int samsung_gpiolib_4bit2_input(struct gpio_chip *chip,
-                                      unsigned int offset)
-{
-       struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-       void __iomem *base = ourchip->base;
-       void __iomem *regcon = base;
-       unsigned long con;
-
-       if (offset > 7)
-               offset -= 8;
-       else
-               regcon -= 4;
-
-       con = __raw_readl(regcon);
-       con &= ~(0xf << con_4bit_shift(offset));
-       __raw_writel(con, regcon);
-
-       gpio_dbg("%s: %p: CON %08lx\n", __func__, base, con);
-
-       return 0;
-}
-
-static int samsung_gpiolib_4bit2_output(struct gpio_chip *chip,
-                                       unsigned int offset, int value)
-{
-       struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-       void __iomem *base = ourchip->base;
-       void __iomem *regcon = base;
-       unsigned long con;
-       unsigned long dat;
-       unsigned con_offset = offset;
-
-       if (con_offset > 7)
-               con_offset -= 8;
-       else
-               regcon -= 4;
-
-       con = __raw_readl(regcon);
-       con &= ~(0xf << con_4bit_shift(con_offset));
-       con |= 0x1 << con_4bit_shift(con_offset);
-
-       dat = __raw_readl(base + GPIODAT_OFF);
-
-       if (value)
-               dat |= 1 << offset;
-       else
-               dat &= ~(1 << offset);
-
-       __raw_writel(dat, base + GPIODAT_OFF);
-       __raw_writel(con, regcon);
-       __raw_writel(dat, base + GPIODAT_OFF);
-
-       gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
-
-       return 0;
-}
-
-void __init samsung_gpiolib_add_4bit(struct s3c_gpio_chip *chip)
-{
-       chip->chip.direction_input = samsung_gpiolib_4bit_input;
-       chip->chip.direction_output = samsung_gpiolib_4bit_output;
-       chip->pm = __gpio_pm(&s3c_gpio_pm_4bit);
-}
-
-void __init samsung_gpiolib_add_4bit2(struct s3c_gpio_chip *chip)
-{
-       chip->chip.direction_input = samsung_gpiolib_4bit2_input;
-       chip->chip.direction_output = samsung_gpiolib_4bit2_output;
-       chip->pm = __gpio_pm(&s3c_gpio_pm_4bit);
-}
-
-void __init samsung_gpiolib_add_4bit_chips(struct s3c_gpio_chip *chip,
-                                          int nr_chips)
-{
-       for (; nr_chips > 0; nr_chips--, chip++) {
-               samsung_gpiolib_add_4bit(chip);
-               s3c_gpiolib_add(chip);
-       }
-}
-
-void __init samsung_gpiolib_add_4bit2_chips(struct s3c_gpio_chip *chip,
-                                           int nr_chips)
-{
-       for (; nr_chips > 0; nr_chips--, chip++) {
-               samsung_gpiolib_add_4bit2(chip);
-               s3c_gpiolib_add(chip);
-       }
-}
-
-void __init samsung_gpiolib_add_2bit_chips(struct s3c_gpio_chip *chip,
-                                          int nr_chips)
-{
-       for (; nr_chips > 0; nr_chips--, chip++)
-               s3c_gpiolib_add(chip);
-}
diff --git a/drivers/gpio/gpio-s5pc100.c b/drivers/gpio/gpio-s5pc100.c
deleted file mode 100644 (file)
index 7f87b0c..0000000
+++ /dev/null
@@ -1,354 +0,0 @@
-/*
- * S5PC100 - GPIOlib support
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com
- *
- *  Copyright 2009 Samsung Electronics Co
- *  Kyungmin Park <kyungmin.park@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-
-#include <mach/map.h>
-#include <mach/regs-gpio.h>
-
-#include <plat/gpio-core.h>
-#include <plat/gpio-cfg.h>
-#include <plat/gpio-cfg-helpers.h>
-
-/* S5PC100 GPIO bank summary:
- *
- * Bank        GPIOs   Style   INT Type
- * A0  8       4Bit    GPIO_INT0
- * A1  5       4Bit    GPIO_INT1
- * B   8       4Bit    GPIO_INT2
- * C   5       4Bit    GPIO_INT3
- * D   7       4Bit    GPIO_INT4
- * E0  8       4Bit    GPIO_INT5
- * E1  6       4Bit    GPIO_INT6
- * F0  8       4Bit    GPIO_INT7
- * F1  8       4Bit    GPIO_INT8
- * F2  8       4Bit    GPIO_INT9
- * F3  4       4Bit    GPIO_INT10
- * G0  8       4Bit    GPIO_INT11
- * G1  3       4Bit    GPIO_INT12
- * G2  7       4Bit    GPIO_INT13
- * G3  7       4Bit    GPIO_INT14
- * H0  8       4Bit    WKUP_INT
- * H1  8       4Bit    WKUP_INT
- * H2  8       4Bit    WKUP_INT
- * H3  8       4Bit    WKUP_INT
- * I   8       4Bit    GPIO_INT15
- * J0  8       4Bit    GPIO_INT16
- * J1  5       4Bit    GPIO_INT17
- * J2  8       4Bit    GPIO_INT18
- * J3  8       4Bit    GPIO_INT19
- * J4  4       4Bit    GPIO_INT20
- * K0  8       4Bit    None
- * K1  6       4Bit    None
- * K2  8       4Bit    None
- * K3  8       4Bit    None
- * L0  8       4Bit    None
- * L1  8       4Bit    None
- * L2  8       4Bit    None
- * L3  8       4Bit    None
- */
-
-static struct s3c_gpio_cfg gpio_cfg = {
-       .set_config     = s3c_gpio_setcfg_s3c64xx_4bit,
-       .set_pull       = s3c_gpio_setpull_updown,
-       .get_pull       = s3c_gpio_getpull_updown,
-};
-
-static struct s3c_gpio_cfg gpio_cfg_eint = {
-       .cfg_eint       = 0xf,
-       .set_config     = s3c_gpio_setcfg_s3c64xx_4bit,
-       .set_pull       = s3c_gpio_setpull_updown,
-       .get_pull       = s3c_gpio_getpull_updown,
-};
-
-static struct s3c_gpio_cfg gpio_cfg_noint = {
-       .set_config     = s3c_gpio_setcfg_s3c64xx_4bit,
-       .set_pull       = s3c_gpio_setpull_updown,
-       .get_pull       = s3c_gpio_getpull_updown,
-};
-
-/*
- * GPIO bank's base address given the index of the bank in the
- * list of all gpio banks.
- */
-#define S5PC100_BANK_BASE(bank_nr)     (S5P_VA_GPIO + ((bank_nr) * 0x20))
-
-/*
- * Following are the gpio banks in S5PC100.
- *
- * The 'config' member when left to NULL, is initialized to the default
- * structure gpio_cfg in the init function below.
- *
- * The 'base' member is also initialized in the init function below.
- * Note: The initialization of 'base' member of s3c_gpio_chip structure
- * uses the above macro and depends on the banks being listed in order here.
- */
-static struct s3c_gpio_chip s5pc100_gpio_chips[] = {
-       {
-               .chip   = {
-                       .base   = S5PC100_GPA0(0),
-                       .ngpio  = S5PC100_GPIO_A0_NR,
-                       .label  = "GPA0",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPA1(0),
-                       .ngpio  = S5PC100_GPIO_A1_NR,
-                       .label  = "GPA1",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPB(0),
-                       .ngpio  = S5PC100_GPIO_B_NR,
-                       .label  = "GPB",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPC(0),
-                       .ngpio  = S5PC100_GPIO_C_NR,
-                       .label  = "GPC",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPD(0),
-                       .ngpio  = S5PC100_GPIO_D_NR,
-                       .label  = "GPD",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPE0(0),
-                       .ngpio  = S5PC100_GPIO_E0_NR,
-                       .label  = "GPE0",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPE1(0),
-                       .ngpio  = S5PC100_GPIO_E1_NR,
-                       .label  = "GPE1",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPF0(0),
-                       .ngpio  = S5PC100_GPIO_F0_NR,
-                       .label  = "GPF0",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPF1(0),
-                       .ngpio  = S5PC100_GPIO_F1_NR,
-                       .label  = "GPF1",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPF2(0),
-                       .ngpio  = S5PC100_GPIO_F2_NR,
-                       .label  = "GPF2",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPF3(0),
-                       .ngpio  = S5PC100_GPIO_F3_NR,
-                       .label  = "GPF3",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPG0(0),
-                       .ngpio  = S5PC100_GPIO_G0_NR,
-                       .label  = "GPG0",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPG1(0),
-                       .ngpio  = S5PC100_GPIO_G1_NR,
-                       .label  = "GPG1",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPG2(0),
-                       .ngpio  = S5PC100_GPIO_G2_NR,
-                       .label  = "GPG2",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPG3(0),
-                       .ngpio  = S5PC100_GPIO_G3_NR,
-                       .label  = "GPG3",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPI(0),
-                       .ngpio  = S5PC100_GPIO_I_NR,
-                       .label  = "GPI",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPJ0(0),
-                       .ngpio  = S5PC100_GPIO_J0_NR,
-                       .label  = "GPJ0",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPJ1(0),
-                       .ngpio  = S5PC100_GPIO_J1_NR,
-                       .label  = "GPJ1",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPJ2(0),
-                       .ngpio  = S5PC100_GPIO_J2_NR,
-                       .label  = "GPJ2",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPJ3(0),
-                       .ngpio  = S5PC100_GPIO_J3_NR,
-                       .label  = "GPJ3",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPJ4(0),
-                       .ngpio  = S5PC100_GPIO_J4_NR,
-                       .label  = "GPJ4",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = S5PC100_GPK0(0),
-                       .ngpio  = S5PC100_GPIO_K0_NR,
-                       .label  = "GPK0",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = S5PC100_GPK1(0),
-                       .ngpio  = S5PC100_GPIO_K1_NR,
-                       .label  = "GPK1",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = S5PC100_GPK2(0),
-                       .ngpio  = S5PC100_GPIO_K2_NR,
-                       .label  = "GPK2",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = S5PC100_GPK3(0),
-                       .ngpio  = S5PC100_GPIO_K3_NR,
-                       .label  = "GPK3",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = S5PC100_GPL0(0),
-                       .ngpio  = S5PC100_GPIO_L0_NR,
-                       .label  = "GPL0",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = S5PC100_GPL1(0),
-                       .ngpio  = S5PC100_GPIO_L1_NR,
-                       .label  = "GPL1",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = S5PC100_GPL2(0),
-                       .ngpio  = S5PC100_GPIO_L2_NR,
-                       .label  = "GPL2",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = S5PC100_GPL3(0),
-                       .ngpio  = S5PC100_GPIO_L3_NR,
-                       .label  = "GPL3",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = S5PC100_GPL4(0),
-                       .ngpio  = S5PC100_GPIO_L4_NR,
-                       .label  = "GPL4",
-               },
-       }, {
-               .base   = (S5P_VA_GPIO + 0xC00),
-               .config = &gpio_cfg_eint,
-               .irq_base = IRQ_EINT(0),
-               .chip   = {
-                       .base   = S5PC100_GPH0(0),
-                       .ngpio  = S5PC100_GPIO_H0_NR,
-                       .label  = "GPH0",
-                       .to_irq = samsung_gpiolib_to_irq,
-               },
-       }, {
-               .base   = (S5P_VA_GPIO + 0xC20),
-               .config = &gpio_cfg_eint,
-               .irq_base = IRQ_EINT(8),
-               .chip   = {
-                       .base   = S5PC100_GPH1(0),
-                       .ngpio  = S5PC100_GPIO_H1_NR,
-                       .label  = "GPH1",
-                       .to_irq = samsung_gpiolib_to_irq,
-               },
-       }, {
-               .base   = (S5P_VA_GPIO + 0xC40),
-               .config = &gpio_cfg_eint,
-               .irq_base = IRQ_EINT(16),
-               .chip   = {
-                       .base   = S5PC100_GPH2(0),
-                       .ngpio  = S5PC100_GPIO_H2_NR,
-                       .label  = "GPH2",
-                       .to_irq = samsung_gpiolib_to_irq,
-               },
-       }, {
-               .base   = (S5P_VA_GPIO + 0xC60),
-               .config = &gpio_cfg_eint,
-               .irq_base = IRQ_EINT(24),
-               .chip   = {
-                       .base   = S5PC100_GPH3(0),
-                       .ngpio  = S5PC100_GPIO_H3_NR,
-                       .label  = "GPH3",
-                       .to_irq = samsung_gpiolib_to_irq,
-               },
-       },
-};
-
-static __init int s5pc100_gpiolib_init(void)
-{
-       struct s3c_gpio_chip *chip = s5pc100_gpio_chips;
-       int nr_chips = ARRAY_SIZE(s5pc100_gpio_chips);
-       int gpioint_group = 0;
-       int i;
-
-       for (i = 0; i < nr_chips; i++, chip++) {
-               if (chip->config == NULL) {
-                       chip->config = &gpio_cfg;
-                       chip->group = gpioint_group++;
-               }
-               if (chip->base == NULL)
-                       chip->base = S5PC100_BANK_BASE(i);
-       }
-
-       samsung_gpiolib_add_4bit_chips(s5pc100_gpio_chips, nr_chips);
-       s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
-
-       return 0;
-}
-core_initcall(s5pc100_gpiolib_init);
diff --git a/drivers/gpio/gpio-s5pv210.c b/drivers/gpio/gpio-s5pv210.c
deleted file mode 100644 (file)
index eb12f16..0000000
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * S5PV210 - GPIOlib support
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <plat/gpio-core.h>
-#include <plat/gpio-cfg.h>
-#include <plat/gpio-cfg-helpers.h>
-#include <mach/map.h>
-
-static struct s3c_gpio_cfg gpio_cfg = {
-       .set_config     = s3c_gpio_setcfg_s3c64xx_4bit,
-       .set_pull       = s3c_gpio_setpull_updown,
-       .get_pull       = s3c_gpio_getpull_updown,
-};
-
-static struct s3c_gpio_cfg gpio_cfg_noint = {
-       .set_config     = s3c_gpio_setcfg_s3c64xx_4bit,
-       .set_pull       = s3c_gpio_setpull_updown,
-       .get_pull       = s3c_gpio_getpull_updown,
-};
-
-/* GPIO bank's base address given the index of the bank in the
- * list of all gpio banks.
- */
-#define S5PV210_BANK_BASE(bank_nr)     (S5P_VA_GPIO + ((bank_nr) * 0x20))
-
-/*
- * Following are the gpio banks in v210.
- *
- * The 'config' member when left to NULL, is initialized to the default
- * structure gpio_cfg in the init function below.
- *
- * The 'base' member is also initialized in the init function below.
- * Note: The initialization of 'base' member of s3c_gpio_chip structure
- * uses the above macro and depends on the banks being listed in order here.
- */
-static struct s3c_gpio_chip s5pv210_gpio_4bit[] = {
-       {
-               .chip   = {
-                       .base   = S5PV210_GPA0(0),
-                       .ngpio  = S5PV210_GPIO_A0_NR,
-                       .label  = "GPA0",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPA1(0),
-                       .ngpio  = S5PV210_GPIO_A1_NR,
-                       .label  = "GPA1",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPB(0),
-                       .ngpio  = S5PV210_GPIO_B_NR,
-                       .label  = "GPB",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPC0(0),
-                       .ngpio  = S5PV210_GPIO_C0_NR,
-                       .label  = "GPC0",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPC1(0),
-                       .ngpio  = S5PV210_GPIO_C1_NR,
-                       .label  = "GPC1",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPD0(0),
-                       .ngpio  = S5PV210_GPIO_D0_NR,
-                       .label  = "GPD0",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPD1(0),
-                       .ngpio  = S5PV210_GPIO_D1_NR,
-                       .label  = "GPD1",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPE0(0),
-                       .ngpio  = S5PV210_GPIO_E0_NR,
-                       .label  = "GPE0",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPE1(0),
-                       .ngpio  = S5PV210_GPIO_E1_NR,
-                       .label  = "GPE1",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPF0(0),
-                       .ngpio  = S5PV210_GPIO_F0_NR,
-                       .label  = "GPF0",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPF1(0),
-                       .ngpio  = S5PV210_GPIO_F1_NR,
-                       .label  = "GPF1",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPF2(0),
-                       .ngpio  = S5PV210_GPIO_F2_NR,
-                       .label  = "GPF2",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPF3(0),
-                       .ngpio  = S5PV210_GPIO_F3_NR,
-                       .label  = "GPF3",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPG0(0),
-                       .ngpio  = S5PV210_GPIO_G0_NR,
-                       .label  = "GPG0",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPG1(0),
-                       .ngpio  = S5PV210_GPIO_G1_NR,
-                       .label  = "GPG1",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPG2(0),
-                       .ngpio  = S5PV210_GPIO_G2_NR,
-                       .label  = "GPG2",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPG3(0),
-                       .ngpio  = S5PV210_GPIO_G3_NR,
-                       .label  = "GPG3",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = S5PV210_GPI(0),
-                       .ngpio  = S5PV210_GPIO_I_NR,
-                       .label  = "GPI",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPJ0(0),
-                       .ngpio  = S5PV210_GPIO_J0_NR,
-                       .label  = "GPJ0",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPJ1(0),
-                       .ngpio  = S5PV210_GPIO_J1_NR,
-                       .label  = "GPJ1",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPJ2(0),
-                       .ngpio  = S5PV210_GPIO_J2_NR,
-                       .label  = "GPJ2",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPJ3(0),
-                       .ngpio  = S5PV210_GPIO_J3_NR,
-                       .label  = "GPJ3",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPJ4(0),
-                       .ngpio  = S5PV210_GPIO_J4_NR,
-                       .label  = "GPJ4",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = S5PV210_MP01(0),
-                       .ngpio  = S5PV210_GPIO_MP01_NR,
-                       .label  = "MP01",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = S5PV210_MP02(0),
-                       .ngpio  = S5PV210_GPIO_MP02_NR,
-                       .label  = "MP02",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = S5PV210_MP03(0),
-                       .ngpio  = S5PV210_GPIO_MP03_NR,
-                       .label  = "MP03",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = S5PV210_MP04(0),
-                       .ngpio  = S5PV210_GPIO_MP04_NR,
-                       .label  = "MP04",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = S5PV210_MP05(0),
-                       .ngpio  = S5PV210_GPIO_MP05_NR,
-                       .label  = "MP05",
-               },
-       }, {
-               .base   = (S5P_VA_GPIO + 0xC00),
-               .config = &gpio_cfg_noint,
-               .irq_base = IRQ_EINT(0),
-               .chip   = {
-                       .base   = S5PV210_GPH0(0),
-                       .ngpio  = S5PV210_GPIO_H0_NR,
-                       .label  = "GPH0",
-                       .to_irq = samsung_gpiolib_to_irq,
-               },
-       }, {
-               .base   = (S5P_VA_GPIO + 0xC20),
-               .config = &gpio_cfg_noint,
-               .irq_base = IRQ_EINT(8),
-               .chip   = {
-                       .base   = S5PV210_GPH1(0),
-                       .ngpio  = S5PV210_GPIO_H1_NR,
-                       .label  = "GPH1",
-                       .to_irq = samsung_gpiolib_to_irq,
-               },
-       }, {
-               .base   = (S5P_VA_GPIO + 0xC40),
-               .config = &gpio_cfg_noint,
-               .irq_base = IRQ_EINT(16),
-               .chip   = {
-                       .base   = S5PV210_GPH2(0),
-                       .ngpio  = S5PV210_GPIO_H2_NR,
-                       .label  = "GPH2",
-                       .to_irq = samsung_gpiolib_to_irq,
-               },
-       }, {
-               .base   = (S5P_VA_GPIO + 0xC60),
-               .config = &gpio_cfg_noint,
-               .irq_base = IRQ_EINT(24),
-               .chip   = {
-                       .base   = S5PV210_GPH3(0),
-                       .ngpio  = S5PV210_GPIO_H3_NR,
-                       .label  = "GPH3",
-                       .to_irq = samsung_gpiolib_to_irq,
-               },
-       },
-};
-
-static __init int s5pv210_gpiolib_init(void)
-{
-       struct s3c_gpio_chip *chip = s5pv210_gpio_4bit;
-       int nr_chips = ARRAY_SIZE(s5pv210_gpio_4bit);
-       int gpioint_group = 0;
-       int i = 0;
-
-       for (i = 0; i < nr_chips; i++, chip++) {
-               if (chip->config == NULL) {
-                       chip->config = &gpio_cfg;
-                       chip->group = gpioint_group++;
-               }
-               if (chip->base == NULL)
-                       chip->base = S5PV210_BANK_BASE(i);
-       }
-
-       samsung_gpiolib_add_4bit_chips(s5pv210_gpio_4bit, nr_chips);
-       s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
-
-       return 0;
-}
-core_initcall(s5pv210_gpiolib_init);
diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c
new file mode 100644 (file)
index 0000000..8662518
--- /dev/null
@@ -0,0 +1,2712 @@
+/*
+ * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *      Ben Dooks <ben@simtec.co.uk>
+ *      http://armlinux.simtec.co.uk/
+ *
+ * SAMSUNG - GPIOlib 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/kernel.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/sysdev.h>
+#include <linux/ioport.h>
+
+#include <asm/irq.h>
+
+#include <mach/hardware.h>
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+#include <mach/regs-gpio.h>
+
+#include <plat/cpu.h>
+#include <plat/gpio-core.h>
+#include <plat/gpio-cfg.h>
+#include <plat/gpio-cfg-helpers.h>
+#include <plat/gpio-fns.h>
+#include <plat/pm.h>
+
+#ifndef DEBUG_GPIO
+#define gpio_dbg(x...) do { } while (0)
+#else
+#define gpio_dbg(x...) printk(KERN_DEBUG x)
+#endif
+
+int samsung_gpio_setpull_updown(struct samsung_gpio_chip *chip,
+                               unsigned int off, samsung_gpio_pull_t pull)
+{
+       void __iomem *reg = chip->base + 0x08;
+       int shift = off * 2;
+       u32 pup;
+
+       pup = __raw_readl(reg);
+       pup &= ~(3 << shift);
+       pup |= pull << shift;
+       __raw_writel(pup, reg);
+
+       return 0;
+}
+
+samsung_gpio_pull_t samsung_gpio_getpull_updown(struct samsung_gpio_chip *chip,
+                                               unsigned int off)
+{
+       void __iomem *reg = chip->base + 0x08;
+       int shift = off * 2;
+       u32 pup = __raw_readl(reg);
+
+       pup >>= shift;
+       pup &= 0x3;
+
+       return (__force samsung_gpio_pull_t)pup;
+}
+
+int s3c2443_gpio_setpull(struct samsung_gpio_chip *chip,
+                        unsigned int off, samsung_gpio_pull_t pull)
+{
+       switch (pull) {
+       case S3C_GPIO_PULL_NONE:
+               pull = 0x01;
+               break;
+       case S3C_GPIO_PULL_UP:
+               pull = 0x00;
+               break;
+       case S3C_GPIO_PULL_DOWN:
+               pull = 0x02;
+               break;
+       }
+       return samsung_gpio_setpull_updown(chip, off, pull);
+}
+
+samsung_gpio_pull_t s3c2443_gpio_getpull(struct samsung_gpio_chip *chip,
+                                        unsigned int off)
+{
+       samsung_gpio_pull_t pull;
+
+       pull = samsung_gpio_getpull_updown(chip, off);
+
+       switch (pull) {
+       case 0x00:
+               pull = S3C_GPIO_PULL_UP;
+               break;
+       case 0x01:
+       case 0x03:
+               pull = S3C_GPIO_PULL_NONE;
+               break;
+       case 0x02:
+               pull = S3C_GPIO_PULL_DOWN;
+               break;
+       }
+
+       return pull;
+}
+
+static int s3c24xx_gpio_setpull_1(struct samsung_gpio_chip *chip,
+                                 unsigned int off, samsung_gpio_pull_t pull,
+                                 samsung_gpio_pull_t updown)
+{
+       void __iomem *reg = chip->base + 0x08;
+       u32 pup = __raw_readl(reg);
+
+       if (pull == updown)
+               pup &= ~(1 << off);
+       else if (pull == S3C_GPIO_PULL_NONE)
+               pup |= (1 << off);
+       else
+               return -EINVAL;
+
+       __raw_writel(pup, reg);
+       return 0;
+}
+
+static samsung_gpio_pull_t s3c24xx_gpio_getpull_1(struct samsung_gpio_chip *chip,
+                                                 unsigned int off,
+                                                 samsung_gpio_pull_t updown)
+{
+       void __iomem *reg = chip->base + 0x08;
+       u32 pup = __raw_readl(reg);
+
+       pup &= (1 << off);
+       return pup ? S3C_GPIO_PULL_NONE : updown;
+}
+
+samsung_gpio_pull_t s3c24xx_gpio_getpull_1up(struct samsung_gpio_chip *chip,
+                                            unsigned int off)
+{
+       return s3c24xx_gpio_getpull_1(chip, off, S3C_GPIO_PULL_UP);
+}
+
+int s3c24xx_gpio_setpull_1up(struct samsung_gpio_chip *chip,
+                            unsigned int off, samsung_gpio_pull_t pull)
+{
+       return s3c24xx_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_UP);
+}
+
+samsung_gpio_pull_t s3c24xx_gpio_getpull_1down(struct samsung_gpio_chip *chip,
+                                              unsigned int off)
+{
+       return s3c24xx_gpio_getpull_1(chip, off, S3C_GPIO_PULL_DOWN);
+}
+
+int s3c24xx_gpio_setpull_1down(struct samsung_gpio_chip *chip,
+                              unsigned int off, samsung_gpio_pull_t pull)
+{
+       return s3c24xx_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_DOWN);
+}
+
+static int exynos4_gpio_setpull(struct samsung_gpio_chip *chip,
+                               unsigned int off, samsung_gpio_pull_t pull)
+{
+       if (pull == S3C_GPIO_PULL_UP)
+               pull = 3;
+
+       return samsung_gpio_setpull_updown(chip, off, pull);
+}
+
+static samsung_gpio_pull_t exynos4_gpio_getpull(struct samsung_gpio_chip *chip,
+                                               unsigned int off)
+{
+       samsung_gpio_pull_t pull;
+
+       pull = samsung_gpio_getpull_updown(chip, off);
+
+       if (pull == 3)
+               pull = S3C_GPIO_PULL_UP;
+
+       return pull;
+}
+
+/*
+ * samsung_gpio_setcfg_2bit - Samsung 2bit style GPIO configuration.
+ * @chip: The gpio chip that is being configured.
+ * @off: The offset for the GPIO being configured.
+ * @cfg: The configuration value to set.
+ *
+ * This helper deal with the GPIO cases where the control register
+ * has two bits of configuration per gpio, which have the following
+ * functions:
+ *     00 = input
+ *     01 = output
+ *     1x = special function
+ */
+
+static int samsung_gpio_setcfg_2bit(struct samsung_gpio_chip *chip,
+                                   unsigned int off, unsigned int cfg)
+{
+       void __iomem *reg = chip->base;
+       unsigned int shift = off * 2;
+       u32 con;
+
+       if (samsung_gpio_is_cfg_special(cfg)) {
+               cfg &= 0xf;
+               if (cfg > 3)
+                       return -EINVAL;
+
+               cfg <<= shift;
+       }
+
+       con = __raw_readl(reg);
+       con &= ~(0x3 << shift);
+       con |= cfg;
+       __raw_writel(con, reg);
+
+       return 0;
+}
+
+/*
+ * samsung_gpio_getcfg_2bit - Samsung 2bit style GPIO configuration read.
+ * @chip: The gpio chip that is being configured.
+ * @off: The offset for the GPIO being configured.
+ *
+ * The reverse of samsung_gpio_setcfg_2bit(). Will return a value whicg
+ * could be directly passed back to samsung_gpio_setcfg_2bit(), from the
+ * S3C_GPIO_SPECIAL() macro.
+ */
+
+static unsigned int samsung_gpio_getcfg_2bit(struct samsung_gpio_chip *chip,
+                                            unsigned int off)
+{
+       u32 con;
+
+       con = __raw_readl(chip->base);
+       con >>= off * 2;
+       con &= 3;
+
+       /* this conversion works for IN and OUT as well as special mode */
+       return S3C_GPIO_SPECIAL(con);
+}
+
+/*
+ * samsung_gpio_setcfg_4bit - Samsung 4bit single register GPIO config.
+ * @chip: The gpio chip that is being configured.
+ * @off: The offset for the GPIO being configured.
+ * @cfg: The configuration value to set.
+ *
+ * This helper deal with the GPIO cases where the control register has 4 bits
+ * of control per GPIO, generally in the form of:
+ *     0000 = Input
+ *     0001 = Output
+ *     others = Special functions (dependent on bank)
+ *
+ * Note, since the code to deal with the case where there are two control
+ * registers instead of one, we do not have a separate set of functions for
+ * each case.
+ */
+
+static int samsung_gpio_setcfg_4bit(struct samsung_gpio_chip *chip,
+                                   unsigned int off, unsigned int cfg)
+{
+       void __iomem *reg = chip->base;
+       unsigned int shift = (off & 7) * 4;
+       u32 con;
+
+       if (off < 8 && chip->chip.ngpio > 8)
+               reg -= 4;
+
+       if (samsung_gpio_is_cfg_special(cfg)) {
+               cfg &= 0xf;
+               cfg <<= shift;
+       }
+
+       con = __raw_readl(reg);
+       con &= ~(0xf << shift);
+       con |= cfg;
+       __raw_writel(con, reg);
+
+       return 0;
+}
+
+/*
+ * samsung_gpio_getcfg_4bit - Samsung 4bit single register GPIO config read.
+ * @chip: The gpio chip that is being configured.
+ * @off: The offset for the GPIO being configured.
+ *
+ * The reverse of samsung_gpio_setcfg_4bit(), turning a gpio configuration
+ * register setting into a value the software can use, such as could be passed
+ * to samsung_gpio_setcfg_4bit().
+ *
+ * @sa samsung_gpio_getcfg_2bit
+ */
+
+static unsigned samsung_gpio_getcfg_4bit(struct samsung_gpio_chip *chip,
+                                        unsigned int off)
+{
+       void __iomem *reg = chip->base;
+       unsigned int shift = (off & 7) * 4;
+       u32 con;
+
+       if (off < 8 && chip->chip.ngpio > 8)
+               reg -= 4;
+
+       con = __raw_readl(reg);
+       con >>= shift;
+       con &= 0xf;
+
+       /* this conversion works for IN and OUT as well as special mode */
+       return S3C_GPIO_SPECIAL(con);
+}
+
+#ifdef CONFIG_PLAT_S3C24XX
+/*
+ * s3c24xx_gpio_setcfg_abank - S3C24XX style GPIO configuration (Bank A)
+ * @chip: The gpio chip that is being configured.
+ * @off: The offset for the GPIO being configured.
+ * @cfg: The configuration value to set.
+ *
+ * This helper deal with the GPIO cases where the control register
+ * has one bit of configuration for the gpio, where setting the bit
+ * means the pin is in special function mode and unset means output.
+ */
+
+static int s3c24xx_gpio_setcfg_abank(struct samsung_gpio_chip *chip,
+                                    unsigned int off, unsigned int cfg)
+{
+       void __iomem *reg = chip->base;
+       unsigned int shift = off;
+       u32 con;
+
+       if (samsung_gpio_is_cfg_special(cfg)) {
+               cfg &= 0xf;
+
+               /* Map output to 0, and SFN2 to 1 */
+               cfg -= 1;
+               if (cfg > 1)
+                       return -EINVAL;
+
+               cfg <<= shift;
+       }
+
+       con = __raw_readl(reg);
+       con &= ~(0x1 << shift);
+       con |= cfg;
+       __raw_writel(con, reg);
+
+       return 0;
+}
+
+/*
+ * s3c24xx_gpio_getcfg_abank - S3C24XX style GPIO configuration read (Bank A)
+ * @chip: The gpio chip that is being configured.
+ * @off: The offset for the GPIO being configured.
+ *
+ * The reverse of s3c24xx_gpio_setcfg_abank() turning an GPIO into a usable
+ * GPIO configuration value.
+ *
+ * @sa samsung_gpio_getcfg_2bit
+ * @sa samsung_gpio_getcfg_4bit
+ */
+
+static unsigned s3c24xx_gpio_getcfg_abank(struct samsung_gpio_chip *chip,
+                                         unsigned int off)
+{
+       u32 con;
+
+       con = __raw_readl(chip->base);
+       con >>= off;
+       con &= 1;
+       con++;
+
+       return S3C_GPIO_SFN(con);
+}
+#endif
+
+#if defined(CONFIG_CPU_S5P6440) || defined(CONFIG_CPU_S5P6450)
+static int s5p64x0_gpio_setcfg_rbank(struct samsung_gpio_chip *chip,
+                                    unsigned int off, unsigned int cfg)
+{
+       void __iomem *reg = chip->base;
+       unsigned int shift;
+       u32 con;
+
+       switch (off) {
+       case 0:
+       case 1:
+       case 2:
+       case 3:
+       case 4:
+       case 5:
+               shift = (off & 7) * 4;
+               reg -= 4;
+               break;
+       case 6:
+               shift = ((off + 1) & 7) * 4;
+               reg -= 4;
+       default:
+               shift = ((off + 1) & 7) * 4;
+               break;
+       }
+
+       if (samsung_gpio_is_cfg_special(cfg)) {
+               cfg &= 0xf;
+               cfg <<= shift;
+       }
+
+       con = __raw_readl(reg);
+       con &= ~(0xf << shift);
+       con |= cfg;
+       __raw_writel(con, reg);
+
+       return 0;
+}
+#endif
+
+static void __init samsung_gpiolib_set_cfg(struct samsung_gpio_cfg *chipcfg,
+                                          int nr_chips)
+{
+       for (; nr_chips > 0; nr_chips--, chipcfg++) {
+               if (!chipcfg->set_config)
+                       chipcfg->set_config = samsung_gpio_setcfg_4bit;
+               if (!chipcfg->get_config)
+                       chipcfg->get_config = samsung_gpio_getcfg_4bit;
+               if (!chipcfg->set_pull)
+                       chipcfg->set_pull = samsung_gpio_setpull_updown;
+               if (!chipcfg->get_pull)
+                       chipcfg->get_pull = samsung_gpio_getpull_updown;
+       }
+}
+
+struct samsung_gpio_cfg s3c24xx_gpiocfg_default = {
+       .set_config     = samsung_gpio_setcfg_2bit,
+       .get_config     = samsung_gpio_getcfg_2bit,
+};
+
+#ifdef CONFIG_PLAT_S3C24XX
+static struct samsung_gpio_cfg s3c24xx_gpiocfg_banka = {
+       .set_config     = s3c24xx_gpio_setcfg_abank,
+       .get_config     = s3c24xx_gpio_getcfg_abank,
+};
+#endif
+
+static struct samsung_gpio_cfg exynos4_gpio_cfg = {
+       .set_pull       = exynos4_gpio_setpull,
+       .get_pull       = exynos4_gpio_getpull,
+       .set_config     = samsung_gpio_setcfg_4bit,
+       .get_config     = samsung_gpio_getcfg_4bit,
+};
+
+#if defined(CONFIG_CPU_S5P6440) || defined(CONFIG_CPU_S5P6450)
+static struct samsung_gpio_cfg s5p64x0_gpio_cfg_rbank = {
+       .cfg_eint       = 0x3,
+       .set_config     = s5p64x0_gpio_setcfg_rbank,
+       .get_config     = samsung_gpio_getcfg_4bit,
+       .set_pull       = samsung_gpio_setpull_updown,
+       .get_pull       = samsung_gpio_getpull_updown,
+};
+#endif
+
+static struct samsung_gpio_cfg samsung_gpio_cfgs[] = {
+       {
+               .cfg_eint       = 0x0,
+       }, {
+               .cfg_eint       = 0x3,
+       }, {
+               .cfg_eint       = 0x7,
+       }, {
+               .cfg_eint       = 0xF,
+       }, {
+               .cfg_eint       = 0x0,
+               .set_config     = samsung_gpio_setcfg_2bit,
+               .get_config     = samsung_gpio_getcfg_2bit,
+       }, {
+               .cfg_eint       = 0x2,
+               .set_config     = samsung_gpio_setcfg_2bit,
+               .get_config     = samsung_gpio_getcfg_2bit,
+       }, {
+               .cfg_eint       = 0x3,
+               .set_config     = samsung_gpio_setcfg_2bit,
+               .get_config     = samsung_gpio_getcfg_2bit,
+       }, {
+               .set_config     = samsung_gpio_setcfg_2bit,
+               .get_config     = samsung_gpio_getcfg_2bit,
+       }, {
+               .set_pull       = exynos4_gpio_setpull,
+               .get_pull       = exynos4_gpio_getpull,
+       }, {
+               .cfg_eint       = 0x3,
+               .set_pull       = exynos4_gpio_setpull,
+               .get_pull       = exynos4_gpio_getpull,
+       }
+};
+
+/*
+ * Default routines for controlling GPIO, based on the original S3C24XX
+ * GPIO functions which deal with the case where each gpio bank of the
+ * chip is as following:
+ *
+ * base + 0x00: Control register, 2 bits per gpio
+ *             gpio n: 2 bits starting at (2*n)
+ *             00 = input, 01 = output, others mean special-function
+ * base + 0x04: Data register, 1 bit per gpio
+ *             bit n: data bit n
+*/
+
+static int samsung_gpiolib_2bit_input(struct gpio_chip *chip, unsigned offset)
+{
+       struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
+       void __iomem *base = ourchip->base;
+       unsigned long flags;
+       unsigned long con;
+
+       samsung_gpio_lock(ourchip, flags);
+
+       con = __raw_readl(base + 0x00);
+       con &= ~(3 << (offset * 2));
+
+       __raw_writel(con, base + 0x00);
+
+       samsung_gpio_unlock(ourchip, flags);
+       return 0;
+}
+
+static int samsung_gpiolib_2bit_output(struct gpio_chip *chip,
+                                      unsigned offset, int value)
+{
+       struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
+       void __iomem *base = ourchip->base;
+       unsigned long flags;
+       unsigned long dat;
+       unsigned long con;
+
+       samsung_gpio_lock(ourchip, flags);
+
+       dat = __raw_readl(base + 0x04);
+       dat &= ~(1 << offset);
+       if (value)
+               dat |= 1 << offset;
+       __raw_writel(dat, base + 0x04);
+
+       con = __raw_readl(base + 0x00);
+       con &= ~(3 << (offset * 2));
+       con |= 1 << (offset * 2);
+
+       __raw_writel(con, base + 0x00);
+       __raw_writel(dat, base + 0x04);
+
+       samsung_gpio_unlock(ourchip, flags);
+       return 0;
+}
+
+/*
+ * The samsung_gpiolib_4bit routines are to control the gpio banks where
+ * the gpio configuration register (GPxCON) has 4 bits per GPIO, as the
+ * following example:
+ *
+ * base + 0x00: Control register, 4 bits per gpio
+ *             gpio n: 4 bits starting at (4*n)
+ *             0000 = input, 0001 = output, others mean special-function
+ * base + 0x04: Data register, 1 bit per gpio
+ *             bit n: data bit n
+ *
+ * Note, since the data register is one bit per gpio and is at base + 0x4
+ * we can use samsung_gpiolib_get and samsung_gpiolib_set to change the
+ * state of the output.
+ */
+
+static int samsung_gpiolib_4bit_input(struct gpio_chip *chip,
+                                     unsigned int offset)
+{
+       struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
+       void __iomem *base = ourchip->base;
+       unsigned long con;
+
+       con = __raw_readl(base + GPIOCON_OFF);
+       con &= ~(0xf << con_4bit_shift(offset));
+       __raw_writel(con, base + GPIOCON_OFF);
+
+       gpio_dbg("%s: %p: CON now %08lx\n", __func__, base, con);
+
+       return 0;
+}
+
+static int samsung_gpiolib_4bit_output(struct gpio_chip *chip,
+                                      unsigned int offset, int value)
+{
+       struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
+       void __iomem *base = ourchip->base;
+       unsigned long con;
+       unsigned long dat;
+
+       con = __raw_readl(base + GPIOCON_OFF);
+       con &= ~(0xf << con_4bit_shift(offset));
+       con |= 0x1 << con_4bit_shift(offset);
+
+       dat = __raw_readl(base + GPIODAT_OFF);
+
+       if (value)
+               dat |= 1 << offset;
+       else
+               dat &= ~(1 << offset);
+
+       __raw_writel(dat, base + GPIODAT_OFF);
+       __raw_writel(con, base + GPIOCON_OFF);
+       __raw_writel(dat, base + GPIODAT_OFF);
+
+       gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
+
+       return 0;
+}
+
+/*
+ * The next set of routines are for the case where the GPIO configuration
+ * registers are 4 bits per GPIO but there is more than one register (the
+ * bank has more than 8 GPIOs.
+ *
+ * This case is the similar to the 4 bit case, but the registers are as
+ * follows:
+ *
+ * base + 0x00: Control register, 4 bits per gpio (lower 8 GPIOs)
+ *             gpio n: 4 bits starting at (4*n)
+ *             0000 = input, 0001 = output, others mean special-function
+ * base + 0x04: Control register, 4 bits per gpio (up to 8 additions GPIOs)
+ *             gpio n: 4 bits starting at (4*n)
+ *             0000 = input, 0001 = output, others mean special-function
+ * base + 0x08: Data register, 1 bit per gpio
+ *             bit n: data bit n
+ *
+ * To allow us to use the samsung_gpiolib_get and samsung_gpiolib_set
+ * routines we store the 'base + 0x4' address so that these routines see
+ * the data register at ourchip->base + 0x04.
+ */
+
+static int samsung_gpiolib_4bit2_input(struct gpio_chip *chip,
+                                      unsigned int offset)
+{
+       struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
+       void __iomem *base = ourchip->base;
+       void __iomem *regcon = base;
+       unsigned long con;
+
+       if (offset > 7)
+               offset -= 8;
+       else
+               regcon -= 4;
+
+       con = __raw_readl(regcon);
+       con &= ~(0xf << con_4bit_shift(offset));
+       __raw_writel(con, regcon);
+
+       gpio_dbg("%s: %p: CON %08lx\n", __func__, base, con);
+
+       return 0;
+}
+
+static int samsung_gpiolib_4bit2_output(struct gpio_chip *chip,
+                                       unsigned int offset, int value)
+{
+       struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
+       void __iomem *base = ourchip->base;
+       void __iomem *regcon = base;
+       unsigned long con;
+       unsigned long dat;
+       unsigned con_offset = offset;
+
+       if (con_offset > 7)
+               con_offset -= 8;
+       else
+               regcon -= 4;
+
+       con = __raw_readl(regcon);
+       con &= ~(0xf << con_4bit_shift(con_offset));
+       con |= 0x1 << con_4bit_shift(con_offset);
+
+       dat = __raw_readl(base + GPIODAT_OFF);
+
+       if (value)
+               dat |= 1 << offset;
+       else
+               dat &= ~(1 << offset);
+
+       __raw_writel(dat, base + GPIODAT_OFF);
+       __raw_writel(con, regcon);
+       __raw_writel(dat, base + GPIODAT_OFF);
+
+       gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
+
+       return 0;
+}
+
+#ifdef CONFIG_PLAT_S3C24XX
+/* The next set of routines are for the case of s3c24xx bank a */
+
+static int s3c24xx_gpiolib_banka_input(struct gpio_chip *chip, unsigned offset)
+{
+       return -EINVAL;
+}
+
+static int s3c24xx_gpiolib_banka_output(struct gpio_chip *chip,
+                                       unsigned offset, int value)
+{
+       struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
+       void __iomem *base = ourchip->base;
+       unsigned long flags;
+       unsigned long dat;
+       unsigned long con;
+
+       local_irq_save(flags);
+
+       con = __raw_readl(base + 0x00);
+       dat = __raw_readl(base + 0x04);
+
+       dat &= ~(1 << offset);
+       if (value)
+               dat |= 1 << offset;
+
+       __raw_writel(dat, base + 0x04);
+
+       con &= ~(1 << offset);
+
+       __raw_writel(con, base + 0x00);
+       __raw_writel(dat, base + 0x04);
+
+       local_irq_restore(flags);
+       return 0;
+}
+#endif
+
+/* The next set of routines are for the case of s5p64x0 bank r */
+
+static int s5p64x0_gpiolib_rbank_input(struct gpio_chip *chip,
+                                      unsigned int offset)
+{
+       struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
+       void __iomem *base = ourchip->base;
+       void __iomem *regcon = base;
+       unsigned long con;
+       unsigned long flags;
+
+       switch (offset) {
+       case 6:
+               offset += 1;
+       case 0:
+       case 1:
+       case 2:
+       case 3:
+       case 4:
+       case 5:
+               regcon -= 4;
+               break;
+       default:
+               offset -= 7;
+               break;
+       }
+
+       samsung_gpio_lock(ourchip, flags);
+
+       con = __raw_readl(regcon);
+       con &= ~(0xf << con_4bit_shift(offset));
+       __raw_writel(con, regcon);
+
+       samsung_gpio_unlock(ourchip, flags);
+
+       return 0;
+}
+
+static int s5p64x0_gpiolib_rbank_output(struct gpio_chip *chip,
+                                       unsigned int offset, int value)
+{
+       struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
+       void __iomem *base = ourchip->base;
+       void __iomem *regcon = base;
+       unsigned long con;
+       unsigned long dat;
+       unsigned long flags;
+       unsigned con_offset  = offset;
+
+       switch (con_offset) {
+       case 6:
+               con_offset += 1;
+       case 0:
+       case 1:
+       case 2:
+       case 3:
+       case 4:
+       case 5:
+               regcon -= 4;
+               break;
+       default:
+               con_offset -= 7;
+               break;
+       }
+
+       samsung_gpio_lock(ourchip, flags);
+
+       con = __raw_readl(regcon);
+       con &= ~(0xf << con_4bit_shift(con_offset));
+       con |= 0x1 << con_4bit_shift(con_offset);
+
+       dat = __raw_readl(base + GPIODAT_OFF);
+       if (value)
+               dat |= 1 << offset;
+       else
+               dat &= ~(1 << offset);
+
+       __raw_writel(con, regcon);
+       __raw_writel(dat, base + GPIODAT_OFF);
+
+       samsung_gpio_unlock(ourchip, flags);
+
+       return 0;
+}
+
+static void samsung_gpiolib_set(struct gpio_chip *chip,
+                               unsigned offset, int value)
+{
+       struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
+       void __iomem *base = ourchip->base;
+       unsigned long flags;
+       unsigned long dat;
+
+       samsung_gpio_lock(ourchip, flags);
+
+       dat = __raw_readl(base + 0x04);
+       dat &= ~(1 << offset);
+       if (value)
+               dat |= 1 << offset;
+       __raw_writel(dat, base + 0x04);
+
+       samsung_gpio_unlock(ourchip, flags);
+}
+
+static int samsung_gpiolib_get(struct gpio_chip *chip, unsigned offset)
+{
+       struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
+       unsigned long val;
+
+       val = __raw_readl(ourchip->base + 0x04);
+       val >>= offset;
+       val &= 1;
+
+       return val;
+}
+
+/*
+ * CONFIG_S3C_GPIO_TRACK enables the tracking of the s3c specific gpios
+ * for use with the configuration calls, and other parts of the s3c gpiolib
+ * support code.
+ *
+ * Not all s3c support code will need this, as some configurations of cpu
+ * may only support one or two different configuration options and have an
+ * easy gpio to samsung_gpio_chip mapping function. If this is the case, then
+ * the machine support file should provide its own samsung_gpiolib_getchip()
+ * and any other necessary functions.
+ */
+
+#ifdef CONFIG_S3C_GPIO_TRACK
+struct samsung_gpio_chip *s3c_gpios[S3C_GPIO_END];
+
+static __init void s3c_gpiolib_track(struct samsung_gpio_chip *chip)
+{
+       unsigned int gpn;
+       int i;
+
+       gpn = chip->chip.base;
+       for (i = 0; i < chip->chip.ngpio; i++, gpn++) {
+               BUG_ON(gpn >= ARRAY_SIZE(s3c_gpios));
+               s3c_gpios[gpn] = chip;
+       }
+}
+#endif /* CONFIG_S3C_GPIO_TRACK */
+
+/*
+ * samsung_gpiolib_add() - add the Samsung gpio_chip.
+ * @chip: The chip to register
+ *
+ * This is a wrapper to gpiochip_add() that takes our specific gpio chip
+ * information and makes the necessary alterations for the platform and
+ * notes the information for use with the configuration systems and any
+ * other parts of the system.
+ */
+
+static void __init samsung_gpiolib_add(struct samsung_gpio_chip *chip)
+{
+       struct gpio_chip *gc = &chip->chip;
+       int ret;
+
+       BUG_ON(!chip->base);
+       BUG_ON(!gc->label);
+       BUG_ON(!gc->ngpio);
+
+       spin_lock_init(&chip->lock);
+
+       if (!gc->direction_input)
+               gc->direction_input = samsung_gpiolib_2bit_input;
+       if (!gc->direction_output)
+               gc->direction_output = samsung_gpiolib_2bit_output;
+       if (!gc->set)
+               gc->set = samsung_gpiolib_set;
+       if (!gc->get)
+               gc->get = samsung_gpiolib_get;
+
+#ifdef CONFIG_PM
+       if (chip->pm != NULL) {
+               if (!chip->pm->save || !chip->pm->resume)
+                       printk(KERN_ERR "gpio: %s has missing PM functions\n",
+                              gc->label);
+       } else
+               printk(KERN_ERR "gpio: %s has no PM function\n", gc->label);
+#endif
+
+       /* gpiochip_add() prints own failure message on error. */
+       ret = gpiochip_add(gc);
+       if (ret >= 0)
+               s3c_gpiolib_track(chip);
+}
+
+static void __init s3c24xx_gpiolib_add_chips(struct samsung_gpio_chip *chip,
+                                            int nr_chips, void __iomem *base)
+{
+       int i;
+       struct gpio_chip *gc = &chip->chip;
+
+       for (i = 0 ; i < nr_chips; i++, chip++) {
+               /* skip banks not present on SoC */
+               if (chip->chip.base >= S3C_GPIO_END)
+                       continue;
+
+               if (!chip->config)
+                       chip->config = &s3c24xx_gpiocfg_default;
+               if (!chip->pm)
+                       chip->pm = __gpio_pm(&samsung_gpio_pm_2bit);
+               if ((base != NULL) && (chip->base == NULL))
+                       chip->base = base + ((i) * 0x10);
+
+               if (!gc->direction_input)
+                       gc->direction_input = samsung_gpiolib_2bit_input;
+               if (!gc->direction_output)
+                       gc->direction_output = samsung_gpiolib_2bit_output;
+
+               samsung_gpiolib_add(chip);
+       }
+}
+
+static void __init samsung_gpiolib_add_2bit_chips(struct samsung_gpio_chip *chip,
+                                                 int nr_chips, void __iomem *base,
+                                                 unsigned int offset)
+{
+       int i;
+
+       for (i = 0 ; i < nr_chips; i++, chip++) {
+               chip->chip.direction_input = samsung_gpiolib_2bit_input;
+               chip->chip.direction_output = samsung_gpiolib_2bit_output;
+
+               if (!chip->config)
+                       chip->config = &samsung_gpio_cfgs[7];
+               if (!chip->pm)
+                       chip->pm = __gpio_pm(&samsung_gpio_pm_2bit);
+               if ((base != NULL) && (chip->base == NULL))
+                       chip->base = base + ((i) * offset);
+
+               samsung_gpiolib_add(chip);
+       }
+}
+
+/*
+ * samsung_gpiolib_add_4bit_chips - 4bit single register GPIO config.
+ * @chip: The gpio chip that is being configured.
+ * @nr_chips: The no of chips (gpio ports) for the GPIO being configured.
+ *
+ * This helper deal with the GPIO cases where the control register has 4 bits
+ * of control per GPIO, generally in the form of:
+ * 0000 = Input
+ * 0001 = Output
+ * others = Special functions (dependent on bank)
+ *
+ * Note, since the code to deal with the case where there are two control
+ * registers instead of one, we do not have a separate set of function
+ * (samsung_gpiolib_add_4bit2_chips)for each case.
+ */
+
+static void __init samsung_gpiolib_add_4bit_chips(struct samsung_gpio_chip *chip,
+                                                 int nr_chips, void __iomem *base)
+{
+       int i;
+
+       for (i = 0 ; i < nr_chips; i++, chip++) {
+               chip->chip.direction_input = samsung_gpiolib_4bit_input;
+               chip->chip.direction_output = samsung_gpiolib_4bit_output;
+
+               if (!chip->config)
+                       chip->config = &samsung_gpio_cfgs[2];
+               if (!chip->pm)
+                       chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
+               if ((base != NULL) && (chip->base == NULL))
+                       chip->base = base + ((i) * 0x20);
+
+               samsung_gpiolib_add(chip);
+       }
+}
+
+static void __init samsung_gpiolib_add_4bit2_chips(struct samsung_gpio_chip *chip,
+                                                  int nr_chips)
+{
+       for (; nr_chips > 0; nr_chips--, chip++) {
+               chip->chip.direction_input = samsung_gpiolib_4bit2_input;
+               chip->chip.direction_output = samsung_gpiolib_4bit2_output;
+
+               if (!chip->config)
+                       chip->config = &samsung_gpio_cfgs[2];
+               if (!chip->pm)
+                       chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
+
+               samsung_gpiolib_add(chip);
+       }
+}
+
+static void __init s5p64x0_gpiolib_add_rbank(struct samsung_gpio_chip *chip,
+                                            int nr_chips)
+{
+       for (; nr_chips > 0; nr_chips--, chip++) {
+               chip->chip.direction_input = s5p64x0_gpiolib_rbank_input;
+               chip->chip.direction_output = s5p64x0_gpiolib_rbank_output;
+
+               if (!chip->pm)
+                       chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
+
+               samsung_gpiolib_add(chip);
+       }
+}
+
+int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset)
+{
+       struct samsung_gpio_chip *samsung_chip = container_of(chip, struct samsung_gpio_chip, chip);
+
+       return samsung_chip->irq_base + offset;
+}
+
+#ifdef CONFIG_PLAT_S3C24XX
+static int s3c24xx_gpiolib_fbank_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+       if (offset < 4)
+               return IRQ_EINT0 + offset;
+
+       if (offset < 8)
+               return IRQ_EINT4 + offset - 4;
+
+       return -EINVAL;
+}
+#endif
+
+#ifdef CONFIG_PLAT_S3C64XX
+static int s3c64xx_gpiolib_mbank_to_irq(struct gpio_chip *chip, unsigned pin)
+{
+       return pin < 5 ? IRQ_EINT(23) + pin : -ENXIO;
+}
+
+static int s3c64xx_gpiolib_lbank_to_irq(struct gpio_chip *chip, unsigned pin)
+{
+       return pin >= 8 ? IRQ_EINT(16) + pin - 8 : -ENXIO;
+}
+#endif
+
+struct samsung_gpio_chip s3c24xx_gpios[] = {
+#ifdef CONFIG_PLAT_S3C24XX
+       {
+               .config = &s3c24xx_gpiocfg_banka,
+               .chip   = {
+                       .base                   = S3C2410_GPA(0),
+                       .owner                  = THIS_MODULE,
+                       .label                  = "GPIOA",
+                       .ngpio                  = 24,
+                       .direction_input        = s3c24xx_gpiolib_banka_input,
+                       .direction_output       = s3c24xx_gpiolib_banka_output,
+               },
+       }, {
+               .chip   = {
+                       .base   = S3C2410_GPB(0),
+                       .owner  = THIS_MODULE,
+                       .label  = "GPIOB",
+                       .ngpio  = 16,
+               },
+       }, {
+               .chip   = {
+                       .base   = S3C2410_GPC(0),
+                       .owner  = THIS_MODULE,
+                       .label  = "GPIOC",
+                       .ngpio  = 16,
+               },
+       }, {
+               .chip   = {
+                       .base   = S3C2410_GPD(0),
+                       .owner  = THIS_MODULE,
+                       .label  = "GPIOD",
+                       .ngpio  = 16,
+               },
+       }, {
+               .chip   = {
+                       .base   = S3C2410_GPE(0),
+                       .label  = "GPIOE",
+                       .owner  = THIS_MODULE,
+                       .ngpio  = 16,
+               },
+       }, {
+               .chip   = {
+                       .base   = S3C2410_GPF(0),
+                       .owner  = THIS_MODULE,
+                       .label  = "GPIOF",
+                       .ngpio  = 8,
+                       .to_irq = s3c24xx_gpiolib_fbank_to_irq,
+               },
+       }, {
+               .irq_base = IRQ_EINT8,
+               .chip   = {
+                       .base   = S3C2410_GPG(0),
+                       .owner  = THIS_MODULE,
+                       .label  = "GPIOG",
+                       .ngpio  = 16,
+                       .to_irq = samsung_gpiolib_to_irq,
+               },
+       }, {
+               .chip   = {
+                       .base   = S3C2410_GPH(0),
+                       .owner  = THIS_MODULE,
+                       .label  = "GPIOH",
+                       .ngpio  = 11,
+               },
+       },
+               /* GPIOS for the S3C2443 and later devices. */
+       {
+               .base   = S3C2440_GPJCON,
+               .chip   = {
+                       .base   = S3C2410_GPJ(0),
+                       .owner  = THIS_MODULE,
+                       .label  = "GPIOJ",
+                       .ngpio  = 16,
+               },
+       }, {
+               .base   = S3C2443_GPKCON,
+               .chip   = {
+                       .base   = S3C2410_GPK(0),
+                       .owner  = THIS_MODULE,
+                       .label  = "GPIOK",
+                       .ngpio  = 16,
+               },
+       }, {
+               .base   = S3C2443_GPLCON,
+               .chip   = {
+                       .base   = S3C2410_GPL(0),
+                       .owner  = THIS_MODULE,
+                       .label  = "GPIOL",
+                       .ngpio  = 15,
+               },
+       }, {
+               .base   = S3C2443_GPMCON,
+               .chip   = {
+                       .base   = S3C2410_GPM(0),
+                       .owner  = THIS_MODULE,
+                       .label  = "GPIOM",
+                       .ngpio  = 2,
+               },
+       },
+#endif
+};
+
+/*
+ * GPIO bank summary:
+ *
+ * Bank        GPIOs   Style   SlpCon  ExtInt Group
+ * A   8       4Bit    Yes     1
+ * B   7       4Bit    Yes     1
+ * C   8       4Bit    Yes     2
+ * D   5       4Bit    Yes     3
+ * E   5       4Bit    Yes     None
+ * F   16      2Bit    Yes     4 [1]
+ * G   7       4Bit    Yes     5
+ * H   10      4Bit[2] Yes     6
+ * I   16      2Bit    Yes     None
+ * J   12      2Bit    Yes     None
+ * K   16      4Bit[2] No      None
+ * L   15      4Bit[2] No      None
+ * M   6       4Bit    No      IRQ_EINT
+ * N   16      2Bit    No      IRQ_EINT
+ * O   16      2Bit    Yes     7
+ * P   15      2Bit    Yes     8
+ * Q   9       2Bit    Yes     9
+ *
+ * [1] BANKF pins 14,15 do not form part of the external interrupt sources
+ * [2] BANK has two control registers, GPxCON0 and GPxCON1
+ */
+
+static struct samsung_gpio_chip s3c64xx_gpios_4bit[] = {
+#ifdef CONFIG_PLAT_S3C64XX
+       {
+               .chip   = {
+                       .base   = S3C64XX_GPA(0),
+                       .ngpio  = S3C64XX_GPIO_A_NR,
+                       .label  = "GPA",
+               },
+       }, {
+               .chip   = {
+                       .base   = S3C64XX_GPB(0),
+                       .ngpio  = S3C64XX_GPIO_B_NR,
+                       .label  = "GPB",
+               },
+       }, {
+               .chip   = {
+                       .base   = S3C64XX_GPC(0),
+                       .ngpio  = S3C64XX_GPIO_C_NR,
+                       .label  = "GPC",
+               },
+       }, {
+               .chip   = {
+                       .base   = S3C64XX_GPD(0),
+                       .ngpio  = S3C64XX_GPIO_D_NR,
+                       .label  = "GPD",
+               },
+       }, {
+               .config = &samsung_gpio_cfgs[0],
+               .chip   = {
+                       .base   = S3C64XX_GPE(0),
+                       .ngpio  = S3C64XX_GPIO_E_NR,
+                       .label  = "GPE",
+               },
+       }, {
+               .base   = S3C64XX_GPG_BASE,
+               .chip   = {
+                       .base   = S3C64XX_GPG(0),
+                       .ngpio  = S3C64XX_GPIO_G_NR,
+                       .label  = "GPG",
+               },
+       }, {
+               .base   = S3C64XX_GPM_BASE,
+               .config = &samsung_gpio_cfgs[1],
+               .chip   = {
+                       .base   = S3C64XX_GPM(0),
+                       .ngpio  = S3C64XX_GPIO_M_NR,
+                       .label  = "GPM",
+                       .to_irq = s3c64xx_gpiolib_mbank_to_irq,
+               },
+       },
+#endif
+};
+
+static struct samsung_gpio_chip s3c64xx_gpios_4bit2[] = {
+#ifdef CONFIG_PLAT_S3C64XX
+       {
+               .base   = S3C64XX_GPH_BASE + 0x4,
+               .chip   = {
+                       .base   = S3C64XX_GPH(0),
+                       .ngpio  = S3C64XX_GPIO_H_NR,
+                       .label  = "GPH",
+               },
+       }, {
+               .base   = S3C64XX_GPK_BASE + 0x4,
+               .config = &samsung_gpio_cfgs[0],
+               .chip   = {
+                       .base   = S3C64XX_GPK(0),
+                       .ngpio  = S3C64XX_GPIO_K_NR,
+                       .label  = "GPK",
+               },
+       }, {
+               .base   = S3C64XX_GPL_BASE + 0x4,
+               .config = &samsung_gpio_cfgs[1],
+               .chip   = {
+                       .base   = S3C64XX_GPL(0),
+                       .ngpio  = S3C64XX_GPIO_L_NR,
+                       .label  = "GPL",
+                       .to_irq = s3c64xx_gpiolib_lbank_to_irq,
+               },
+       },
+#endif
+};
+
+static struct samsung_gpio_chip s3c64xx_gpios_2bit[] = {
+#ifdef CONFIG_PLAT_S3C64XX
+       {
+               .base   = S3C64XX_GPF_BASE,
+               .config = &samsung_gpio_cfgs[6],
+               .chip   = {
+                       .base   = S3C64XX_GPF(0),
+                       .ngpio  = S3C64XX_GPIO_F_NR,
+                       .label  = "GPF",
+               },
+       }, {
+               .config = &samsung_gpio_cfgs[7],
+               .chip   = {
+                       .base   = S3C64XX_GPI(0),
+                       .ngpio  = S3C64XX_GPIO_I_NR,
+                       .label  = "GPI",
+               },
+       }, {
+               .config = &samsung_gpio_cfgs[7],
+               .chip   = {
+                       .base   = S3C64XX_GPJ(0),
+                       .ngpio  = S3C64XX_GPIO_J_NR,
+                       .label  = "GPJ",
+               },
+       }, {
+               .config = &samsung_gpio_cfgs[6],
+               .chip   = {
+                       .base   = S3C64XX_GPO(0),
+                       .ngpio  = S3C64XX_GPIO_O_NR,
+                       .label  = "GPO",
+               },
+       }, {
+               .config = &samsung_gpio_cfgs[6],
+               .chip   = {
+                       .base   = S3C64XX_GPP(0),
+                       .ngpio  = S3C64XX_GPIO_P_NR,
+                       .label  = "GPP",
+               },
+       }, {
+               .config = &samsung_gpio_cfgs[6],
+               .chip   = {
+                       .base   = S3C64XX_GPQ(0),
+                       .ngpio  = S3C64XX_GPIO_Q_NR,
+                       .label  = "GPQ",
+               },
+       }, {
+               .base   = S3C64XX_GPN_BASE,
+               .irq_base = IRQ_EINT(0),
+               .config = &samsung_gpio_cfgs[5],
+               .chip   = {
+                       .base   = S3C64XX_GPN(0),
+                       .ngpio  = S3C64XX_GPIO_N_NR,
+                       .label  = "GPN",
+                       .to_irq = samsung_gpiolib_to_irq,
+               },
+       },
+#endif
+};
+
+/*
+ * S5P6440 GPIO bank summary:
+ *
+ * Bank        GPIOs   Style   SlpCon  ExtInt Group
+ * A   6       4Bit    Yes     1
+ * B   7       4Bit    Yes     1
+ * C   8       4Bit    Yes     2
+ * F   2       2Bit    Yes     4 [1]
+ * G   7       4Bit    Yes     5
+ * H   10      4Bit[2] Yes     6
+ * I   16      2Bit    Yes     None
+ * J   12      2Bit    Yes     None
+ * N   16      2Bit    No      IRQ_EINT
+ * P   8       2Bit    Yes     8
+ * R   15      4Bit[2] Yes     8
+ */
+
+static struct samsung_gpio_chip s5p6440_gpios_4bit[] = {
+#ifdef CONFIG_CPU_S5P6440
+       {
+               .chip   = {
+                       .base   = S5P6440_GPA(0),
+                       .ngpio  = S5P6440_GPIO_A_NR,
+                       .label  = "GPA",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5P6440_GPB(0),
+                       .ngpio  = S5P6440_GPIO_B_NR,
+                       .label  = "GPB",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5P6440_GPC(0),
+                       .ngpio  = S5P6440_GPIO_C_NR,
+                       .label  = "GPC",
+               },
+       }, {
+               .base   = S5P64X0_GPG_BASE,
+               .chip   = {
+                       .base   = S5P6440_GPG(0),
+                       .ngpio  = S5P6440_GPIO_G_NR,
+                       .label  = "GPG",
+               },
+       },
+#endif
+};
+
+static struct samsung_gpio_chip s5p6440_gpios_4bit2[] = {
+#ifdef CONFIG_CPU_S5P6440
+       {
+               .base   = S5P64X0_GPH_BASE + 0x4,
+               .chip   = {
+                       .base   = S5P6440_GPH(0),
+                       .ngpio  = S5P6440_GPIO_H_NR,
+                       .label  = "GPH",
+               },
+       },
+#endif
+};
+
+static struct samsung_gpio_chip s5p6440_gpios_rbank[] = {
+#ifdef CONFIG_CPU_S5P6440
+       {
+               .base   = S5P64X0_GPR_BASE + 0x4,
+               .config = &s5p64x0_gpio_cfg_rbank,
+               .chip   = {
+                       .base   = S5P6440_GPR(0),
+                       .ngpio  = S5P6440_GPIO_R_NR,
+                       .label  = "GPR",
+               },
+       },
+#endif
+};
+
+static struct samsung_gpio_chip s5p6440_gpios_2bit[] = {
+#ifdef CONFIG_CPU_S5P6440
+       {
+               .base   = S5P64X0_GPF_BASE,
+               .config = &samsung_gpio_cfgs[6],
+               .chip   = {
+                       .base   = S5P6440_GPF(0),
+                       .ngpio  = S5P6440_GPIO_F_NR,
+                       .label  = "GPF",
+               },
+       }, {
+               .base   = S5P64X0_GPI_BASE,
+               .config = &samsung_gpio_cfgs[4],
+               .chip   = {
+                       .base   = S5P6440_GPI(0),
+                       .ngpio  = S5P6440_GPIO_I_NR,
+                       .label  = "GPI",
+               },
+       }, {
+               .base   = S5P64X0_GPJ_BASE,
+               .config = &samsung_gpio_cfgs[4],
+               .chip   = {
+                       .base   = S5P6440_GPJ(0),
+                       .ngpio  = S5P6440_GPIO_J_NR,
+                       .label  = "GPJ",
+               },
+       }, {
+               .base   = S5P64X0_GPN_BASE,
+               .config = &samsung_gpio_cfgs[5],
+               .chip   = {
+                       .base   = S5P6440_GPN(0),
+                       .ngpio  = S5P6440_GPIO_N_NR,
+                       .label  = "GPN",
+               },
+       }, {
+               .base   = S5P64X0_GPP_BASE,
+               .config = &samsung_gpio_cfgs[6],
+               .chip   = {
+                       .base   = S5P6440_GPP(0),
+                       .ngpio  = S5P6440_GPIO_P_NR,
+                       .label  = "GPP",
+               },
+       },
+#endif
+};
+
+/*
+ * S5P6450 GPIO bank summary:
+ *
+ * Bank        GPIOs   Style   SlpCon  ExtInt Group
+ * A   6       4Bit    Yes     1
+ * B   7       4Bit    Yes     1
+ * C   8       4Bit    Yes     2
+ * D   8       4Bit    Yes     None
+ * F   2       2Bit    Yes     None
+ * G   14      4Bit[2] Yes     5
+ * H   10      4Bit[2] Yes     6
+ * I   16      2Bit    Yes     None
+ * J   12      2Bit    Yes     None
+ * K   5       4Bit    Yes     None
+ * N   16      2Bit    No      IRQ_EINT
+ * P   11      2Bit    Yes     8
+ * Q   14      2Bit    Yes     None
+ * R   15      4Bit[2] Yes     None
+ * S   8       2Bit    Yes     None
+ *
+ * [1] BANKF pins 14,15 do not form part of the external interrupt sources
+ * [2] BANK has two control registers, GPxCON0 and GPxCON1
+ */
+
+static struct samsung_gpio_chip s5p6450_gpios_4bit[] = {
+#ifdef CONFIG_CPU_S5P6450
+       {
+               .chip   = {
+                       .base   = S5P6450_GPA(0),
+                       .ngpio  = S5P6450_GPIO_A_NR,
+                       .label  = "GPA",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5P6450_GPB(0),
+                       .ngpio  = S5P6450_GPIO_B_NR,
+                       .label  = "GPB",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5P6450_GPC(0),
+                       .ngpio  = S5P6450_GPIO_C_NR,
+                       .label  = "GPC",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5P6450_GPD(0),
+                       .ngpio  = S5P6450_GPIO_D_NR,
+                       .label  = "GPD",
+               },
+       }, {
+               .base   = S5P6450_GPK_BASE,
+               .chip   = {
+                       .base   = S5P6450_GPK(0),
+                       .ngpio  = S5P6450_GPIO_K_NR,
+                       .label  = "GPK",
+               },
+       },
+#endif
+};
+
+static struct samsung_gpio_chip s5p6450_gpios_4bit2[] = {
+#ifdef CONFIG_CPU_S5P6450
+       {
+               .base   = S5P64X0_GPG_BASE + 0x4,
+               .chip   = {
+                       .base   = S5P6450_GPG(0),
+                       .ngpio  = S5P6450_GPIO_G_NR,
+                       .label  = "GPG",
+               },
+       }, {
+               .base   = S5P64X0_GPH_BASE + 0x4,
+               .chip   = {
+                       .base   = S5P6450_GPH(0),
+                       .ngpio  = S5P6450_GPIO_H_NR,
+                       .label  = "GPH",
+               },
+       },
+#endif
+};
+
+static struct samsung_gpio_chip s5p6450_gpios_rbank[] = {
+#ifdef CONFIG_CPU_S5P6450
+       {
+               .base   = S5P64X0_GPR_BASE + 0x4,
+               .config = &s5p64x0_gpio_cfg_rbank,
+               .chip   = {
+                       .base   = S5P6450_GPR(0),
+                       .ngpio  = S5P6450_GPIO_R_NR,
+                       .label  = "GPR",
+               },
+       },
+#endif
+};
+
+static struct samsung_gpio_chip s5p6450_gpios_2bit[] = {
+#ifdef CONFIG_CPU_S5P6450
+       {
+               .base   = S5P64X0_GPF_BASE,
+               .config = &samsung_gpio_cfgs[6],
+               .chip   = {
+                       .base   = S5P6450_GPF(0),
+                       .ngpio  = S5P6450_GPIO_F_NR,
+                       .label  = "GPF",
+               },
+       }, {
+               .base   = S5P64X0_GPI_BASE,
+               .config = &samsung_gpio_cfgs[4],
+               .chip   = {
+                       .base   = S5P6450_GPI(0),
+                       .ngpio  = S5P6450_GPIO_I_NR,
+                       .label  = "GPI",
+               },
+       }, {
+               .base   = S5P64X0_GPJ_BASE,
+               .config = &samsung_gpio_cfgs[4],
+               .chip   = {
+                       .base   = S5P6450_GPJ(0),
+                       .ngpio  = S5P6450_GPIO_J_NR,
+                       .label  = "GPJ",
+               },
+       }, {
+               .base   = S5P64X0_GPN_BASE,
+               .config = &samsung_gpio_cfgs[5],
+               .chip   = {
+                       .base   = S5P6450_GPN(0),
+                       .ngpio  = S5P6450_GPIO_N_NR,
+                       .label  = "GPN",
+               },
+       }, {
+               .base   = S5P64X0_GPP_BASE,
+               .config = &samsung_gpio_cfgs[6],
+               .chip   = {
+                       .base   = S5P6450_GPP(0),
+                       .ngpio  = S5P6450_GPIO_P_NR,
+                       .label  = "GPP",
+               },
+       }, {
+               .base   = S5P6450_GPQ_BASE,
+               .config = &samsung_gpio_cfgs[5],
+               .chip   = {
+                       .base   = S5P6450_GPQ(0),
+                       .ngpio  = S5P6450_GPIO_Q_NR,
+                       .label  = "GPQ",
+               },
+       }, {
+               .base   = S5P6450_GPS_BASE,
+               .config = &samsung_gpio_cfgs[6],
+               .chip   = {
+                       .base   = S5P6450_GPS(0),
+                       .ngpio  = S5P6450_GPIO_S_NR,
+                       .label  = "GPS",
+               },
+       },
+#endif
+};
+
+/*
+ * S5PC100 GPIO bank summary:
+ *
+ * Bank        GPIOs   Style   INT Type
+ * A0  8       4Bit    GPIO_INT0
+ * A1  5       4Bit    GPIO_INT1
+ * B   8       4Bit    GPIO_INT2
+ * C   5       4Bit    GPIO_INT3
+ * D   7       4Bit    GPIO_INT4
+ * E0  8       4Bit    GPIO_INT5
+ * E1  6       4Bit    GPIO_INT6
+ * F0  8       4Bit    GPIO_INT7
+ * F1  8       4Bit    GPIO_INT8
+ * F2  8       4Bit    GPIO_INT9
+ * F3  4       4Bit    GPIO_INT10
+ * G0  8       4Bit    GPIO_INT11
+ * G1  3       4Bit    GPIO_INT12
+ * G2  7       4Bit    GPIO_INT13
+ * G3  7       4Bit    GPIO_INT14
+ * H0  8       4Bit    WKUP_INT
+ * H1  8       4Bit    WKUP_INT
+ * H2  8       4Bit    WKUP_INT
+ * H3  8       4Bit    WKUP_INT
+ * I   8       4Bit    GPIO_INT15
+ * J0  8       4Bit    GPIO_INT16
+ * J1  5       4Bit    GPIO_INT17
+ * J2  8       4Bit    GPIO_INT18
+ * J3  8       4Bit    GPIO_INT19
+ * J4  4       4Bit    GPIO_INT20
+ * K0  8       4Bit    None
+ * K1  6       4Bit    None
+ * K2  8       4Bit    None
+ * K3  8       4Bit    None
+ * L0  8       4Bit    None
+ * L1  8       4Bit    None
+ * L2  8       4Bit    None
+ * L3  8       4Bit    None
+ */
+
+static struct samsung_gpio_chip s5pc100_gpios_4bit[] = {
+#ifdef CONFIG_CPU_S5PC100
+       {
+               .chip   = {
+                       .base   = S5PC100_GPA0(0),
+                       .ngpio  = S5PC100_GPIO_A0_NR,
+                       .label  = "GPA0",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPA1(0),
+                       .ngpio  = S5PC100_GPIO_A1_NR,
+                       .label  = "GPA1",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPB(0),
+                       .ngpio  = S5PC100_GPIO_B_NR,
+                       .label  = "GPB",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPC(0),
+                       .ngpio  = S5PC100_GPIO_C_NR,
+                       .label  = "GPC",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPD(0),
+                       .ngpio  = S5PC100_GPIO_D_NR,
+                       .label  = "GPD",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPE0(0),
+                       .ngpio  = S5PC100_GPIO_E0_NR,
+                       .label  = "GPE0",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPE1(0),
+                       .ngpio  = S5PC100_GPIO_E1_NR,
+                       .label  = "GPE1",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPF0(0),
+                       .ngpio  = S5PC100_GPIO_F0_NR,
+                       .label  = "GPF0",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPF1(0),
+                       .ngpio  = S5PC100_GPIO_F1_NR,
+                       .label  = "GPF1",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPF2(0),
+                       .ngpio  = S5PC100_GPIO_F2_NR,
+                       .label  = "GPF2",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPF3(0),
+                       .ngpio  = S5PC100_GPIO_F3_NR,
+                       .label  = "GPF3",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPG0(0),
+                       .ngpio  = S5PC100_GPIO_G0_NR,
+                       .label  = "GPG0",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPG1(0),
+                       .ngpio  = S5PC100_GPIO_G1_NR,
+                       .label  = "GPG1",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPG2(0),
+                       .ngpio  = S5PC100_GPIO_G2_NR,
+                       .label  = "GPG2",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPG3(0),
+                       .ngpio  = S5PC100_GPIO_G3_NR,
+                       .label  = "GPG3",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPI(0),
+                       .ngpio  = S5PC100_GPIO_I_NR,
+                       .label  = "GPI",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPJ0(0),
+                       .ngpio  = S5PC100_GPIO_J0_NR,
+                       .label  = "GPJ0",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPJ1(0),
+                       .ngpio  = S5PC100_GPIO_J1_NR,
+                       .label  = "GPJ1",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPJ2(0),
+                       .ngpio  = S5PC100_GPIO_J2_NR,
+                       .label  = "GPJ2",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPJ3(0),
+                       .ngpio  = S5PC100_GPIO_J3_NR,
+                       .label  = "GPJ3",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPJ4(0),
+                       .ngpio  = S5PC100_GPIO_J4_NR,
+                       .label  = "GPJ4",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPK0(0),
+                       .ngpio  = S5PC100_GPIO_K0_NR,
+                       .label  = "GPK0",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPK1(0),
+                       .ngpio  = S5PC100_GPIO_K1_NR,
+                       .label  = "GPK1",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPK2(0),
+                       .ngpio  = S5PC100_GPIO_K2_NR,
+                       .label  = "GPK2",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPK3(0),
+                       .ngpio  = S5PC100_GPIO_K3_NR,
+                       .label  = "GPK3",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPL0(0),
+                       .ngpio  = S5PC100_GPIO_L0_NR,
+                       .label  = "GPL0",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPL1(0),
+                       .ngpio  = S5PC100_GPIO_L1_NR,
+                       .label  = "GPL1",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPL2(0),
+                       .ngpio  = S5PC100_GPIO_L2_NR,
+                       .label  = "GPL2",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPL3(0),
+                       .ngpio  = S5PC100_GPIO_L3_NR,
+                       .label  = "GPL3",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPL4(0),
+                       .ngpio  = S5PC100_GPIO_L4_NR,
+                       .label  = "GPL4",
+               },
+       }, {
+               .base   = (S5P_VA_GPIO + 0xC00),
+               .irq_base = IRQ_EINT(0),
+               .chip   = {
+                       .base   = S5PC100_GPH0(0),
+                       .ngpio  = S5PC100_GPIO_H0_NR,
+                       .label  = "GPH0",
+                       .to_irq = samsung_gpiolib_to_irq,
+               },
+       }, {
+               .base   = (S5P_VA_GPIO + 0xC20),
+               .irq_base = IRQ_EINT(8),
+               .chip   = {
+                       .base   = S5PC100_GPH1(0),
+                       .ngpio  = S5PC100_GPIO_H1_NR,
+                       .label  = "GPH1",
+                       .to_irq = samsung_gpiolib_to_irq,
+               },
+       }, {
+               .base   = (S5P_VA_GPIO + 0xC40),
+               .irq_base = IRQ_EINT(16),
+               .chip   = {
+                       .base   = S5PC100_GPH2(0),
+                       .ngpio  = S5PC100_GPIO_H2_NR,
+                       .label  = "GPH2",
+                       .to_irq = samsung_gpiolib_to_irq,
+               },
+       }, {
+               .base   = (S5P_VA_GPIO + 0xC60),
+               .irq_base = IRQ_EINT(24),
+               .chip   = {
+                       .base   = S5PC100_GPH3(0),
+                       .ngpio  = S5PC100_GPIO_H3_NR,
+                       .label  = "GPH3",
+                       .to_irq = samsung_gpiolib_to_irq,
+               },
+       },
+#endif
+};
+
+/*
+ * Followings are the gpio banks in S5PV210/S5PC110
+ *
+ * The 'config' member when left to NULL, is initialized to the default
+ * structure samsung_gpio_cfgs[3] in the init function below.
+ *
+ * The 'base' member is also initialized in the init function below.
+ * Note: The initialization of 'base' member of samsung_gpio_chip structure
+ * uses the above macro and depends on the banks being listed in order here.
+ */
+
+static struct samsung_gpio_chip s5pv210_gpios_4bit[] = {
+#ifdef CONFIG_CPU_S5PV210
+       {
+               .chip   = {
+                       .base   = S5PV210_GPA0(0),
+                       .ngpio  = S5PV210_GPIO_A0_NR,
+                       .label  = "GPA0",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPA1(0),
+                       .ngpio  = S5PV210_GPIO_A1_NR,
+                       .label  = "GPA1",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPB(0),
+                       .ngpio  = S5PV210_GPIO_B_NR,
+                       .label  = "GPB",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPC0(0),
+                       .ngpio  = S5PV210_GPIO_C0_NR,
+                       .label  = "GPC0",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPC1(0),
+                       .ngpio  = S5PV210_GPIO_C1_NR,
+                       .label  = "GPC1",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPD0(0),
+                       .ngpio  = S5PV210_GPIO_D0_NR,
+                       .label  = "GPD0",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPD1(0),
+                       .ngpio  = S5PV210_GPIO_D1_NR,
+                       .label  = "GPD1",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPE0(0),
+                       .ngpio  = S5PV210_GPIO_E0_NR,
+                       .label  = "GPE0",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPE1(0),
+                       .ngpio  = S5PV210_GPIO_E1_NR,
+                       .label  = "GPE1",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPF0(0),
+                       .ngpio  = S5PV210_GPIO_F0_NR,
+                       .label  = "GPF0",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPF1(0),
+                       .ngpio  = S5PV210_GPIO_F1_NR,
+                       .label  = "GPF1",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPF2(0),
+                       .ngpio  = S5PV210_GPIO_F2_NR,
+                       .label  = "GPF2",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPF3(0),
+                       .ngpio  = S5PV210_GPIO_F3_NR,
+                       .label  = "GPF3",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPG0(0),
+                       .ngpio  = S5PV210_GPIO_G0_NR,
+                       .label  = "GPG0",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPG1(0),
+                       .ngpio  = S5PV210_GPIO_G1_NR,
+                       .label  = "GPG1",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPG2(0),
+                       .ngpio  = S5PV210_GPIO_G2_NR,
+                       .label  = "GPG2",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPG3(0),
+                       .ngpio  = S5PV210_GPIO_G3_NR,
+                       .label  = "GPG3",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPI(0),
+                       .ngpio  = S5PV210_GPIO_I_NR,
+                       .label  = "GPI",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPJ0(0),
+                       .ngpio  = S5PV210_GPIO_J0_NR,
+                       .label  = "GPJ0",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPJ1(0),
+                       .ngpio  = S5PV210_GPIO_J1_NR,
+                       .label  = "GPJ1",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPJ2(0),
+                       .ngpio  = S5PV210_GPIO_J2_NR,
+                       .label  = "GPJ2",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPJ3(0),
+                       .ngpio  = S5PV210_GPIO_J3_NR,
+                       .label  = "GPJ3",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPJ4(0),
+                       .ngpio  = S5PV210_GPIO_J4_NR,
+                       .label  = "GPJ4",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_MP01(0),
+                       .ngpio  = S5PV210_GPIO_MP01_NR,
+                       .label  = "MP01",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_MP02(0),
+                       .ngpio  = S5PV210_GPIO_MP02_NR,
+                       .label  = "MP02",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_MP03(0),
+                       .ngpio  = S5PV210_GPIO_MP03_NR,
+                       .label  = "MP03",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_MP04(0),
+                       .ngpio  = S5PV210_GPIO_MP04_NR,
+                       .label  = "MP04",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_MP05(0),
+                       .ngpio  = S5PV210_GPIO_MP05_NR,
+                       .label  = "MP05",
+               },
+       }, {
+               .base   = (S5P_VA_GPIO + 0xC00),
+               .irq_base = IRQ_EINT(0),
+               .chip   = {
+                       .base   = S5PV210_GPH0(0),
+                       .ngpio  = S5PV210_GPIO_H0_NR,
+                       .label  = "GPH0",
+                       .to_irq = samsung_gpiolib_to_irq,
+               },
+       }, {
+               .base   = (S5P_VA_GPIO + 0xC20),
+               .irq_base = IRQ_EINT(8),
+               .chip   = {
+                       .base   = S5PV210_GPH1(0),
+                       .ngpio  = S5PV210_GPIO_H1_NR,
+                       .label  = "GPH1",
+                       .to_irq = samsung_gpiolib_to_irq,
+               },
+       }, {
+               .base   = (S5P_VA_GPIO + 0xC40),
+               .irq_base = IRQ_EINT(16),
+               .chip   = {
+                       .base   = S5PV210_GPH2(0),
+                       .ngpio  = S5PV210_GPIO_H2_NR,
+                       .label  = "GPH2",
+                       .to_irq = samsung_gpiolib_to_irq,
+               },
+       }, {
+               .base   = (S5P_VA_GPIO + 0xC60),
+               .irq_base = IRQ_EINT(24),
+               .chip   = {
+                       .base   = S5PV210_GPH3(0),
+                       .ngpio  = S5PV210_GPIO_H3_NR,
+                       .label  = "GPH3",
+                       .to_irq = samsung_gpiolib_to_irq,
+               },
+       },
+#endif
+};
+
+/*
+ * Followings are the gpio banks in EXYNOS4210
+ *
+ * The 'config' member when left to NULL, is initialized to the default
+ * structure samsung_gpio_cfgs[3] in the init function below.
+ *
+ * The 'base' member is also initialized in the init function below.
+ * Note: The initialization of 'base' member of samsung_gpio_chip structure
+ * uses the above macro and depends on the banks being listed in order here.
+ */
+
+static struct samsung_gpio_chip exynos4_gpios_1[] = {
+#ifdef CONFIG_ARCH_EXYNOS4
+       {
+               .chip   = {
+                       .base   = EXYNOS4_GPA0(0),
+                       .ngpio  = EXYNOS4_GPIO_A0_NR,
+                       .label  = "GPA0",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPA1(0),
+                       .ngpio  = EXYNOS4_GPIO_A1_NR,
+                       .label  = "GPA1",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPB(0),
+                       .ngpio  = EXYNOS4_GPIO_B_NR,
+                       .label  = "GPB",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPC0(0),
+                       .ngpio  = EXYNOS4_GPIO_C0_NR,
+                       .label  = "GPC0",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPC1(0),
+                       .ngpio  = EXYNOS4_GPIO_C1_NR,
+                       .label  = "GPC1",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPD0(0),
+                       .ngpio  = EXYNOS4_GPIO_D0_NR,
+                       .label  = "GPD0",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPD1(0),
+                       .ngpio  = EXYNOS4_GPIO_D1_NR,
+                       .label  = "GPD1",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPE0(0),
+                       .ngpio  = EXYNOS4_GPIO_E0_NR,
+                       .label  = "GPE0",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPE1(0),
+                       .ngpio  = EXYNOS4_GPIO_E1_NR,
+                       .label  = "GPE1",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPE2(0),
+                       .ngpio  = EXYNOS4_GPIO_E2_NR,
+                       .label  = "GPE2",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPE3(0),
+                       .ngpio  = EXYNOS4_GPIO_E3_NR,
+                       .label  = "GPE3",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPE4(0),
+                       .ngpio  = EXYNOS4_GPIO_E4_NR,
+                       .label  = "GPE4",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPF0(0),
+                       .ngpio  = EXYNOS4_GPIO_F0_NR,
+                       .label  = "GPF0",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPF1(0),
+                       .ngpio  = EXYNOS4_GPIO_F1_NR,
+                       .label  = "GPF1",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPF2(0),
+                       .ngpio  = EXYNOS4_GPIO_F2_NR,
+                       .label  = "GPF2",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPF3(0),
+                       .ngpio  = EXYNOS4_GPIO_F3_NR,
+                       .label  = "GPF3",
+               },
+       },
+#endif
+};
+
+static struct samsung_gpio_chip exynos4_gpios_2[] = {
+#ifdef CONFIG_ARCH_EXYNOS4
+       {
+               .chip   = {
+                       .base   = EXYNOS4_GPJ0(0),
+                       .ngpio  = EXYNOS4_GPIO_J0_NR,
+                       .label  = "GPJ0",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPJ1(0),
+                       .ngpio  = EXYNOS4_GPIO_J1_NR,
+                       .label  = "GPJ1",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPK0(0),
+                       .ngpio  = EXYNOS4_GPIO_K0_NR,
+                       .label  = "GPK0",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPK1(0),
+                       .ngpio  = EXYNOS4_GPIO_K1_NR,
+                       .label  = "GPK1",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPK2(0),
+                       .ngpio  = EXYNOS4_GPIO_K2_NR,
+                       .label  = "GPK2",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPK3(0),
+                       .ngpio  = EXYNOS4_GPIO_K3_NR,
+                       .label  = "GPK3",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPL0(0),
+                       .ngpio  = EXYNOS4_GPIO_L0_NR,
+                       .label  = "GPL0",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPL1(0),
+                       .ngpio  = EXYNOS4_GPIO_L1_NR,
+                       .label  = "GPL1",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPL2(0),
+                       .ngpio  = EXYNOS4_GPIO_L2_NR,
+                       .label  = "GPL2",
+               },
+       }, {
+               .config = &samsung_gpio_cfgs[8],
+               .chip   = {
+                       .base   = EXYNOS4_GPY0(0),
+                       .ngpio  = EXYNOS4_GPIO_Y0_NR,
+                       .label  = "GPY0",
+               },
+       }, {
+               .config = &samsung_gpio_cfgs[8],
+               .chip   = {
+                       .base   = EXYNOS4_GPY1(0),
+                       .ngpio  = EXYNOS4_GPIO_Y1_NR,
+                       .label  = "GPY1",
+               },
+       }, {
+               .config = &samsung_gpio_cfgs[8],
+               .chip   = {
+                       .base   = EXYNOS4_GPY2(0),
+                       .ngpio  = EXYNOS4_GPIO_Y2_NR,
+                       .label  = "GPY2",
+               },
+       }, {
+               .config = &samsung_gpio_cfgs[8],
+               .chip   = {
+                       .base   = EXYNOS4_GPY3(0),
+                       .ngpio  = EXYNOS4_GPIO_Y3_NR,
+                       .label  = "GPY3",
+               },
+       }, {
+               .config = &samsung_gpio_cfgs[8],
+               .chip   = {
+                       .base   = EXYNOS4_GPY4(0),
+                       .ngpio  = EXYNOS4_GPIO_Y4_NR,
+                       .label  = "GPY4",
+               },
+       }, {
+               .config = &samsung_gpio_cfgs[8],
+               .chip   = {
+                       .base   = EXYNOS4_GPY5(0),
+                       .ngpio  = EXYNOS4_GPIO_Y5_NR,
+                       .label  = "GPY5",
+               },
+       }, {
+               .config = &samsung_gpio_cfgs[8],
+               .chip   = {
+                       .base   = EXYNOS4_GPY6(0),
+                       .ngpio  = EXYNOS4_GPIO_Y6_NR,
+                       .label  = "GPY6",
+               },
+       }, {
+               .base   = (S5P_VA_GPIO2 + 0xC00),
+               .config = &samsung_gpio_cfgs[9],
+               .irq_base = IRQ_EINT(0),
+               .chip   = {
+                       .base   = EXYNOS4_GPX0(0),
+                       .ngpio  = EXYNOS4_GPIO_X0_NR,
+                       .label  = "GPX0",
+                       .to_irq = samsung_gpiolib_to_irq,
+               },
+       }, {
+               .base   = (S5P_VA_GPIO2 + 0xC20),
+               .config = &samsung_gpio_cfgs[9],
+               .irq_base = IRQ_EINT(8),
+               .chip   = {
+                       .base   = EXYNOS4_GPX1(0),
+                       .ngpio  = EXYNOS4_GPIO_X1_NR,
+                       .label  = "GPX1",
+                       .to_irq = samsung_gpiolib_to_irq,
+               },
+       }, {
+               .base   = (S5P_VA_GPIO2 + 0xC40),
+               .config = &samsung_gpio_cfgs[9],
+               .irq_base = IRQ_EINT(16),
+               .chip   = {
+                       .base   = EXYNOS4_GPX2(0),
+                       .ngpio  = EXYNOS4_GPIO_X2_NR,
+                       .label  = "GPX2",
+                       .to_irq = samsung_gpiolib_to_irq,
+               },
+       }, {
+               .base   = (S5P_VA_GPIO2 + 0xC60),
+               .config = &samsung_gpio_cfgs[9],
+               .irq_base = IRQ_EINT(24),
+               .chip   = {
+                       .base   = EXYNOS4_GPX3(0),
+                       .ngpio  = EXYNOS4_GPIO_X3_NR,
+                       .label  = "GPX3",
+                       .to_irq = samsung_gpiolib_to_irq,
+               },
+       },
+#endif
+};
+
+static struct samsung_gpio_chip exynos4_gpios_3[] = {
+#ifdef CONFIG_ARCH_EXYNOS4
+       {
+               .chip   = {
+                       .base   = EXYNOS4_GPZ(0),
+                       .ngpio  = EXYNOS4_GPIO_Z_NR,
+                       .label  = "GPZ",
+               },
+       },
+#endif
+};
+
+/* TODO: cleanup soc_is_* */
+static __init int samsung_gpiolib_init(void)
+{
+       struct samsung_gpio_chip *chip;
+       int i, nr_chips;
+       int group = 0;
+
+       samsung_gpiolib_set_cfg(samsung_gpio_cfgs, ARRAY_SIZE(samsung_gpio_cfgs));
+
+       if (soc_is_s3c24xx()) {
+               s3c24xx_gpiolib_add_chips(s3c24xx_gpios,
+                               ARRAY_SIZE(s3c24xx_gpios), S3C24XX_VA_GPIO);
+       } else if (soc_is_s3c64xx()) {
+               samsung_gpiolib_add_2bit_chips(s3c64xx_gpios_2bit,
+                               ARRAY_SIZE(s3c64xx_gpios_2bit),
+                               S3C64XX_VA_GPIO + 0xE0, 0x20);
+               samsung_gpiolib_add_4bit_chips(s3c64xx_gpios_4bit,
+                               ARRAY_SIZE(s3c64xx_gpios_4bit),
+                               S3C64XX_VA_GPIO);
+               samsung_gpiolib_add_4bit2_chips(s3c64xx_gpios_4bit2,
+                               ARRAY_SIZE(s3c64xx_gpios_4bit2));
+       } else if (soc_is_s5p6440()) {
+               samsung_gpiolib_add_2bit_chips(s5p6440_gpios_2bit,
+                               ARRAY_SIZE(s5p6440_gpios_2bit), NULL, 0x0);
+               samsung_gpiolib_add_4bit_chips(s5p6440_gpios_4bit,
+                               ARRAY_SIZE(s5p6440_gpios_4bit), S5P_VA_GPIO);
+               samsung_gpiolib_add_4bit2_chips(s5p6440_gpios_4bit2,
+                               ARRAY_SIZE(s5p6440_gpios_4bit2));
+               s5p64x0_gpiolib_add_rbank(s5p6440_gpios_rbank,
+                               ARRAY_SIZE(s5p6440_gpios_rbank));
+       } else if (soc_is_s5p6450()) {
+               samsung_gpiolib_add_2bit_chips(s5p6450_gpios_2bit,
+                               ARRAY_SIZE(s5p6450_gpios_2bit), NULL, 0x0);
+               samsung_gpiolib_add_4bit_chips(s5p6450_gpios_4bit,
+                               ARRAY_SIZE(s5p6450_gpios_4bit), S5P_VA_GPIO);
+               samsung_gpiolib_add_4bit2_chips(s5p6450_gpios_4bit2,
+                               ARRAY_SIZE(s5p6450_gpios_4bit2));
+               s5p64x0_gpiolib_add_rbank(s5p6450_gpios_rbank,
+                               ARRAY_SIZE(s5p6450_gpios_rbank));
+       } else if (soc_is_s5pc100()) {
+               group = 0;
+               chip = s5pc100_gpios_4bit;
+               nr_chips = ARRAY_SIZE(s5pc100_gpios_4bit);
+
+               for (i = 0; i < nr_chips; i++, chip++) {
+                       if (!chip->config) {
+                               chip->config = &samsung_gpio_cfgs[3];
+                               chip->group = group++;
+                       }
+               }
+               samsung_gpiolib_add_4bit_chips(s5pc100_gpios_4bit, nr_chips, S5P_VA_GPIO);
+#if defined(CONFIG_CPU_S5PC100) && defined(CONFIG_S5P_GPIO_INT)
+               s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
+#endif
+       } else if (soc_is_s5pv210()) {
+               group = 0;
+               chip = s5pv210_gpios_4bit;
+               nr_chips = ARRAY_SIZE(s5pv210_gpios_4bit);
+
+               for (i = 0; i < nr_chips; i++, chip++) {
+                       if (!chip->config) {
+                               chip->config = &samsung_gpio_cfgs[3];
+                               chip->group = group++;
+                       }
+               }
+               samsung_gpiolib_add_4bit_chips(s5pv210_gpios_4bit, nr_chips, S5P_VA_GPIO);
+#if defined(CONFIG_CPU_S5PV210) && defined(CONFIG_S5P_GPIO_INT)
+               s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
+#endif
+       } else if (soc_is_exynos4210()) {
+               group = 0;
+
+               /* gpio part1 */
+               chip = exynos4_gpios_1;
+               nr_chips = ARRAY_SIZE(exynos4_gpios_1);
+
+               for (i = 0; i < nr_chips; i++, chip++) {
+                       if (!chip->config) {
+                               chip->config = &exynos4_gpio_cfg;
+                               chip->group = group++;
+                       }
+               }
+               samsung_gpiolib_add_4bit_chips(exynos4_gpios_1, nr_chips, S5P_VA_GPIO1);
+
+               /* gpio part2 */
+               chip = exynos4_gpios_2;
+               nr_chips = ARRAY_SIZE(exynos4_gpios_2);
+
+               for (i = 0; i < nr_chips; i++, chip++) {
+                       if (!chip->config) {
+                               chip->config = &exynos4_gpio_cfg;
+                               chip->group = group++;
+                       }
+               }
+               samsung_gpiolib_add_4bit_chips(exynos4_gpios_2, nr_chips, S5P_VA_GPIO2);
+
+               /* gpio part3 */
+               chip = exynos4_gpios_3;
+               nr_chips = ARRAY_SIZE(exynos4_gpios_3);
+
+               for (i = 0; i < nr_chips; i++, chip++) {
+                       if (!chip->config) {
+                               chip->config = &exynos4_gpio_cfg;
+                               chip->group = group++;
+                       }
+               }
+               samsung_gpiolib_add_4bit_chips(exynos4_gpios_3, nr_chips, S5P_VA_GPIO3);
+
+#if defined(CONFIG_CPU_EXYNOS4210) && defined(CONFIG_S5P_GPIO_INT)
+               s5p_register_gpioint_bank(IRQ_GPIO_XA, 0, IRQ_GPIO1_NR_GROUPS);
+               s5p_register_gpioint_bank(IRQ_GPIO_XB, IRQ_GPIO1_NR_GROUPS, IRQ_GPIO2_NR_GROUPS);
+#endif
+       } else {
+               WARN(1, "Unknown SoC in gpio-samsung, no GPIOs added\n");
+               return -ENODEV;
+       }
+
+       return 0;
+}
+core_initcall(samsung_gpiolib_init);
+
+int s3c_gpio_cfgpin(unsigned int pin, unsigned int config)
+{
+       struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
+       unsigned long flags;
+       int offset;
+       int ret;
+
+       if (!chip)
+               return -EINVAL;
+
+       offset = pin - chip->chip.base;
+
+       samsung_gpio_lock(chip, flags);
+       ret = samsung_gpio_do_setcfg(chip, offset, config);
+       samsung_gpio_unlock(chip, flags);
+
+       return ret;
+}
+EXPORT_SYMBOL(s3c_gpio_cfgpin);
+
+int s3c_gpio_cfgpin_range(unsigned int start, unsigned int nr,
+                         unsigned int cfg)
+{
+       int ret;
+
+       for (; nr > 0; nr--, start++) {
+               ret = s3c_gpio_cfgpin(start, cfg);
+               if (ret != 0)
+                       return ret;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(s3c_gpio_cfgpin_range);
+
+int s3c_gpio_cfgall_range(unsigned int start, unsigned int nr,
+                         unsigned int cfg, samsung_gpio_pull_t pull)
+{
+       int ret;
+
+       for (; nr > 0; nr--, start++) {
+               s3c_gpio_setpull(start, pull);
+               ret = s3c_gpio_cfgpin(start, cfg);
+               if (ret != 0)
+                       return ret;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(s3c_gpio_cfgall_range);
+
+unsigned s3c_gpio_getcfg(unsigned int pin)
+{
+       struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
+       unsigned long flags;
+       unsigned ret = 0;
+       int offset;
+
+       if (chip) {
+               offset = pin - chip->chip.base;
+
+               samsung_gpio_lock(chip, flags);
+               ret = samsung_gpio_do_getcfg(chip, offset);
+               samsung_gpio_unlock(chip, flags);
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL(s3c_gpio_getcfg);
+
+int s3c_gpio_setpull(unsigned int pin, samsung_gpio_pull_t pull)
+{
+       struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
+       unsigned long flags;
+       int offset, ret;
+
+       if (!chip)
+               return -EINVAL;
+
+       offset = pin - chip->chip.base;
+
+       samsung_gpio_lock(chip, flags);
+       ret = samsung_gpio_do_setpull(chip, offset, pull);
+       samsung_gpio_unlock(chip, flags);
+
+       return ret;
+}
+EXPORT_SYMBOL(s3c_gpio_setpull);
+
+samsung_gpio_pull_t s3c_gpio_getpull(unsigned int pin)
+{
+       struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
+       unsigned long flags;
+       int offset;
+       u32 pup = 0;
+
+       if (chip) {
+               offset = pin - chip->chip.base;
+
+               samsung_gpio_lock(chip, flags);
+               pup = samsung_gpio_do_getpull(chip, offset);
+               samsung_gpio_unlock(chip, flags);
+       }
+
+       return (__force samsung_gpio_pull_t)pup;
+}
+EXPORT_SYMBOL(s3c_gpio_getpull);
+
+/* gpiolib wrappers until these are totally eliminated */
+
+void s3c2410_gpio_pullup(unsigned int pin, unsigned int to)
+{
+       int ret;
+
+       WARN_ON(to);    /* should be none of these left */
+
+       if (!to) {
+               /* if pull is enabled, try first with up, and if that
+                * fails, try using down */
+
+               ret = s3c_gpio_setpull(pin, S3C_GPIO_PULL_UP);
+               if (ret)
+                       s3c_gpio_setpull(pin, S3C_GPIO_PULL_DOWN);
+       } else {
+               s3c_gpio_setpull(pin, S3C_GPIO_PULL_NONE);
+       }
+}
+EXPORT_SYMBOL(s3c2410_gpio_pullup);
+
+void s3c2410_gpio_setpin(unsigned int pin, unsigned int to)
+{
+       /* do this via gpiolib until all users removed */
+
+       gpio_request(pin, "temporary");
+       gpio_set_value(pin, to);
+       gpio_free(pin);
+}
+EXPORT_SYMBOL(s3c2410_gpio_setpin);
+
+unsigned int s3c2410_gpio_getpin(unsigned int pin)
+{
+       struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
+       unsigned long offs = pin - chip->chip.base;
+
+       return __raw_readl(chip->base + 0x04) & (1 << offs);
+}
+EXPORT_SYMBOL(s3c2410_gpio_getpin);
+
+#ifdef CONFIG_S5P_GPIO_DRVSTR
+s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin)
+{
+       struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
+       unsigned int off;
+       void __iomem *reg;
+       int shift;
+       u32 drvstr;
+
+       if (!chip)
+               return -EINVAL;
+
+       off = pin - chip->chip.base;
+       shift = off * 2;
+       reg = chip->base + 0x0C;
+
+       drvstr = __raw_readl(reg);
+       drvstr = drvstr >> shift;
+       drvstr &= 0x3;
+
+       return (__force s5p_gpio_drvstr_t)drvstr;
+}
+EXPORT_SYMBOL(s5p_gpio_get_drvstr);
+
+int s5p_gpio_set_drvstr(unsigned int pin, s5p_gpio_drvstr_t drvstr)
+{
+       struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
+       unsigned int off;
+       void __iomem *reg;
+       int shift;
+       u32 tmp;
+
+       if (!chip)
+               return -EINVAL;
+
+       off = pin - chip->chip.base;
+       shift = off * 2;
+       reg = chip->base + 0x0C;
+
+       tmp = __raw_readl(reg);
+       tmp &= ~(0x3 << shift);
+       tmp |= drvstr << shift;
+
+       __raw_writel(tmp, reg);
+
+       return 0;
+}
+EXPORT_SYMBOL(s5p_gpio_set_drvstr);
+#endif /* CONFIG_S5P_GPIO_DRVSTR */
+
+#ifdef CONFIG_PLAT_S3C24XX
+unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change)
+{
+       unsigned long flags;
+       unsigned long misccr;
+
+       local_irq_save(flags);
+       misccr = __raw_readl(S3C24XX_MISCCR);
+       misccr &= ~clear;
+       misccr ^= change;
+       __raw_writel(misccr, S3C24XX_MISCCR);
+       local_irq_restore(flags);
+
+       return misccr;
+}
+EXPORT_SYMBOL(s3c2410_modify_misccr);
+#endif
index 9b347ac..9ec854a 100644 (file)
@@ -335,6 +335,7 @@ config SENSORS_I5K_AMB
 
 config SENSORS_F71805F
        tristate "Fintek F71805F/FG, F71806F/FG and F71872F/FG"
+       depends on !PPC
        help
          If you say yes here you get support for hardware monitoring
          features of the Fintek F71805F/FG, F71806F/FG and F71872F/FG
@@ -345,6 +346,7 @@ config SENSORS_F71805F
 
 config SENSORS_F71882FG
        tristate "Fintek F71882FG and compatibles"
+       depends on !PPC
        help
          If you say yes here you get support for hardware monitoring
          features of many Fintek Super-I/O (LPC) chips. The currently
@@ -468,6 +470,7 @@ config SENSORS_IBMPEX
 
 config SENSORS_IT87
        tristate "ITE IT87xx and compatibles"
+       depends on !PPC
        select HWMON_VID
        help
          If you say yes here you get support for ITE IT8705F, IT8712F,
@@ -824,6 +827,7 @@ config SENSORS_NTC_THERMISTOR
 
 config SENSORS_PC87360
        tristate "National Semiconductor PC87360 family"
+       depends on !PPC
        select HWMON_VID
        help
          If you say yes here you get access to the hardware monitoring
@@ -837,6 +841,7 @@ config SENSORS_PC87360
 
 config SENSORS_PC87427
        tristate "National Semiconductor PC87427"
+       depends on !PPC
        help
          If you say yes here you get access to the hardware monitoring
          functions of the National Semiconductor PC87427 Super-I/O chip.
@@ -928,7 +933,7 @@ config SENSORS_SMM665
 
 config SENSORS_DME1737
        tristate "SMSC DME1737, SCH311x and compatibles"
-       depends on I2C && EXPERIMENTAL
+       depends on I2C && EXPERIMENTAL && !PPC
        select HWMON_VID
        help
          If you say yes here you get support for the hardware monitoring
@@ -970,6 +975,7 @@ config SENSORS_EMC6W201
 
 config SENSORS_SMSC47M1
        tristate "SMSC LPC47M10x and compatibles"
+       depends on !PPC
        help
          If you say yes here you get support for the integrated fan
          monitoring and control capabilities of the SMSC LPC47B27x,
@@ -1003,7 +1009,7 @@ config SENSORS_SMSC47M192
 
 config SENSORS_SMSC47B397
        tristate "SMSC LPC47B397-NC"
-       depends on EXPERIMENTAL
+       depends on EXPERIMENTAL && !PPC
        help
          If you say yes here you get support for the SMSC LPC47B397-NC
          sensor chip.
@@ -1017,6 +1023,7 @@ config SENSORS_SCH56XX_COMMON
 
 config SENSORS_SCH5627
        tristate "SMSC SCH5627"
+       depends on !PPC
        select SENSORS_SCH56XX_COMMON
        help
          If you say yes here you get support for the hardware monitoring
@@ -1027,6 +1034,7 @@ config SENSORS_SCH5627
 
 config SENSORS_SCH5636
        tristate "SMSC SCH5636"
+       depends on !PPC
        select SENSORS_SCH56XX_COMMON
        help
          SMSC SCH5636 Super I/O chips include an embedded microcontroller for
@@ -1150,6 +1158,7 @@ config SENSORS_VIA686A
 
 config SENSORS_VT1211
        tristate "VIA VT1211"
+       depends on !PPC
        select HWMON_VID
        help
          If you say yes here then you get support for hardware monitoring
@@ -1262,6 +1271,7 @@ config SENSORS_W83L786NG
 
 config SENSORS_W83627HF
        tristate "Winbond W83627HF, W83627THF, W83637HF, W83687THF, W83697HF"
+       depends on !PPC
        select HWMON_VID
        help
          If you say yes here you get support for the Winbond W836X7 series
@@ -1272,7 +1282,8 @@ config SENSORS_W83627HF
          will be called w83627hf.
 
 config SENSORS_W83627EHF
-       tristate "Winbond W83627EHF/EHG/DHG, W83667HG, NCT6775F, NCT6776F"
+       tristate "Winbond W83627EHF/EHG/DHG/UHG, W83667HG, NCT6775F, NCT6776F"
+       depends on !PPC
        select HWMON_VID
        help
          If you say yes here you get support for the hardware
@@ -1281,7 +1292,8 @@ config SENSORS_W83627EHF
          This driver also supports the W83627EHG, which is the lead-free
          version of the W83627EHF, and the W83627DHG, which is a similar
          chip suited for specific Intel processors that use PECI such as
-         the Core 2 Duo.
+         the Core 2 Duo. And also the W83627UHG, which is a stripped down
+         version of the W83627DHG (as far as hardware monitoring goes.)
 
          This driver also supports Nuvoton W83667HG, W83667HG-B, NCT6775F
          (also known as W83667HG-I), and NCT6776F.
index d46c0c7..df29a7f 100644 (file)
@@ -58,10 +58,9 @@ static inline int ad7414_temp_from_reg(s16 reg)
 
 static inline int ad7414_read(struct i2c_client *client, u8 reg)
 {
-       if (reg == AD7414_REG_TEMP) {
-               int value = i2c_smbus_read_word_data(client, reg);
-               return (value < 0) ? value : swab16(value);
-       } else
+       if (reg == AD7414_REG_TEMP)
+               return i2c_smbus_read_word_swapped(client, reg);
+       else
                return i2c_smbus_read_byte_data(client, reg);
 }
 
index ffc781f..8cb718c 100644 (file)
@@ -76,20 +76,6 @@ static struct i2c_driver ad7418_driver = {
        .id_table       = ad7418_id,
 };
 
-/* All registers are word-sized, except for the configuration registers.
- * AD7418 uses a high-byte first convention. Do NOT use those functions to
- * access the configuration registers CONF and CONF2, as they are byte-sized.
- */
-static inline int ad7418_read(struct i2c_client *client, u8 reg)
-{
-       return swab16(i2c_smbus_read_word_data(client, reg));
-}
-
-static inline int ad7418_write(struct i2c_client *client, u8 reg, u16 value)
-{
-       return i2c_smbus_write_word_data(client, reg, swab16(value));
-}
-
 static void ad7418_init_client(struct i2c_client *client)
 {
        struct ad7418_data *data = i2c_get_clientdata(client);
@@ -128,7 +114,9 @@ static struct ad7418_data *ad7418_update_device(struct device *dev)
                udelay(30);
 
                for (i = 0; i < 3; i++) {
-                       data->temp[i] = ad7418_read(client, AD7418_REG_TEMP[i]);
+                       data->temp[i] =
+                               i2c_smbus_read_word_swapped(client,
+                                               AD7418_REG_TEMP[i]);
                }
 
                for (i = 0, ch = 4; i < data->adc_max; i++, ch--) {
@@ -138,11 +126,12 @@ static struct ad7418_data *ad7418_update_device(struct device *dev)
 
                        udelay(15);
                        data->in[data->adc_max - 1 - i] =
-                               ad7418_read(client, AD7418_REG_ADC);
+                               i2c_smbus_read_word_swapped(client,
+                                               AD7418_REG_ADC);
                }
 
                /* restore old configuration value */
-               ad7418_write(client, AD7418_REG_CONF, cfg);
+               i2c_smbus_write_word_swapped(client, AD7418_REG_CONF, cfg);
 
                data->last_updated = jiffies;
                data->valid = 1;
@@ -182,7 +171,9 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *devattr,
 
        mutex_lock(&data->lock);
        data->temp[attr->index] = LM75_TEMP_TO_REG(temp);
-       ad7418_write(client, AD7418_REG_TEMP[attr->index], data->temp[attr->index]);
+       i2c_smbus_write_word_swapped(client,
+                                    AD7418_REG_TEMP[attr->index],
+                                    data->temp[attr->index]);
        mutex_unlock(&data->lock);
        return count;
 }
index e9beeda..eedca3c 100644 (file)
@@ -59,19 +59,6 @@ struct ads1015_data {
        struct ads1015_channel_data channel_data[ADS1015_CHANNELS];
 };
 
-static s32 ads1015_read_reg(struct i2c_client *client, unsigned int reg)
-{
-       s32 data = i2c_smbus_read_word_data(client, reg);
-
-       return (data < 0) ? data : swab16(data);
-}
-
-static s32 ads1015_write_reg(struct i2c_client *client, unsigned int reg,
-                            u16 val)
-{
-       return i2c_smbus_write_word_data(client, reg, swab16(val));
-}
-
 static int ads1015_read_value(struct i2c_client *client, unsigned int channel,
                              int *value)
 {
@@ -87,7 +74,7 @@ static int ads1015_read_value(struct i2c_client *client, unsigned int channel,
        mutex_lock(&data->update_lock);
 
        /* get channel parameters */
-       res = ads1015_read_reg(client, ADS1015_CONFIG);
+       res = i2c_smbus_read_word_swapped(client, ADS1015_CONFIG);
        if (res < 0)
                goto err_unlock;
        config = res;
@@ -101,13 +88,13 @@ static int ads1015_read_value(struct i2c_client *client, unsigned int channel,
        config |= (pga & 0x0007) << 9;
        config |= (data_rate & 0x0007) << 5;
 
-       res = ads1015_write_reg(client, ADS1015_CONFIG, config);
+       res = i2c_smbus_write_word_swapped(client, ADS1015_CONFIG, config);
        if (res < 0)
                goto err_unlock;
 
        /* wait until conversion finished */
        msleep(conversion_time_ms);
-       res = ads1015_read_reg(client, ADS1015_CONFIG);
+       res = i2c_smbus_read_word_swapped(client, ADS1015_CONFIG);
        if (res < 0)
                goto err_unlock;
        config = res;
@@ -117,7 +104,7 @@ static int ads1015_read_value(struct i2c_client *client, unsigned int channel,
                goto err_unlock;
        }
 
-       res = ads1015_read_reg(client, ADS1015_CONVERSION);
+       res = i2c_smbus_read_word_swapped(client, ADS1015_CONVERSION);
        if (res < 0)
                goto err_unlock;
        conversion = res;
index c42c5a6..cfcc3b6 100644 (file)
@@ -74,13 +74,6 @@ static int ads7828_detect(struct i2c_client *client,
 static int ads7828_probe(struct i2c_client *client,
                         const struct i2c_device_id *id);
 
-/* The ADS7828 returns the 12-bit sample in two bytes,
-       these are read as a word then byte-swapped */
-static u16 ads7828_read_value(struct i2c_client *client, u8 reg)
-{
-       return swab16(i2c_smbus_read_word_data(client, reg));
-}
-
 static inline u8 channel_cmd_byte(int ch)
 {
        /* cmd byte C2,C1,C0 - see datasheet */
@@ -104,7 +97,8 @@ static struct ads7828_data *ads7828_update_device(struct device *dev)
 
                for (ch = 0; ch < ADS7828_NCH; ch++) {
                        u8 cmd = channel_cmd_byte(ch);
-                       data->adc_input[ch] = ads7828_read_value(client, cmd);
+                       data->adc_input[ch] =
+                               i2c_smbus_read_word_swapped(client, cmd);
                }
                data->last_updated = jiffies;
                data->valid = 1;
@@ -203,7 +197,7 @@ static int ads7828_detect(struct i2c_client *client,
        for (ch = 0; ch < ADS7828_NCH; ch++) {
                u16 in_data;
                u8 cmd = channel_cmd_byte(ch);
-               in_data = ads7828_read_value(client, cmd);
+               in_data = i2c_smbus_read_word_swapped(client, cmd);
                if (in_data & 0xF000) {
                        pr_debug("%s : Doesn't look like an ads7828 device\n",
                                 __func__);
index c02a052..d7bd1f3 100644 (file)
@@ -829,17 +829,17 @@ static int asb100_read_value(struct i2c_client *client, u16 reg)
                /* convert from ISA to LM75 I2C addresses */
                switch (reg & 0xff) {
                case 0x50: /* TEMP */
-                       res = swab16(i2c_smbus_read_word_data(cl, 0));
+                       res = i2c_smbus_read_word_swapped(cl, 0);
                        break;
                case 0x52: /* CONFIG */
                        res = i2c_smbus_read_byte_data(cl, 1);
                        break;
                case 0x53: /* HYST */
-                       res = swab16(i2c_smbus_read_word_data(cl, 2));
+                       res = i2c_smbus_read_word_swapped(cl, 2);
                        break;
                case 0x55: /* MAX */
                default:
-                       res = swab16(i2c_smbus_read_word_data(cl, 3));
+                       res = i2c_smbus_read_word_swapped(cl, 3);
                        break;
                }
        }
@@ -877,10 +877,10 @@ static void asb100_write_value(struct i2c_client *client, u16 reg, u16 value)
                        i2c_smbus_write_byte_data(cl, 1, value & 0xff);
                        break;
                case 0x53: /* HYST */
-                       i2c_smbus_write_word_data(cl, 2, swab16(value));
+                       i2c_smbus_write_word_swapped(cl, 2, value);
                        break;
                case 0x55: /* MAX */
-                       i2c_smbus_write_word_data(cl, 3, swab16(value));
+                       i2c_smbus_write_word_swapped(cl, 3, value);
                        break;
                }
        }
index ce18c04..104b376 100644 (file)
@@ -60,14 +60,13 @@ MODULE_PARM_DESC(tjmax, "TjMax value in degrees Celsius");
 #ifdef CONFIG_SMP
 #define TO_PHYS_ID(cpu)                cpu_data(cpu).phys_proc_id
 #define TO_CORE_ID(cpu)                cpu_data(cpu).cpu_core_id
-#define TO_ATTR_NO(cpu)                (TO_CORE_ID(cpu) + BASE_SYSFS_ATTR_NO)
 #define for_each_sibling(i, cpu)       for_each_cpu(i, cpu_sibling_mask(cpu))
 #else
 #define TO_PHYS_ID(cpu)                (cpu)
 #define TO_CORE_ID(cpu)                (cpu)
-#define TO_ATTR_NO(cpu)                (cpu)
 #define for_each_sibling(i, cpu)       for (i = 0; false; )
 #endif
+#define TO_ATTR_NO(cpu)                (TO_CORE_ID(cpu) + BASE_SYSFS_ATTR_NO)
 
 /*
  * Per-Core Temperature Data
index e113634..ef1ac99 100644 (file)
@@ -80,24 +80,6 @@ struct ds1621_data {
        u8 conf;                        /* Register encoding, combined */
 };
 
-/* Temperature registers are word-sized.
-   DS1621 uses a high-byte first convention, which is exactly opposite to
-   the SMBus standard. */
-static int ds1621_read_temp(struct i2c_client *client, u8 reg)
-{
-       int ret;
-
-       ret = i2c_smbus_read_word_data(client, reg);
-       if (ret < 0)
-               return ret;
-       return swab16(ret);
-}
-
-static int ds1621_write_temp(struct i2c_client *client, u8 reg, u16 value)
-{
-       return i2c_smbus_write_word_data(client, reg, swab16(value));
-}
-
 static void ds1621_init_client(struct i2c_client *client)
 {
        u8 conf, new_conf;
@@ -136,7 +118,7 @@ static struct ds1621_data *ds1621_update_client(struct device *dev)
                data->conf = i2c_smbus_read_byte_data(client, DS1621_REG_CONF);
 
                for (i = 0; i < ARRAY_SIZE(data->temp); i++)
-                       data->temp[i] = ds1621_read_temp(client,
+                       data->temp[i] = i2c_smbus_read_word_swapped(client,
                                                         DS1621_REG_TEMP[i]);
 
                /* reset alarms if necessary */
@@ -177,8 +159,8 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *da,
 
        mutex_lock(&data->update_lock);
        data->temp[attr->index] = val;
-       ds1621_write_temp(client, DS1621_REG_TEMP[attr->index],
-                         data->temp[attr->index]);
+       i2c_smbus_write_word_swapped(client, DS1621_REG_TEMP[attr->index],
+                                    data->temp[attr->index]);
        mutex_unlock(&data->update_lock);
        return count;
 }
index 4f7c3fc..225ae4f 100644 (file)
@@ -75,33 +75,13 @@ struct ds620_data {
        s16 temp[3];            /* Register values, word */
 };
 
-/*
- *  Temperature registers are word-sized.
- *  DS620 uses a high-byte first convention, which is exactly opposite to
- *  the SMBus standard.
- */
-static int ds620_read_temp(struct i2c_client *client, u8 reg)
-{
-       int ret;
-
-       ret = i2c_smbus_read_word_data(client, reg);
-       if (ret < 0)
-               return ret;
-       return swab16(ret);
-}
-
-static int ds620_write_temp(struct i2c_client *client, u8 reg, u16 value)
-{
-       return i2c_smbus_write_word_data(client, reg, swab16(value));
-}
-
 static void ds620_init_client(struct i2c_client *client)
 {
        struct ds620_platform_data *ds620_info = client->dev.platform_data;
        u16 conf, new_conf;
 
        new_conf = conf =
-           swab16(i2c_smbus_read_word_data(client, DS620_REG_CONF));
+           i2c_smbus_read_word_swapped(client, DS620_REG_CONF);
 
        /* switch to continuous conversion mode */
        new_conf &= ~DS620_REG_CONFIG_1SHOT;
@@ -118,8 +98,7 @@ static void ds620_init_client(struct i2c_client *client)
        new_conf |= DS620_REG_CONFIG_R1 | DS620_REG_CONFIG_R0;
 
        if (conf != new_conf)
-               i2c_smbus_write_word_data(client, DS620_REG_CONF,
-                                         swab16(new_conf));
+               i2c_smbus_write_word_swapped(client, DS620_REG_CONF, new_conf);
 
        /* start conversion */
        i2c_smbus_write_byte(client, DS620_COM_START);
@@ -141,8 +120,8 @@ static struct ds620_data *ds620_update_client(struct device *dev)
                dev_dbg(&client->dev, "Starting ds620 update\n");
 
                for (i = 0; i < ARRAY_SIZE(data->temp); i++) {
-                       res = ds620_read_temp(client,
-                                             DS620_REG_TEMP[i]);
+                       res = i2c_smbus_read_word_swapped(client,
+                                                         DS620_REG_TEMP[i]);
                        if (res < 0) {
                                ret = ERR_PTR(res);
                                goto abort;
@@ -191,8 +170,8 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *da,
 
        mutex_lock(&data->update_lock);
        data->temp[attr->index] = val;
-       ds620_write_temp(client, DS620_REG_TEMP[attr->index],
-                        data->temp[attr->index]);
+       i2c_smbus_write_word_swapped(client, DS620_REG_TEMP[attr->index],
+                                    data->temp[attr->index]);
        mutex_unlock(&data->update_lock);
        return count;
 }
@@ -210,16 +189,15 @@ static ssize_t show_alarm(struct device *dev, struct device_attribute *da,
                return PTR_ERR(data);
 
        /* reset alarms if necessary */
-       res = i2c_smbus_read_word_data(client, DS620_REG_CONF);
+       res = i2c_smbus_read_word_swapped(client, DS620_REG_CONF);
        if (res < 0)
                return res;
 
-       conf = swab16(res);
-       new_conf = conf;
+       new_conf = conf = res;
        new_conf &= ~attr->index;
        if (conf != new_conf) {
-               res = i2c_smbus_write_word_data(client, DS620_REG_CONF,
-                                               swab16(new_conf));
+               res = i2c_smbus_write_word_swapped(client, DS620_REG_CONF,
+                                                  new_conf);
                if (res < 0)
                        return res;
        }
index e7ae574..a13e2da 100644 (file)
@@ -591,7 +591,7 @@ static int gl518_remove(struct i2c_client *client)
 static int gl518_read_value(struct i2c_client *client, u8 reg)
 {
        if ((reg >= 0x07) && (reg <= 0x0c))
-               return swab16(i2c_smbus_read_word_data(client, reg));
+               return i2c_smbus_read_word_swapped(client, reg);
        else
                return i2c_smbus_read_byte_data(client, reg);
 }
@@ -599,7 +599,7 @@ static int gl518_read_value(struct i2c_client *client, u8 reg)
 static int gl518_write_value(struct i2c_client *client, u8 reg, u16 value)
 {
        if ((reg >= 0x07) && (reg <= 0x0c))
-               return i2c_smbus_write_word_data(client, reg, swab16(value));
+               return i2c_smbus_write_word_swapped(client, reg, value);
        else
                return i2c_smbus_write_byte_data(client, reg, value);
 }
index 131ea86..cd6085b 100644 (file)
@@ -821,7 +821,7 @@ static int gl520_remove(struct i2c_client *client)
 static int gl520_read_value(struct i2c_client *client, u8 reg)
 {
        if ((reg >= 0x07) && (reg <= 0x0c))
-               return swab16(i2c_smbus_read_word_data(client, reg));
+               return i2c_smbus_read_word_swapped(client, reg);
        else
                return i2c_smbus_read_byte_data(client, reg);
 }
@@ -829,7 +829,7 @@ static int gl520_read_value(struct i2c_client *client, u8 reg)
 static int gl520_write_value(struct i2c_client *client, u8 reg, u16 value)
 {
        if ((reg >= 0x07) && (reg <= 0x0c))
-               return i2c_smbus_write_word_data(client, reg, swab16(value));
+               return i2c_smbus_write_word_swapped(client, reg, value);
        else
                return i2c_smbus_write_byte_data(client, reg, value);
 }
index 783d0c1..6a967d7 100644 (file)
@@ -147,8 +147,9 @@ struct aem_data {
        int                     id;
        struct aem_ipmi_data    ipmi;
 
-       /* Function to update sensors */
+       /* Function and buffer to update sensors */
        void (*update)(struct aem_data *data);
+       struct aem_read_sensor_resp *rs_resp;
 
        /*
         * AEM 1.x sensors:
@@ -245,8 +246,6 @@ static void aem_bmc_gone(int iface);
 static void aem_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data);
 
 static void aem_remove_sensors(struct aem_data *data);
-static int aem_init_aem1(struct aem_ipmi_data *probe);
-static int aem_init_aem2(struct aem_ipmi_data *probe);
 static int aem1_find_sensors(struct aem_data *data);
 static int aem2_find_sensors(struct aem_data *data);
 static void update_aem1_sensors(struct aem_data *data);
@@ -357,13 +356,14 @@ static void aem_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data)
 
 /* Sensor support functions */
 
-/* Read a sensor value */
+/* Read a sensor value; must be called with data->lock held */
 static int aem_read_sensor(struct aem_data *data, u8 elt, u8 reg,
                           void *buf, size_t size)
 {
        int rs_size, res;
        struct aem_read_sensor_req rs_req;
-       struct aem_read_sensor_resp *rs_resp;
+       /* Use preallocated rx buffer */
+       struct aem_read_sensor_resp *rs_resp = data->rs_resp;
        struct aem_ipmi_data *ipmi = &data->ipmi;
 
        /* AEM registers are 1, 2, 4 or 8 bytes */
@@ -389,10 +389,6 @@ static int aem_read_sensor(struct aem_data *data, u8 elt, u8 reg,
        ipmi->tx_message.data_len = sizeof(rs_req);
 
        rs_size = sizeof(*rs_resp) + size;
-       rs_resp = kzalloc(rs_size, GFP_KERNEL);
-       if (!rs_resp)
-               return -ENOMEM;
-
        ipmi->rx_msg_data = rs_resp;
        ipmi->rx_msg_len = rs_size;
 
@@ -435,7 +431,6 @@ static int aem_read_sensor(struct aem_data *data, u8 elt, u8 reg,
        res = 0;
 
 out:
-       kfree(rs_resp);
        return res;
 }
 
@@ -493,6 +488,7 @@ static void aem_delete(struct aem_data *data)
 {
        list_del(&data->list);
        aem_remove_sensors(data);
+       kfree(data->rs_resp);
        hwmon_device_unregister(data->hwmon_dev);
        ipmi_destroy_user(data->ipmi.user);
        platform_set_drvdata(data->pdev, NULL);
@@ -570,24 +566,31 @@ static int aem_init_aem1_inst(struct aem_ipmi_data *probe, u8 module_handle)
        platform_set_drvdata(data->pdev, data);
 
        /* Set up IPMI interface */
-       if (aem_init_ipmi_data(&data->ipmi, probe->interface,
-                              probe->bmc_device))
+       res = aem_init_ipmi_data(&data->ipmi, probe->interface,
+                                probe->bmc_device);
+       if (res)
                goto ipmi_err;
 
        /* Register with hwmon */
        data->hwmon_dev = hwmon_device_register(&data->pdev->dev);
-
        if (IS_ERR(data->hwmon_dev)) {
                dev_err(&data->pdev->dev, "Unable to register hwmon "
                        "device for IPMI interface %d\n",
                        probe->interface);
+               res = PTR_ERR(data->hwmon_dev);
                goto hwmon_reg_err;
        }
 
        data->update = update_aem1_sensors;
+       data->rs_resp = kzalloc(sizeof(*(data->rs_resp)) + 8, GFP_KERNEL);
+       if (!data->rs_resp) {
+               res = -ENOMEM;
+               goto alloc_resp_err;
+       }
 
        /* Find sensors */
-       if (aem1_find_sensors(data))
+       res = aem1_find_sensors(data);
+       if (res)
                goto sensor_err;
 
        /* Add to our list of AEM devices */
@@ -599,6 +602,8 @@ static int aem_init_aem1_inst(struct aem_ipmi_data *probe, u8 module_handle)
        return 0;
 
 sensor_err:
+       kfree(data->rs_resp);
+alloc_resp_err:
        hwmon_device_unregister(data->hwmon_dev);
 hwmon_reg_err:
        ipmi_destroy_user(data->ipmi.user);
@@ -614,7 +619,7 @@ id_err:
 }
 
 /* Find and initialize all AEM1 instances */
-static int aem_init_aem1(struct aem_ipmi_data *probe)
+static void aem_init_aem1(struct aem_ipmi_data *probe)
 {
        int num, i, err;
 
@@ -625,11 +630,8 @@ static int aem_init_aem1(struct aem_ipmi_data *probe)
                        dev_err(probe->bmc_device,
                                "Error %d initializing AEM1 0x%X\n",
                                err, i);
-                       return err;
                }
        }
-
-       return 0;
 }
 
 /* Probe functions for AEM2 devices */
@@ -704,24 +706,31 @@ static int aem_init_aem2_inst(struct aem_ipmi_data *probe,
        platform_set_drvdata(data->pdev, data);
 
        /* Set up IPMI interface */
-       if (aem_init_ipmi_data(&data->ipmi, probe->interface,
-                              probe->bmc_device))
+       res = aem_init_ipmi_data(&data->ipmi, probe->interface,
+                                probe->bmc_device);
+       if (res)
                goto ipmi_err;
 
        /* Register with hwmon */
        data->hwmon_dev = hwmon_device_register(&data->pdev->dev);
-
        if (IS_ERR(data->hwmon_dev)) {
                dev_err(&data->pdev->dev, "Unable to register hwmon "
                        "device for IPMI interface %d\n",
                        probe->interface);
+               res = PTR_ERR(data->hwmon_dev);
                goto hwmon_reg_err;
        }
 
        data->update = update_aem2_sensors;
+       data->rs_resp = kzalloc(sizeof(*(data->rs_resp)) + 8, GFP_KERNEL);
+       if (!data->rs_resp) {
+               res = -ENOMEM;
+               goto alloc_resp_err;
+       }
 
        /* Find sensors */
-       if (aem2_find_sensors(data))
+       res = aem2_find_sensors(data);
+       if (res)
                goto sensor_err;
 
        /* Add to our list of AEM devices */
@@ -733,6 +742,8 @@ static int aem_init_aem2_inst(struct aem_ipmi_data *probe,
        return 0;
 
 sensor_err:
+       kfree(data->rs_resp);
+alloc_resp_err:
        hwmon_device_unregister(data->hwmon_dev);
 hwmon_reg_err:
        ipmi_destroy_user(data->ipmi.user);
@@ -748,7 +759,7 @@ id_err:
 }
 
 /* Find and initialize all AEM2 instances */
-static int aem_init_aem2(struct aem_ipmi_data *probe)
+static void aem_init_aem2(struct aem_ipmi_data *probe)
 {
        struct aem_find_instance_resp fi_resp;
        int err;
@@ -767,12 +778,9 @@ static int aem_init_aem2(struct aem_ipmi_data *probe)
                        dev_err(probe->bmc_device,
                                "Error %d initializing AEM2 0x%X\n",
                                err, fi_resp.module_handle);
-                       return err;
                }
                i++;
        }
-
-       return 0;
 }
 
 /* Probe a BMC for AEM firmware instances */
index 02cebb7..2d3d728 100644 (file)
@@ -154,8 +154,6 @@ static int jc42_probe(struct i2c_client *client,
                      const struct i2c_device_id *id);
 static int jc42_detect(struct i2c_client *client, struct i2c_board_info *info);
 static int jc42_remove(struct i2c_client *client);
-static int jc42_read_value(struct i2c_client *client, u8 reg);
-static int jc42_write_value(struct i2c_client *client, u8 reg, u16 value);
 
 static struct jc42_data *jc42_update_device(struct device *dev);
 
@@ -187,7 +185,7 @@ static int jc42_suspend(struct device *dev)
        struct jc42_data *data = i2c_get_clientdata(client);
 
        data->config |= JC42_CFG_SHUTDOWN;
-       jc42_write_value(client, JC42_REG_CONFIG, data->config);
+       i2c_smbus_write_word_swapped(client, JC42_REG_CONFIG, data->config);
        return 0;
 }
 
@@ -197,7 +195,7 @@ static int jc42_resume(struct device *dev)
        struct jc42_data *data = i2c_get_clientdata(client);
 
        data->config &= ~JC42_CFG_SHUTDOWN;
-       jc42_write_value(client, JC42_REG_CONFIG, data->config);
+       i2c_smbus_write_word_swapped(client, JC42_REG_CONFIG, data->config);
        return 0;
 }
 
@@ -315,7 +313,7 @@ static ssize_t set_##value(struct device *dev,                              \
                return -EINVAL;                                         \
        mutex_lock(&data->update_lock);                                 \
        data->value = jc42_temp_to_reg(val, data->extended);            \
-       err = jc42_write_value(client, reg, data->value);               \
+       err = i2c_smbus_write_word_swapped(client, reg, data->value);   \
        if (err < 0)                                                    \
                ret = err;                                              \
        mutex_unlock(&data->update_lock);                               \
@@ -357,7 +355,8 @@ static ssize_t set_temp_crit_hyst(struct device *dev,
        data->config = (data->config
                        & ~(JC42_CFG_HYST_MASK << JC42_CFG_HYST_SHIFT))
          | (hyst << JC42_CFG_HYST_SHIFT);
-       err = jc42_write_value(client, JC42_REG_CONFIG, data->config);
+       err = i2c_smbus_write_word_swapped(client, JC42_REG_CONFIG,
+                                          data->config);
        if (err < 0)
                ret = err;
        mutex_unlock(&data->update_lock);
@@ -452,10 +451,10 @@ static int jc42_detect(struct i2c_client *new_client,
                                     I2C_FUNC_SMBUS_WORD_DATA))
                return -ENODEV;
 
-       cap = jc42_read_value(new_client, JC42_REG_CAP);
-       config = jc42_read_value(new_client, JC42_REG_CONFIG);
-       manid = jc42_read_value(new_client, JC42_REG_MANID);
-       devid = jc42_read_value(new_client, JC42_REG_DEVICEID);
+       cap = i2c_smbus_read_word_swapped(new_client, JC42_REG_CAP);
+       config = i2c_smbus_read_word_swapped(new_client, JC42_REG_CONFIG);
+       manid = i2c_smbus_read_word_swapped(new_client, JC42_REG_MANID);
+       devid = i2c_smbus_read_word_swapped(new_client, JC42_REG_DEVICEID);
 
        if (cap < 0 || config < 0 || manid < 0 || devid < 0)
                return -ENODEV;
@@ -489,14 +488,14 @@ static int jc42_probe(struct i2c_client *new_client,
        i2c_set_clientdata(new_client, data);
        mutex_init(&data->update_lock);
 
-       cap = jc42_read_value(new_client, JC42_REG_CAP);
+       cap = i2c_smbus_read_word_swapped(new_client, JC42_REG_CAP);
        if (cap < 0) {
                err = -EINVAL;
                goto exit_free;
        }
        data->extended = !!(cap & JC42_CAP_RANGE);
 
-       config = jc42_read_value(new_client, JC42_REG_CONFIG);
+       config = i2c_smbus_read_word_swapped(new_client, JC42_REG_CONFIG);
        if (config < 0) {
                err = -EINVAL;
                goto exit_free;
@@ -504,7 +503,8 @@ static int jc42_probe(struct i2c_client *new_client,
        data->orig_config = config;
        if (config & JC42_CFG_SHUTDOWN) {
                config &= ~JC42_CFG_SHUTDOWN;
-               jc42_write_value(new_client, JC42_REG_CONFIG, config);
+               i2c_smbus_write_word_swapped(new_client, JC42_REG_CONFIG,
+                                            config);
        }
        data->config = config;
 
@@ -535,25 +535,12 @@ static int jc42_remove(struct i2c_client *client)
        hwmon_device_unregister(data->hwmon_dev);
        sysfs_remove_group(&client->dev.kobj, &jc42_group);
        if (data->config != data->orig_config)
-               jc42_write_value(client, JC42_REG_CONFIG, data->orig_config);
+               i2c_smbus_write_word_swapped(client, JC42_REG_CONFIG,
+                                            data->orig_config);
        kfree(data);
        return 0;
 }
 
-/* All registers are word-sized. */
-static int jc42_read_value(struct i2c_client *client, u8 reg)
-{
-       int ret = i2c_smbus_read_word_data(client, reg);
-       if (ret < 0)
-               return ret;
-       return swab16(ret);
-}
-
-static int jc42_write_value(struct i2c_client *client, u8 reg, u16 value)
-{
-       return i2c_smbus_write_word_data(client, reg, swab16(value));
-}
-
 static struct jc42_data *jc42_update_device(struct device *dev)
 {
        struct i2c_client *client = to_i2c_client(dev);
@@ -564,28 +551,29 @@ static struct jc42_data *jc42_update_device(struct device *dev)
        mutex_lock(&data->update_lock);
 
        if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
-               val = jc42_read_value(client, JC42_REG_TEMP);
+               val = i2c_smbus_read_word_swapped(client, JC42_REG_TEMP);
                if (val < 0) {
                        ret = ERR_PTR(val);
                        goto abort;
                }
                data->temp_input = val;
 
-               val = jc42_read_value(client, JC42_REG_TEMP_CRITICAL);
+               val = i2c_smbus_read_word_swapped(client,
+                                                 JC42_REG_TEMP_CRITICAL);
                if (val < 0) {
                        ret = ERR_PTR(val);
                        goto abort;
                }
                data->temp_crit = val;
 
-               val = jc42_read_value(client, JC42_REG_TEMP_LOWER);
+               val = i2c_smbus_read_word_swapped(client, JC42_REG_TEMP_LOWER);
                if (val < 0) {
                        ret = ERR_PTR(val);
                        goto abort;
                }
                data->temp_min = val;
 
-               val = jc42_read_value(client, JC42_REG_TEMP_UPPER);
+               val = i2c_smbus_read_word_swapped(client, JC42_REG_TEMP_UPPER);
                if (val < 0) {
                        ret = ERR_PTR(val);
                        goto abort;
index 29b9030..9e64d96 100644 (file)
@@ -34,7 +34,7 @@ static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4c,
 #define LM73_REG_CTRL          0x04
 #define LM73_REG_ID            0x07
 
-#define LM73_ID                        0x9001 /* or 0x190 after a swab16() */
+#define LM73_ID                        0x9001  /* 0x0190, byte-swapped */
 #define DRVNAME                        "lm73"
 #define LM73_TEMP_MIN          (-40)
 #define LM73_TEMP_MAX          150
@@ -57,7 +57,7 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *da,
        /* Write value */
        value = (short) SENSORS_LIMIT(temp/250, (LM73_TEMP_MIN*4),
                (LM73_TEMP_MAX*4)) << 5;
-       i2c_smbus_write_word_data(client, attr->index, swab16(value));
+       i2c_smbus_write_word_swapped(client, attr->index, value);
        return count;
 }
 
@@ -68,8 +68,8 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *da,
        struct i2c_client *client = to_i2c_client(dev);
        /* use integer division instead of equivalent right shift to
           guarantee arithmetic shift and preserve the sign */
-       int temp = ((s16) (swab16(i2c_smbus_read_word_data(client,
-               attr->index)))*250) / 32;
+       int temp = ((s16) (i2c_smbus_read_word_swapped(client,
+                   attr->index))*250) / 32;
        return sprintf(buf, "%d\n", temp);
 }
 
@@ -150,17 +150,31 @@ static int lm73_detect(struct i2c_client *new_client,
                        struct i2c_board_info *info)
 {
        struct i2c_adapter *adapter = new_client->adapter;
-       u16 id;
-       u8 ctrl;
+       int id, ctrl, conf;
 
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
                                        I2C_FUNC_SMBUS_WORD_DATA))
                return -ENODEV;
 
+       /*
+        * Do as much detection as possible with byte reads first, as word
+        * reads can confuse other devices.
+        */
+       ctrl = i2c_smbus_read_byte_data(new_client, LM73_REG_CTRL);
+       if (ctrl < 0 || (ctrl & 0x10))
+               return -ENODEV;
+
+       conf = i2c_smbus_read_byte_data(new_client, LM73_REG_CONF);
+       if (conf < 0 || (conf & 0x0c))
+               return -ENODEV;
+
+       id = i2c_smbus_read_byte_data(new_client, LM73_REG_ID);
+       if (id < 0 || id != (LM73_ID & 0xff))
+               return -ENODEV;
+
        /* Check device ID */
        id = i2c_smbus_read_word_data(new_client, LM73_REG_ID);
-       ctrl = i2c_smbus_read_byte_data(new_client, LM73_REG_CTRL);
-       if ((id != LM73_ID) || (ctrl & 0x10))
+       if (id < 0 || id != LM73_ID)
                return -ENODEV;
 
        strlcpy(info->type, "lm73", I2C_NAME_SIZE);
index 90126a2..1888dd0 100644 (file)
@@ -384,13 +384,10 @@ static struct i2c_driver lm75_driver = {
  */
 static int lm75_read_value(struct i2c_client *client, u8 reg)
 {
-       int value;
-
        if (reg == LM75_REG_CONF)
                return i2c_smbus_read_byte_data(client, reg);
-
-       value = i2c_smbus_read_word_data(client, reg);
-       return (value < 0) ? value : swab16(value);
+       else
+               return i2c_smbus_read_word_swapped(client, reg);
 }
 
 static int lm75_write_value(struct i2c_client *client, u8 reg, u16 value)
@@ -398,7 +395,7 @@ static int lm75_write_value(struct i2c_client *client, u8 reg, u16 value)
        if (reg == LM75_REG_CONF)
                return i2c_smbus_write_byte_data(client, reg, value);
        else
-               return i2c_smbus_write_word_data(client, reg, swab16(value));
+               return i2c_smbus_write_word_swapped(client, reg, value);
 }
 
 static struct lm75_data *lm75_update_device(struct device *dev)
index b28a297..8dfc678 100644 (file)
@@ -365,7 +365,7 @@ static u16 lm77_read_value(struct i2c_client *client, u8 reg)
        if (reg == LM77_REG_CONF)
                return i2c_smbus_read_byte_data(client, reg);
        else
-               return swab16(i2c_smbus_read_word_data(client, reg));
+               return i2c_smbus_read_word_swapped(client, reg);
 }
 
 static int lm77_write_value(struct i2c_client *client, u8 reg, u16 value)
@@ -373,7 +373,7 @@ static int lm77_write_value(struct i2c_client *client, u8 reg, u16 value)
        if (reg == LM77_REG_CONF)
                return i2c_smbus_write_byte_data(client, reg, value);
        else
-               return i2c_smbus_write_word_data(client, reg, swab16(value));
+               return i2c_smbus_write_word_swapped(client, reg, value);
 }
 
 static void lm77_init_client(struct i2c_client *client)
index 90ddb87..615bc4f 100644 (file)
@@ -1105,41 +1105,37 @@ static DEVICE_ATTR(pec, S_IWUSR | S_IRUGO, show_pec, set_pec);
  */
 
 /* Return 0 if detection is successful, -ENODEV otherwise */
-static int lm90_detect(struct i2c_client *new_client,
+static int lm90_detect(struct i2c_client *client,
                       struct i2c_board_info *info)
 {
-       struct i2c_adapter *adapter = new_client->adapter;
-       int address = new_client->addr;
+       struct i2c_adapter *adapter = client->adapter;
+       int address = client->addr;
        const char *name = NULL;
-       int man_id, chip_id, reg_config1, reg_config2, reg_convrate;
+       int man_id, chip_id, config1, config2, convrate;
 
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
                return -ENODEV;
 
        /* detection and identification */
-       if ((man_id = i2c_smbus_read_byte_data(new_client,
-                                               LM90_REG_R_MAN_ID)) < 0
-        || (chip_id = i2c_smbus_read_byte_data(new_client,
-                                               LM90_REG_R_CHIP_ID)) < 0
-        || (reg_config1 = i2c_smbus_read_byte_data(new_client,
-                                               LM90_REG_R_CONFIG1)) < 0
-        || (reg_convrate = i2c_smbus_read_byte_data(new_client,
-                                               LM90_REG_R_CONVRATE)) < 0)
+       man_id = i2c_smbus_read_byte_data(client, LM90_REG_R_MAN_ID);
+       chip_id = i2c_smbus_read_byte_data(client, LM90_REG_R_CHIP_ID);
+       config1 = i2c_smbus_read_byte_data(client, LM90_REG_R_CONFIG1);
+       convrate = i2c_smbus_read_byte_data(client, LM90_REG_R_CONVRATE);
+       if (man_id < 0 || chip_id < 0 || config1 < 0 || convrate < 0)
                return -ENODEV;
 
        if (man_id == 0x01 || man_id == 0x5C || man_id == 0x41) {
-               reg_config2 = i2c_smbus_read_byte_data(new_client,
-                                               LM90_REG_R_CONFIG2);
-               if (reg_config2 < 0)
+               config2 = i2c_smbus_read_byte_data(client, LM90_REG_R_CONFIG2);
+               if (config2 < 0)
                        return -ENODEV;
        } else
-               reg_config2 = 0;        /* Make compiler happy */
+               config2 = 0;            /* Make compiler happy */
 
        if ((address == 0x4C || address == 0x4D)
         && man_id == 0x01) { /* National Semiconductor */
-               if ((reg_config1 & 0x2A) == 0x00
-                && (reg_config2 & 0xF8) == 0x00
-                && reg_convrate <= 0x09) {
+               if ((config1 & 0x2A) == 0x00
+                && (config2 & 0xF8) == 0x00
+                && convrate <= 0x09) {
                        if (address == 0x4C
                         && (chip_id & 0xF0) == 0x20) { /* LM90 */
                                name = "lm90";
@@ -1163,8 +1159,8 @@ static int lm90_detect(struct i2c_client *new_client,
        if ((address == 0x4C || address == 0x4D)
         && man_id == 0x41) { /* Analog Devices */
                if ((chip_id & 0xF0) == 0x40 /* ADM1032 */
-                && (reg_config1 & 0x3F) == 0x00
-                && reg_convrate <= 0x0A) {
+                && (config1 & 0x3F) == 0x00
+                && convrate <= 0x0A) {
                        name = "adm1032";
                        /* The ADM1032 supports PEC, but only if combined
                           transactions are not used. */
@@ -1173,18 +1169,18 @@ static int lm90_detect(struct i2c_client *new_client,
                                info->flags |= I2C_CLIENT_PEC;
                } else
                if (chip_id == 0x51 /* ADT7461 */
-                && (reg_config1 & 0x1B) == 0x00
-                && reg_convrate <= 0x0A) {
+                && (config1 & 0x1B) == 0x00
+                && convrate <= 0x0A) {
                        name = "adt7461";
                } else
                if (chip_id == 0x57 /* ADT7461A, NCT1008 */
-                && (reg_config1 & 0x1B) == 0x00
-                && reg_convrate <= 0x0A) {
+                && (config1 & 0x1B) == 0x00
+                && convrate <= 0x0A) {
                        name = "adt7461a";
                }
        } else
        if (man_id == 0x4D) { /* Maxim */
-               int reg_emerg, reg_emerg2, reg_status2;
+               int emerg, emerg2, status2;
 
                /*
                 * We read MAX6659_REG_R_REMOTE_EMERG twice, and re-read
@@ -1192,13 +1188,15 @@ static int lm90_detect(struct i2c_client *new_client,
                 * exists, both readings will reflect the same value. Otherwise,
                 * the readings will be different.
                 */
-               if ((reg_emerg = i2c_smbus_read_byte_data(new_client,
-                                               MAX6659_REG_R_REMOTE_EMERG)) < 0
-                || i2c_smbus_read_byte_data(new_client, LM90_REG_R_MAN_ID) < 0
-                || (reg_emerg2 = i2c_smbus_read_byte_data(new_client,
-                                               MAX6659_REG_R_REMOTE_EMERG)) < 0
-                || (reg_status2 = i2c_smbus_read_byte_data(new_client,
-                                               MAX6696_REG_R_STATUS2)) < 0)
+               emerg = i2c_smbus_read_byte_data(client,
+                                                MAX6659_REG_R_REMOTE_EMERG);
+               man_id = i2c_smbus_read_byte_data(client,
+                                                 LM90_REG_R_MAN_ID);
+               emerg2 = i2c_smbus_read_byte_data(client,
+                                                 MAX6659_REG_R_REMOTE_EMERG);
+               status2 = i2c_smbus_read_byte_data(client,
+                                                  MAX6696_REG_R_STATUS2);
+               if (emerg < 0 || man_id < 0 || emerg2 < 0 || status2 < 0)
                        return -ENODEV;
 
                /*
@@ -1216,8 +1214,8 @@ static int lm90_detect(struct i2c_client *new_client,
                 */
                if (chip_id == man_id
                 && (address == 0x4C || address == 0x4D || address == 0x4E)
-                && (reg_config1 & 0x1F) == (man_id & 0x0F)
-                && reg_convrate <= 0x09) {
+                && (config1 & 0x1F) == (man_id & 0x0F)
+                && convrate <= 0x09) {
                        if (address == 0x4C)
                                name = "max6657";
                        else
@@ -1235,10 +1233,10 @@ static int lm90_detect(struct i2c_client *new_client,
                 * one of those registers exists.
                 */
                if (chip_id == 0x01
-                && (reg_config1 & 0x10) == 0x00
-                && (reg_status2 & 0x01) == 0x00
-                && reg_emerg == reg_emerg2
-                && reg_convrate <= 0x07) {
+                && (config1 & 0x10) == 0x00
+                && (status2 & 0x01) == 0x00
+                && emerg == emerg2
+                && convrate <= 0x07) {
                        name = "max6696";
                } else
                /*
@@ -1248,8 +1246,8 @@ static int lm90_detect(struct i2c_client *new_client,
                 * second to last bit of config1 (software reset).
                 */
                if (chip_id == 0x01
-                && (reg_config1 & 0x03) == 0x00
-                && reg_convrate <= 0x07) {
+                && (config1 & 0x03) == 0x00
+                && convrate <= 0x07) {
                        name = "max6680";
                } else
                /*
@@ -1258,21 +1256,21 @@ static int lm90_detect(struct i2c_client *new_client,
                 * register are unused and should return zero when read.
                 */
                if (chip_id == 0x59
-                && (reg_config1 & 0x3f) == 0x00
-                && reg_convrate <= 0x07) {
+                && (config1 & 0x3f) == 0x00
+                && convrate <= 0x07) {
                        name = "max6646";
                }
        } else
        if (address == 0x4C
         && man_id == 0x5C) { /* Winbond/Nuvoton */
-               if ((reg_config1 & 0x2A) == 0x00
-                && (reg_config2 & 0xF8) == 0x00) {
+               if ((config1 & 0x2A) == 0x00
+                && (config2 & 0xF8) == 0x00) {
                        if (chip_id == 0x01 /* W83L771W/G */
-                        && reg_convrate <= 0x09) {
+                        && convrate <= 0x09) {
                                name = "w83l771";
                        } else
                        if ((chip_id & 0xFE) == 0x10 /* W83L771AWG/ASG */
-                        && reg_convrate <= 0x08) {
+                        && convrate <= 0x08) {
                                name = "w83l771";
                        }
                }
@@ -1280,9 +1278,9 @@ static int lm90_detect(struct i2c_client *new_client,
        if (address >= 0x48 && address <= 0x4F
         && man_id == 0xA1) { /*  NXP Semiconductor/Philips */
                if (chip_id == 0x00
-                && (reg_config1 & 0x2A) == 0x00
-                && (reg_config2 & 0xFE) == 0x00
-                && reg_convrate <= 0x09) {
+                && (config1 & 0x2A) == 0x00
+                && (config2 & 0xFE) == 0x00
+                && convrate <= 0x09) {
                        name = "sa56004";
                }
        }
@@ -1301,19 +1299,18 @@ static int lm90_detect(struct i2c_client *new_client,
 
 static void lm90_remove_files(struct i2c_client *client, struct lm90_data *data)
 {
+       struct device *dev = &client->dev;
+
        if (data->flags & LM90_HAVE_TEMP3)
-               sysfs_remove_group(&client->dev.kobj, &lm90_temp3_group);
+               sysfs_remove_group(&dev->kobj, &lm90_temp3_group);
        if (data->flags & LM90_HAVE_EMERGENCY_ALARM)
-               sysfs_remove_group(&client->dev.kobj,
-                                  &lm90_emergency_alarm_group);
+               sysfs_remove_group(&dev->kobj, &lm90_emergency_alarm_group);
        if (data->flags & LM90_HAVE_EMERGENCY)
-               sysfs_remove_group(&client->dev.kobj,
-                                  &lm90_emergency_group);
+               sysfs_remove_group(&dev->kobj, &lm90_emergency_group);
        if (data->flags & LM90_HAVE_OFFSET)
-               device_remove_file(&client->dev,
-                                  &sensor_dev_attr_temp2_offset.dev_attr);
-       device_remove_file(&client->dev, &dev_attr_pec);
-       sysfs_remove_group(&client->dev.kobj, &lm90_group);
+               device_remove_file(dev, &sensor_dev_attr_temp2_offset.dev_attr);
+       device_remove_file(dev, &dev_attr_pec);
+       sysfs_remove_group(&dev->kobj, &lm90_group);
 }
 
 static void lm90_init_client(struct i2c_client *client)
@@ -1362,10 +1359,11 @@ static void lm90_init_client(struct i2c_client *client)
                i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1, config);
 }
 
-static int lm90_probe(struct i2c_client *new_client,
+static int lm90_probe(struct i2c_client *client,
                      const struct i2c_device_id *id)
 {
-       struct i2c_adapter *adapter = to_i2c_adapter(new_client->dev.parent);
+       struct device *dev = &client->dev;
+       struct i2c_adapter *adapter = to_i2c_adapter(dev->parent);
        struct lm90_data *data;
        int err;
 
@@ -1374,14 +1372,14 @@ static int lm90_probe(struct i2c_client *new_client,
                err = -ENOMEM;
                goto exit;
        }
-       i2c_set_clientdata(new_client, data);
+       i2c_set_clientdata(client, data);
        mutex_init(&data->update_lock);
 
        /* Set the device type */
        data->kind = id->driver_data;
        if (data->kind == adm1032) {
                if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE))
-                       new_client->flags &= ~I2C_CLIENT_PEC;
+                       client->flags &= ~I2C_CLIENT_PEC;
        }
 
        /* Different devices have different alarm bits triggering the
@@ -1396,43 +1394,41 @@ static int lm90_probe(struct i2c_client *new_client,
        data->max_convrate = lm90_params[data->kind].max_convrate;
 
        /* Initialize the LM90 chip */
-       lm90_init_client(new_client);
+       lm90_init_client(client);
 
        /* Register sysfs hooks */
-       err = sysfs_create_group(&new_client->dev.kobj, &lm90_group);
+       err = sysfs_create_group(&dev->kobj, &lm90_group);
        if (err)
                goto exit_free;
-       if (new_client->flags & I2C_CLIENT_PEC) {
-               err = device_create_file(&new_client->dev, &dev_attr_pec);
+       if (client->flags & I2C_CLIENT_PEC) {
+               err = device_create_file(dev, &dev_attr_pec);
                if (err)
                        goto exit_remove_files;
        }
        if (data->flags & LM90_HAVE_OFFSET) {
-               err = device_create_file(&new_client->dev,
+               err = device_create_file(dev,
                                        &sensor_dev_attr_temp2_offset.dev_attr);
                if (err)
                        goto exit_remove_files;
        }
        if (data->flags & LM90_HAVE_EMERGENCY) {
-               err = sysfs_create_group(&new_client->dev.kobj,
-                                        &lm90_emergency_group);
+               err = sysfs_create_group(&dev->kobj, &lm90_emergency_group);
                if (err)
                        goto exit_remove_files;
        }
        if (data->flags & LM90_HAVE_EMERGENCY_ALARM) {
-               err = sysfs_create_group(&new_client->dev.kobj,
+               err = sysfs_create_group(&dev->kobj,
                                         &lm90_emergency_alarm_group);
                if (err)
                        goto exit_remove_files;
        }
        if (data->flags & LM90_HAVE_TEMP3) {
-               err = sysfs_create_group(&new_client->dev.kobj,
-                                        &lm90_temp3_group);
+               err = sysfs_create_group(&dev->kobj, &lm90_temp3_group);
                if (err)
                        goto exit_remove_files;
        }
 
-       data->hwmon_dev = hwmon_device_register(&new_client->dev);
+       data->hwmon_dev = hwmon_device_register(dev);
        if (IS_ERR(data->hwmon_dev)) {
                err = PTR_ERR(data->hwmon_dev);
                goto exit_remove_files;
@@ -1441,7 +1437,7 @@ static int lm90_probe(struct i2c_client *new_client,
        return 0;
 
 exit_remove_files:
-       lm90_remove_files(new_client, data);
+       lm90_remove_files(client, data);
 exit_free:
        kfree(data);
 exit:
index 7c31e62..8fcbd4d 100644 (file)
@@ -117,16 +117,16 @@ static struct lm92_data *lm92_update_device(struct device *dev)
        if (time_after(jiffies, data->last_updated + HZ)
         || !data->valid) {
                dev_dbg(&client->dev, "Updating lm92 data\n");
-               data->temp1_input = swab16(i2c_smbus_read_word_data(client,
-                                   LM92_REG_TEMP));
-               data->temp1_hyst = swab16(i2c_smbus_read_word_data(client,
-                                   LM92_REG_TEMP_HYST));
-               data->temp1_crit = swab16(i2c_smbus_read_word_data(client,
-                                   LM92_REG_TEMP_CRIT));
-               data->temp1_min = swab16(i2c_smbus_read_word_data(client,
-                                   LM92_REG_TEMP_LOW));
-               data->temp1_max = swab16(i2c_smbus_read_word_data(client,
-                                   LM92_REG_TEMP_HIGH));
+               data->temp1_input = i2c_smbus_read_word_swapped(client,
+                                   LM92_REG_TEMP);
+               data->temp1_hyst = i2c_smbus_read_word_swapped(client,
+                                   LM92_REG_TEMP_HYST);
+               data->temp1_crit = i2c_smbus_read_word_swapped(client,
+                                   LM92_REG_TEMP_CRIT);
+               data->temp1_min = i2c_smbus_read_word_swapped(client,
+                                   LM92_REG_TEMP_LOW);
+               data->temp1_max = i2c_smbus_read_word_swapped(client,
+                                   LM92_REG_TEMP_HIGH);
 
                data->last_updated = jiffies;
                data->valid = 1;
@@ -158,7 +158,7 @@ static ssize_t set_##value(struct device *dev, struct device_attribute *attr, co
  \
        mutex_lock(&data->update_lock); \
        data->value = TEMP_TO_REG(val); \
-       i2c_smbus_write_word_data(client, reg, swab16(data->value)); \
+       i2c_smbus_write_word_swapped(client, reg, data->value); \
        mutex_unlock(&data->update_lock); \
        return count; \
 }
@@ -194,8 +194,8 @@ static ssize_t set_temp1_crit_hyst(struct device *dev, struct device_attribute *
 
        mutex_lock(&data->update_lock);
        data->temp1_hyst = TEMP_FROM_REG(data->temp1_crit) - val;
-       i2c_smbus_write_word_data(client, LM92_REG_TEMP_HYST,
-                                 swab16(TEMP_TO_REG(data->temp1_hyst)));
+       i2c_smbus_write_word_swapped(client, LM92_REG_TEMP_HYST,
+                                    TEMP_TO_REG(data->temp1_hyst));
        mutex_unlock(&data->update_lock);
        return count;
 }
index dd2d7b9..385886a 100644 (file)
@@ -137,10 +137,10 @@ static int max16065_read_adc(struct i2c_client *client, int reg)
 {
        int rv;
 
-       rv = i2c_smbus_read_word_data(client, reg);
+       rv = i2c_smbus_read_word_swapped(client, reg);
        if (unlikely(rv < 0))
                return rv;
-       return ((rv & 0xff) << 2) | ((rv >> 14) & 0x03);
+       return rv >> 6;
 }
 
 static struct max16065_data *max16065_update_device(struct device *dev)
index 1c8c981..1539878 100644 (file)
@@ -83,25 +83,6 @@ static inline int sht21_rh_ticks_to_per_cent_mille(int ticks)
 }
 
 /**
- * sht21_read_word_data() - read word from register
- * @client: I2C client device
- * @reg: I2C command byte
- *
- * Returns value, negative errno on error.
- */
-static inline int sht21_read_word_data(struct i2c_client *client, u8 reg)
-{
-       int ret = i2c_smbus_read_word_data(client, reg);
-       if (ret < 0)
-               return ret;
-       /*
-        * SMBus specifies low byte first, but the SHT21 returns MSB
-        * first, so we have to swab16 the values
-        */
-       return swab16(ret);
-}
-
-/**
  * sht21_update_measurements() - get updated measurements from device
  * @client: I2C client device
  *
@@ -119,12 +100,13 @@ static int sht21_update_measurements(struct i2c_client *client)
         * maximum two measurements per second at 12bit accuracy shall be made.
         */
        if (time_after(jiffies, sht21->last_update + HZ / 2) || !sht21->valid) {
-               ret = sht21_read_word_data(client, SHT21_TRIG_T_MEASUREMENT_HM);
+               ret = i2c_smbus_read_word_swapped(client,
+                                                 SHT21_TRIG_T_MEASUREMENT_HM);
                if (ret < 0)
                        goto out;
                sht21->temperature = sht21_temp_ticks_to_millicelsius(ret);
-               ret = sht21_read_word_data(client,
-                                       SHT21_TRIG_RH_MEASUREMENT_HM);
+               ret = i2c_smbus_read_word_swapped(client,
+                                                 SHT21_TRIG_RH_MEASUREMENT_HM);
                if (ret < 0)
                        goto out;
                sht21->humidity = sht21_rh_ticks_to_per_cent_mille(ret);
index 425df5b..4116381 100644 (file)
@@ -214,33 +214,26 @@ static int smm665_read_adc(struct smm665_data *data, int adc)
         *
         * Neither i2c_smbus_read_byte() nor
         * i2c_smbus_read_block_data() worked here,
-        * so use i2c_smbus_read_word_data() instead.
+        * so use i2c_smbus_read_word_swapped() instead.
         * We could also try to use i2c_master_recv(),
         * but that is not always supported.
         */
-       rv = i2c_smbus_read_word_data(client, 0);
+       rv = i2c_smbus_read_word_swapped(client, 0);
        if (rv < 0) {
                dev_dbg(&client->dev, "Failed to read ADC value: error %d", rv);
                return -1;
        }
        /*
         * Validate/verify readback adc channel (in bit 11..14).
-        * High byte is in lower 8 bit of rv, so only shift by 3.
         */
-       radc = (rv >> 3) & 0x0f;
+       radc = (rv >> 11) & 0x0f;
        if (radc != adc) {
                dev_dbg(&client->dev, "Unexpected RADC: Expected %d got %d",
                        adc, radc);
                return -EIO;
        }
-       /*
-        * Chip replies with H/L, while SMBus expects L/H.
-        * Thus, byte order is reversed, and we have to swap
-        * the result.
-        */
-       rv = swab16(rv) & SMM665_ADC_MASK;
 
-       return rv;
+       return rv & SMM665_ADC_MASK;
 }
 
 static struct smm665_data *smm665_update_device(struct device *dev)
index 9fb7516..65c88ff 100644 (file)
@@ -113,7 +113,7 @@ struct smsc47b397_data {
        u8 temp[4];
 };
 
-static int smsc47b397_read_value(struct smsc47b397_datadata, u8 reg)
+static int smsc47b397_read_value(struct smsc47b397_data *data, u8 reg)
 {
        int res;
 
@@ -265,7 +265,8 @@ static int __devinit smsc47b397_probe(struct platform_device *pdev)
                return -EBUSY;
        }
 
-       if (!(data = kzalloc(sizeof(struct smsc47b397_data), GFP_KERNEL))) {
+       data = kzalloc(sizeof(struct smsc47b397_data), GFP_KERNEL);
+       if (!data) {
                err = -ENOMEM;
                goto error_release;
        }
@@ -276,7 +277,8 @@ static int __devinit smsc47b397_probe(struct platform_device *pdev)
        mutex_init(&data->update_lock);
        platform_set_drvdata(pdev, data);
 
-       if ((err = sysfs_create_group(&dev->kobj, &smsc47b397_group)))
+       err = sysfs_create_group(&dev->kobj, &smsc47b397_group);
+       if (err)
                goto error_free;
 
        data->hwmon_dev = hwmon_device_register(dev);
@@ -345,7 +347,7 @@ static int __init smsc47b397_find(unsigned short *addr)
        superio_enter();
        id = force_id ? force_id : superio_inb(SUPERIO_REG_DEVID);
 
-       switch(id) {
+       switch (id) {
        case 0x81:
                name = "SCH5307-NS";
                break;
@@ -379,7 +381,8 @@ static int __init smsc47b397_init(void)
        unsigned short address;
        int ret;
 
-       if ((ret = smsc47b397_find(&address)))
+       ret = smsc47b397_find(&address);
+       if (ret)
                return ret;
 
        ret = platform_driver_register(&smsc47b397_driver);
index 5bd1949..643aa8c 100644 (file)
@@ -55,19 +55,6 @@ struct tmp102 {
        int temp[3];
 };
 
-/* SMBus specifies low byte first, but the TMP102 returns high byte first,
- * so we have to swab16 the values */
-static inline int tmp102_read_reg(struct i2c_client *client, u8 reg)
-{
-       int result = i2c_smbus_read_word_data(client, reg);
-       return result < 0 ? result : swab16(result);
-}
-
-static inline int tmp102_write_reg(struct i2c_client *client, u8 reg, u16 val)
-{
-       return i2c_smbus_write_word_data(client, reg, swab16(val));
-}
-
 /* convert left adjusted 13-bit TMP102 register value to milliCelsius */
 static inline int tmp102_reg_to_mC(s16 val)
 {
@@ -94,7 +81,8 @@ static struct tmp102 *tmp102_update_device(struct i2c_client *client)
        if (time_after(jiffies, tmp102->last_update + HZ / 3)) {
                int i;
                for (i = 0; i < ARRAY_SIZE(tmp102->temp); ++i) {
-                       int status = tmp102_read_reg(client, tmp102_reg[i]);
+                       int status = i2c_smbus_read_word_swapped(client,
+                                                                tmp102_reg[i]);
                        if (status > -1)
                                tmp102->temp[i] = tmp102_reg_to_mC(status);
                }
@@ -130,8 +118,8 @@ static ssize_t tmp102_set_temp(struct device *dev,
 
        mutex_lock(&tmp102->lock);
        tmp102->temp[sda->index] = val;
-       status = tmp102_write_reg(client, tmp102_reg[sda->index],
-                                 tmp102_mC_to_reg(val));
+       status = i2c_smbus_write_word_swapped(client, tmp102_reg[sda->index],
+                                             tmp102_mC_to_reg(val));
        mutex_unlock(&tmp102->lock);
        return status ? : count;
 }
@@ -178,18 +166,19 @@ static int __devinit tmp102_probe(struct i2c_client *client,
        }
        i2c_set_clientdata(client, tmp102);
 
-       status = tmp102_read_reg(client, TMP102_CONF_REG);
+       status = i2c_smbus_read_word_swapped(client, TMP102_CONF_REG);
        if (status < 0) {
                dev_err(&client->dev, "error reading config register\n");
                goto fail_free;
        }
        tmp102->config_orig = status;
-       status = tmp102_write_reg(client, TMP102_CONF_REG, TMP102_CONFIG);
+       status = i2c_smbus_write_word_swapped(client, TMP102_CONF_REG,
+                                             TMP102_CONFIG);
        if (status < 0) {
                dev_err(&client->dev, "error writing config register\n");
                goto fail_restore_config;
        }
-       status = tmp102_read_reg(client, TMP102_CONF_REG);
+       status = i2c_smbus_read_word_swapped(client, TMP102_CONF_REG);
        if (status < 0) {
                dev_err(&client->dev, "error reading config register\n");
                goto fail_restore_config;
@@ -222,7 +211,8 @@ static int __devinit tmp102_probe(struct i2c_client *client,
 fail_remove_sysfs:
        sysfs_remove_group(&client->dev.kobj, &tmp102_attr_group);
 fail_restore_config:
-       tmp102_write_reg(client, TMP102_CONF_REG, tmp102->config_orig);
+       i2c_smbus_write_word_swapped(client, TMP102_CONF_REG,
+                                    tmp102->config_orig);
 fail_free:
        kfree(tmp102);
 
@@ -240,10 +230,10 @@ static int __devexit tmp102_remove(struct i2c_client *client)
        if (tmp102->config_orig & TMP102_CONF_SD) {
                int config;
 
-               config = tmp102_read_reg(client, TMP102_CONF_REG);
+               config = i2c_smbus_read_word_swapped(client, TMP102_CONF_REG);
                if (config >= 0)
-                       tmp102_write_reg(client, TMP102_CONF_REG,
-                                        config | TMP102_CONF_SD);
+                       i2c_smbus_write_word_swapped(client, TMP102_CONF_REG,
+                                                    config | TMP102_CONF_SD);
        }
 
        kfree(tmp102);
@@ -257,12 +247,12 @@ static int tmp102_suspend(struct device *dev)
        struct i2c_client *client = to_i2c_client(dev);
        int config;
 
-       config = tmp102_read_reg(client, TMP102_CONF_REG);
+       config = i2c_smbus_read_word_swapped(client, TMP102_CONF_REG);
        if (config < 0)
                return config;
 
        config |= TMP102_CONF_SD;
-       return tmp102_write_reg(client, TMP102_CONF_REG, config);
+       return i2c_smbus_write_word_swapped(client, TMP102_CONF_REG, config);
 }
 
 static int tmp102_resume(struct device *dev)
@@ -270,12 +260,12 @@ static int tmp102_resume(struct device *dev)
        struct i2c_client *client = to_i2c_client(dev);
        int config;
 
-       config = tmp102_read_reg(client, TMP102_CONF_REG);
+       config = i2c_smbus_read_word_swapped(client, TMP102_CONF_REG);
        if (config < 0)
                return config;
 
        config &= ~TMP102_CONF_SD;
-       return tmp102_write_reg(client, TMP102_CONF_REG, config);
+       return i2c_smbus_write_word_swapped(client, TMP102_CONF_REG, config);
 }
 
 static const struct dev_pm_ops tmp102_dev_pm_ops = {
index 98aab4b..93f5fc7 100644 (file)
@@ -1,7 +1,7 @@
 /*
     w83627ehf - Driver for the hardware monitoring functionality of
                the Winbond W83627EHF Super-I/O chip
-    Copyright (C) 2005  Jean Delvare <khali@linux-fr.org>
+    Copyright (C) 2005-2011  Jean Delvare <khali@linux-fr.org>
     Copyright (C) 2006  Yuan Mu (Winbond),
                        Rudolf Marek <r.marek@assembler.cz>
                        David Hubbard <david.c.hubbard@gmail.com>
@@ -39,6 +39,7 @@
                                               0x8860 0xa1
     w83627dhg    9      5       4       3      0xa020 0xc1    0x5ca3
     w83627dhg-p  9      5       4       3      0xb070 0xc1    0x5ca3
+    w83627uhg    8      2       2       2      0xa230 0xc1    0x5ca3
     w83667hg     9      5       3       3      0xa510 0xc1    0x5ca3
     w83667hg-b   9      5       3       4      0xb350 0xc1    0x5ca3
     nct6775f     9      4       3       9      0xb470 0xc1    0x5ca3
 #include <linux/io.h>
 #include "lm75.h"
 
-enum kinds { w83627ehf, w83627dhg, w83627dhg_p, w83667hg, w83667hg_b, nct6775,
-       nct6776 };
+enum kinds {
+       w83627ehf, w83627dhg, w83627dhg_p, w83627uhg,
+       w83667hg, w83667hg_b, nct6775, nct6776,
+};
 
 /* used to set data->name = w83627ehf_device_names[data->sio_kind] */
 static const char * const w83627ehf_device_names[] = {
        "w83627ehf",
        "w83627dhg",
        "w83627dhg",
+       "w83627uhg",
        "w83667hg",
        "w83667hg",
        "nct6775",
@@ -104,6 +108,7 @@ MODULE_PARM_DESC(fan_debounce, "Enable debouncing for fan RPM signal");
 #define SIO_W83627EHG_ID       0x8860
 #define SIO_W83627DHG_ID       0xa020
 #define SIO_W83627DHG_P_ID     0xb070
+#define SIO_W83627UHG_ID       0xa230
 #define SIO_W83667HG_ID                0xa510
 #define SIO_W83667HG_B_ID      0xb350
 #define SIO_NCT6775_ID         0xb470
@@ -388,18 +393,23 @@ div_from_reg(u8 reg)
        return 1 << reg;
 }
 
-/* Some of analog inputs have internal scaling (2x), 8mV is ADC LSB */
-
-static u8 scale_in[10] = { 8, 8, 16, 16, 8, 8, 8, 16, 16, 8 };
+/* Some of the voltage inputs have internal scaling, the tables below
+ * contain 8 (the ADC LSB in mV) * scaling factor * 100 */
+static const u16 scale_in_common[10] = {
+       800, 800, 1600, 1600, 800, 800, 800, 1600, 1600, 800
+};
+static const u16 scale_in_w83627uhg[9] = {
+       800, 800, 3328, 3424, 800, 800, 0, 3328, 3400
+};
 
-static inline long in_from_reg(u8 reg, u8 nr)
+static inline long in_from_reg(u8 reg, u8 nr, const u16 *scale_in)
 {
-       return reg * scale_in[nr];
+       return DIV_ROUND_CLOSEST(reg * scale_in[nr], 100);
 }
 
-static inline u8 in_to_reg(u32 val, u8 nr)
+static inline u8 in_to_reg(u32 val, u8 nr, const u16 *scale_in)
 {
-       return SENSORS_LIMIT(((val + (scale_in[nr] / 2)) / scale_in[nr]), 0,
+       return SENSORS_LIMIT(DIV_ROUND_CLOSEST(val * 100, scale_in[nr]), 0,
                             255);
 }
 
@@ -430,6 +440,7 @@ struct w83627ehf_data {
        const u16 *REG_FAN_STOP_TIME;
        const u16 *REG_FAN_MAX_OUTPUT;
        const u16 *REG_FAN_STEP_OUTPUT;
+       const u16 *scale_in;
 
        unsigned int (*fan_from_reg)(u16 reg, unsigned int divreg);
        unsigned int (*fan_from_reg_min)(u16 reg, unsigned int divreg);
@@ -481,7 +492,8 @@ struct w83627ehf_data {
        u8 vrm;
 
        u16 have_temp;
-       u8 in6_skip;
+       u8 in6_skip:1;
+       u8 temp3_val_only:1;
 };
 
 struct w83627ehf_sio_data {
@@ -907,7 +919,8 @@ show_##reg(struct device *dev, struct device_attribute *attr, \
        struct sensor_device_attribute *sensor_attr = \
                to_sensor_dev_attr(attr); \
        int nr = sensor_attr->index; \
-       return sprintf(buf, "%ld\n", in_from_reg(data->reg[nr], nr)); \
+       return sprintf(buf, "%ld\n", in_from_reg(data->reg[nr], nr, \
+                      data->scale_in)); \
 }
 show_in_reg(in)
 show_in_reg(in_min)
@@ -928,7 +941,7 @@ store_in_##reg(struct device *dev, struct device_attribute *attr, \
        if (err < 0) \
                return err; \
        mutex_lock(&data->update_lock); \
-       data->in_##reg[nr] = in_to_reg(val, nr); \
+       data->in_##reg[nr] = in_to_reg(val, nr, data->scale_in); \
        w83627ehf_write_value(data, W83627EHF_REG_IN_##REG(nr), \
                              data->in_##reg[nr]); \
        mutex_unlock(&data->update_lock); \
@@ -1617,25 +1630,28 @@ static struct sensor_device_attribute sda_sf3_arrays_fan4[] = {
                    store_fan_step_output, 3),
 };
 
+static struct sensor_device_attribute sda_sf3_arrays_fan3[] = {
+       SENSOR_ATTR(pwm3_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time,
+                   store_fan_stop_time, 2),
+       SENSOR_ATTR(pwm3_start_output, S_IWUSR | S_IRUGO, show_fan_start_output,
+                   store_fan_start_output, 2),
+       SENSOR_ATTR(pwm3_stop_output, S_IWUSR | S_IRUGO, show_fan_stop_output,
+                   store_fan_stop_output, 2),
+};
+
 static struct sensor_device_attribute sda_sf3_arrays[] = {
        SENSOR_ATTR(pwm1_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time,
                    store_fan_stop_time, 0),
        SENSOR_ATTR(pwm2_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time,
                    store_fan_stop_time, 1),
-       SENSOR_ATTR(pwm3_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time,
-                   store_fan_stop_time, 2),
        SENSOR_ATTR(pwm1_start_output, S_IWUSR | S_IRUGO, show_fan_start_output,
                    store_fan_start_output, 0),
        SENSOR_ATTR(pwm2_start_output, S_IWUSR | S_IRUGO, show_fan_start_output,
                    store_fan_start_output, 1),
-       SENSOR_ATTR(pwm3_start_output, S_IWUSR | S_IRUGO, show_fan_start_output,
-                   store_fan_start_output, 2),
        SENSOR_ATTR(pwm1_stop_output, S_IWUSR | S_IRUGO, show_fan_stop_output,
                    store_fan_stop_output, 0),
        SENSOR_ATTR(pwm2_stop_output, S_IWUSR | S_IRUGO, show_fan_stop_output,
                    store_fan_stop_output, 1),
-       SENSOR_ATTR(pwm3_stop_output, S_IWUSR | S_IRUGO, show_fan_stop_output,
-                   store_fan_stop_output, 2),
 };
 
 
@@ -1728,6 +1744,8 @@ static void w83627ehf_device_remove_files(struct device *dev)
                    data->REG_FAN_STEP_OUTPUT[attr->index] != 0xff)
                        device_remove_file(dev, &attr->dev_attr);
        }
+       for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan3); i++)
+               device_remove_file(dev, &sda_sf3_arrays_fan3[i].dev_attr);
        for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan4); i++)
                device_remove_file(dev, &sda_sf3_arrays_fan4[i].dev_attr);
        for (i = 0; i < data->in_num; i++) {
@@ -1756,6 +1774,8 @@ static void w83627ehf_device_remove_files(struct device *dev)
                        continue;
                device_remove_file(dev, &sda_temp_input[i].dev_attr);
                device_remove_file(dev, &sda_temp_label[i].dev_attr);
+               if (i == 2 && data->temp3_val_only)
+                       continue;
                device_remove_file(dev, &sda_temp_max[i].dev_attr);
                device_remove_file(dev, &sda_temp_max_hyst[i].dev_attr);
                if (i > 2)
@@ -1808,11 +1828,24 @@ static inline void __devinit w83627ehf_init_device(struct w83627ehf_data *data,
        case w83627ehf:
                diode = w83627ehf_read_value(data, W83627EHF_REG_DIODE);
                break;
+       case w83627uhg:
+               diode = 0x00;
+               break;
        default:
                diode = 0x70;
        }
        for (i = 0; i < 3; i++) {
-               if ((tmp & (0x02 << i)))
+               const char *label = NULL;
+
+               if (data->temp_label)
+                       label = data->temp_label[data->temp_src[i]];
+
+               /* Digital source overrides analog type */
+               if (label && strncmp(label, "PECI", 4) == 0)
+                       data->temp_type[i] = 6;
+               else if (label && strncmp(label, "AMD", 3) == 0)
+                       data->temp_type[i] = 5;
+               else if ((tmp & (0x02 << i)))
                        data->temp_type[i] = (diode & (0x10 << i)) ? 1 : 3;
                else
                        data->temp_type[i] = 4; /* thermistor */
@@ -1846,11 +1879,31 @@ static void w82627ehf_swap_tempreg(struct w83627ehf_data *data,
 }
 
 static void __devinit
+w83627ehf_set_temp_reg_ehf(struct w83627ehf_data *data, int n_temp)
+{
+       int i;
+
+       for (i = 0; i < n_temp; i++) {
+               data->reg_temp[i] = W83627EHF_REG_TEMP[i];
+               data->reg_temp_over[i] = W83627EHF_REG_TEMP_OVER[i];
+               data->reg_temp_hyst[i] = W83627EHF_REG_TEMP_HYST[i];
+               data->reg_temp_config[i] = W83627EHF_REG_TEMP_CONFIG[i];
+       }
+}
+
+static void __devinit
 w83627ehf_check_fan_inputs(const struct w83627ehf_sio_data *sio_data,
                           struct w83627ehf_data *data)
 {
        int fan3pin, fan4pin, fan4min, fan5pin, regval;
 
+       /* The W83627UHG is simple, only two fan inputs, no config */
+       if (sio_data->kind == w83627uhg) {
+               data->has_fan = 0x03; /* fan1 and fan2 */
+               data->has_fan_min = 0x03;
+               return;
+       }
+
        superio_enter(sio_data->sioreg);
 
        /* fan4 and fan5 share some pins with the GPIO and serial flash */
@@ -1942,23 +1995,24 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
 
        /* 627EHG and 627EHF have 10 voltage inputs; 627DHG and 667HG have 9 */
        data->in_num = (sio_data->kind == w83627ehf) ? 10 : 9;
-       /* 667HG, NCT6775F, and NCT6776F have 3 pwms */
-       data->pwm_num = (sio_data->kind == w83667hg
-                        || sio_data->kind == w83667hg_b
-                        || sio_data->kind == nct6775
-                        || sio_data->kind == nct6776) ? 3 : 4;
+       /* 667HG, NCT6775F, and NCT6776F have 3 pwms, and 627UHG has only 2 */
+       switch (sio_data->kind) {
+       default:
+               data->pwm_num = 4;
+               break;
+       case w83667hg:
+       case w83667hg_b:
+       case nct6775:
+       case nct6776:
+               data->pwm_num = 3;
+               break;
+       case w83627uhg:
+               data->pwm_num = 2;
+               break;
+       }
 
+       /* Default to 3 temperature inputs, code below will adjust as needed */
        data->have_temp = 0x07;
-       /* Check temp3 configuration bit for 667HG */
-       if (sio_data->kind == w83667hg) {
-               u8 reg;
-
-               reg = w83627ehf_read_value(data, W83627EHF_REG_TEMP_CONFIG[2]);
-               if (reg & 0x01)
-                       data->have_temp &= ~(1 << 2);
-               else
-                       data->in6_skip = 1;     /* either temp3 or in6 */
-       }
 
        /* Deal with temperature register setup first. */
        if (sio_data->kind == nct6775 || sio_data->kind == nct6776) {
@@ -2035,16 +2089,12 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
        } else if (sio_data->kind == w83667hg_b) {
                u8 reg;
 
+               w83627ehf_set_temp_reg_ehf(data, 4);
+
                /*
                 * Temperature sources are selected with bank 0, registers 0x49
                 * and 0x4a.
                 */
-               for (i = 0; i < ARRAY_SIZE(W83627EHF_REG_TEMP); i++) {
-                       data->reg_temp[i] = W83627EHF_REG_TEMP[i];
-                       data->reg_temp_over[i] = W83627EHF_REG_TEMP_OVER[i];
-                       data->reg_temp_hyst[i] = W83627EHF_REG_TEMP_HYST[i];
-                       data->reg_temp_config[i] = W83627EHF_REG_TEMP_CONFIG[i];
-               }
                reg = w83627ehf_read_value(data, 0x4a);
                data->temp_src[0] = reg >> 5;
                reg = w83627ehf_read_value(data, 0x49);
@@ -2078,13 +2128,60 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
                        data->in6_skip = 1;
 
                data->temp_label = w83667hg_b_temp_label;
+       } else if (sio_data->kind == w83627uhg) {
+               u8 reg;
+
+               w83627ehf_set_temp_reg_ehf(data, 3);
+
+               /*
+                * Temperature sources for temp1 and temp2 are selected with
+                * bank 0, registers 0x49 and 0x4a.
+                */
+               data->temp_src[0] = 0;  /* SYSTIN */
+               reg = w83627ehf_read_value(data, 0x49) & 0x07;
+               /* Adjust to have the same mapping as other source registers */
+               if (reg == 0)
+                       data->temp_src[1]++;
+               else if (reg >= 2 && reg <= 5)
+                       data->temp_src[1] += 2;
+               else    /* should never happen */
+                       data->have_temp &= ~(1 << 1);
+               reg = w83627ehf_read_value(data, 0x4a);
+               data->temp_src[2] = reg >> 5;
+
+               /*
+                * Skip temp3 if source is invalid or the same as temp1
+                * or temp2.
+                */
+               if (data->temp_src[2] == 2 || data->temp_src[2] == 3 ||
+                   data->temp_src[2] == data->temp_src[0] ||
+                   ((data->have_temp & (1 << 1)) &&
+                    data->temp_src[2] == data->temp_src[1]))
+                       data->have_temp &= ~(1 << 2);
+               else
+                       data->temp3_val_only = 1;       /* No limit regs */
+
+               data->in6_skip = 1;                     /* No VIN3 */
+
+               data->temp_label = w83667hg_b_temp_label;
        } else {
+               w83627ehf_set_temp_reg_ehf(data, 3);
+
                /* Temperature sources are fixed */
-               for (i = 0; i < 3; i++) {
-                       data->reg_temp[i] = W83627EHF_REG_TEMP[i];
-                       data->reg_temp_over[i] = W83627EHF_REG_TEMP_OVER[i];
-                       data->reg_temp_hyst[i] = W83627EHF_REG_TEMP_HYST[i];
-                       data->reg_temp_config[i] = W83627EHF_REG_TEMP_CONFIG[i];
+
+               if (sio_data->kind == w83667hg) {
+                       u8 reg;
+
+                       /*
+                        * Chip supports either AUXTIN or VIN3. Try to find
+                        * out which one.
+                        */
+                       reg = w83627ehf_read_value(data,
+                                               W83627EHF_REG_TEMP_CONFIG[2]);
+                       if (reg & 0x01)
+                               data->have_temp &= ~(1 << 2);
+                       else
+                               data->in6_skip = 1;
                }
        }
 
@@ -2144,6 +2241,12 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
                  W83627EHF_REG_FAN_STEP_OUTPUT_COMMON;
        }
 
+       /* Setup input voltage scaling factors */
+       if (sio_data->kind == w83627uhg)
+               data->scale_in = scale_in_w83627uhg;
+       else
+               data->scale_in = scale_in_common;
+
        /* Initialize the chip */
        w83627ehf_init_device(data, sio_data->kind);
 
@@ -2160,7 +2263,7 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
                err = device_create_file(dev, &dev_attr_cpu0_vid);
                if (err)
                        goto exit_release;
-       } else {
+       } else if (sio_data->kind != w83627uhg) {
                superio_select(sio_data->sioreg, W83627EHF_LD_HWM);
                if (superio_inb(sio_data->sioreg, SIO_REG_VID_CTRL) & 0x80) {
                        /* Set VID input sensibility if needed. In theory the
@@ -2250,7 +2353,14 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
                                goto exit_remove;
                }
        }
-       /* if fan4 is enabled create the sf3 files for it */
+       /* if fan3 and fan4 are enabled create the sf3 files for them */
+       if ((data->has_fan & (1 << 2)) && data->pwm_num >= 3)
+               for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan3); i++) {
+                       err = device_create_file(dev,
+                                       &sda_sf3_arrays_fan3[i].dev_attr);
+                       if (err)
+                               goto exit_remove;
+               }
        if ((data->has_fan & (1 << 3)) && data->pwm_num >= 4)
                for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan4); i++) {
                        err = device_create_file(dev,
@@ -2318,6 +2428,8 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
                        if (err)
                                goto exit_remove;
                }
+               if (i == 2 && data->temp3_val_only)
+                       continue;
                if (data->reg_temp_over[i]) {
                        err = device_create_file(dev,
                                &sda_temp_max[i].dev_attr);
@@ -2401,6 +2513,7 @@ static int __init w83627ehf_find(int sioaddr, unsigned short *addr,
        static const char __initdata sio_name_W83627EHG[] = "W83627EHG";
        static const char __initdata sio_name_W83627DHG[] = "W83627DHG";
        static const char __initdata sio_name_W83627DHG_P[] = "W83627DHG-P";
+       static const char __initdata sio_name_W83627UHG[] = "W83627UHG";
        static const char __initdata sio_name_W83667HG[] = "W83667HG";
        static const char __initdata sio_name_W83667HG_B[] = "W83667HG-B";
        static const char __initdata sio_name_NCT6775[] = "NCT6775F";
@@ -2433,6 +2546,10 @@ static int __init w83627ehf_find(int sioaddr, unsigned short *addr,
                sio_data->kind = w83627dhg_p;
                sio_name = sio_name_W83627DHG_P;
                break;
+       case SIO_W83627UHG_ID:
+               sio_data->kind = w83627uhg;
+               sio_name = sio_name_W83627UHG;
+               break;
        case SIO_W83667HG_ID:
                sio_data->kind = w83667hg;
                sio_name = sio_name_W83667HG;
index eed43a0..65b685e 100644 (file)
@@ -1245,17 +1245,17 @@ w83781d_read_value_i2c(struct w83781d_data *data, u16 reg)
                /* convert from ISA to LM75 I2C addresses */
                switch (reg & 0xff) {
                case 0x50:      /* TEMP */
-                       res = swab16(i2c_smbus_read_word_data(cl, 0));
+                       res = i2c_smbus_read_word_swapped(cl, 0);
                        break;
                case 0x52:      /* CONFIG */
                        res = i2c_smbus_read_byte_data(cl, 1);
                        break;
                case 0x53:      /* HYST */
-                       res = swab16(i2c_smbus_read_word_data(cl, 2));
+                       res = i2c_smbus_read_word_swapped(cl, 2);
                        break;
                case 0x55:      /* OVER */
                default:
-                       res = swab16(i2c_smbus_read_word_data(cl, 3));
+                       res = i2c_smbus_read_word_swapped(cl, 3);
                        break;
                }
        }
@@ -1289,10 +1289,10 @@ w83781d_write_value_i2c(struct w83781d_data *data, u16 reg, u16 value)
                        i2c_smbus_write_byte_data(cl, 1, value & 0xff);
                        break;
                case 0x53:      /* HYST */
-                       i2c_smbus_write_word_data(cl, 2, swab16(value));
+                       i2c_smbus_write_word_swapped(cl, 2, value);
                        break;
                case 0x55:      /* OVER */
-                       i2c_smbus_write_word_data(cl, 3, swab16(value));
+                       i2c_smbus_write_word_swapped(cl, 3, value);
                        break;
                }
        }
index ab876f9..ed9a989 100644 (file)
@@ -146,7 +146,7 @@ static int mthca_buddy_init(struct mthca_buddy *buddy, int max_order)
 
        buddy->bits = kzalloc((buddy->max_order + 1) * sizeof (long *),
                              GFP_KERNEL);
-       buddy->num_free = kzalloc((buddy->max_order + 1) * sizeof (int *),
+       buddy->num_free = kcalloc((buddy->max_order + 1), sizeof *buddy->num_free,
                                  GFP_KERNEL);
        if (!buddy->bits || !buddy->num_free)
                goto err_out;
index afaf4ac..894afac 100644 (file)
@@ -271,13 +271,9 @@ int qib_make_rc_req(struct qib_qp *qp)
                        goto bail;
                }
                wqe = get_swqe_ptr(qp, qp->s_last);
-               while (qp->s_last != qp->s_acked) {
-                       qib_send_complete(qp, wqe, IB_WC_SUCCESS);
-                       if (++qp->s_last >= qp->s_size)
-                               qp->s_last = 0;
-                       wqe = get_swqe_ptr(qp, qp->s_last);
-               }
-               qib_send_complete(qp, wqe, IB_WC_WR_FLUSH_ERR);
+               qib_send_complete(qp, wqe, qp->s_last != qp->s_acked ?
+                       IB_WC_SUCCESS : IB_WC_WR_FLUSH_ERR);
+               /* will get called again */
                goto done;
        }
 
index 84e8c29..c42b8f3 100644 (file)
@@ -151,7 +151,6 @@ int iser_initialize_task_headers(struct iscsi_task *task,
        tx_desc->tx_sg[0].length = ISER_HEADERS_LEN;
        tx_desc->tx_sg[0].lkey   = device->mr->lkey;
 
-       iser_task->headers_initialized  = 1;
        iser_task->iser_conn            = iser_conn;
        return 0;
 }
@@ -166,8 +165,7 @@ iscsi_iser_task_init(struct iscsi_task *task)
 {
        struct iscsi_iser_task *iser_task = task->dd_data;
 
-       if (!iser_task->headers_initialized)
-               if (iser_initialize_task_headers(task, &iser_task->desc))
+       if (iser_initialize_task_headers(task, &iser_task->desc))
                        return -ENOMEM;
 
        /* mgmt task */
@@ -278,6 +276,13 @@ iscsi_iser_task_xmit(struct iscsi_task *task)
 static void iscsi_iser_cleanup_task(struct iscsi_task *task)
 {
        struct iscsi_iser_task *iser_task = task->dd_data;
+       struct iser_tx_desc     *tx_desc = &iser_task->desc;
+
+       struct iscsi_iser_conn *iser_conn = task->conn->dd_data;
+       struct iser_device     *device    = iser_conn->ib_conn->device;
+
+       ib_dma_unmap_single(device->ib_device,
+               tx_desc->dma_addr, ISER_HEADERS_LEN, DMA_TO_DEVICE);
 
        /* mgmt tasks do not need special cleanup */
        if (!task->sc)
index db6f3ce..db7ea37 100644 (file)
@@ -257,7 +257,8 @@ struct iser_conn {
        struct list_head             conn_list;       /* entry in ig conn list */
 
        char                         *login_buf;
-       u64                          login_dma;
+       char                         *login_req_buf, *login_resp_buf;
+       u64                          login_req_dma, login_resp_dma;
        unsigned int                 rx_desc_head;
        struct iser_rx_desc          *rx_descs;
        struct ib_recv_wr            rx_wr[ISER_MIN_POSTED_RX];
@@ -277,7 +278,6 @@ struct iscsi_iser_task {
        struct iser_regd_buf         rdma_regd[ISER_DIRS_NUM];/* regd rdma buf */
        struct iser_data_buf         data[ISER_DIRS_NUM];     /* orig. data des*/
        struct iser_data_buf         data_copy[ISER_DIRS_NUM];/* contig. copy  */
-       int                          headers_initialized;
 };
 
 struct iser_page_vec {
index f299de6..a607542 100644 (file)
@@ -221,8 +221,14 @@ void iser_free_rx_descriptors(struct iser_conn *ib_conn)
        struct iser_device *device = ib_conn->device;
 
        if (ib_conn->login_buf) {
-               ib_dma_unmap_single(device->ib_device, ib_conn->login_dma,
-                       ISER_RX_LOGIN_SIZE, DMA_FROM_DEVICE);
+               if (ib_conn->login_req_dma)
+                       ib_dma_unmap_single(device->ib_device,
+                               ib_conn->login_req_dma,
+                               ISCSI_DEF_MAX_RECV_SEG_LEN, DMA_TO_DEVICE);
+               if (ib_conn->login_resp_dma)
+                       ib_dma_unmap_single(device->ib_device,
+                               ib_conn->login_resp_dma,
+                               ISER_RX_LOGIN_SIZE, DMA_FROM_DEVICE);
                kfree(ib_conn->login_buf);
        }
 
@@ -394,6 +400,7 @@ int iser_send_control(struct iscsi_conn *conn,
        unsigned long data_seg_len;
        int err = 0;
        struct iser_device *device;
+       struct iser_conn *ib_conn = iser_conn->ib_conn;
 
        /* build the tx desc regd header and add it to the tx desc dto */
        mdesc->type = ISCSI_TX_CONTROL;
@@ -409,9 +416,19 @@ int iser_send_control(struct iscsi_conn *conn,
                        iser_err("data present on non login task!!!\n");
                        goto send_control_error;
                }
-               memcpy(iser_conn->ib_conn->login_buf, task->data,
+
+               ib_dma_sync_single_for_cpu(device->ib_device,
+                       ib_conn->login_req_dma, task->data_count,
+                       DMA_TO_DEVICE);
+
+               memcpy(iser_conn->ib_conn->login_req_buf, task->data,
                                                        task->data_count);
-               tx_dsg->addr    = iser_conn->ib_conn->login_dma;
+
+               ib_dma_sync_single_for_device(device->ib_device,
+                       ib_conn->login_req_dma, task->data_count,
+                       DMA_TO_DEVICE);
+
+               tx_dsg->addr    = iser_conn->ib_conn->login_req_dma;
                tx_dsg->length  = task->data_count;
                tx_dsg->lkey    = device->mr->lkey;
                mdesc->num_sge = 2;
@@ -445,8 +462,8 @@ void iser_rcv_completion(struct iser_rx_desc *rx_desc,
        int rx_buflen, outstanding, count, err;
 
        /* differentiate between login to all other PDUs */
-       if ((char *)rx_desc == ib_conn->login_buf) {
-               rx_dma = ib_conn->login_dma;
+       if ((char *)rx_desc == ib_conn->login_resp_buf) {
+               rx_dma = ib_conn->login_resp_dma;
                rx_buflen = ISER_RX_LOGIN_SIZE;
        } else {
                rx_dma = rx_desc->dma_addr;
@@ -473,7 +490,7 @@ void iser_rcv_completion(struct iser_rx_desc *rx_desc,
         * for the posted rx bufs refcount to become zero handles everything   */
        conn->ib_conn->post_recv_buf_count--;
 
-       if (rx_dma == ib_conn->login_dma)
+       if (rx_dma == ib_conn->login_resp_dma)
                return;
 
        outstanding = ib_conn->post_recv_buf_count;
index ede1475..e28877c 100644 (file)
@@ -155,20 +155,39 @@ static int iser_create_ib_conn_res(struct iser_conn *ib_conn)
 {
        struct iser_device      *device;
        struct ib_qp_init_attr  init_attr;
-       int                     ret = -ENOMEM;
+       int                     req_err, resp_err, ret = -ENOMEM;
        struct ib_fmr_pool_param params;
 
        BUG_ON(ib_conn->device == NULL);
 
        device = ib_conn->device;
 
-       ib_conn->login_buf = kmalloc(ISER_RX_LOGIN_SIZE, GFP_KERNEL);
+       ib_conn->login_buf = kmalloc(ISCSI_DEF_MAX_RECV_SEG_LEN +
+                                       ISER_RX_LOGIN_SIZE, GFP_KERNEL);
        if (!ib_conn->login_buf)
                goto out_err;
 
-       ib_conn->login_dma = ib_dma_map_single(ib_conn->device->ib_device,
-                               (void *)ib_conn->login_buf, ISER_RX_LOGIN_SIZE,
-                               DMA_FROM_DEVICE);
+       ib_conn->login_req_buf  = ib_conn->login_buf;
+       ib_conn->login_resp_buf = ib_conn->login_buf + ISCSI_DEF_MAX_RECV_SEG_LEN;
+
+       ib_conn->login_req_dma = ib_dma_map_single(ib_conn->device->ib_device,
+                               (void *)ib_conn->login_req_buf,
+                               ISCSI_DEF_MAX_RECV_SEG_LEN, DMA_TO_DEVICE);
+
+       ib_conn->login_resp_dma = ib_dma_map_single(ib_conn->device->ib_device,
+                               (void *)ib_conn->login_resp_buf,
+                               ISER_RX_LOGIN_SIZE, DMA_FROM_DEVICE);
+
+       req_err  = ib_dma_mapping_error(device->ib_device, ib_conn->login_req_dma);
+       resp_err = ib_dma_mapping_error(device->ib_device, ib_conn->login_resp_dma);
+
+       if (req_err || resp_err) {
+               if (req_err)
+                       ib_conn->login_req_dma = 0;
+               if (resp_err)
+                       ib_conn->login_resp_dma = 0;
+               goto out_err;
+       }
 
        ib_conn->page_vec = kmalloc(sizeof(struct iser_page_vec) +
                                    (sizeof(u64) * (ISCSI_ISER_SG_TABLESIZE +1)),
@@ -658,11 +677,11 @@ int iser_post_recvl(struct iser_conn *ib_conn)
        struct ib_sge     sge;
        int ib_ret;
 
-       sge.addr   = ib_conn->login_dma;
+       sge.addr   = ib_conn->login_resp_dma;
        sge.length = ISER_RX_LOGIN_SIZE;
        sge.lkey   = ib_conn->device->mr->lkey;
 
-       rx_wr.wr_id   = (unsigned long)ib_conn->login_buf;
+       rx_wr.wr_id   = (unsigned long)ib_conn->login_resp_buf;
        rx_wr.sg_list = &sge;
        rx_wr.num_sge = 1;
        rx_wr.next    = NULL;
index 6b6616a..4720f68 100644 (file)
@@ -192,9 +192,6 @@ struct mapped_device {
        /* forced geometry settings */
        struct hd_geometry geometry;
 
-       /* For saving the address of __make_request for request based dm */
-       make_request_fn *saved_make_request_fn;
-
        /* sysfs handle */
        struct kobject kobj;
 
@@ -1403,7 +1400,7 @@ out:
  * The request function that just remaps the bio built up by
  * dm_merge_bvec.
  */
-static int _dm_request(struct request_queue *q, struct bio *bio)
+static void _dm_request(struct request_queue *q, struct bio *bio)
 {
        int rw = bio_data_dir(bio);
        struct mapped_device *md = q->queuedata;
@@ -1424,19 +1421,12 @@ static int _dm_request(struct request_queue *q, struct bio *bio)
                        queue_io(md, bio);
                else
                        bio_io_error(bio);
-               return 0;
+               return;
        }
 
        __split_and_process_bio(md, bio);
        up_read(&md->io_lock);
-       return 0;
-}
-
-static int dm_make_request(struct request_queue *q, struct bio *bio)
-{
-       struct mapped_device *md = q->queuedata;
-
-       return md->saved_make_request_fn(q, bio); /* call __make_request() */
+       return;
 }
 
 static int dm_request_based(struct mapped_device *md)
@@ -1444,14 +1434,14 @@ static int dm_request_based(struct mapped_device *md)
        return blk_queue_stackable(md->queue);
 }
 
-static int dm_request(struct request_queue *q, struct bio *bio)
+static void dm_request(struct request_queue *q, struct bio *bio)
 {
        struct mapped_device *md = q->queuedata;
 
        if (dm_request_based(md))
-               return dm_make_request(q, bio);
-
-       return _dm_request(q, bio);
+               blk_queue_bio(q, bio);
+       else
+               _dm_request(q, bio);
 }
 
 void dm_dispatch_request(struct request *rq)
@@ -2191,7 +2181,6 @@ static int dm_init_request_based_queue(struct mapped_device *md)
                return 0;
 
        md->queue = q;
-       md->saved_make_request_fn = md->queue->make_request_fn;
        dm_init_md_queue(md);
        blk_queue_softirq_done(md->queue, dm_softirq_done);
        blk_queue_prep_rq(md->queue, dm_prep_fn);
index 60816b1..918fb8a 100644 (file)
@@ -169,7 +169,7 @@ static void add_sector(struct faulty_conf *conf, sector_t start, int mode)
                conf->nfaults = n+1;
 }
 
-static int make_request(struct mddev *mddev, struct bio *bio)
+static void make_request(struct mddev *mddev, struct bio *bio)
 {
        struct faulty_conf *conf = mddev->private;
        int failit = 0;
@@ -181,7 +181,7 @@ static int make_request(struct mddev *mddev, struct bio *bio)
                         * just fail immediately
                         */
                        bio_endio(bio, -EIO);
-                       return 0;
+                       return;
                }
 
                if (check_sector(conf, bio->bi_sector, bio->bi_sector+(bio->bi_size>>9),
@@ -211,15 +211,15 @@ static int make_request(struct mddev *mddev, struct bio *bio)
        }
        if (failit) {
                struct bio *b = bio_clone_mddev(bio, GFP_NOIO, mddev);
+
                b->bi_bdev = conf->rdev->bdev;
                b->bi_private = bio;
                b->bi_end_io = faulty_fail;
-               generic_make_request(b);
-               return 0;
-       } else {
+               bio = b;
+       } else
                bio->bi_bdev = conf->rdev->bdev;
-               return 1;
-       }
+
+       generic_make_request(bio);
 }
 
 static void status(struct seq_file *seq, struct mddev *mddev)
index 10c5844..a820358 100644 (file)
@@ -264,14 +264,14 @@ static int linear_stop (struct mddev *mddev)
        return 0;
 }
 
-static int linear_make_request (struct mddev *mddev, struct bio *bio)
+static void linear_make_request(struct mddev *mddev, struct bio *bio)
 {
        struct dev_info *tmp_dev;
        sector_t start_sector;
 
        if (unlikely(bio->bi_rw & REQ_FLUSH)) {
                md_flush_request(mddev, bio);
-               return 0;
+               return;
        }
 
        rcu_read_lock();
@@ -293,7 +293,7 @@ static int linear_make_request (struct mddev *mddev, struct bio *bio)
                       (unsigned long long)start_sector);
                rcu_read_unlock();
                bio_io_error(bio);
-               return 0;
+               return;
        }
        if (unlikely(bio->bi_sector + (bio->bi_size >> 9) >
                     tmp_dev->end_sector)) {
@@ -307,20 +307,17 @@ static int linear_make_request (struct mddev *mddev, struct bio *bio)
 
                bp = bio_split(bio, end_sector - bio->bi_sector);
 
-               if (linear_make_request(mddev, &bp->bio1))
-                       generic_make_request(&bp->bio1);
-               if (linear_make_request(mddev, &bp->bio2))
-                       generic_make_request(&bp->bio2);
+               linear_make_request(mddev, &bp->bio1);
+               linear_make_request(mddev, &bp->bio2);
                bio_pair_release(bp);
-               return 0;
+               return;
        }
                    
        bio->bi_bdev = tmp_dev->rdev->bdev;
        bio->bi_sector = bio->bi_sector - start_sector
                + tmp_dev->rdev->data_offset;
        rcu_read_unlock();
-
-       return 1;
+       generic_make_request(bio);
 }
 
 static void linear_status (struct seq_file *seq, struct mddev *mddev)
index 266e82e..2acb328 100644 (file)
@@ -332,18 +332,17 @@ static DEFINE_SPINLOCK(all_mddevs_lock);
  * call has finished, the bio has been linked into some internal structure
  * and so is visible to ->quiesce(), so we don't need the refcount any more.
  */
-static int md_make_request(struct request_queue *q, struct bio *bio)
+static void md_make_request(struct request_queue *q, struct bio *bio)
 {
        const int rw = bio_data_dir(bio);
        struct mddev *mddev = q->queuedata;
-       int rv;
        int cpu;
        unsigned int sectors;
 
        if (mddev == NULL || mddev->pers == NULL
            || !mddev->ready) {
                bio_io_error(bio);
-               return 0;
+               return;
        }
        smp_rmb(); /* Ensure implications of  'active' are visible */
        rcu_read_lock();
@@ -368,7 +367,7 @@ static int md_make_request(struct request_queue *q, struct bio *bio)
         * go away inside make_request
         */
        sectors = bio_sectors(bio);
-       rv = mddev->pers->make_request(mddev, bio);
+       mddev->pers->make_request(mddev, bio);
 
        cpu = part_stat_lock();
        part_stat_inc(cpu, &mddev->gendisk->part0, ios[rw]);
@@ -377,8 +376,6 @@ static int md_make_request(struct request_queue *q, struct bio *bio)
 
        if (atomic_dec_and_test(&mddev->active_io) && mddev->suspended)
                wake_up(&mddev->sb_wait);
-
-       return rv;
 }
 
 /* mddev_suspend makes sure no new requests are submitted
@@ -477,8 +474,7 @@ static void md_submit_flush_data(struct work_struct *ws)
                bio_endio(bio, 0);
        else {
                bio->bi_rw &= ~REQ_FLUSH;
-               if (mddev->pers->make_request(mddev, bio))
-                       generic_make_request(bio);
+               mddev->pers->make_request(mddev, bio);
        }
 
        mddev->flush_bio = NULL;
index 51c1d91..cf742d9 100644 (file)
@@ -419,7 +419,7 @@ struct md_personality
        int level;
        struct list_head list;
        struct module *owner;
-       int (*make_request)(struct mddev *mddev, struct bio *bio);
+       void (*make_request)(struct mddev *mddev, struct bio *bio);
        int (*run)(struct mddev *mddev);
        int (*stop)(struct mddev *mddev);
        void (*status)(struct seq_file *seq, struct mddev *mddev);
index d32c785..ad20a28 100644 (file)
@@ -106,7 +106,7 @@ static void multipath_end_request(struct bio *bio, int error)
        rdev_dec_pending(rdev, conf->mddev);
 }
 
-static int multipath_make_request(struct mddev *mddev, struct bio * bio)
+static void multipath_make_request(struct mddev *mddev, struct bio * bio)
 {
        struct mpconf *conf = mddev->private;
        struct multipath_bh * mp_bh;
@@ -114,7 +114,7 @@ static int multipath_make_request(struct mddev *mddev, struct bio * bio)
 
        if (unlikely(bio->bi_rw & REQ_FLUSH)) {
                md_flush_request(mddev, bio);
-               return 0;
+               return;
        }
 
        mp_bh = mempool_alloc(conf->pool, GFP_NOIO);
@@ -126,7 +126,7 @@ static int multipath_make_request(struct mddev *mddev, struct bio * bio)
        if (mp_bh->path < 0) {
                bio_endio(bio, -EIO);
                mempool_free(mp_bh, conf->pool);
-               return 0;
+               return;
        }
        multipath = conf->multipaths + mp_bh->path;
 
@@ -137,7 +137,7 @@ static int multipath_make_request(struct mddev *mddev, struct bio * bio)
        mp_bh->bio.bi_end_io = multipath_end_request;
        mp_bh->bio.bi_private = mp_bh;
        generic_make_request(&mp_bh->bio);
-       return 0;
+       return;
 }
 
 static void multipath_status (struct seq_file *seq, struct mddev *mddev)
index 0eb08a4..27e19e2 100644 (file)
@@ -468,7 +468,7 @@ static inline int is_io_in_chunk_boundary(struct mddev *mddev,
        }
 }
 
-static int raid0_make_request(struct mddev *mddev, struct bio *bio)
+static void raid0_make_request(struct mddev *mddev, struct bio *bio)
 {
        unsigned int chunk_sects;
        sector_t sector_offset;
@@ -477,7 +477,7 @@ static int raid0_make_request(struct mddev *mddev, struct bio *bio)
 
        if (unlikely(bio->bi_rw & REQ_FLUSH)) {
                md_flush_request(mddev, bio);
-               return 0;
+               return;
        }
 
        chunk_sects = mddev->chunk_sectors;
@@ -497,13 +497,10 @@ static int raid0_make_request(struct mddev *mddev, struct bio *bio)
                else
                        bp = bio_split(bio, chunk_sects -
                                       sector_div(sector, chunk_sects));
-               if (raid0_make_request(mddev, &bp->bio1))
-                       generic_make_request(&bp->bio1);
-               if (raid0_make_request(mddev, &bp->bio2))
-                       generic_make_request(&bp->bio2);
-
+               raid0_make_request(mddev, &bp->bio1);
+               raid0_make_request(mddev, &bp->bio2);
                bio_pair_release(bp);
-               return 0;
+               return;
        }
 
        sector_offset = bio->bi_sector;
@@ -513,10 +510,9 @@ static int raid0_make_request(struct mddev *mddev, struct bio *bio)
        bio->bi_bdev = tmp_dev->bdev;
        bio->bi_sector = sector_offset + zone->dev_start +
                tmp_dev->data_offset;
-       /*
-        * Let the main block layer submit the IO and resolve recursion:
-        */
-       return 1;
+
+       generic_make_request(bio);
+       return;
 
 bad_map:
        printk("md/raid0:%s: make_request bug: can't convert block across chunks"
@@ -525,7 +521,7 @@ bad_map:
               (unsigned long long)bio->bi_sector, bio->bi_size >> 10);
 
        bio_io_error(bio);
-       return 0;
+       return;
 }
 
 static void raid0_status(struct seq_file *seq, struct mddev *mddev)
index 4602fc5..cae8746 100644 (file)
@@ -807,7 +807,7 @@ do_sync_io:
        pr_debug("%dB behind alloc failed, doing sync I/O\n", bio->bi_size);
 }
 
-static int make_request(struct mddev *mddev, struct bio * bio)
+static void make_request(struct mddev *mddev, struct bio * bio)
 {
        struct r1conf *conf = mddev->private;
        struct mirror_info *mirror;
@@ -892,7 +892,7 @@ read_again:
                if (rdisk < 0) {
                        /* couldn't find anywhere to read from */
                        raid_end_bio_io(r1_bio);
-                       return 0;
+                       return;
                }
                mirror = conf->mirrors + rdisk;
 
@@ -950,7 +950,7 @@ read_again:
                        goto read_again;
                } else
                        generic_make_request(read_bio);
-               return 0;
+               return;
        }
 
        /*
@@ -1151,8 +1151,6 @@ read_again:
 
        if (do_sync || !bitmap || !plugged)
                md_wakeup_thread(mddev->thread);
-
-       return 0;
 }
 
 static void status(struct seq_file *seq, struct mddev *mddev)
@@ -2193,7 +2191,6 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, int *skipp
                bio->bi_next = NULL;
                bio->bi_flags &= ~(BIO_POOL_MASK-1);
                bio->bi_flags |= 1 << BIO_UPTODATE;
-               bio->bi_comp_cpu = -1;
                bio->bi_rw = READ;
                bio->bi_vcnt = 0;
                bio->bi_idx = 0;
index c025a82..dde6dd4 100644 (file)
@@ -842,7 +842,7 @@ static void unfreeze_array(struct r10conf *conf)
        spin_unlock_irq(&conf->resync_lock);
 }
 
-static int make_request(struct mddev *mddev, struct bio * bio)
+static void make_request(struct mddev *mddev, struct bio * bio)
 {
        struct r10conf *conf = mddev->private;
        struct mirror_info *mirror;
@@ -861,7 +861,7 @@ static int make_request(struct mddev *mddev, struct bio * bio)
 
        if (unlikely(bio->bi_rw & REQ_FLUSH)) {
                md_flush_request(mddev, bio);
-               return 0;
+               return;
        }
 
        /* If this request crosses a chunk boundary, we need to
@@ -893,10 +893,8 @@ static int make_request(struct mddev *mddev, struct bio * bio)
                conf->nr_waiting++;
                spin_unlock_irq(&conf->resync_lock);
 
-               if (make_request(mddev, &bp->bio1))
-                       generic_make_request(&bp->bio1);
-               if (make_request(mddev, &bp->bio2))
-                       generic_make_request(&bp->bio2);
+               make_request(mddev, &bp->bio1);
+               make_request(mddev, &bp->bio2);
 
                spin_lock_irq(&conf->resync_lock);
                conf->nr_waiting--;
@@ -904,14 +902,14 @@ static int make_request(struct mddev *mddev, struct bio * bio)
                spin_unlock_irq(&conf->resync_lock);
 
                bio_pair_release(bp);
-               return 0;
+               return;
        bad_map:
                printk("md/raid10:%s: make_request bug: can't convert block across chunks"
                       " or bigger than %dk %llu %d\n", mdname(mddev), chunk_sects/2,
                       (unsigned long long)bio->bi_sector, bio->bi_size >> 10);
 
                bio_io_error(bio);
-               return 0;
+               return;
        }
 
        md_write_start(mddev, bio);
@@ -954,7 +952,7 @@ read_again:
                slot = r10_bio->read_slot;
                if (disk < 0) {
                        raid_end_bio_io(r10_bio);
-                       return 0;
+                       return;
                }
                mirror = conf->mirrors + disk;
 
@@ -1002,7 +1000,7 @@ read_again:
                        goto read_again;
                } else
                        generic_make_request(read_bio);
-               return 0;
+               return;
        }
 
        /*
@@ -1176,7 +1174,6 @@ retry_write:
 
        if (do_sync || !mddev->bitmap || !plugged)
                md_wakeup_thread(mddev->thread);
-       return 0;
 }
 
 static void status(struct seq_file *seq, struct mddev *mddev)
index f6fe053..bb1b461 100644 (file)
@@ -3688,7 +3688,7 @@ static struct stripe_head *__get_priority_stripe(struct r5conf *conf)
        return sh;
 }
 
-static int make_request(struct mddev *mddev, struct bio * bi)
+static void make_request(struct mddev *mddev, struct bio * bi)
 {
        struct r5conf *conf = mddev->private;
        int dd_idx;
@@ -3701,7 +3701,7 @@ static int make_request(struct mddev *mddev, struct bio * bi)
 
        if (unlikely(bi->bi_rw & REQ_FLUSH)) {
                md_flush_request(mddev, bi);
-               return 0;
+               return;
        }
 
        md_write_start(mddev, bi);
@@ -3709,7 +3709,7 @@ static int make_request(struct mddev *mddev, struct bio * bi)
        if (rw == READ &&
             mddev->reshape_position == MaxSector &&
             chunk_aligned_read(mddev,bi))
-               return 0;
+               return;
 
        logical_sector = bi->bi_sector & ~((sector_t)STRIPE_SECTORS-1);
        last_sector = bi->bi_sector + (bi->bi_size>>9);
@@ -3844,8 +3844,6 @@ static int make_request(struct mddev *mddev, struct bio * bi)
 
                bio_endio(bi, 0);
        }
-
-       return 0;
 }
 
 static sector_t raid5_size(struct mddev *mddev, sector_t sectors, int raid_disks);
index cf7214e..38019ba 100644 (file)
@@ -11,4 +11,4 @@ ccflags-y += -Idrivers/media/dvb/frontends/
 ccflags-y += -Idrivers/media/common/tuners/
 
 # For the staging CI driver cxd2099
-ccflags-y += -Idrivers/staging/cxd2099/
+ccflags-y += -Idrivers/staging/media/cxd2099/
index 7d0710b..26c8b9e 100644 (file)
@@ -102,6 +102,7 @@ obj-$(CONFIG_DVB_USB_IT913X) += dvb-usb-it913x.o
 
 dvb-usb-mxl111sf-objs = mxl111sf.o mxl111sf-phy.o mxl111sf-i2c.o mxl111sf-gpio.o
 obj-$(CONFIG_DVB_USB_MXL111SF) += dvb-usb-mxl111sf.o
+obj-$(CONFIG_DVB_USB_MXL111SF) += mxl111sf-demod.o
 obj-$(CONFIG_DVB_USB_MXL111SF) += mxl111sf-tuner.o
 
 ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
index 2ad33ba..2d08c9b 100644 (file)
@@ -37,6 +37,7 @@
 #define USB_VID_HAUPPAUGE                      0x2040
 #define USB_VID_HYPER_PALTEK                   0x1025
 #define USB_VID_INTEL                          0x8086
+#define USB_VID_ITETECH                                0x048d
 #define USB_VID_KWORLD                         0xeb2a
 #define USB_VID_KWORLD_2                       0x1b80
 #define USB_VID_KYE                            0x0458
 #define USB_PID_GRANDTEC_DVBT_USB_COLD                 0x0fa0
 #define USB_PID_GRANDTEC_DVBT_USB_WARM                 0x0fa1
 #define USB_PID_INTEL_CE9500                           0x9500
+#define USB_PID_ITETECH_IT9135                         0x9135
 #define USB_PID_KWORLD_399U                            0xe399
 #define USB_PID_KWORLD_399U_2                          0xe400
 #define USB_PID_KWORLD_395U                            0xe396
index f027a2c..c462261 100644 (file)
@@ -60,6 +60,17 @@ struct it913x_state {
        u8 id;
 };
 
+struct ite_config {
+       u8 chip_ver;
+       u16 chip_type;
+       u32 firmware;
+       u8 tuner_id_0;
+       u8 tuner_id_1;
+       u8 dual_mode;
+};
+
+struct ite_config it913x_config;
+
 static int it913x_bulk_write(struct usb_device *dev,
                                u8 *snd, int len, u8 pipe)
 {
@@ -191,18 +202,23 @@ static int it913x_read_reg(struct usb_device *udev, u32 reg)
 static u32 it913x_query(struct usb_device *udev, u8 pro)
 {
        int ret;
-       u32 res = 0;
        u8 data[4];
        ret = it913x_io(udev, READ_LONG, pro, CMD_DEMOD_READ,
-               0x1222, 0, &data[0], 1);
-       if (data[0] == 0x1) {
-               ret = it913x_io(udev, READ_SHORT, pro,
+               0x1222, 0, &data[0], 3);
+
+       it913x_config.chip_ver = data[0];
+       it913x_config.chip_type = (u16)(data[2] << 8) + data[1];
+
+       info("Chip Version=%02x Chip Type=%04x", it913x_config.chip_ver,
+               it913x_config.chip_type);
+
+       ret |= it913x_io(udev, READ_SHORT, pro,
                        CMD_QUERYINFO, 0, 0x1, &data[0], 4);
-               res = (data[0] << 24) + (data[1] << 16) +
+
+       it913x_config.firmware = (data[0] << 24) + (data[1] << 16) +
                        (data[2] << 8) + data[3];
-       }
 
-       return (ret < 0) ? 0 : res;
+       return (ret < 0) ? 0 : it913x_config.firmware;
 }
 
 static int it913x_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
@@ -336,26 +352,35 @@ static int it913x_identify_state(struct usb_device *udev,
                int *cold)
 {
        int ret = 0, firm_no;
-       u8 reg, adap, ep, tun0, tun1;
+       u8 reg, remote;
 
        firm_no = it913x_return_status(udev);
 
-       ep = it913x_read_reg(udev, 0x49ac);
-       adap = it913x_read_reg(udev, 0x49c5);
-       tun0 = it913x_read_reg(udev, 0x49d0);
-       info("No. Adapters=%x Endpoints=%x Tuner Type=%x", adap, ep, tun0);
+       /* checnk for dual mode */
+       it913x_config.dual_mode =  it913x_read_reg(udev, 0x49c5);
+
+       /* TODO different remotes */
+       remote = it913x_read_reg(udev, 0x49ac); /* Remote */
+       if (remote == 0)
+               props->rc.core.rc_codes = NULL;
+
+       /* TODO at the moment tuner_id is always assigned to 0x38 */
+       it913x_config.tuner_id_0 = it913x_read_reg(udev, 0x49d0);
+
+       info("Dual mode=%x Remote=%x Tuner Type=%x", it913x_config.dual_mode
+               , remote, it913x_config.tuner_id_0);
 
        if (firm_no > 0) {
                *cold = 0;
                return 0;
        }
 
-       if (adap > 2) {
-               tun1 = it913x_read_reg(udev, 0x49e0);
+       if (it913x_config.dual_mode) {
+               it913x_config.tuner_id_1 = it913x_read_reg(udev, 0x49e0);
                ret = it913x_wr_reg(udev, DEV_0, GPIOH1_EN, 0x1);
                ret |= it913x_wr_reg(udev, DEV_0, GPIOH1_ON, 0x1);
                ret |= it913x_wr_reg(udev, DEV_0, GPIOH1_O, 0x1);
-               msleep(50); /* Delay noticed reset cycle ? */
+               msleep(50);
                ret |= it913x_wr_reg(udev, DEV_0, GPIOH1_O, 0x0);
                msleep(50);
                reg = it913x_read_reg(udev, GPIOH1_O);
@@ -366,14 +391,19 @@ static int it913x_identify_state(struct usb_device *udev,
                                ret = it913x_wr_reg(udev, DEV_0,
                                        GPIOH1_O, 0x0);
                }
+               props->num_adapters = 2;
        } else
                props->num_adapters = 1;
 
        reg = it913x_read_reg(udev, IO_MUX_POWER_CLK);
 
-       ret |= it913x_wr_reg(udev, DEV_0, 0x4bfb, CHIP2_I2C_ADDR);
-
-       ret |= it913x_wr_reg(udev, DEV_0,  CLK_O_EN, 0x1);
+       if (it913x_config.dual_mode) {
+               ret |= it913x_wr_reg(udev, DEV_0, 0x4bfb, CHIP2_I2C_ADDR);
+               ret |= it913x_wr_reg(udev, DEV_0,  CLK_O_EN, 0x1);
+       } else {
+               ret |= it913x_wr_reg(udev, DEV_0, 0x4bfb, 0x0);
+               ret |= it913x_wr_reg(udev, DEV_0,  CLK_O_EN, 0x0);
+       }
 
        *cold = 1;
 
@@ -403,13 +433,11 @@ static int it913x_download_firmware(struct usb_device *udev,
                                        const struct firmware *fw)
 {
        int ret = 0, i;
-       u8 packet_size, dlen, tun1;
+       u8 packet_size, dlen;
        u8 *fw_data;
 
        packet_size = 0x29;
 
-       tun1 = it913x_read_reg(udev, 0x49e0);
-
        ret = it913x_wr_reg(udev, DEV_0,  I2C_CLK, I2C_CLK_100);
 
        info("FRM Starting Firmware Download");
@@ -444,11 +472,12 @@ static int it913x_download_firmware(struct usb_device *udev,
        ret |= it913x_wr_reg(udev, DEV_0,  I2C_CLK, I2C_CLK_400);
 
        /* Tuner function */
-       ret |= it913x_wr_reg(udev, DEV_0_DMOD , 0xec4c, 0xa0);
+       if (it913x_config.dual_mode)
+               ret |= it913x_wr_reg(udev, DEV_0_DMOD , 0xec4c, 0xa0);
 
        ret |= it913x_wr_reg(udev, DEV_0,  PADODPU, 0x0);
        ret |= it913x_wr_reg(udev, DEV_0,  AGC_O_D, 0x0);
-       if (tun1 > 0) {
+       if (it913x_config.dual_mode) {
                ret |= it913x_wr_reg(udev, DEV_1,  PADODPU, 0x0);
                ret |= it913x_wr_reg(udev, DEV_1,  AGC_O_D, 0x0);
        }
@@ -475,9 +504,28 @@ static int it913x_frontend_attach(struct dvb_usb_adapter *adap)
        u8 adf = it913x_read_reg(udev, IO_MUX_POWER_CLK);
        u8 adap_addr = I2C_BASE_ADDR + (adap->id << 5);
        u16 ep_size = adap->props.fe[0].stream.u.bulk.buffersize;
+       u8 tuner_id, tuner_type;
+
+       if (adap->id == 0)
+               tuner_id = it913x_config.tuner_id_0;
+       else
+               tuner_id = it913x_config.tuner_id_1;
+
+       /* TODO we always use IT9137 possible references here*/
+       /* Documentation suggests don't care */
+       switch (tuner_id) {
+       case 0x51:
+       case 0x52:
+       case 0x60:
+       case 0x61:
+       case 0x62:
+       default:
+       case 0x38:
+               tuner_type = IT9137;
+       }
 
        adap->fe_adap[0].fe = dvb_attach(it913x_fe_attach,
-               &adap->dev->i2c_adap, adap_addr, adf, IT9137);
+               &adap->dev->i2c_adap, adap_addr, adf, tuner_type);
 
        if (adap->id == 0 && adap->fe_adap[0].fe) {
                ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2_SW_RST, 0x1);
@@ -533,6 +581,7 @@ static int it913x_probe(struct usb_interface *intf,
 
 static struct usb_device_id it913x_table[] = {
        { USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_UB499_2T_T09) },
+       { USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9135) },
        {}              /* Terminating entry */
 };
 
@@ -608,12 +657,14 @@ static struct dvb_usb_device_properties it913x_properties = {
                .rc_codes       = RC_MAP_KWORLD_315U,
        },
        .i2c_algo         = &it913x_i2c_algo,
-       .num_device_descs = 1,
+       .num_device_descs = 2,
        .devices = {
                {   "Kworld UB499-2T T09(IT9137)",
                        { &it913x_table[0], NULL },
                        },
-
+               {   "ITE 9135 Generic",
+                       { &it913x_table[1], NULL },
+                       },
        }
 };
 
@@ -647,5 +698,5 @@ module_exit(it913x_module_exit);
 
 MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>");
 MODULE_DESCRIPTION("it913x USB 2 Driver");
-MODULE_VERSION("1.06");
+MODULE_VERSION("1.07");
 MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/mxl111sf-demod.c b/drivers/media/dvb/dvb-usb/mxl111sf-demod.c
new file mode 100644 (file)
index 0000000..d1f5837
--- /dev/null
@@ -0,0 +1,614 @@
+/*
+ *  mxl111sf-demod.c - driver for the MaxLinear MXL111SF DVB-T demodulator
+ *
+ *  Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "mxl111sf-demod.h"
+#include "mxl111sf-reg.h"
+
+/* debug */
+static int mxl111sf_demod_debug;
+module_param_named(debug, mxl111sf_demod_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able)).");
+
+#define mxl_dbg(fmt, arg...) \
+       if (mxl111sf_demod_debug) \
+               mxl_printk(KERN_DEBUG, fmt, ##arg)
+
+/* ------------------------------------------------------------------------ */
+
+struct mxl111sf_demod_state {
+       struct mxl111sf_state *mxl_state;
+
+       struct mxl111sf_demod_config *cfg;
+
+       struct dvb_frontend fe;
+};
+
+/* ------------------------------------------------------------------------ */
+
+static int mxl111sf_demod_read_reg(struct mxl111sf_demod_state *state,
+                                  u8 addr, u8 *data)
+{
+       return (state->cfg->read_reg) ?
+               state->cfg->read_reg(state->mxl_state, addr, data) :
+               -EINVAL;
+}
+
+static int mxl111sf_demod_write_reg(struct mxl111sf_demod_state *state,
+                                   u8 addr, u8 data)
+{
+       return (state->cfg->write_reg) ?
+               state->cfg->write_reg(state->mxl_state, addr, data) :
+               -EINVAL;
+}
+
+static
+int mxl111sf_demod_program_regs(struct mxl111sf_demod_state *state,
+                               struct mxl111sf_reg_ctrl_info *ctrl_reg_info)
+{
+       return (state->cfg->program_regs) ?
+               state->cfg->program_regs(state->mxl_state, ctrl_reg_info) :
+               -EINVAL;
+}
+
+/* ------------------------------------------------------------------------ */
+/* TPS */
+
+static
+int mxl1x1sf_demod_get_tps_code_rate(struct mxl111sf_demod_state *state,
+                                    fe_code_rate_t *code_rate)
+{
+       u8 val;
+       int ret = mxl111sf_demod_read_reg(state, V6_CODE_RATE_TPS_REG, &val);
+       /* bit<2:0> - 000:1/2, 001:2/3, 010:3/4, 011:5/6, 100:7/8 */
+       if (mxl_fail(ret))
+               goto fail;
+
+       switch (val & V6_CODE_RATE_TPS_MASK) {
+       case 0:
+               *code_rate = FEC_1_2;
+               break;
+       case 1:
+               *code_rate = FEC_2_3;
+               break;
+       case 2:
+               *code_rate = FEC_3_4;
+               break;
+       case 3:
+               *code_rate = FEC_5_6;
+               break;
+       case 4:
+               *code_rate = FEC_7_8;
+               break;
+       }
+fail:
+       return ret;
+}
+
+static
+int mxl1x1sf_demod_get_tps_constellation(struct mxl111sf_demod_state *state,
+                                        fe_modulation_t *constellation)
+{
+       u8 val;
+       int ret = mxl111sf_demod_read_reg(state, V6_MODORDER_TPS_REG, &val);
+       /* Constellation, 00 : QPSK, 01 : 16QAM, 10:64QAM */
+       if (mxl_fail(ret))
+               goto fail;
+
+       switch ((val & V6_PARAM_CONSTELLATION_MASK) >> 4) {
+       case 0:
+               *constellation = QPSK;
+               break;
+       case 1:
+               *constellation = QAM_16;
+               break;
+       case 2:
+               *constellation = QAM_64;
+               break;
+       }
+fail:
+       return ret;
+}
+
+static
+int mxl1x1sf_demod_get_tps_guard_fft_mode(struct mxl111sf_demod_state *state,
+                                         fe_transmit_mode_t *fft_mode)
+{
+       u8 val;
+       int ret = mxl111sf_demod_read_reg(state, V6_MODE_TPS_REG, &val);
+       /* FFT Mode, 00:2K, 01:8K, 10:4K */
+       if (mxl_fail(ret))
+               goto fail;
+
+       switch ((val & V6_PARAM_FFT_MODE_MASK) >> 2) {
+       case 0:
+               *fft_mode = TRANSMISSION_MODE_2K;
+               break;
+       case 1:
+               *fft_mode = TRANSMISSION_MODE_8K;
+               break;
+       case 2:
+               *fft_mode = TRANSMISSION_MODE_4K;
+               break;
+       }
+fail:
+       return ret;
+}
+
+static
+int mxl1x1sf_demod_get_tps_guard_interval(struct mxl111sf_demod_state *state,
+                                         fe_guard_interval_t *guard)
+{
+       u8 val;
+       int ret = mxl111sf_demod_read_reg(state, V6_CP_TPS_REG, &val);
+       /* 00:1/32, 01:1/16, 10:1/8, 11:1/4 */
+       if (mxl_fail(ret))
+               goto fail;
+
+       switch ((val & V6_PARAM_GI_MASK) >> 4) {
+       case 0:
+               *guard = GUARD_INTERVAL_1_32;
+               break;
+       case 1:
+               *guard = GUARD_INTERVAL_1_16;
+               break;
+       case 2:
+               *guard = GUARD_INTERVAL_1_8;
+               break;
+       case 3:
+               *guard = GUARD_INTERVAL_1_4;
+               break;
+       }
+fail:
+       return ret;
+}
+
+static
+int mxl1x1sf_demod_get_tps_hierarchy(struct mxl111sf_demod_state *state,
+                                    fe_hierarchy_t *hierarchy)
+{
+       u8 val;
+       int ret = mxl111sf_demod_read_reg(state, V6_TPS_HIERACHY_REG, &val);
+       /* bit<6:4> - 000:Non hierarchy, 001:1, 010:2, 011:4 */
+       if (mxl_fail(ret))
+               goto fail;
+
+       switch ((val & V6_TPS_HIERARCHY_INFO_MASK) >> 6) {
+       case 0:
+               *hierarchy = HIERARCHY_NONE;
+               break;
+       case 1:
+               *hierarchy = HIERARCHY_1;
+               break;
+       case 2:
+               *hierarchy = HIERARCHY_2;
+               break;
+       case 3:
+               *hierarchy = HIERARCHY_4;
+               break;
+       }
+fail:
+       return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+/* LOCKS */
+
+static
+int mxl1x1sf_demod_get_sync_lock_status(struct mxl111sf_demod_state *state,
+                                       int *sync_lock)
+{
+       u8 val = 0;
+       int ret = mxl111sf_demod_read_reg(state, V6_SYNC_LOCK_REG, &val);
+       if (mxl_fail(ret))
+               goto fail;
+       *sync_lock = (val & SYNC_LOCK_MASK) >> 4;
+fail:
+       return ret;
+}
+
+static
+int mxl1x1sf_demod_get_rs_lock_status(struct mxl111sf_demod_state *state,
+                                     int *rs_lock)
+{
+       u8 val = 0;
+       int ret = mxl111sf_demod_read_reg(state, V6_RS_LOCK_DET_REG, &val);
+       if (mxl_fail(ret))
+               goto fail;
+       *rs_lock = (val & RS_LOCK_DET_MASK) >> 3;
+fail:
+       return ret;
+}
+
+static
+int mxl1x1sf_demod_get_tps_lock_status(struct mxl111sf_demod_state *state,
+                                      int *tps_lock)
+{
+       u8 val = 0;
+       int ret = mxl111sf_demod_read_reg(state, V6_TPS_LOCK_REG, &val);
+       if (mxl_fail(ret))
+               goto fail;
+       *tps_lock = (val & V6_PARAM_TPS_LOCK_MASK) >> 6;
+fail:
+       return ret;
+}
+
+static
+int mxl1x1sf_demod_get_fec_lock_status(struct mxl111sf_demod_state *state,
+                                      int *fec_lock)
+{
+       u8 val = 0;
+       int ret = mxl111sf_demod_read_reg(state, V6_IRQ_STATUS_REG, &val);
+       if (mxl_fail(ret))
+               goto fail;
+       *fec_lock = (val & IRQ_MASK_FEC_LOCK) >> 4;
+fail:
+       return ret;
+}
+
+#if 0
+static
+int mxl1x1sf_demod_get_cp_lock_status(struct mxl111sf_demod_state *state,
+                                     int *cp_lock)
+{
+       u8 val = 0;
+       int ret = mxl111sf_demod_read_reg(state, V6_CP_LOCK_DET_REG, &val);
+       if (mxl_fail(ret))
+               goto fail;
+       *cp_lock = (val & V6_CP_LOCK_DET_MASK) >> 2;
+fail:
+       return ret;
+}
+#endif
+
+static int mxl1x1sf_demod_reset_irq_status(struct mxl111sf_demod_state *state)
+{
+       return mxl111sf_demod_write_reg(state, 0x0e, 0xff);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int mxl111sf_demod_set_frontend(struct dvb_frontend *fe,
+                                      struct dvb_frontend_parameters *param)
+{
+       struct mxl111sf_demod_state *state = fe->demodulator_priv;
+       int ret = 0;
+
+       struct mxl111sf_reg_ctrl_info phy_pll_patch[] = {
+               {0x00, 0xff, 0x01}, /* change page to 1 */
+               {0x40, 0xff, 0x05},
+               {0x40, 0xff, 0x01},
+               {0x41, 0xff, 0xca},
+               {0x41, 0xff, 0xc0},
+               {0x00, 0xff, 0x00}, /* change page to 0 */
+               {0,    0,    0}
+       };
+
+       mxl_dbg("()");
+
+       if (fe->ops.tuner_ops.set_params) {
+               ret = fe->ops.tuner_ops.set_params(fe, param);
+               if (mxl_fail(ret))
+                       goto fail;
+               msleep(50);
+       }
+       ret = mxl111sf_demod_program_regs(state, phy_pll_patch);
+       mxl_fail(ret);
+       msleep(50);
+       ret = mxl1x1sf_demod_reset_irq_status(state);
+       mxl_fail(ret);
+       msleep(100);
+fail:
+       return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+#if 0
+/* resets TS Packet error count */
+/* After setting 7th bit of V5_PER_COUNT_RESET_REG, it should be reset to 0. */
+static
+int mxl1x1sf_demod_reset_packet_error_count(struct mxl111sf_demod_state *state)
+{
+       struct mxl111sf_reg_ctrl_info reset_per_count[] = {
+               {0x20, 0x01, 0x01},
+               {0x20, 0x01, 0x00},
+               {0,    0,    0}
+       };
+       return mxl111sf_demod_program_regs(state, reset_per_count);
+}
+#endif
+
+/* returns TS Packet error count */
+/* PER Count = FEC_PER_COUNT * (2 ** (FEC_PER_SCALE * 4)) */
+static int mxl111sf_demod_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+       struct mxl111sf_demod_state *state = fe->demodulator_priv;
+       u32 fec_per_count, fec_per_scale;
+       u8 val;
+       int ret;
+
+       *ucblocks = 0;
+
+       /* FEC_PER_COUNT Register */
+       ret = mxl111sf_demod_read_reg(state, V6_FEC_PER_COUNT_REG, &val);
+       if (mxl_fail(ret))
+               goto fail;
+
+       fec_per_count = val;
+
+       /* FEC_PER_SCALE Register */
+       ret = mxl111sf_demod_read_reg(state, V6_FEC_PER_SCALE_REG, &val);
+       if (mxl_fail(ret))
+               goto fail;
+
+       val &= V6_FEC_PER_SCALE_MASK;
+       val *= 4;
+
+       fec_per_scale = 1 << val;
+
+       fec_per_count *= fec_per_scale;
+
+       *ucblocks = fec_per_count;
+fail:
+       return ret;
+}
+
+#ifdef MXL111SF_DEMOD_ENABLE_CALCULATIONS
+/* FIXME: leaving this enabled breaks the build on some architectures,
+ * and we shouldn't have any floating point math in the kernel, anyway.
+ *
+ * These macros need to be re-written, but it's harmless to simply
+ * return zero for now. */
+#define CALCULATE_BER(avg_errors, count) \
+       ((u32)(avg_errors * 4)/(count*64*188*8))
+#define CALCULATE_SNR(data) \
+       ((u32)((10 * (u32)data / 64) - 2.5))
+#else
+#define CALCULATE_BER(avg_errors, count) 0
+#define CALCULATE_SNR(data) 0
+#endif
+
+static int mxl111sf_demod_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+       struct mxl111sf_demod_state *state = fe->demodulator_priv;
+       u8 val1, val2, val3;
+       int ret;
+
+       *ber = 0;
+
+       ret = mxl111sf_demod_read_reg(state, V6_RS_AVG_ERRORS_LSB_REG, &val1);
+       if (mxl_fail(ret))
+               goto fail;
+       ret = mxl111sf_demod_read_reg(state, V6_RS_AVG_ERRORS_MSB_REG, &val2);
+       if (mxl_fail(ret))
+               goto fail;
+       ret = mxl111sf_demod_read_reg(state, V6_N_ACCUMULATE_REG, &val3);
+       if (mxl_fail(ret))
+               goto fail;
+
+       *ber = CALCULATE_BER((val1 | (val2 << 8)), val3);
+fail:
+       return ret;
+}
+
+static int mxl111sf_demod_calc_snr(struct mxl111sf_demod_state *state,
+                                  u16 *snr)
+{
+       u8 val1, val2;
+       int ret;
+
+       *snr = 0;
+
+       ret = mxl111sf_demod_read_reg(state, V6_SNR_RB_LSB_REG, &val1);
+       if (mxl_fail(ret))
+               goto fail;
+       ret = mxl111sf_demod_read_reg(state, V6_SNR_RB_MSB_REG, &val2);
+       if (mxl_fail(ret))
+               goto fail;
+
+       *snr = CALCULATE_SNR(val1 | ((val2 & 0x03) << 8));
+fail:
+       return ret;
+}
+
+static int mxl111sf_demod_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+       struct mxl111sf_demod_state *state = fe->demodulator_priv;
+
+       int ret = mxl111sf_demod_calc_snr(state, snr);
+       if (mxl_fail(ret))
+               goto fail;
+
+       *snr /= 10; /* 0.1 dB */
+fail:
+       return ret;
+}
+
+static int mxl111sf_demod_read_status(struct dvb_frontend *fe,
+                                     fe_status_t *status)
+{
+       struct mxl111sf_demod_state *state = fe->demodulator_priv;
+       int ret, locked, cr_lock, sync_lock, fec_lock;
+
+       *status = 0;
+
+       ret = mxl1x1sf_demod_get_rs_lock_status(state, &locked);
+       if (mxl_fail(ret))
+               goto fail;
+       ret = mxl1x1sf_demod_get_tps_lock_status(state, &cr_lock);
+       if (mxl_fail(ret))
+               goto fail;
+       ret = mxl1x1sf_demod_get_sync_lock_status(state, &sync_lock);
+       if (mxl_fail(ret))
+               goto fail;
+       ret = mxl1x1sf_demod_get_fec_lock_status(state, &fec_lock);
+       if (mxl_fail(ret))
+               goto fail;
+
+       if (locked)
+               *status |= FE_HAS_SIGNAL;
+       if (cr_lock)
+               *status |= FE_HAS_CARRIER;
+       if (sync_lock)
+               *status |= FE_HAS_SYNC;
+       if (fec_lock) /* false positives? */
+               *status |= FE_HAS_VITERBI;
+
+       if ((locked) && (cr_lock) && (sync_lock))
+               *status |= FE_HAS_LOCK;
+fail:
+       return ret;
+}
+
+static int mxl111sf_demod_read_signal_strength(struct dvb_frontend *fe,
+                                              u16 *signal_strength)
+{
+       struct mxl111sf_demod_state *state = fe->demodulator_priv;
+       fe_modulation_t constellation;
+       u16 snr;
+
+       mxl111sf_demod_calc_snr(state, &snr);
+       mxl1x1sf_demod_get_tps_constellation(state, &constellation);
+
+       switch (constellation) {
+       case QPSK:
+               *signal_strength = (snr >= 1300) ?
+                       min(65535, snr * 44) : snr * 38;
+               break;
+       case QAM_16:
+               *signal_strength = (snr >= 1500) ?
+                       min(65535, snr * 38) : snr * 33;
+               break;
+       case QAM_64:
+               *signal_strength = (snr >= 2000) ?
+                       min(65535, snr * 29) : snr * 25;
+               break;
+       default:
+               *signal_strength = 0;
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int mxl111sf_demod_get_frontend(struct dvb_frontend *fe,
+                                      struct dvb_frontend_parameters *p)
+{
+       struct mxl111sf_demod_state *state = fe->demodulator_priv;
+
+       mxl_dbg("()");
+#if 0
+       p->inversion = /* FIXME */ ? INVERSION_ON : INVERSION_OFF;
+#endif
+       if (fe->ops.tuner_ops.get_bandwidth)
+               fe->ops.tuner_ops.get_bandwidth(fe, &p->u.ofdm.bandwidth);
+       if (fe->ops.tuner_ops.get_frequency)
+               fe->ops.tuner_ops.get_frequency(fe, &p->frequency);
+       mxl1x1sf_demod_get_tps_code_rate(state, &p->u.ofdm.code_rate_HP);
+       mxl1x1sf_demod_get_tps_code_rate(state, &p->u.ofdm.code_rate_LP);
+       mxl1x1sf_demod_get_tps_constellation(state, &p->u.ofdm.constellation);
+       mxl1x1sf_demod_get_tps_guard_fft_mode(state,
+                                             &p->u.ofdm.transmission_mode);
+       mxl1x1sf_demod_get_tps_guard_interval(state,
+                                             &p->u.ofdm.guard_interval);
+       mxl1x1sf_demod_get_tps_hierarchy(state,
+                                        &p->u.ofdm.hierarchy_information);
+
+       return 0;
+}
+
+static
+int mxl111sf_demod_get_tune_settings(struct dvb_frontend *fe,
+                                    struct dvb_frontend_tune_settings *tune)
+{
+       tune->min_delay_ms = 1000;
+       return 0;
+}
+
+static void mxl111sf_demod_release(struct dvb_frontend *fe)
+{
+       struct mxl111sf_demod_state *state = fe->demodulator_priv;
+       mxl_dbg("()");
+       kfree(state);
+       fe->demodulator_priv = NULL;
+}
+
+static struct dvb_frontend_ops mxl111sf_demod_ops = {
+
+       .info = {
+               .name               = "MaxLinear MxL111SF DVB-T demodulator",
+               .type               = FE_OFDM,
+               .frequency_min      = 177000000,
+               .frequency_max      = 858000000,
+               .frequency_stepsize = 166666,
+               .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+                       FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+                       FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
+                       FE_CAN_QAM_AUTO |
+                       FE_CAN_HIERARCHY_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
+                       FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_RECOVER
+       },
+       .release              = mxl111sf_demod_release,
+#if 0
+       .init                 = mxl111sf_init,
+       .i2c_gate_ctrl        = mxl111sf_i2c_gate_ctrl,
+#endif
+       .set_frontend         = mxl111sf_demod_set_frontend,
+       .get_frontend         = mxl111sf_demod_get_frontend,
+       .get_tune_settings    = mxl111sf_demod_get_tune_settings,
+       .read_status          = mxl111sf_demod_read_status,
+       .read_signal_strength = mxl111sf_demod_read_signal_strength,
+       .read_ber             = mxl111sf_demod_read_ber,
+       .read_snr             = mxl111sf_demod_read_snr,
+       .read_ucblocks        = mxl111sf_demod_read_ucblocks,
+};
+
+struct dvb_frontend *mxl111sf_demod_attach(struct mxl111sf_state *mxl_state,
+                                          struct mxl111sf_demod_config *cfg)
+{
+       struct mxl111sf_demod_state *state = NULL;
+
+       mxl_dbg("()");
+
+       state = kzalloc(sizeof(struct mxl111sf_demod_state), GFP_KERNEL);
+       if (state == NULL)
+               return NULL;
+
+       state->mxl_state = mxl_state;
+       state->cfg = cfg;
+
+       memcpy(&state->fe.ops, &mxl111sf_demod_ops,
+              sizeof(struct dvb_frontend_ops));
+
+       state->fe.demodulator_priv = state;
+       return &state->fe;
+}
+EXPORT_SYMBOL_GPL(mxl111sf_demod_attach);
+
+MODULE_DESCRIPTION("MaxLinear MxL111SF DVB-T demodulator driver");
+MODULE_AUTHOR("Michael Krufky <mkrufky@kernellabs.com>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.1");
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/dvb/dvb-usb/mxl111sf-demod.h b/drivers/media/dvb/dvb-usb/mxl111sf-demod.h
new file mode 100644 (file)
index 0000000..432706a
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ *  mxl111sf-demod.h - driver for the MaxLinear MXL111SF DVB-T demodulator
+ *
+ *  Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __MXL111SF_DEMOD_H__
+#define __MXL111SF_DEMOD_H__
+
+#include "dvb_frontend.h"
+#include "mxl111sf.h"
+
+struct mxl111sf_demod_config {
+       int (*read_reg)(struct mxl111sf_state *state, u8 addr, u8 *data);
+       int (*write_reg)(struct mxl111sf_state *state, u8 addr, u8 data);
+       int (*program_regs)(struct mxl111sf_state *state,
+                           struct mxl111sf_reg_ctrl_info *ctrl_reg_info);
+};
+
+#if defined(CONFIG_DVB_USB_MXL111SF) || \
+       (defined(CONFIG_DVB_USB_MXL111SF_MODULE) && defined(MODULE))
+extern
+struct dvb_frontend *mxl111sf_demod_attach(struct mxl111sf_state *mxl_state,
+                                          struct mxl111sf_demod_config *cfg);
+#else
+static inline
+struct dvb_frontend *mxl111sf_demod_attach(struct mxl111sf_state *mxl_state,
+                                          struct mxl111sf_demod_config *cfg)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return NULL;
+}
+#endif /* CONFIG_DVB_USB_MXL111SF */
+
+#endif /* __MXL111SF_DEMOD_H__ */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
index 546ba59..b5c98da 100644 (file)
@@ -17,6 +17,7 @@
 #include "mxl111sf-i2c.h"
 #include "mxl111sf-gpio.h"
 
+#include "mxl111sf-demod.h"
 #include "mxl111sf-tuner.h"
 
 #include "lgdt3305.h"
@@ -362,6 +363,22 @@ static int mxl111sf_ep6_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
        return ret;
 }
 
+static int mxl111sf_ep4_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
+{
+       struct dvb_usb_device *d = adap->dev;
+       struct mxl111sf_state *state = d->priv;
+       int ret = 0;
+
+       deb_info("%s(%d)\n", __func__, onoff);
+
+       if (onoff) {
+               ret = mxl111sf_enable_usb_output(state);
+               mxl_fail(ret);
+       }
+
+       return ret;
+}
+
 /* ------------------------------------------------------------------------ */
 
 static struct lgdt3305_config hauppauge_lgdt3305_config = {
@@ -438,6 +455,70 @@ fail:
        return ret;
 }
 
+static struct mxl111sf_demod_config mxl_demod_config = {
+       .read_reg        = mxl111sf_read_reg,
+       .write_reg       = mxl111sf_write_reg,
+       .program_regs    = mxl111sf_ctrl_program_regs,
+};
+
+static int mxl111sf_attach_demod(struct dvb_usb_adapter *adap)
+{
+       struct dvb_usb_device *d = adap->dev;
+       struct mxl111sf_state *state = d->priv;
+       int fe_id = adap->num_frontends_initialized;
+       struct mxl111sf_adap_state *adap_state = adap->fe_adap[fe_id].priv;
+       int ret;
+
+       deb_adv("%s()\n", __func__);
+
+       /* save a pointer to the dvb_usb_device in device state */
+       state->d = d;
+       adap_state->alt_mode = (dvb_usb_mxl111sf_isoc) ? 1 : 2;
+       state->alt_mode = adap_state->alt_mode;
+
+       if (usb_set_interface(adap->dev->udev, 0, state->alt_mode) < 0)
+               err("set interface failed");
+
+       state->gpio_mode = MXL111SF_GPIO_MOD_DVBT;
+       adap_state->gpio_mode = state->gpio_mode;
+       adap_state->device_mode = MXL_SOC_MODE;
+       adap_state->ep6_clockphase = 1;
+
+       ret = mxl1x1sf_soft_reset(state);
+       if (mxl_fail(ret))
+               goto fail;
+       ret = mxl111sf_init_tuner_demod(state);
+       if (mxl_fail(ret))
+               goto fail;
+
+       ret = mxl1x1sf_set_device_mode(state, adap_state->device_mode);
+       if (mxl_fail(ret))
+               goto fail;
+
+       ret = mxl111sf_enable_usb_output(state);
+       if (mxl_fail(ret))
+               goto fail;
+       ret = mxl1x1sf_top_master_ctrl(state, 1);
+       if (mxl_fail(ret))
+               goto fail;
+
+       /* dont care if this fails */
+       mxl111sf_init_port_expander(state);
+
+       adap->fe_adap[fe_id].fe = dvb_attach(mxl111sf_demod_attach, state,
+                             &mxl_demod_config);
+       if (adap->fe_adap[fe_id].fe) {
+               adap_state->fe_init = adap->fe_adap[fe_id].fe->ops.init;
+               adap->fe_adap[fe_id].fe->ops.init = mxl111sf_adap_fe_init;
+               adap_state->fe_sleep = adap->fe_adap[fe_id].fe->ops.sleep;
+               adap->fe_adap[fe_id].fe->ops.sleep = mxl111sf_adap_fe_sleep;
+               return 0;
+       }
+       ret = -EIO;
+fail:
+       return ret;
+}
+
 static inline int mxl111sf_set_ant_path(struct mxl111sf_state *state,
                                        int antpath)
 {
@@ -567,7 +648,8 @@ struct i2c_algorithm mxl111sf_i2c_algo = {
 #endif
 };
 
-/* DVB USB Driver stuff */
+static struct dvb_usb_device_properties mxl111sf_dvbt_bulk_properties;
+static struct dvb_usb_device_properties mxl111sf_dvbt_isoc_properties;
 static struct dvb_usb_device_properties mxl111sf_atsc_bulk_properties;
 static struct dvb_usb_device_properties mxl111sf_atsc_isoc_properties;
 
@@ -580,9 +662,15 @@ static int mxl111sf_probe(struct usb_interface *intf,
 
        if (((dvb_usb_mxl111sf_isoc) &&
             (0 == dvb_usb_device_init(intf,
+                                      &mxl111sf_dvbt_isoc_properties,
+                                      THIS_MODULE, &d, adapter_nr) ||
+             0 == dvb_usb_device_init(intf,
                                       &mxl111sf_atsc_isoc_properties,
                                       THIS_MODULE, &d, adapter_nr))) ||
            0 == dvb_usb_device_init(intf,
+                                    &mxl111sf_dvbt_bulk_properties,
+                                    THIS_MODULE, &d, adapter_nr) ||
+           0 == dvb_usb_device_init(intf,
                                     &mxl111sf_atsc_bulk_properties,
                                     THIS_MODULE, &d, adapter_nr) || 0) {
 
@@ -669,6 +757,36 @@ static struct usb_device_id mxl111sf_table[] = {
 MODULE_DEVICE_TABLE(usb, mxl111sf_table);
 
 
+#define MXL111SF_EP4_BULK_STREAMING_CONFIG             \
+       .streaming_ctrl = mxl111sf_ep4_streaming_ctrl,  \
+       .stream = {                                     \
+               .type = USB_BULK,                       \
+               .count = 5,                             \
+               .endpoint = 0x04,                       \
+               .u = {                                  \
+                       .bulk = {                       \
+                               .buffersize = 8192,     \
+                       }                               \
+               }                                       \
+       }
+
+/* FIXME: works for v6 but not v8 silicon */
+#define MXL111SF_EP4_ISOC_STREAMING_CONFIG             \
+       .streaming_ctrl = mxl111sf_ep4_streaming_ctrl,  \
+       .stream = {                                     \
+               .type = USB_ISOC,                       \
+               .count = 5,                             \
+               .endpoint = 0x04,                       \
+               .u = {                                  \
+                       .isoc = {                       \
+                               .framesperurb = 96,     \
+                               /* FIXME: v6 SILICON: */        \
+                               .framesize = 564,       \
+                               .interval = 1,          \
+                       }                               \
+               }                                       \
+       }
+
 #define MXL111SF_EP6_BULK_STREAMING_CONFIG             \
        .streaming_ctrl = mxl111sf_ep6_streaming_ctrl,  \
        .stream = {                                     \
@@ -712,7 +830,7 @@ MODULE_DEVICE_TABLE(usb, mxl111sf_table);
        .generic_bulk_ctrl_endpoint_response = MXL_EP1_REG_READ, \
        .size_of_priv     = sizeof(struct mxl111sf_state)
 
-static struct dvb_usb_device_properties mxl111sf_atsc_bulk_properties = {
+static struct dvb_usb_device_properties mxl111sf_dvbt_bulk_properties = {
        MXL111SF_DEFAULT_DEVICE_PROPERTIES,
 
        .num_adapters = 1,
@@ -723,10 +841,106 @@ static struct dvb_usb_device_properties mxl111sf_atsc_bulk_properties = {
                .fe = {{
                        .size_of_priv     = sizeof(struct mxl111sf_adap_state),
 
+                       .frontend_attach  = mxl111sf_attach_demod,
+                       .tuner_attach     = mxl111sf_attach_tuner,
+
+                       MXL111SF_EP4_BULK_STREAMING_CONFIG,
+               } },
+               },
+       },
+       .num_device_descs = 4,
+       .devices = {
+               {   "Hauppauge 126xxx DVBT (bulk)",
+                       { NULL },
+                       { &mxl111sf_table[4], &mxl111sf_table[8],
+                         NULL },
+               },
+               {   "Hauppauge 117xxx DVBT (bulk)",
+                       { NULL },
+                       { &mxl111sf_table[15], &mxl111sf_table[18],
+                         NULL },
+               },
+               {   "Hauppauge 138xxx DVBT (bulk)",
+                       { NULL },
+                       { &mxl111sf_table[20], &mxl111sf_table[22],
+                         &mxl111sf_table[24], &mxl111sf_table[26],
+                         NULL },
+               },
+               {   "Hauppauge 126xxx (tp-bulk)",
+                       { NULL },
+                       { &mxl111sf_table[28], &mxl111sf_table[30],
+                         NULL },
+               },
+       }
+};
+
+static struct dvb_usb_device_properties mxl111sf_dvbt_isoc_properties = {
+       MXL111SF_DEFAULT_DEVICE_PROPERTIES,
+
+       .num_adapters = 1,
+       .adapter = {
+               {
+               .fe_ioctl_override = mxl111sf_fe_ioctl_override,
+               .num_frontends = 1,
+               .fe = {{
+                       .size_of_priv     = sizeof(struct mxl111sf_adap_state),
+
+                       .frontend_attach  = mxl111sf_attach_demod,
+                       .tuner_attach     = mxl111sf_attach_tuner,
+
+                       MXL111SF_EP4_ISOC_STREAMING_CONFIG,
+               } },
+               },
+       },
+       .num_device_descs = 4,
+       .devices = {
+               {   "Hauppauge 126xxx DVBT (isoc)",
+                       { NULL },
+                       { &mxl111sf_table[4], &mxl111sf_table[8],
+                         NULL },
+               },
+               {   "Hauppauge 117xxx DVBT (isoc)",
+                       { NULL },
+                       { &mxl111sf_table[15], &mxl111sf_table[18],
+                         NULL },
+               },
+               {   "Hauppauge 138xxx DVBT (isoc)",
+                       { NULL },
+                       { &mxl111sf_table[20], &mxl111sf_table[22],
+                         &mxl111sf_table[24], &mxl111sf_table[26],
+                         NULL },
+               },
+               {   "Hauppauge 126xxx (tp-isoc)",
+                       { NULL },
+                       { &mxl111sf_table[28], &mxl111sf_table[30],
+                         NULL },
+               },
+       }
+};
+
+static struct dvb_usb_device_properties mxl111sf_atsc_bulk_properties = {
+       MXL111SF_DEFAULT_DEVICE_PROPERTIES,
+
+       .num_adapters = 1,
+       .adapter = {
+               {
+               .fe_ioctl_override = mxl111sf_fe_ioctl_override,
+               .num_frontends = 2,
+               .fe = {{
+                       .size_of_priv     = sizeof(struct mxl111sf_adap_state),
+
                        .frontend_attach  = mxl111sf_lgdt3305_frontend_attach,
                        .tuner_attach     = mxl111sf_attach_tuner,
 
                        MXL111SF_EP6_BULK_STREAMING_CONFIG,
+               },
+               {
+                       .size_of_priv     = sizeof(struct mxl111sf_adap_state),
+
+                       .frontend_attach  = mxl111sf_attach_demod,
+                       .tuner_attach     = mxl111sf_attach_tuner,
+
+                       MXL111SF_EP4_BULK_STREAMING_CONFIG,
                }},
                },
        },
@@ -776,7 +990,7 @@ static struct dvb_usb_device_properties mxl111sf_atsc_isoc_properties = {
        .adapter = {
                {
                .fe_ioctl_override = mxl111sf_fe_ioctl_override,
-               .num_frontends = 1,
+               .num_frontends = 2,
                .fe = {{
                        .size_of_priv     = sizeof(struct mxl111sf_adap_state),
 
@@ -784,6 +998,14 @@ static struct dvb_usb_device_properties mxl111sf_atsc_isoc_properties = {
                        .tuner_attach     = mxl111sf_attach_tuner,
 
                        MXL111SF_EP6_ISOC_STREAMING_CONFIG,
+               },
+               {
+                       .size_of_priv     = sizeof(struct mxl111sf_adap_state),
+
+                       .frontend_attach  = mxl111sf_attach_demod,
+                       .tuner_attach     = mxl111sf_attach_tuner,
+
+                       MXL111SF_EP4_ISOC_STREAMING_CONFIG,
                }},
                },
        },
index 5a2c7bb..364d89f 100644 (file)
@@ -133,7 +133,7 @@ extern int dvb_usb_mxl111sf_debug;
 /* The following allows the mxl_fail() macro defined below to work
  * in externel modules, such as mxl111sf-tuner.ko, even though
  * dvb_usb_mxl111sf_debug is not defined within those modules */
-#ifdef __MXL111SF_TUNER_H__
+#if (defined(__MXL111SF_TUNER_H__)) || (defined(__MXL111SF_DEMOD_H__))
 #define MXL_ADV_DEBUG_ENABLED MXL_ADV_DBG
 #else
 #define MXL_ADV_DEBUG_ENABLED dvb_usb_mxl111sf_debug
index 8987361..13ebeff 100644 (file)
@@ -11,4 +11,4 @@ ccflags-y += -Idrivers/media/dvb/frontends/
 ccflags-y += -Idrivers/media/common/tuners/
 
 # For the staging CI driver cxd2099
-ccflags-y += -Idrivers/staging/cxd2099/
+ccflags-y += -Idrivers/staging/media/cxd2099/
index 95ddcc4..db20904 100644 (file)
@@ -128,8 +128,10 @@ struct tea5764_write_regs {
        u16 rdsbbl;                             /* PAUSEDET & RDSBBL */
 } __attribute__ ((packed));
 
-#ifndef RADIO_TEA5764_XTAL
+#ifdef CONFIG_RADIO_TEA5764_XTAL
 #define RADIO_TEA5764_XTAL 1
+#else
+#define RADIO_TEA5764_XTAL 0
 #endif
 
 static int radio_nr = -1;
index d285c8c..b303a3f 100644 (file)
@@ -517,6 +517,13 @@ config VIDEO_NOON010PC30
 
 source "drivers/media/video/m5mols/Kconfig"
 
+config VIDEO_S5K6AA
+       tristate "Samsung S5K6AAFX sensor support"
+       depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+       ---help---
+         This is a V4L2 sensor-level driver for Samsung S5K6AA(FX) 1.3M
+         camera sensor with an embedded SoC image signal processor.
+
 comment "Flash devices"
 
 config VIDEO_ADP1653
@@ -736,6 +743,8 @@ source "drivers/media/video/cx88/Kconfig"
 
 source "drivers/media/video/cx23885/Kconfig"
 
+source "drivers/media/video/cx25821/Kconfig"
+
 source "drivers/media/video/au0828/Kconfig"
 
 source "drivers/media/video/ivtv/Kconfig"
index 11fff97..117f9c4 100644 (file)
@@ -72,6 +72,7 @@ obj-$(CONFIG_VIDEO_MT9V032) += mt9v032.o
 obj-$(CONFIG_VIDEO_SR030PC30)  += sr030pc30.o
 obj-$(CONFIG_VIDEO_NOON010PC30)        += noon010pc30.o
 obj-$(CONFIG_VIDEO_M5MOLS)     += m5mols/
+obj-$(CONFIG_VIDEO_S5K6AA)     += s5k6aa.o
 obj-$(CONFIG_VIDEO_ADP1653)    += adp1653.o
 
 obj-$(CONFIG_SOC_CAMERA_IMX074)                += imx074.o
@@ -104,6 +105,7 @@ obj-$(CONFIG_VIDEO_CX88) += cx88/
 obj-$(CONFIG_VIDEO_EM28XX) += em28xx/
 obj-$(CONFIG_VIDEO_TLG2300) += tlg2300/
 obj-$(CONFIG_VIDEO_CX231XX) += cx231xx/
+obj-$(CONFIG_VIDEO_CX25821) += cx25821/
 obj-$(CONFIG_VIDEO_USBVISION) += usbvision/
 obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2/
 obj-$(CONFIG_VIDEO_CPIA2) += cpia2/
index 774715d..8c775c5 100644 (file)
@@ -94,6 +94,7 @@ struct atmel_isi {
        unsigned int                    irq;
 
        struct isi_platform_data        *pdata;
+       u16                             width_flags;    /* max 12 bits */
 
        struct list_head                video_buffer_list;
        struct frame_buffer             *active;
@@ -248,9 +249,9 @@ static int atmel_isi_wait_status(struct atmel_isi *isi, int wait_reset)
 /* ------------------------------------------------------------------
        Videobuf operations
    ------------------------------------------------------------------*/
-static int queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
-                               unsigned int *nplanes, unsigned int sizes[],
-                               void *alloc_ctxs[])
+static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+                               unsigned int *nbuffers, unsigned int *nplanes,
+                               unsigned int sizes[], void *alloc_ctxs[])
 {
        struct soc_camera_device *icd = soc_camera_from_vb2q(vq);
        struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
@@ -647,50 +648,42 @@ static bool isi_camera_packing_supported(const struct soc_mbus_pixelfmt *fmt)
                 fmt->packing == SOC_MBUS_PACKING_EXTEND16);
 }
 
-static unsigned long make_bus_param(struct atmel_isi *isi)
-{
-       unsigned long flags;
-       /*
-        * Platform specified synchronization and pixel clock polarities are
-        * only a recommendation and are only used during probing. Atmel ISI
-        * camera interface only works in master mode, i.e., uses HSYNC and
-        * VSYNC signals from the sensor
-        */
-       flags = SOCAM_MASTER |
-               SOCAM_HSYNC_ACTIVE_HIGH |
-               SOCAM_HSYNC_ACTIVE_LOW |
-               SOCAM_VSYNC_ACTIVE_HIGH |
-               SOCAM_VSYNC_ACTIVE_LOW |
-               SOCAM_PCLK_SAMPLE_RISING |
-               SOCAM_PCLK_SAMPLE_FALLING |
-               SOCAM_DATA_ACTIVE_HIGH;
-
-       if (isi->pdata->data_width_flags & ISI_DATAWIDTH_10)
-               flags |= SOCAM_DATAWIDTH_10;
-
-       if (isi->pdata->data_width_flags & ISI_DATAWIDTH_8)
-               flags |= SOCAM_DATAWIDTH_8;
-
-       if (flags & SOCAM_DATAWIDTH_MASK)
-               return flags;
-
-       return 0;
-}
+#define ISI_BUS_PARAM (V4L2_MBUS_MASTER |      \
+               V4L2_MBUS_HSYNC_ACTIVE_HIGH |   \
+               V4L2_MBUS_HSYNC_ACTIVE_LOW |    \
+               V4L2_MBUS_VSYNC_ACTIVE_HIGH |   \
+               V4L2_MBUS_VSYNC_ACTIVE_LOW |    \
+               V4L2_MBUS_PCLK_SAMPLE_RISING |  \
+               V4L2_MBUS_PCLK_SAMPLE_FALLING | \
+               V4L2_MBUS_DATA_ACTIVE_HIGH)
 
 static int isi_camera_try_bus_param(struct soc_camera_device *icd,
                                    unsigned char buswidth)
 {
+       struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
        struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct atmel_isi *isi = ici->priv;
-       unsigned long camera_flags;
+       struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
+       unsigned long common_flags;
        int ret;
 
-       camera_flags = icd->ops->query_bus_param(icd);
-       ret = soc_camera_bus_param_compatible(camera_flags,
-                                       make_bus_param(isi));
-       if (!ret)
-               return -EINVAL;
-       return 0;
+       ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
+       if (!ret) {
+               common_flags = soc_mbus_config_compatible(&cfg,
+                                                         ISI_BUS_PARAM);
+               if (!common_flags) {
+                       dev_warn(icd->parent,
+                                "Flags incompatible: camera 0x%x, host 0x%x\n",
+                                cfg.flags, ISI_BUS_PARAM);
+                       return -EINVAL;
+               }
+       } else if (ret != -ENOIOCTLCMD) {
+               return ret;
+       }
+
+       if ((1 << (buswidth - 1)) & isi->width_flags)
+               return 0;
+       return -EINVAL;
 }
 
 
@@ -812,59 +805,71 @@ static int isi_camera_querycap(struct soc_camera_host *ici,
 
 static int isi_camera_set_bus_param(struct soc_camera_device *icd, u32 pixfmt)
 {
+       struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
        struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct atmel_isi *isi = ici->priv;
-       unsigned long bus_flags, camera_flags, common_flags;
+       struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
+       unsigned long common_flags;
        int ret;
        u32 cfg1 = 0;
 
-       camera_flags = icd->ops->query_bus_param(icd);
-
-       bus_flags = make_bus_param(isi);
-       common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags);
-       dev_dbg(icd->parent, "Flags cam: 0x%lx host: 0x%lx common: 0x%lx\n",
-               camera_flags, bus_flags, common_flags);
-       if (!common_flags)
-               return -EINVAL;
+       ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
+       if (!ret) {
+               common_flags = soc_mbus_config_compatible(&cfg,
+                                                         ISI_BUS_PARAM);
+               if (!common_flags) {
+                       dev_warn(icd->parent,
+                                "Flags incompatible: camera 0x%x, host 0x%x\n",
+                                cfg.flags, ISI_BUS_PARAM);
+                       return -EINVAL;
+               }
+       } else if (ret != -ENOIOCTLCMD) {
+               return ret;
+       } else {
+               common_flags = ISI_BUS_PARAM;
+       }
+       dev_dbg(icd->parent, "Flags cam: 0x%x host: 0x%x common: 0x%lx\n",
+               cfg.flags, ISI_BUS_PARAM, common_flags);
 
        /* Make choises, based on platform preferences */
-       if ((common_flags & SOCAM_HSYNC_ACTIVE_HIGH) &&
-           (common_flags & SOCAM_HSYNC_ACTIVE_LOW)) {
+       if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) &&
+           (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) {
                if (isi->pdata->hsync_act_low)
-                       common_flags &= ~SOCAM_HSYNC_ACTIVE_HIGH;
+                       common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH;
                else
-                       common_flags &= ~SOCAM_HSYNC_ACTIVE_LOW;
+                       common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW;
        }
 
-       if ((common_flags & SOCAM_VSYNC_ACTIVE_HIGH) &&
-           (common_flags & SOCAM_VSYNC_ACTIVE_LOW)) {
+       if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) &&
+           (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) {
                if (isi->pdata->vsync_act_low)
-                       common_flags &= ~SOCAM_VSYNC_ACTIVE_HIGH;
+                       common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH;
                else
-                       common_flags &= ~SOCAM_VSYNC_ACTIVE_LOW;
+                       common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW;
        }
 
-       if ((common_flags & SOCAM_PCLK_SAMPLE_RISING) &&
-           (common_flags & SOCAM_PCLK_SAMPLE_FALLING)) {
+       if ((common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) &&
+           (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)) {
                if (isi->pdata->pclk_act_falling)
-                       common_flags &= ~SOCAM_PCLK_SAMPLE_RISING;
+                       common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_RISING;
                else
-                       common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING;
+                       common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_FALLING;
        }
 
-       ret = icd->ops->set_bus_param(icd, common_flags);
-       if (ret < 0) {
-               dev_dbg(icd->parent, "Camera set_bus_param(%lx) returned %d\n",
+       cfg.flags = common_flags;
+       ret = v4l2_subdev_call(sd, video, s_mbus_config, &cfg);
+       if (ret < 0 && ret != -ENOIOCTLCMD) {
+               dev_dbg(icd->parent, "camera s_mbus_config(0x%lx) returned %d\n",
                        common_flags, ret);
                return ret;
        }
 
        /* set bus param for ISI */
-       if (common_flags & SOCAM_HSYNC_ACTIVE_LOW)
+       if (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
                cfg1 |= ISI_CFG1_HSYNC_POL_ACTIVE_LOW;
-       if (common_flags & SOCAM_VSYNC_ACTIVE_LOW)
+       if (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
                cfg1 |= ISI_CFG1_VSYNC_POL_ACTIVE_LOW;
-       if (common_flags & SOCAM_PCLK_SAMPLE_FALLING)
+       if (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
                cfg1 |= ISI_CFG1_PIXCLK_POL_ACTIVE_FALLING;
 
        if (isi->pdata->has_emb_sync)
@@ -983,6 +988,11 @@ static int __devinit atmel_isi_probe(struct platform_device *pdev)
                goto err_ioremap;
        }
 
+       if (pdata->data_width_flags & ISI_DATAWIDTH_8)
+               isi->width_flags = 1 << 7;
+       if (pdata->data_width_flags & ISI_DATAWIDTH_10)
+               isi->width_flags |= 1 << 9;
+
        isi_writel(isi, ISI_CTRL, ISI_CTRL_DIS);
 
        irq = platform_get_irq(pdev, 0);
index 9e2f870..c6ff32a 100644 (file)
@@ -1085,6 +1085,8 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev,
                setup.addr = ADDR_UNSET;
                setup.type = cx->options.tuner;
                setup.mode_mask = T_ANALOG_TV;  /* matches TV tuners */
+               if (cx->options.radio > 0)
+                       setup.mode_mask |= T_RADIO;
                setup.tuner_callback = (setup.type == TUNER_XC2028) ?
                        cx18_reset_tuner_gpio : NULL;
                cx18_call_all(cx, tuner, s_type_addr, &setup);
similarity index 99%
rename from drivers/staging/cx25821/cx25821-video.c
rename to drivers/media/video/cx25821/cx25821-video.c
index 084fc08..4d6907c 100644 (file)
@@ -1312,7 +1312,7 @@ int cx25821_vidioc_s_input(struct file *file, void *priv, unsigned int i)
                        return err;
        }
 
-       if (i > 2) {
+       if (i >= CX25821_NR_INPUT) {
                dprintk(1, "%s(): -EINVAL\n", __func__);
                return -EINVAL;
        }
similarity index 99%
rename from drivers/staging/cx25821/cx25821.h
rename to drivers/media/video/cx25821/cx25821.h
index db2615b..2d2d009 100644 (file)
@@ -98,6 +98,7 @@
 #define CX25821_BOARD_CONEXANT_ATHENA10 1
 #define MAX_VID_CHANNEL_NUM     12
 #define VID_CHANNEL_NUM 8
+#define CX25821_NR_INPUT 2
 
 struct cx25821_fmt {
        char *name;
@@ -196,7 +197,7 @@ struct cx25821_board {
        unsigned char radio_addr;
 
        u32 clk_freq;
-       struct cx25821_input input[2];
+       struct cx25821_input input[CX25821_NR_INPUT];
 };
 
 struct cx25821_subid {
index 4240f0b..9b747c2 100644 (file)
@@ -1923,6 +1923,8 @@ struct usb_device_id em28xx_id_table[] = {
                        .driver_info = EM2860_BOARD_TERRATEC_AV350 },
        { USB_DEVICE(0x0ccd, 0x0096),
                        .driver_info = EM2860_BOARD_TERRATEC_GRABBY },
+       { USB_DEVICE(0x0ccd, 0x10AF),
+                       .driver_info = EM2860_BOARD_TERRATEC_GRABBY },
        { USB_DEVICE(0x0fd9, 0x0033),
                        .driver_info = EM2860_BOARD_ELGATO_VIDEO_CAPTURE},
        { USB_DEVICE(0x185b, 0x2870),
index 0382ea7..8775e26 100644 (file)
 
 #include <linux/delay.h>
 #include <linux/i2c.h>
+#include <linux/v4l2-mediabus.h>
 #include <linux/slab.h>
 #include <linux/videodev2.h>
 
 #include <media/soc_camera.h>
-#include <media/soc_mediabus.h>
 #include <media/v4l2-subdev.h>
 #include <media/v4l2-chip-ident.h>
 
@@ -267,6 +267,17 @@ static int imx074_g_chip_ident(struct v4l2_subdev *sd,
        return 0;
 }
 
+static int imx074_g_mbus_config(struct v4l2_subdev *sd,
+                               struct v4l2_mbus_config *cfg)
+{
+       cfg->type = V4L2_MBUS_CSI2;
+       cfg->flags = V4L2_MBUS_CSI2_2_LANE |
+               V4L2_MBUS_CSI2_CHANNEL_0 |
+               V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
+
+       return 0;
+}
+
 static struct v4l2_subdev_video_ops imx074_subdev_video_ops = {
        .s_stream       = imx074_s_stream,
        .s_mbus_fmt     = imx074_s_fmt,
@@ -275,6 +286,7 @@ static struct v4l2_subdev_video_ops imx074_subdev_video_ops = {
        .enum_mbus_fmt  = imx074_enum_fmt,
        .g_crop         = imx074_g_crop,
        .cropcap        = imx074_cropcap,
+       .g_mbus_config  = imx074_g_mbus_config,
 };
 
 static struct v4l2_subdev_core_ops imx074_subdev_core_ops = {
@@ -286,28 +298,7 @@ static struct v4l2_subdev_ops imx074_subdev_ops = {
        .video  = &imx074_subdev_video_ops,
 };
 
-/*
- * We have to provide soc-camera operations, but we don't have anything to say
- * there. The MIPI CSI2 driver will provide .query_bus_param and .set_bus_param
- */
-static unsigned long imx074_query_bus_param(struct soc_camera_device *icd)
-{
-       return 0;
-}
-
-static int imx074_set_bus_param(struct soc_camera_device *icd,
-                                unsigned long flags)
-{
-       return -EINVAL;
-}
-
-static struct soc_camera_ops imx074_ops = {
-       .query_bus_param        = imx074_query_bus_param,
-       .set_bus_param          = imx074_set_bus_param,
-};
-
-static int imx074_video_probe(struct soc_camera_device *icd,
-                             struct i2c_client *client)
+static int imx074_video_probe(struct i2c_client *client)
 {
        int ret;
        u16 id;
@@ -417,17 +408,10 @@ static int imx074_probe(struct i2c_client *client,
                        const struct i2c_device_id *did)
 {
        struct imx074 *priv;
-       struct soc_camera_device *icd = client->dev.platform_data;
        struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
-       struct soc_camera_link *icl;
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
        int ret;
 
-       if (!icd) {
-               dev_err(&client->dev, "IMX074: missing soc-camera data!\n");
-               return -EINVAL;
-       }
-
-       icl = to_soc_camera_link(icd);
        if (!icl) {
                dev_err(&client->dev, "IMX074: missing platform data!\n");
                return -EINVAL;
@@ -445,12 +429,10 @@ static int imx074_probe(struct i2c_client *client,
 
        v4l2_i2c_subdev_init(&priv->subdev, client, &imx074_subdev_ops);
 
-       icd->ops        = &imx074_ops;
        priv->fmt       = &imx074_colour_fmts[0];
 
-       ret = imx074_video_probe(icd, client);
+       ret = imx074_video_probe(client);
        if (ret < 0) {
-               icd->ops = NULL;
                kfree(priv);
                return ret;
        }
@@ -461,10 +443,8 @@ static int imx074_probe(struct i2c_client *client,
 static int imx074_remove(struct i2c_client *client)
 {
        struct imx074 *priv = to_imx074(client);
-       struct soc_camera_device *icd = client->dev.platform_data;
-       struct soc_camera_link *icl = to_soc_camera_link(icd);
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
 
-       icd->ops = NULL;
        if (icl->free_bus)
                icl->free_bus(icl);
        kfree(priv);
index 0fb7552..41108a9 100644 (file)
@@ -1180,6 +1180,8 @@ static int __devinit ivtv_probe(struct pci_dev *pdev,
                setup.addr = ADDR_UNSET;
                setup.type = itv->options.tuner;
                setup.mode_mask = T_ANALOG_TV;  /* matches TV tuners */
+               if (itv->options.radio > 0)
+                       setup.mode_mask |= T_RADIO;
                setup.tuner_callback = (setup.type == TUNER_XC2028) ?
                        ivtv_reset_tuner_gpio : NULL;
                ivtv_call_all(itv, tuner, s_type_addr, &setup);
index 1141b97..80ec64d 100644 (file)
@@ -883,7 +883,8 @@ static int mcam_read_setup(struct mcam_camera *cam)
  * Videobuf2 interface code.
  */
 
-static int mcam_vb_queue_setup(struct vb2_queue *vq, unsigned int *nbufs,
+static int mcam_vb_queue_setup(struct vb2_queue *vq,
+               const struct v4l2_format *fmt, unsigned int *nbufs,
                unsigned int *num_planes, unsigned int sizes[],
                void *alloc_ctxs[])
 {
index 9594b52..12897e8 100644 (file)
@@ -738,9 +738,10 @@ static const struct v4l2_ioctl_ops m2mtest_ioctl_ops = {
  * Queue operations
  */
 
-static int m2mtest_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
-                               unsigned int *nplanes, unsigned int sizes[],
-                               void *alloc_ctxs[])
+static int m2mtest_queue_setup(struct vb2_queue *vq,
+                               const struct v4l2_format *fmt,
+                               unsigned int *nbuffers, unsigned int *nplanes,
+                               unsigned int sizes[], void *alloc_ctxs[])
 {
        struct m2mtest_ctx *ctx = vb2_get_drv_priv(vq);
        struct m2mtest_q_data *q_data;
index 4da9cca..63ae5c6 100644 (file)
 #include <linux/i2c.h>
 #include <linux/log2.h>
 
+#include <media/soc_camera.h>
+#include <media/soc_mediabus.h>
 #include <media/v4l2-subdev.h>
 #include <media/v4l2-chip-ident.h>
-#include <media/soc_camera.h>
+#include <media/v4l2-ctrls.h>
 
 /*
  * mt9m001 i2c address 0x5d
@@ -84,15 +86,19 @@ static const struct mt9m001_datafmt mt9m001_monochrome_fmts[] = {
 
 struct mt9m001 {
        struct v4l2_subdev subdev;
+       struct v4l2_ctrl_handler hdl;
+       struct {
+               /* exposure/auto-exposure cluster */
+               struct v4l2_ctrl *autoexposure;
+               struct v4l2_ctrl *exposure;
+       };
        struct v4l2_rect rect;  /* Sensor window */
        const struct mt9m001_datafmt *fmt;
        const struct mt9m001_datafmt *fmts;
        int num_fmts;
        int model;      /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */
-       unsigned int gain;
-       unsigned int exposure;
+       unsigned int total_h;
        unsigned short y_skip_top;      /* Lines to skip at the top */
-       unsigned char autoexposure;
 };
 
 static struct mt9m001 *to_mt9m001(const struct i2c_client *client)
@@ -165,54 +171,13 @@ static int mt9m001_s_stream(struct v4l2_subdev *sd, int enable)
        return 0;
 }
 
-static int mt9m001_set_bus_param(struct soc_camera_device *icd,
-                                unsigned long flags)
-{
-       struct soc_camera_link *icl = to_soc_camera_link(icd);
-       unsigned long width_flag = flags & SOCAM_DATAWIDTH_MASK;
-
-       /* Only one width bit may be set */
-       if (!is_power_of_2(width_flag))
-               return -EINVAL;
-
-       if (icl->set_bus_param)
-               return icl->set_bus_param(icl, width_flag);
-
-       /*
-        * Without board specific bus width settings we only support the
-        * sensors native bus width
-        */
-       if (width_flag == SOCAM_DATAWIDTH_10)
-               return 0;
-
-       return -EINVAL;
-}
-
-static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd)
-{
-       struct soc_camera_link *icl = to_soc_camera_link(icd);
-       /* MT9M001 has all capture_format parameters fixed */
-       unsigned long flags = SOCAM_PCLK_SAMPLE_FALLING |
-               SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH |
-               SOCAM_DATA_ACTIVE_HIGH | SOCAM_MASTER;
-
-       if (icl->query_bus_param)
-               flags |= icl->query_bus_param(icl) & SOCAM_DATAWIDTH_MASK;
-       else
-               flags |= SOCAM_DATAWIDTH_10;
-
-       return soc_camera_apply_sensor_flags(icl, flags);
-}
-
 static int mt9m001_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
        struct mt9m001 *mt9m001 = to_mt9m001(client);
        struct v4l2_rect rect = a->c;
-       struct soc_camera_device *icd = client->dev.platform_data;
        int ret;
        const u16 hblank = 9, vblank = 25;
-       unsigned int total_h;
 
        if (mt9m001->fmts == mt9m001_colour_fmts)
                /*
@@ -231,7 +196,7 @@ static int mt9m001_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
        soc_camera_limit_side(&rect.top, &rect.height,
                     MT9M001_ROW_SKIP, MT9M001_MIN_HEIGHT, MT9M001_MAX_HEIGHT);
 
-       total_h = rect.height + mt9m001->y_skip_top + vblank;
+       mt9m001->total_h = rect.height + mt9m001->y_skip_top + vblank;
 
        /* Blanking and start values - default... */
        ret = reg_write(client, MT9M001_HORIZONTAL_BLANKING, hblank);
@@ -240,7 +205,7 @@ static int mt9m001_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
 
        /*
         * The caller provides a supported format, as verified per
-        * call to icd->try_fmt()
+        * call to .try_mbus_fmt()
         */
        if (!ret)
                ret = reg_write(client, MT9M001_COLUMN_START, rect.left);
@@ -251,17 +216,8 @@ static int mt9m001_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
        if (!ret)
                ret = reg_write(client, MT9M001_WINDOW_HEIGHT,
                                rect.height + mt9m001->y_skip_top - 1);
-       if (!ret && mt9m001->autoexposure) {
-               ret = reg_write(client, MT9M001_SHUTTER_WIDTH, total_h);
-               if (!ret) {
-                       const struct v4l2_queryctrl *qctrl =
-                               soc_camera_find_qctrl(icd->ops,
-                                                     V4L2_CID_EXPOSURE);
-                       mt9m001->exposure = (524 + (total_h - 1) *
-                                (qctrl->maximum - qctrl->minimum)) /
-                               1048 + qctrl->minimum;
-               }
-       }
+       if (!ret && v4l2_ctrl_g_ctrl(mt9m001->autoexposure) == V4L2_EXPOSURE_AUTO)
+               ret = reg_write(client, MT9M001_SHUTTER_WIDTH, mt9m001->total_h);
 
        if (!ret)
                mt9m001->rect = rect;
@@ -421,107 +377,48 @@ static int mt9m001_s_register(struct v4l2_subdev *sd,
 }
 #endif
 
-static const struct v4l2_queryctrl mt9m001_controls[] = {
-       {
-               .id             = V4L2_CID_VFLIP,
-               .type           = V4L2_CTRL_TYPE_BOOLEAN,
-               .name           = "Flip Vertically",
-               .minimum        = 0,
-               .maximum        = 1,
-               .step           = 1,
-               .default_value  = 0,
-       }, {
-               .id             = V4L2_CID_GAIN,
-               .type           = V4L2_CTRL_TYPE_INTEGER,
-               .name           = "Gain",
-               .minimum        = 0,
-               .maximum        = 127,
-               .step           = 1,
-               .default_value  = 64,
-               .flags          = V4L2_CTRL_FLAG_SLIDER,
-       }, {
-               .id             = V4L2_CID_EXPOSURE,
-               .type           = V4L2_CTRL_TYPE_INTEGER,
-               .name           = "Exposure",
-               .minimum        = 1,
-               .maximum        = 255,
-               .step           = 1,
-               .default_value  = 255,
-               .flags          = V4L2_CTRL_FLAG_SLIDER,
-       }, {
-               .id             = V4L2_CID_EXPOSURE_AUTO,
-               .type           = V4L2_CTRL_TYPE_BOOLEAN,
-               .name           = "Automatic Exposure",
-               .minimum        = 0,
-               .maximum        = 1,
-               .step           = 1,
-               .default_value  = 1,
-       }
-};
-
-static struct soc_camera_ops mt9m001_ops = {
-       .set_bus_param          = mt9m001_set_bus_param,
-       .query_bus_param        = mt9m001_query_bus_param,
-       .controls               = mt9m001_controls,
-       .num_controls           = ARRAY_SIZE(mt9m001_controls),
-};
-
-static int mt9m001_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+static int mt9m001_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
 {
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct mt9m001 *mt9m001 = to_mt9m001(client);
-       int data;
+       struct mt9m001 *mt9m001 = container_of(ctrl->handler,
+                                              struct mt9m001, hdl);
+       s32 min, max;
 
        switch (ctrl->id) {
-       case V4L2_CID_VFLIP:
-               data = reg_read(client, MT9M001_READ_OPTIONS2);
-               if (data < 0)
-                       return -EIO;
-               ctrl->value = !!(data & 0x8000);
-               break;
        case V4L2_CID_EXPOSURE_AUTO:
-               ctrl->value = mt9m001->autoexposure;
-               break;
-       case V4L2_CID_GAIN:
-               ctrl->value = mt9m001->gain;
-               break;
-       case V4L2_CID_EXPOSURE:
-               ctrl->value = mt9m001->exposure;
+               min = mt9m001->exposure->minimum;
+               max = mt9m001->exposure->maximum;
+               mt9m001->exposure->val =
+                       (524 + (mt9m001->total_h - 1) * (max - min)) / 1048 + min;
                break;
        }
        return 0;
 }
 
-static int mt9m001_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+static int mt9m001_s_ctrl(struct v4l2_ctrl *ctrl)
 {
+       struct mt9m001 *mt9m001 = container_of(ctrl->handler,
+                                              struct mt9m001, hdl);
+       struct v4l2_subdev *sd = &mt9m001->subdev;
        struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct mt9m001 *mt9m001 = to_mt9m001(client);
-       struct soc_camera_device *icd = client->dev.platform_data;
-       const struct v4l2_queryctrl *qctrl;
+       struct v4l2_ctrl *exp = mt9m001->exposure;
        int data;
 
-       qctrl = soc_camera_find_qctrl(&mt9m001_ops, ctrl->id);
-
-       if (!qctrl)
-               return -EINVAL;
-
        switch (ctrl->id) {
        case V4L2_CID_VFLIP:
-               if (ctrl->value)
+               if (ctrl->val)
                        data = reg_set(client, MT9M001_READ_OPTIONS2, 0x8000);
                else
                        data = reg_clear(client, MT9M001_READ_OPTIONS2, 0x8000);
                if (data < 0)
                        return -EIO;
-               break;
+               return 0;
+
        case V4L2_CID_GAIN:
-               if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum)
-                       return -EINVAL;
                /* See Datasheet Table 7, Gain settings. */
-               if (ctrl->value <= qctrl->default_value) {
+               if (ctrl->val <= ctrl->default_value) {
                        /* Pack it into 0..1 step 0.125, register values 0..8 */
-                       unsigned long range = qctrl->default_value - qctrl->minimum;
-                       data = ((ctrl->value - qctrl->minimum) * 8 + range / 2) / range;
+                       unsigned long range = ctrl->default_value - ctrl->minimum;
+                       data = ((ctrl->val - ctrl->minimum) * 8 + range / 2) / range;
 
                        dev_dbg(&client->dev, "Setting gain %d\n", data);
                        data = reg_write(client, MT9M001_GLOBAL_GAIN, data);
@@ -530,8 +427,8 @@ static int mt9m001_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
                } else {
                        /* Pack it into 1.125..15 variable step, register values 9..67 */
                        /* We assume qctrl->maximum - qctrl->default_value - 1 > 0 */
-                       unsigned long range = qctrl->maximum - qctrl->default_value - 1;
-                       unsigned long gain = ((ctrl->value - qctrl->default_value - 1) *
+                       unsigned long range = ctrl->maximum - ctrl->default_value - 1;
+                       unsigned long gain = ((ctrl->val - ctrl->default_value - 1) *
                                               111 + range / 2) / range + 9;
 
                        if (gain <= 32)
@@ -547,66 +444,44 @@ static int mt9m001_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
                        if (data < 0)
                                return -EIO;
                }
+               return 0;
 
-               /* Success */
-               mt9m001->gain = ctrl->value;
-               break;
-       case V4L2_CID_EXPOSURE:
-               /* mt9m001 has maximum == default */
-               if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum)
-                       return -EINVAL;
-               else {
-                       unsigned long range = qctrl->maximum - qctrl->minimum;
-                       unsigned long shutter = ((ctrl->value - qctrl->minimum) * 1048 +
+       case V4L2_CID_EXPOSURE_AUTO:
+               if (ctrl->val == V4L2_EXPOSURE_MANUAL) {
+                       unsigned long range = exp->maximum - exp->minimum;
+                       unsigned long shutter = ((exp->val - exp->minimum) * 1048 +
                                                 range / 2) / range + 1;
 
                        dev_dbg(&client->dev,
                                "Setting shutter width from %d to %lu\n",
-                               reg_read(client, MT9M001_SHUTTER_WIDTH),
-                               shutter);
+                               reg_read(client, MT9M001_SHUTTER_WIDTH), shutter);
                        if (reg_write(client, MT9M001_SHUTTER_WIDTH, shutter) < 0)
                                return -EIO;
-                       mt9m001->exposure = ctrl->value;
-                       mt9m001->autoexposure = 0;
-               }
-               break;
-       case V4L2_CID_EXPOSURE_AUTO:
-               if (ctrl->value) {
+               } else {
                        const u16 vblank = 25;
-                       unsigned int total_h = mt9m001->rect.height +
+
+                       mt9m001->total_h = mt9m001->rect.height +
                                mt9m001->y_skip_top + vblank;
-                       if (reg_write(client, MT9M001_SHUTTER_WIDTH,
-                                     total_h) < 0)
+                       if (reg_write(client, MT9M001_SHUTTER_WIDTH, mt9m001->total_h) < 0)
                                return -EIO;
-                       qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE);
-                       mt9m001->exposure = (524 + (total_h - 1) *
-                                (qctrl->maximum - qctrl->minimum)) /
-                               1048 + qctrl->minimum;
-                       mt9m001->autoexposure = 1;
-               } else
-                       mt9m001->autoexposure = 0;
-               break;
+               }
+               return 0;
        }
-       return 0;
+       return -EINVAL;
 }
 
 /*
  * Interface active, can use i2c. If it fails, it can indeed mean, that
  * this wasn't our capture interface, so, we wait for the right one
  */
-static int mt9m001_video_probe(struct soc_camera_device *icd,
+static int mt9m001_video_probe(struct soc_camera_link *icl,
                               struct i2c_client *client)
 {
        struct mt9m001 *mt9m001 = to_mt9m001(client);
-       struct soc_camera_link *icl = to_soc_camera_link(icd);
        s32 data;
        unsigned long flags;
        int ret;
 
-       /* We must have a parent by now. And it cannot be a wrong one. */
-       BUG_ON(!icd->parent ||
-              to_soc_camera_host(icd->parent)->nr != icd->iface);
-
        /* Enable the chip */
        data = reg_write(client, MT9M001_CHIP_ENABLE, 1);
        dev_dbg(&client->dev, "write: %d\n", data);
@@ -661,18 +536,11 @@ static int mt9m001_video_probe(struct soc_camera_device *icd,
                dev_err(&client->dev, "Failed to initialise the camera\n");
 
        /* mt9m001_init() has reset the chip, returning registers to defaults */
-       mt9m001->gain = 64;
-       mt9m001->exposure = 255;
-
-       return ret;
+       return v4l2_ctrl_handler_setup(&mt9m001->hdl);
 }
 
-static void mt9m001_video_remove(struct soc_camera_device *icd)
+static void mt9m001_video_remove(struct soc_camera_link *icl)
 {
-       struct soc_camera_link *icl = to_soc_camera_link(icd);
-
-       dev_dbg(icd->pdev, "Video removed: %p, %p\n",
-               icd->parent, icd->vdev);
        if (icl->free_bus)
                icl->free_bus(icl);
 }
@@ -687,9 +555,12 @@ static int mt9m001_g_skip_top_lines(struct v4l2_subdev *sd, u32 *lines)
        return 0;
 }
 
+static const struct v4l2_ctrl_ops mt9m001_ctrl_ops = {
+       .g_volatile_ctrl = mt9m001_g_volatile_ctrl,
+       .s_ctrl = mt9m001_s_ctrl,
+};
+
 static struct v4l2_subdev_core_ops mt9m001_subdev_core_ops = {
-       .g_ctrl         = mt9m001_g_ctrl,
-       .s_ctrl         = mt9m001_s_ctrl,
        .g_chip_ident   = mt9m001_g_chip_ident,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
        .g_register     = mt9m001_g_register,
@@ -710,6 +581,40 @@ static int mt9m001_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
        return 0;
 }
 
+static int mt9m001_g_mbus_config(struct v4l2_subdev *sd,
+                               struct v4l2_mbus_config *cfg)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+       /* MT9M001 has all capture_format parameters fixed */
+       cfg->flags = V4L2_MBUS_PCLK_SAMPLE_FALLING |
+               V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_HIGH |
+               V4L2_MBUS_DATA_ACTIVE_HIGH | V4L2_MBUS_MASTER;
+       cfg->type = V4L2_MBUS_PARALLEL;
+       cfg->flags = soc_camera_apply_board_flags(icl, cfg);
+
+       return 0;
+}
+
+static int mt9m001_s_mbus_config(struct v4l2_subdev *sd,
+                               const struct v4l2_mbus_config *cfg)
+{
+       const struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+       struct mt9m001 *mt9m001 = to_mt9m001(client);
+       unsigned int bps = soc_mbus_get_fmtdesc(mt9m001->fmt->code)->bits_per_sample;
+
+       if (icl->set_bus_param)
+               return icl->set_bus_param(icl, 1 << (bps - 1));
+
+       /*
+        * Without board specific bus width settings we only support the
+        * sensors native bus width
+        */
+       return bps == 10 ? 0 : -EINVAL;
+}
+
 static struct v4l2_subdev_video_ops mt9m001_subdev_video_ops = {
        .s_stream       = mt9m001_s_stream,
        .s_mbus_fmt     = mt9m001_s_fmt,
@@ -719,6 +624,8 @@ static struct v4l2_subdev_video_ops mt9m001_subdev_video_ops = {
        .g_crop         = mt9m001_g_crop,
        .cropcap        = mt9m001_cropcap,
        .enum_mbus_fmt  = mt9m001_enum_fmt,
+       .g_mbus_config  = mt9m001_g_mbus_config,
+       .s_mbus_config  = mt9m001_s_mbus_config,
 };
 
 static struct v4l2_subdev_sensor_ops mt9m001_subdev_sensor_ops = {
@@ -735,17 +642,10 @@ static int mt9m001_probe(struct i2c_client *client,
                         const struct i2c_device_id *did)
 {
        struct mt9m001 *mt9m001;
-       struct soc_camera_device *icd = client->dev.platform_data;
        struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
-       struct soc_camera_link *icl;
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
        int ret;
 
-       if (!icd) {
-               dev_err(&client->dev, "MT9M001: missing soc-camera data!\n");
-               return -EINVAL;
-       }
-
-       icl = to_soc_camera_link(icd);
        if (!icl) {
                dev_err(&client->dev, "MT9M001 driver needs platform data\n");
                return -EINVAL;
@@ -762,25 +662,40 @@ static int mt9m001_probe(struct i2c_client *client,
                return -ENOMEM;
 
        v4l2_i2c_subdev_init(&mt9m001->subdev, client, &mt9m001_subdev_ops);
+       v4l2_ctrl_handler_init(&mt9m001->hdl, 4);
+       v4l2_ctrl_new_std(&mt9m001->hdl, &mt9m001_ctrl_ops,
+                       V4L2_CID_VFLIP, 0, 1, 1, 0);
+       v4l2_ctrl_new_std(&mt9m001->hdl, &mt9m001_ctrl_ops,
+                       V4L2_CID_GAIN, 0, 127, 1, 64);
+       mt9m001->exposure = v4l2_ctrl_new_std(&mt9m001->hdl, &mt9m001_ctrl_ops,
+                       V4L2_CID_EXPOSURE, 1, 255, 1, 255);
+       /*
+        * Simulated autoexposure. If enabled, we calculate shutter width
+        * ourselves in the driver based on vertical blanking and frame width
+        */
+       mt9m001->autoexposure = v4l2_ctrl_new_std_menu(&mt9m001->hdl,
+                       &mt9m001_ctrl_ops, V4L2_CID_EXPOSURE_AUTO, 1, 0,
+                       V4L2_EXPOSURE_AUTO);
+       mt9m001->subdev.ctrl_handler = &mt9m001->hdl;
+       if (mt9m001->hdl.error) {
+               int err = mt9m001->hdl.error;
 
-       /* Second stage probe - when a capture adapter is there */
-       icd->ops                = &mt9m001_ops;
+               kfree(mt9m001);
+               return err;
+       }
+       v4l2_ctrl_auto_cluster(2, &mt9m001->autoexposure,
+                                       V4L2_EXPOSURE_MANUAL, true);
 
+       /* Second stage probe - when a capture adapter is there */
        mt9m001->y_skip_top     = 0;
        mt9m001->rect.left      = MT9M001_COLUMN_SKIP;
        mt9m001->rect.top       = MT9M001_ROW_SKIP;
        mt9m001->rect.width     = MT9M001_MAX_WIDTH;
        mt9m001->rect.height    = MT9M001_MAX_HEIGHT;
 
-       /*
-        * Simulated autoexposure. If enabled, we calculate shutter width
-        * ourselves in the driver based on vertical blanking and frame width
-        */
-       mt9m001->autoexposure = 1;
-
-       ret = mt9m001_video_probe(icd, client);
+       ret = mt9m001_video_probe(icl, client);
        if (ret) {
-               icd->ops = NULL;
+               v4l2_ctrl_handler_free(&mt9m001->hdl);
                kfree(mt9m001);
        }
 
@@ -790,10 +705,11 @@ static int mt9m001_probe(struct i2c_client *client,
 static int mt9m001_remove(struct i2c_client *client)
 {
        struct mt9m001 *mt9m001 = to_mt9m001(client);
-       struct soc_camera_device *icd = client->dev.platform_data;
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
 
-       icd->ops = NULL;
-       mt9m001_video_remove(icd);
+       v4l2_device_unregister_subdev(&mt9m001->subdev);
+       v4l2_ctrl_handler_free(&mt9m001->hdl);
+       mt9m001_video_remove(icl);
        kfree(mt9m001);
 
        return 0;
index 07af26e..f023cc0 100644 (file)
 #include <linux/log2.h>
 #include <linux/gpio.h>
 #include <linux/delay.h>
+#include <linux/v4l2-mediabus.h>
 
+#include <media/soc_camera.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ctrls.h>
 #include <media/v4l2-chip-ident.h>
-#include <media/soc_camera.h>
 
 /*
  * MT9M111, MT9M112 and MT9M131:
@@ -177,6 +179,8 @@ enum mt9m111_context {
 
 struct mt9m111 {
        struct v4l2_subdev subdev;
+       struct v4l2_ctrl_handler hdl;
+       struct v4l2_ctrl *gain;
        int model;      /* V4L2_IDENT_MT9M111 or V4L2_IDENT_MT9M112 code
                         * from v4l2-chip-ident.h */
        enum mt9m111_context context;
@@ -185,13 +189,8 @@ struct mt9m111 {
        int power_count;
        const struct mt9m111_datafmt *fmt;
        int lastpage;   /* PageMap cache value */
-       unsigned int gain;
-       unsigned char autoexposure;
        unsigned char datawidth;
        unsigned int powered:1;
-       unsigned int hflip:1;
-       unsigned int vflip:1;
-       unsigned int autowhitebalance:1;
 };
 
 static struct mt9m111 *to_mt9m111(const struct i2c_client *client)
@@ -363,21 +362,6 @@ static int mt9m111_reset(struct mt9m111 *mt9m111)
        return ret;
 }
 
-static unsigned long mt9m111_query_bus_param(struct soc_camera_device *icd)
-{
-       struct soc_camera_link *icl = to_soc_camera_link(icd);
-       unsigned long flags = SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING |
-               SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH |
-               SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATAWIDTH_8;
-
-       return soc_camera_apply_sensor_flags(icl, flags);
-}
-
-static int mt9m111_set_bus_param(struct soc_camera_device *icd, unsigned long f)
-{
-       return 0;
-}
-
 static int mt9m111_make_rect(struct mt9m111 *mt9m111,
                             struct v4l2_rect *rect)
 {
@@ -660,50 +644,6 @@ static int mt9m111_s_register(struct v4l2_subdev *sd,
 }
 #endif
 
-static const struct v4l2_queryctrl mt9m111_controls[] = {
-       {
-               .id             = V4L2_CID_VFLIP,
-               .type           = V4L2_CTRL_TYPE_BOOLEAN,
-               .name           = "Flip Verticaly",
-               .minimum        = 0,
-               .maximum        = 1,
-               .step           = 1,
-               .default_value  = 0,
-       }, {
-               .id             = V4L2_CID_HFLIP,
-               .type           = V4L2_CTRL_TYPE_BOOLEAN,
-               .name           = "Flip Horizontaly",
-               .minimum        = 0,
-               .maximum        = 1,
-               .step           = 1,
-               .default_value  = 0,
-       }, {    /* gain = 1/32*val (=>gain=1 if val==32) */
-               .id             = V4L2_CID_GAIN,
-               .type           = V4L2_CTRL_TYPE_INTEGER,
-               .name           = "Gain",
-               .minimum        = 0,
-               .maximum        = 63 * 2 * 2,
-               .step           = 1,
-               .default_value  = 32,
-               .flags          = V4L2_CTRL_FLAG_SLIDER,
-       }, {
-               .id             = V4L2_CID_EXPOSURE_AUTO,
-               .type           = V4L2_CTRL_TYPE_BOOLEAN,
-               .name           = "Auto Exposure",
-               .minimum        = 0,
-               .maximum        = 1,
-               .step           = 1,
-               .default_value  = 1,
-       }
-};
-
-static struct soc_camera_ops mt9m111_ops = {
-       .query_bus_param        = mt9m111_query_bus_param,
-       .set_bus_param          = mt9m111_set_bus_param,
-       .controls               = mt9m111_controls,
-       .num_controls           = ARRAY_SIZE(mt9m111_controls),
-};
-
 static int mt9m111_set_flip(struct mt9m111 *mt9m111, int flip, int mask)
 {
        struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
@@ -744,7 +684,6 @@ static int mt9m111_set_global_gain(struct mt9m111 *mt9m111, int gain)
        if (gain > 63 * 2 * 2)
                return -EINVAL;
 
-       mt9m111->gain = gain;
        if ((gain >= 64 * 2) && (gain < 63 * 2 * 2))
                val = (1 << 10) | (1 << 9) | (gain / 4);
        else if ((gain >= 64) && (gain < 64 * 2))
@@ -758,118 +697,47 @@ static int mt9m111_set_global_gain(struct mt9m111 *mt9m111, int gain)
 static int mt9m111_set_autoexposure(struct mt9m111 *mt9m111, int on)
 {
        struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
-       int ret;
 
        if (on)
-               ret = reg_set(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOEXPO_EN);
-       else
-               ret = reg_clear(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOEXPO_EN);
-
-       if (!ret)
-               mt9m111->autoexposure = on;
-
-       return ret;
+               return reg_set(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOEXPO_EN);
+       return reg_clear(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOEXPO_EN);
 }
 
 static int mt9m111_set_autowhitebalance(struct mt9m111 *mt9m111, int on)
 {
        struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
-       int ret;
 
        if (on)
-               ret = reg_set(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOWHITEBAL_EN);
-       else
-               ret = reg_clear(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOWHITEBAL_EN);
-
-       if (!ret)
-               mt9m111->autowhitebalance = on;
-
-       return ret;
-}
-
-static int mt9m111_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
-       int data;
-
-       switch (ctrl->id) {
-       case V4L2_CID_VFLIP:
-               if (mt9m111->context == HIGHPOWER)
-                       data = reg_read(READ_MODE_B);
-               else
-                       data = reg_read(READ_MODE_A);
-
-               if (data < 0)
-                       return -EIO;
-               ctrl->value = !!(data & MT9M111_RMB_MIRROR_ROWS);
-               break;
-       case V4L2_CID_HFLIP:
-               if (mt9m111->context == HIGHPOWER)
-                       data = reg_read(READ_MODE_B);
-               else
-                       data = reg_read(READ_MODE_A);
-
-               if (data < 0)
-                       return -EIO;
-               ctrl->value = !!(data & MT9M111_RMB_MIRROR_COLS);
-               break;
-       case V4L2_CID_GAIN:
-               data = mt9m111_get_global_gain(mt9m111);
-               if (data < 0)
-                       return data;
-               ctrl->value = data;
-               break;
-       case V4L2_CID_EXPOSURE_AUTO:
-               ctrl->value = mt9m111->autoexposure;
-               break;
-       case V4L2_CID_AUTO_WHITE_BALANCE:
-               ctrl->value = mt9m111->autowhitebalance;
-               break;
-       }
-       return 0;
+               return reg_set(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOWHITEBAL_EN);
+       return reg_clear(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOWHITEBAL_EN);
 }
 
-static int mt9m111_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+static int mt9m111_s_ctrl(struct v4l2_ctrl *ctrl)
 {
-       struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
-       const struct v4l2_queryctrl *qctrl;
-       int ret;
-
-       qctrl = soc_camera_find_qctrl(&mt9m111_ops, ctrl->id);
-       if (!qctrl)
-               return -EINVAL;
+       struct mt9m111 *mt9m111 = container_of(ctrl->handler,
+                                              struct mt9m111, hdl);
 
        switch (ctrl->id) {
        case V4L2_CID_VFLIP:
-               mt9m111->vflip = ctrl->value;
-               ret = mt9m111_set_flip(mt9m111, ctrl->value,
+               return mt9m111_set_flip(mt9m111, ctrl->val,
                                        MT9M111_RMB_MIRROR_ROWS);
-               break;
        case V4L2_CID_HFLIP:
-               mt9m111->hflip = ctrl->value;
-               ret = mt9m111_set_flip(mt9m111, ctrl->value,
+               return mt9m111_set_flip(mt9m111, ctrl->val,
                                        MT9M111_RMB_MIRROR_COLS);
-               break;
        case V4L2_CID_GAIN:
-               ret = mt9m111_set_global_gain(mt9m111, ctrl->value);
-               break;
+               return mt9m111_set_global_gain(mt9m111, ctrl->val);
        case V4L2_CID_EXPOSURE_AUTO:
-               ret =  mt9m111_set_autoexposure(mt9m111, ctrl->value);
-               break;
+               return mt9m111_set_autoexposure(mt9m111, ctrl->val);
        case V4L2_CID_AUTO_WHITE_BALANCE:
-               ret =  mt9m111_set_autowhitebalance(mt9m111, ctrl->value);
-               break;
-       default:
-               ret = -EINVAL;
+               return mt9m111_set_autowhitebalance(mt9m111, ctrl->val);
        }
 
-       return ret;
+       return -EINVAL;
 }
 
 static int mt9m111_suspend(struct mt9m111 *mt9m111)
 {
-       mt9m111->gain = mt9m111_get_global_gain(mt9m111);
+       v4l2_ctrl_s_ctrl(mt9m111->gain, mt9m111_get_global_gain(mt9m111));
 
        return 0;
 }
@@ -879,11 +747,7 @@ static void mt9m111_restore_state(struct mt9m111 *mt9m111)
        mt9m111_set_context(mt9m111, mt9m111->context);
        mt9m111_set_pixfmt(mt9m111, mt9m111->fmt->code);
        mt9m111_setup_rect(mt9m111, &mt9m111->rect);
-       mt9m111_set_flip(mt9m111, mt9m111->hflip, MT9M111_RMB_MIRROR_COLS);
-       mt9m111_set_flip(mt9m111, mt9m111->vflip, MT9M111_RMB_MIRROR_ROWS);
-       mt9m111_set_global_gain(mt9m111, mt9m111->gain);
-       mt9m111_set_autoexposure(mt9m111, mt9m111->autoexposure);
-       mt9m111_set_autowhitebalance(mt9m111, mt9m111->autowhitebalance);
+       v4l2_ctrl_handler_setup(&mt9m111->hdl);
 }
 
 static int mt9m111_resume(struct mt9m111 *mt9m111)
@@ -911,8 +775,6 @@ static int mt9m111_init(struct mt9m111 *mt9m111)
                ret = mt9m111_reset(mt9m111);
        if (!ret)
                ret = mt9m111_set_context(mt9m111, mt9m111->context);
-       if (!ret)
-               ret = mt9m111_set_autoexposure(mt9m111, mt9m111->autoexposure);
        if (ret)
                dev_err(&client->dev, "mt9m111 init failed: %d\n", ret);
        return ret;
@@ -922,22 +784,12 @@ static int mt9m111_init(struct mt9m111 *mt9m111)
  * Interface active, can use i2c. If it fails, it can indeed mean, that
  * this wasn't our capture interface, so, we wait for the right one
  */
-static int mt9m111_video_probe(struct soc_camera_device *icd,
-                              struct i2c_client *client)
+static int mt9m111_video_probe(struct i2c_client *client)
 {
        struct mt9m111 *mt9m111 = to_mt9m111(client);
        s32 data;
        int ret;
 
-       /* We must have a parent by now. And it cannot be a wrong one. */
-       BUG_ON(!icd->parent ||
-              to_soc_camera_host(icd->parent)->nr != icd->iface);
-
-       mt9m111->lastpage = -1;
-
-       mt9m111->autoexposure = 1;
-       mt9m111->autowhitebalance = 1;
-
        data = reg_read(CHIP_VERSION);
 
        switch (data) {
@@ -951,17 +803,16 @@ static int mt9m111_video_probe(struct soc_camera_device *icd,
                dev_info(&client->dev, "Detected a MT9M112 chip ID %x\n", data);
                break;
        default:
-               ret = -ENODEV;
                dev_err(&client->dev,
                        "No MT9M111/MT9M112/MT9M131 chip detected register read %x\n",
                        data);
-               goto ei2c;
+               return -ENODEV;
        }
 
        ret = mt9m111_init(mt9m111);
-
-ei2c:
-       return ret;
+       if (ret)
+               return ret;
+       return v4l2_ctrl_handler_setup(&mt9m111->hdl);
 }
 
 static int mt9m111_s_power(struct v4l2_subdev *sd, int on)
@@ -998,9 +849,11 @@ out:
        return ret;
 }
 
+static const struct v4l2_ctrl_ops mt9m111_ctrl_ops = {
+       .s_ctrl = mt9m111_s_ctrl,
+};
+
 static struct v4l2_subdev_core_ops mt9m111_subdev_core_ops = {
-       .g_ctrl         = mt9m111_g_ctrl,
-       .s_ctrl         = mt9m111_s_ctrl,
        .g_chip_ident   = mt9m111_g_chip_ident,
        .s_power        = mt9m111_s_power,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
@@ -1019,6 +872,21 @@ static int mt9m111_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
        return 0;
 }
 
+static int mt9m111_g_mbus_config(struct v4l2_subdev *sd,
+                               struct v4l2_mbus_config *cfg)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+       cfg->flags = V4L2_MBUS_MASTER | V4L2_MBUS_PCLK_SAMPLE_RISING |
+               V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_HIGH |
+               V4L2_MBUS_DATA_ACTIVE_HIGH;
+       cfg->type = V4L2_MBUS_PARALLEL;
+       cfg->flags = soc_camera_apply_board_flags(icl, cfg);
+
+       return 0;
+}
+
 static struct v4l2_subdev_video_ops mt9m111_subdev_video_ops = {
        .s_mbus_fmt     = mt9m111_s_fmt,
        .g_mbus_fmt     = mt9m111_g_fmt,
@@ -1027,6 +895,7 @@ static struct v4l2_subdev_video_ops mt9m111_subdev_video_ops = {
        .g_crop         = mt9m111_g_crop,
        .cropcap        = mt9m111_cropcap,
        .enum_mbus_fmt  = mt9m111_enum_fmt,
+       .g_mbus_config  = mt9m111_g_mbus_config,
 };
 
 static struct v4l2_subdev_ops mt9m111_subdev_ops = {
@@ -1038,17 +907,10 @@ static int mt9m111_probe(struct i2c_client *client,
                         const struct i2c_device_id *did)
 {
        struct mt9m111 *mt9m111;
-       struct soc_camera_device *icd = client->dev.platform_data;
        struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
-       struct soc_camera_link *icl;
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
        int ret;
 
-       if (!icd) {
-               dev_err(&client->dev, "mt9m111: soc-camera data missing!\n");
-               return -EINVAL;
-       }
-
-       icl = to_soc_camera_link(icd);
        if (!icl) {
                dev_err(&client->dev, "mt9m111: driver needs platform data\n");
                return -EINVAL;
@@ -1065,19 +927,37 @@ static int mt9m111_probe(struct i2c_client *client,
                return -ENOMEM;
 
        v4l2_i2c_subdev_init(&mt9m111->subdev, client, &mt9m111_subdev_ops);
+       v4l2_ctrl_handler_init(&mt9m111->hdl, 5);
+       v4l2_ctrl_new_std(&mt9m111->hdl, &mt9m111_ctrl_ops,
+                       V4L2_CID_VFLIP, 0, 1, 1, 0);
+       v4l2_ctrl_new_std(&mt9m111->hdl, &mt9m111_ctrl_ops,
+                       V4L2_CID_HFLIP, 0, 1, 1, 0);
+       v4l2_ctrl_new_std(&mt9m111->hdl, &mt9m111_ctrl_ops,
+                       V4L2_CID_AUTO_WHITE_BALANCE, 0, 1, 1, 1);
+       mt9m111->gain = v4l2_ctrl_new_std(&mt9m111->hdl, &mt9m111_ctrl_ops,
+                       V4L2_CID_GAIN, 0, 63 * 2 * 2, 1, 32);
+       v4l2_ctrl_new_std_menu(&mt9m111->hdl,
+                       &mt9m111_ctrl_ops, V4L2_CID_EXPOSURE_AUTO, 1, 0,
+                       V4L2_EXPOSURE_AUTO);
+       mt9m111->subdev.ctrl_handler = &mt9m111->hdl;
+       if (mt9m111->hdl.error) {
+               int err = mt9m111->hdl.error;
 
-       /* Second stage probe - when a capture adapter is there */
-       icd->ops                = &mt9m111_ops;
+               kfree(mt9m111);
+               return err;
+       }
 
+       /* Second stage probe - when a capture adapter is there */
        mt9m111->rect.left      = MT9M111_MIN_DARK_COLS;
        mt9m111->rect.top       = MT9M111_MIN_DARK_ROWS;
        mt9m111->rect.width     = MT9M111_MAX_WIDTH;
        mt9m111->rect.height    = MT9M111_MAX_HEIGHT;
        mt9m111->fmt            = &mt9m111_colour_fmts[0];
+       mt9m111->lastpage       = -1;
 
-       ret = mt9m111_video_probe(icd, client);
+       ret = mt9m111_video_probe(client);
        if (ret) {
-               icd->ops = NULL;
+               v4l2_ctrl_handler_free(&mt9m111->hdl);
                kfree(mt9m111);
        }
 
@@ -1087,9 +967,9 @@ static int mt9m111_probe(struct i2c_client *client,
 static int mt9m111_remove(struct i2c_client *client)
 {
        struct mt9m111 *mt9m111 = to_mt9m111(client);
-       struct soc_camera_device *icd = client->dev.platform_data;
 
-       icd->ops = NULL;
+       v4l2_device_unregister_subdev(&mt9m111->subdev);
+       v4l2_ctrl_handler_free(&mt9m111->hdl);
        kfree(mt9m111);
 
        return 0;
index 30547cc..7ee84cc 100644 (file)
 #include <linux/log2.h>
 #include <linux/pm.h>
 #include <linux/slab.h>
+#include <linux/v4l2-mediabus.h>
 #include <linux/videodev2.h>
 
 #include <media/soc_camera.h>
 #include <media/v4l2-chip-ident.h>
 #include <media/v4l2-subdev.h>
+#include <media/v4l2-ctrls.h>
+
+/*
+ * ATTENTION: this driver still cannot be used outside of the soc-camera
+ * framework because of its PM implementation, using the video_device node.
+ * If hardware becomes available for testing, alternative PM approaches shall
+ * be considered and tested.
+ */
 
 /*
  * mt9t031 i2c address 0x5d
 #define MT9T031_COLUMN_SKIP            32
 #define MT9T031_ROW_SKIP               20
 
-#define MT9T031_BUS_PARAM      (SOCAM_PCLK_SAMPLE_RISING |     \
-       SOCAM_PCLK_SAMPLE_FALLING | SOCAM_HSYNC_ACTIVE_HIGH |   \
-       SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_DATA_ACTIVE_HIGH |      \
-       SOCAM_MASTER | SOCAM_DATAWIDTH_10)
-
 struct mt9t031 {
        struct v4l2_subdev subdev;
+       struct v4l2_ctrl_handler hdl;
+       struct {
+               /* exposure/auto-exposure cluster */
+               struct v4l2_ctrl *autoexposure;
+               struct v4l2_ctrl *exposure;
+       };
        struct v4l2_rect rect;  /* Sensor window */
        int model;      /* V4L2_IDENT_MT9T031* codes from v4l2-chip-ident.h */
        u16 xskip;
        u16 yskip;
-       unsigned int gain;
+       unsigned int total_h;
        unsigned short y_skip_top;      /* Lines to skip at the top */
-       unsigned int exposure;
-       unsigned char autoexposure;
 };
 
 static struct mt9t031 *to_mt9t031(const struct i2c_client *client)
@@ -179,95 +187,6 @@ static int mt9t031_s_stream(struct v4l2_subdev *sd, int enable)
        return 0;
 }
 
-static int mt9t031_set_bus_param(struct soc_camera_device *icd,
-                                unsigned long flags)
-{
-       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
-
-       /* The caller should have queried our parameters, check anyway */
-       if (flags & ~MT9T031_BUS_PARAM)
-               return -EINVAL;
-
-       if (flags & SOCAM_PCLK_SAMPLE_FALLING)
-               reg_clear(client, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000);
-       else
-               reg_set(client, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000);
-
-       return 0;
-}
-
-static unsigned long mt9t031_query_bus_param(struct soc_camera_device *icd)
-{
-       struct soc_camera_link *icl = to_soc_camera_link(icd);
-
-       return soc_camera_apply_sensor_flags(icl, MT9T031_BUS_PARAM);
-}
-
-enum {
-       MT9T031_CTRL_VFLIP,
-       MT9T031_CTRL_HFLIP,
-       MT9T031_CTRL_GAIN,
-       MT9T031_CTRL_EXPOSURE,
-       MT9T031_CTRL_EXPOSURE_AUTO,
-};
-
-static const struct v4l2_queryctrl mt9t031_controls[] = {
-       [MT9T031_CTRL_VFLIP] = {
-               .id             = V4L2_CID_VFLIP,
-               .type           = V4L2_CTRL_TYPE_BOOLEAN,
-               .name           = "Flip Vertically",
-               .minimum        = 0,
-               .maximum        = 1,
-               .step           = 1,
-               .default_value  = 0,
-       },
-       [MT9T031_CTRL_HFLIP] = {
-               .id             = V4L2_CID_HFLIP,
-               .type           = V4L2_CTRL_TYPE_BOOLEAN,
-               .name           = "Flip Horizontally",
-               .minimum        = 0,
-               .maximum        = 1,
-               .step           = 1,
-               .default_value  = 0,
-       },
-       [MT9T031_CTRL_GAIN] = {
-               .id             = V4L2_CID_GAIN,
-               .type           = V4L2_CTRL_TYPE_INTEGER,
-               .name           = "Gain",
-               .minimum        = 0,
-               .maximum        = 127,
-               .step           = 1,
-               .default_value  = 64,
-               .flags          = V4L2_CTRL_FLAG_SLIDER,
-       },
-       [MT9T031_CTRL_EXPOSURE] = {
-               .id             = V4L2_CID_EXPOSURE,
-               .type           = V4L2_CTRL_TYPE_INTEGER,
-               .name           = "Exposure",
-               .minimum        = 1,
-               .maximum        = 255,
-               .step           = 1,
-               .default_value  = 255,
-               .flags          = V4L2_CTRL_FLAG_SLIDER,
-       },
-       [MT9T031_CTRL_EXPOSURE_AUTO] = {
-               .id             = V4L2_CID_EXPOSURE_AUTO,
-               .type           = V4L2_CTRL_TYPE_BOOLEAN,
-               .name           = "Automatic Exposure",
-               .minimum        = 0,
-               .maximum        = 1,
-               .step           = 1,
-               .default_value  = 1,
-       }
-};
-
-static struct soc_camera_ops mt9t031_ops = {
-       .set_bus_param          = mt9t031_set_bus_param,
-       .query_bus_param        = mt9t031_query_bus_param,
-       .controls               = mt9t031_controls,
-       .num_controls           = ARRAY_SIZE(mt9t031_controls),
-};
-
 /* target must be _even_ */
 static u16 mt9t031_skip(s32 *source, s32 target, s32 max)
 {
@@ -353,7 +272,7 @@ static int mt9t031_set_params(struct i2c_client *client,
 
        /*
         * The caller provides a supported format, as guaranteed by
-        * icd->try_fmt_cap(), soc_camera_s_crop() and soc_camera_cropcap()
+        * .try_mbus_fmt(), soc_camera_s_crop() and soc_camera_cropcap()
         */
        if (ret >= 0)
                ret = reg_write(client, MT9T031_COLUMN_START, rect->left);
@@ -364,17 +283,10 @@ static int mt9t031_set_params(struct i2c_client *client,
        if (ret >= 0)
                ret = reg_write(client, MT9T031_WINDOW_HEIGHT,
                                rect->height + mt9t031->y_skip_top - 1);
-       if (ret >= 0 && mt9t031->autoexposure) {
-               unsigned int total_h = rect->height + mt9t031->y_skip_top + vblank;
-               ret = set_shutter(client, total_h);
-               if (ret >= 0) {
-                       const u32 shutter_max = MT9T031_MAX_HEIGHT + vblank;
-                       const struct v4l2_queryctrl *qctrl =
-                               &mt9t031_controls[MT9T031_CTRL_EXPOSURE];
-                       mt9t031->exposure = (shutter_max / 2 + (total_h - 1) *
-                                (qctrl->maximum - qctrl->minimum)) /
-                               shutter_max + qctrl->minimum;
-               }
+       if (ret >= 0 && v4l2_ctrl_g_ctrl(mt9t031->autoexposure) == V4L2_EXPOSURE_AUTO) {
+               mt9t031->total_h = rect->height + mt9t031->y_skip_top + vblank;
+
+               ret = set_shutter(client, mt9t031->total_h);
        }
 
        /* Re-enable register update, commit all changes */
@@ -543,71 +455,57 @@ static int mt9t031_s_register(struct v4l2_subdev *sd,
 }
 #endif
 
-static int mt9t031_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+static int mt9t031_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
 {
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct mt9t031 *mt9t031 = to_mt9t031(client);
-       int data;
+       struct mt9t031 *mt9t031 = container_of(ctrl->handler,
+                                              struct mt9t031, hdl);
+       const u32 shutter_max = MT9T031_MAX_HEIGHT + MT9T031_VERTICAL_BLANK;
+       s32 min, max;
 
        switch (ctrl->id) {
-       case V4L2_CID_VFLIP:
-               data = reg_read(client, MT9T031_READ_MODE_2);
-               if (data < 0)
-                       return -EIO;
-               ctrl->value = !!(data & 0x8000);
-               break;
-       case V4L2_CID_HFLIP:
-               data = reg_read(client, MT9T031_READ_MODE_2);
-               if (data < 0)
-                       return -EIO;
-               ctrl->value = !!(data & 0x4000);
-               break;
        case V4L2_CID_EXPOSURE_AUTO:
-               ctrl->value = mt9t031->autoexposure;
-               break;
-       case V4L2_CID_GAIN:
-               ctrl->value = mt9t031->gain;
-               break;
-       case V4L2_CID_EXPOSURE:
-               ctrl->value = mt9t031->exposure;
+               min = mt9t031->exposure->minimum;
+               max = mt9t031->exposure->maximum;
+               mt9t031->exposure->val =
+                       (shutter_max / 2 + (mt9t031->total_h - 1) * (max - min))
+                               / shutter_max + min;
                break;
        }
        return 0;
 }
 
-static int mt9t031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+static int mt9t031_s_ctrl(struct v4l2_ctrl *ctrl)
 {
+       struct mt9t031 *mt9t031 = container_of(ctrl->handler,
+                                              struct mt9t031, hdl);
+       struct v4l2_subdev *sd = &mt9t031->subdev;
        struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct mt9t031 *mt9t031 = to_mt9t031(client);
-       const struct v4l2_queryctrl *qctrl;
+       struct v4l2_ctrl *exp = mt9t031->exposure;
        int data;
 
        switch (ctrl->id) {
        case V4L2_CID_VFLIP:
-               if (ctrl->value)
+               if (ctrl->val)
                        data = reg_set(client, MT9T031_READ_MODE_2, 0x8000);
                else
                        data = reg_clear(client, MT9T031_READ_MODE_2, 0x8000);
                if (data < 0)
                        return -EIO;
-               break;
+               return 0;
        case V4L2_CID_HFLIP:
-               if (ctrl->value)
+               if (ctrl->val)
                        data = reg_set(client, MT9T031_READ_MODE_2, 0x4000);
                else
                        data = reg_clear(client, MT9T031_READ_MODE_2, 0x4000);
                if (data < 0)
                        return -EIO;
-               break;
+               return 0;
        case V4L2_CID_GAIN:
-               qctrl = &mt9t031_controls[MT9T031_CTRL_GAIN];
-               if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum)
-                       return -EINVAL;
                /* See Datasheet Table 7, Gain settings. */
-               if (ctrl->value <= qctrl->default_value) {
+               if (ctrl->val <= ctrl->default_value) {
                        /* Pack it into 0..1 step 0.125, register values 0..8 */
-                       unsigned long range = qctrl->default_value - qctrl->minimum;
-                       data = ((ctrl->value - qctrl->minimum) * 8 + range / 2) / range;
+                       unsigned long range = ctrl->default_value - ctrl->minimum;
+                       data = ((ctrl->val - ctrl->minimum) * 8 + range / 2) / range;
 
                        dev_dbg(&client->dev, "Setting gain %d\n", data);
                        data = reg_write(client, MT9T031_GLOBAL_GAIN, data);
@@ -616,9 +514,9 @@ static int mt9t031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
                } else {
                        /* Pack it into 1.125..128 variable step, register values 9..0x7860 */
                        /* We assume qctrl->maximum - qctrl->default_value - 1 > 0 */
-                       unsigned long range = qctrl->maximum - qctrl->default_value - 1;
+                       unsigned long range = ctrl->maximum - ctrl->default_value - 1;
                        /* calculated gain: map 65..127 to 9..1024 step 0.125 */
-                       unsigned long gain = ((ctrl->value - qctrl->default_value - 1) *
+                       unsigned long gain = ((ctrl->val - ctrl->default_value - 1) *
                                               1015 + range / 2) / range + 9;
 
                        if (gain <= 32)         /* calculated gain 9..32 -> 9..32 */
@@ -635,19 +533,13 @@ static int mt9t031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
                        if (data < 0)
                                return -EIO;
                }
+               return 0;
 
-               /* Success */
-               mt9t031->gain = ctrl->value;
-               break;
-       case V4L2_CID_EXPOSURE:
-               qctrl = &mt9t031_controls[MT9T031_CTRL_EXPOSURE];
-               /* mt9t031 has maximum == default */
-               if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum)
-                       return -EINVAL;
-               else {
-                       const unsigned long range = qctrl->maximum - qctrl->minimum;
-                       const u32 shutter = ((ctrl->value - qctrl->minimum) * 1048 +
-                                            range / 2) / range + 1;
+       case V4L2_CID_EXPOSURE_AUTO:
+               if (ctrl->val == V4L2_EXPOSURE_MANUAL) {
+                       unsigned int range = exp->maximum - exp->minimum;
+                       unsigned int shutter = ((exp->val - exp->minimum) * 1048 +
+                                                range / 2) / range + 1;
                        u32 old;
 
                        get_shutter(client, &old);
@@ -655,27 +547,15 @@ static int mt9t031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
                                old, shutter);
                        if (set_shutter(client, shutter) < 0)
                                return -EIO;
-                       mt9t031->exposure = ctrl->value;
-                       mt9t031->autoexposure = 0;
-               }
-               break;
-       case V4L2_CID_EXPOSURE_AUTO:
-               if (ctrl->value) {
+               } else {
                        const u16 vblank = MT9T031_VERTICAL_BLANK;
-                       const u32 shutter_max = MT9T031_MAX_HEIGHT + vblank;
-                       unsigned int total_h = mt9t031->rect.height +
+                       mt9t031->total_h = mt9t031->rect.height +
                                mt9t031->y_skip_top + vblank;
 
-                       if (set_shutter(client, total_h) < 0)
+                       if (set_shutter(client, mt9t031->total_h) < 0)
                                return -EIO;
-                       qctrl = &mt9t031_controls[MT9T031_CTRL_EXPOSURE];
-                       mt9t031->exposure = (shutter_max / 2 + (total_h - 1) *
-                                (qctrl->maximum - qctrl->minimum)) /
-                               shutter_max + qctrl->minimum;
-                       mt9t031->autoexposure = 1;
-               } else
-                       mt9t031->autoexposure = 0;
-               break;
+               }
+               return 0;
        default:
                return -EINVAL;
        }
@@ -700,8 +580,7 @@ static int mt9t031_runtime_suspend(struct device *dev)
 static int mt9t031_runtime_resume(struct device *dev)
 {
        struct video_device *vdev = to_video_device(dev);
-       struct soc_camera_device *icd = dev_get_drvdata(vdev->parent);
-       struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
+       struct v4l2_subdev *sd = soc_camera_vdev_to_subdev(vdev);
        struct i2c_client *client = v4l2_get_subdevdata(sd);
        struct mt9t031 *mt9t031 = to_mt9t031(client);
 
@@ -734,6 +613,19 @@ static struct device_type mt9t031_dev_type = {
        .pm     = &mt9t031_dev_pm_ops,
 };
 
+static int mt9t031_s_power(struct v4l2_subdev *sd, int on)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct video_device *vdev = soc_camera_i2c_to_vdev(client);
+
+       if (on)
+               vdev->dev.type = &mt9t031_dev_type;
+       else
+               vdev->dev.type = NULL;
+
+       return 0;
+}
+
 /*
  * Interface active, can use i2c. If it fails, it can indeed mean, that
  * this wasn't our capture interface, so, we wait for the right one
@@ -741,7 +633,6 @@ static struct device_type mt9t031_dev_type = {
 static int mt9t031_video_probe(struct i2c_client *client)
 {
        struct mt9t031 *mt9t031 = to_mt9t031(client);
-       struct video_device *vdev = soc_camera_i2c_to_vdev(client);
        s32 data;
        int ret;
 
@@ -768,11 +659,7 @@ static int mt9t031_video_probe(struct i2c_client *client)
        if (ret < 0)
                dev_err(&client->dev, "Failed to initialise the camera\n");
        else
-               vdev->dev.type = &mt9t031_dev_type;
-
-       /* mt9t031_idle() has reset the chip to default. */
-       mt9t031->exposure = 255;
-       mt9t031->gain = 64;
+               v4l2_ctrl_handler_setup(&mt9t031->hdl);
 
        return ret;
 }
@@ -787,10 +674,14 @@ static int mt9t031_g_skip_top_lines(struct v4l2_subdev *sd, u32 *lines)
        return 0;
 }
 
+static const struct v4l2_ctrl_ops mt9t031_ctrl_ops = {
+       .g_volatile_ctrl = mt9t031_g_volatile_ctrl,
+       .s_ctrl = mt9t031_s_ctrl,
+};
+
 static struct v4l2_subdev_core_ops mt9t031_subdev_core_ops = {
-       .g_ctrl         = mt9t031_g_ctrl,
-       .s_ctrl         = mt9t031_s_ctrl,
        .g_chip_ident   = mt9t031_g_chip_ident,
+       .s_power        = mt9t031_s_power,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
        .g_register     = mt9t031_g_register,
        .s_register     = mt9t031_s_register,
@@ -807,6 +698,34 @@ static int mt9t031_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
        return 0;
 }
 
+static int mt9t031_g_mbus_config(struct v4l2_subdev *sd,
+                               struct v4l2_mbus_config *cfg)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+       cfg->flags = V4L2_MBUS_MASTER | V4L2_MBUS_PCLK_SAMPLE_RISING |
+               V4L2_MBUS_PCLK_SAMPLE_FALLING | V4L2_MBUS_HSYNC_ACTIVE_HIGH |
+               V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_DATA_ACTIVE_HIGH;
+       cfg->type = V4L2_MBUS_PARALLEL;
+       cfg->flags = soc_camera_apply_board_flags(icl, cfg);
+
+       return 0;
+}
+
+static int mt9t031_s_mbus_config(struct v4l2_subdev *sd,
+                               const struct v4l2_mbus_config *cfg)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+       if (soc_camera_apply_board_flags(icl, cfg) &
+           V4L2_MBUS_PCLK_SAMPLE_FALLING)
+               return reg_clear(client, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000);
+       else
+               return reg_set(client, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000);
+}
+
 static struct v4l2_subdev_video_ops mt9t031_subdev_video_ops = {
        .s_stream       = mt9t031_s_stream,
        .s_mbus_fmt     = mt9t031_s_fmt,
@@ -816,6 +735,8 @@ static struct v4l2_subdev_video_ops mt9t031_subdev_video_ops = {
        .g_crop         = mt9t031_g_crop,
        .cropcap        = mt9t031_cropcap,
        .enum_mbus_fmt  = mt9t031_enum_fmt,
+       .g_mbus_config  = mt9t031_g_mbus_config,
+       .s_mbus_config  = mt9t031_s_mbus_config,
 };
 
 static struct v4l2_subdev_sensor_ops mt9t031_subdev_sensor_ops = {
@@ -832,18 +753,13 @@ static int mt9t031_probe(struct i2c_client *client,
                         const struct i2c_device_id *did)
 {
        struct mt9t031 *mt9t031;
-       struct soc_camera_device *icd = client->dev.platform_data;
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
        struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
        int ret;
 
-       if (icd) {
-               struct soc_camera_link *icl = to_soc_camera_link(icd);
-               if (!icl) {
-                       dev_err(&client->dev, "MT9T031 driver needs platform data\n");
-                       return -EINVAL;
-               }
-
-               icd->ops = &mt9t031_ops;
+       if (!icl) {
+               dev_err(&client->dev, "MT9T031 driver needs platform data\n");
+               return -EINVAL;
        }
 
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) {
@@ -857,6 +773,33 @@ static int mt9t031_probe(struct i2c_client *client,
                return -ENOMEM;
 
        v4l2_i2c_subdev_init(&mt9t031->subdev, client, &mt9t031_subdev_ops);
+       v4l2_ctrl_handler_init(&mt9t031->hdl, 5);
+       v4l2_ctrl_new_std(&mt9t031->hdl, &mt9t031_ctrl_ops,
+                       V4L2_CID_VFLIP, 0, 1, 1, 0);
+       v4l2_ctrl_new_std(&mt9t031->hdl, &mt9t031_ctrl_ops,
+                       V4L2_CID_HFLIP, 0, 1, 1, 0);
+       v4l2_ctrl_new_std(&mt9t031->hdl, &mt9t031_ctrl_ops,
+                       V4L2_CID_GAIN, 0, 127, 1, 64);
+
+       /*
+        * Simulated autoexposure. If enabled, we calculate shutter width
+        * ourselves in the driver based on vertical blanking and frame width
+        */
+       mt9t031->autoexposure = v4l2_ctrl_new_std_menu(&mt9t031->hdl,
+                       &mt9t031_ctrl_ops, V4L2_CID_EXPOSURE_AUTO, 1, 0,
+                       V4L2_EXPOSURE_AUTO);
+       mt9t031->exposure = v4l2_ctrl_new_std(&mt9t031->hdl, &mt9t031_ctrl_ops,
+                       V4L2_CID_EXPOSURE, 1, 255, 1, 255);
+
+       mt9t031->subdev.ctrl_handler = &mt9t031->hdl;
+       if (mt9t031->hdl.error) {
+               int err = mt9t031->hdl.error;
+
+               kfree(mt9t031);
+               return err;
+       }
+       v4l2_ctrl_auto_cluster(2, &mt9t031->autoexposure,
+                               V4L2_EXPOSURE_MANUAL, true);
 
        mt9t031->y_skip_top     = 0;
        mt9t031->rect.left      = MT9T031_COLUMN_SKIP;
@@ -864,12 +807,6 @@ static int mt9t031_probe(struct i2c_client *client,
        mt9t031->rect.width     = MT9T031_MAX_WIDTH;
        mt9t031->rect.height    = MT9T031_MAX_HEIGHT;
 
-       /*
-        * Simulated autoexposure. If enabled, we calculate shutter width
-        * ourselves in the driver based on vertical blanking and frame width
-        */
-       mt9t031->autoexposure = 1;
-
        mt9t031->xskip = 1;
        mt9t031->yskip = 1;
 
@@ -880,8 +817,7 @@ static int mt9t031_probe(struct i2c_client *client,
        mt9t031_disable(client);
 
        if (ret) {
-               if (icd)
-                       icd->ops = NULL;
+               v4l2_ctrl_handler_free(&mt9t031->hdl);
                kfree(mt9t031);
        }
 
@@ -891,10 +827,9 @@ static int mt9t031_probe(struct i2c_client *client,
 static int mt9t031_remove(struct i2c_client *client)
 {
        struct mt9t031 *mt9t031 = to_mt9t031(client);
-       struct soc_camera_device *icd = client->dev.platform_data;
 
-       if (icd)
-               icd->ops = NULL;
+       v4l2_device_unregister_subdev(&mt9t031->subdev);
+       v4l2_ctrl_handler_free(&mt9t031->hdl);
        kfree(mt9t031);
 
        return 0;
index d2e0a50..32114a3 100644 (file)
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/v4l2-mediabus.h>
 #include <linux/videodev2.h>
 
 #include <media/mt9t112.h>
 #include <media/soc_camera.h>
-#include <media/soc_mediabus.h>
 #include <media/v4l2-chip-ident.h>
 #include <media/v4l2-common.h>
 
 /* #define EXT_CLOCK 24000000 */
 
 /************************************************************************
-
-
                        macro
-
-
 ************************************************************************/
 /*
  * frame size
 #define VAR8(id, offset) _VAR(id, offset, 0x8000)
 
 /************************************************************************
-
-
                        struct
-
-
 ************************************************************************/
-struct mt9t112_frame_size {
-       u16 width;
-       u16 height;
-};
-
 struct mt9t112_format {
        enum v4l2_mbus_pixelcode code;
        enum v4l2_colorspace colorspace;
@@ -102,21 +89,17 @@ struct mt9t112_priv {
        struct v4l2_subdev               subdev;
        struct mt9t112_camera_info      *info;
        struct i2c_client               *client;
-       struct soc_camera_device         icd;
-       struct mt9t112_frame_size        frame;
+       struct v4l2_rect                 frame;
        const struct mt9t112_format     *format;
        int                              model;
        u32                              flags;
 /* for flags */
-#define INIT_DONE  (1<<0)
+#define INIT_DONE      (1 << 0)
+#define PCLK_RISING    (1 << 1)
 };
 
 /************************************************************************
-
-
                        supported format
-
-
 ************************************************************************/
 
 static const struct mt9t112_format mt9t112_cfmts[] = {
@@ -154,11 +137,7 @@ static const struct mt9t112_format mt9t112_cfmts[] = {
 };
 
 /************************************************************************
-
-
                        general function
-
-
 ************************************************************************/
 static struct mt9t112_priv *to_mt9t112(const struct i2c_client *client)
 {
@@ -326,50 +305,47 @@ static int mt9t112_clock_info(const struct i2c_client *client, u32 ext)
        n = (n >> 8) & 0x003f;
 
        enable = ((6000 > ext) || (54000 < ext)) ? "X" : "";
-       dev_info(&client->dev, "EXTCLK          : %10u K %s\n", ext, enable);
+       dev_dbg(&client->dev, "EXTCLK          : %10u K %s\n", ext, enable);
 
        vco = 2 * m * ext / (n+1);
        enable = ((384000 > vco) || (768000 < vco)) ? "X" : "";
-       dev_info(&client->dev, "VCO             : %10u K %s\n", vco, enable);
+       dev_dbg(&client->dev, "VCO             : %10u K %s\n", vco, enable);
 
        clk = vco / (p1+1) / (p2+1);
        enable = (96000 < clk) ? "X" : "";
-       dev_info(&client->dev, "PIXCLK          : %10u K %s\n", clk, enable);
+       dev_dbg(&client->dev, "PIXCLK          : %10u K %s\n", clk, enable);
 
        clk = vco / (p3+1);
        enable = (768000 < clk) ? "X" : "";
-       dev_info(&client->dev, "MIPICLK         : %10u K %s\n", clk, enable);
+       dev_dbg(&client->dev, "MIPICLK         : %10u K %s\n", clk, enable);
 
        clk = vco / (p6+1);
        enable = (96000 < clk) ? "X" : "";
-       dev_info(&client->dev, "MCU CLK         : %10u K %s\n", clk, enable);
+       dev_dbg(&client->dev, "MCU CLK         : %10u K %s\n", clk, enable);
 
        clk = vco / (p5+1);
        enable = (54000 < clk) ? "X" : "";
-       dev_info(&client->dev, "SOC CLK         : %10u K %s\n", clk, enable);
+       dev_dbg(&client->dev, "SOC CLK         : %10u K %s\n", clk, enable);
 
        clk = vco / (p4+1);
        enable = (70000 < clk) ? "X" : "";
-       dev_info(&client->dev, "Sensor CLK      : %10u K %s\n", clk, enable);
+       dev_dbg(&client->dev, "Sensor CLK      : %10u K %s\n", clk, enable);
 
        clk = vco / (p7+1);
-       dev_info(&client->dev, "External sensor : %10u K\n", clk);
+       dev_dbg(&client->dev, "External sensor : %10u K\n", clk);
 
        clk = ext / (n+1);
        enable = ((2000 > clk) || (24000 < clk)) ? "X" : "";
-       dev_info(&client->dev, "PFD             : %10u K %s\n", clk, enable);
+       dev_dbg(&client->dev, "PFD             : %10u K %s\n", clk, enable);
 
        return 0;
 }
 #endif
 
-static void mt9t112_frame_check(u32 *width, u32 *height)
+static void mt9t112_frame_check(u32 *width, u32 *height, u32 *left, u32 *top)
 {
-       if (*width > MAX_WIDTH)
-               *width = MAX_WIDTH;
-
-       if (*height > MAX_HEIGHT)
-               *height = MAX_HEIGHT;
+       soc_camera_limit_side(left, width, 0, 0, MAX_WIDTH);
+       soc_camera_limit_side(top, height, 0, 0, MAX_HEIGHT);
 }
 
 static int mt9t112_set_a_frame_size(const struct i2c_client *client,
@@ -758,48 +734,7 @@ static int mt9t112_init_camera(const struct i2c_client *client)
 }
 
 /************************************************************************
-
-
-                       soc_camera_ops
-
-
-************************************************************************/
-static int mt9t112_set_bus_param(struct soc_camera_device *icd,
-                                unsigned long  flags)
-{
-       return 0;
-}
-
-static unsigned long mt9t112_query_bus_param(struct soc_camera_device *icd)
-{
-       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
-       struct mt9t112_priv *priv = to_mt9t112(client);
-       struct soc_camera_link *icl = to_soc_camera_link(icd);
-       unsigned long flags = SOCAM_MASTER | SOCAM_VSYNC_ACTIVE_HIGH |
-               SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_DATA_ACTIVE_HIGH;
-
-       flags |= (priv->info->flags & MT9T112_FLAG_PCLK_RISING_EDGE) ?
-               SOCAM_PCLK_SAMPLE_RISING : SOCAM_PCLK_SAMPLE_FALLING;
-
-       if (priv->info->flags & MT9T112_FLAG_DATAWIDTH_8)
-               flags |= SOCAM_DATAWIDTH_8;
-       else
-               flags |= SOCAM_DATAWIDTH_10;
-
-       return soc_camera_apply_sensor_flags(icl, flags);
-}
-
-static struct soc_camera_ops mt9t112_ops = {
-       .set_bus_param          = mt9t112_set_bus_param,
-       .query_bus_param        = mt9t112_query_bus_param,
-};
-
-/************************************************************************
-
-
                        v4l2_subdev_core_ops
-
-
 ************************************************************************/
 static int mt9t112_g_chip_ident(struct v4l2_subdev *sd,
                                struct v4l2_dbg_chip_ident *id)
@@ -850,11 +785,7 @@ static struct v4l2_subdev_core_ops mt9t112_subdev_core_ops = {
 
 
 /************************************************************************
-
-
                        v4l2_subdev_video_ops
-
-
 ************************************************************************/
 static int mt9t112_s_stream(struct v4l2_subdev *sd, int enable)
 {
@@ -877,8 +808,7 @@ static int mt9t112_s_stream(struct v4l2_subdev *sd, int enable)
        }
 
        if (!(priv->flags & INIT_DONE)) {
-               u16 param = (MT9T112_FLAG_PCLK_RISING_EDGE &
-                            priv->info->flags) ? 0x0001 : 0x0000;
+               u16 param = PCLK_RISING & priv->flags ? 0x0001 : 0x0000;
 
                ECHECKER(ret, mt9t112_init_camera(client));
 
@@ -910,19 +840,12 @@ static int mt9t112_s_stream(struct v4l2_subdev *sd, int enable)
        return ret;
 }
 
-static int mt9t112_set_params(struct i2c_client *client, u32 width, u32 height,
+static int mt9t112_set_params(struct mt9t112_priv *priv,
+                             const struct v4l2_rect *rect,
                              enum v4l2_mbus_pixelcode code)
 {
-       struct mt9t112_priv *priv = to_mt9t112(client);
        int i;
 
-       priv->format = NULL;
-
-       /*
-        * frame size check
-        */
-       mt9t112_frame_check(&width, &height);
-
        /*
         * get color format
         */
@@ -933,8 +856,13 @@ static int mt9t112_set_params(struct i2c_client *client, u32 width, u32 height,
        if (i == ARRAY_SIZE(mt9t112_cfmts))
                return -EINVAL;
 
-       priv->frame.width  = (u16)width;
-       priv->frame.height = (u16)height;
+       priv->frame  = *rect;
+
+       /*
+        * frame size check
+        */
+       mt9t112_frame_check(&priv->frame.width, &priv->frame.height,
+                           &priv->frame.left, &priv->frame.top);
 
        priv->format = mt9t112_cfmts + i;
 
@@ -945,9 +873,12 @@ static int mt9t112_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
 {
        a->bounds.left                  = 0;
        a->bounds.top                   = 0;
-       a->bounds.width                 = VGA_WIDTH;
-       a->bounds.height                = VGA_HEIGHT;
-       a->defrect                      = a->bounds;
+       a->bounds.width                 = MAX_WIDTH;
+       a->bounds.height                = MAX_HEIGHT;
+       a->defrect.left                 = 0;
+       a->defrect.top                  = 0;
+       a->defrect.width                = VGA_WIDTH;
+       a->defrect.height               = VGA_HEIGHT;
        a->type                         = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        a->pixelaspect.numerator        = 1;
        a->pixelaspect.denominator      = 1;
@@ -957,11 +888,11 @@ static int mt9t112_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
 
 static int mt9t112_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
 {
-       a->c.left       = 0;
-       a->c.top        = 0;
-       a->c.width      = VGA_WIDTH;
-       a->c.height     = VGA_HEIGHT;
-       a->type         = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct mt9t112_priv *priv = to_mt9t112(client);
+
+       a->c    = priv->frame;
+       a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
        return 0;
 }
@@ -969,10 +900,10 @@ static int mt9t112_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
 static int mt9t112_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct mt9t112_priv *priv = to_mt9t112(client);
        struct v4l2_rect *rect = &a->c;
 
-       return mt9t112_set_params(client, rect->width, rect->height,
-                                V4L2_MBUS_FMT_UYVY8_2X8);
+       return mt9t112_set_params(priv, rect, priv->format->code);
 }
 
 static int mt9t112_g_fmt(struct v4l2_subdev *sd,
@@ -981,16 +912,9 @@ static int mt9t112_g_fmt(struct v4l2_subdev *sd,
        struct i2c_client *client = v4l2_get_subdevdata(sd);
        struct mt9t112_priv *priv = to_mt9t112(client);
 
-       if (!priv->format) {
-               int ret = mt9t112_set_params(client, VGA_WIDTH, VGA_HEIGHT,
-                                            V4L2_MBUS_FMT_UYVY8_2X8);
-               if (ret < 0)
-                       return ret;
-       }
-
        mf->width       = priv->frame.width;
        mf->height      = priv->frame.height;
-       /* TODO: set colorspace */
+       mf->colorspace  = priv->format->colorspace;
        mf->code        = priv->format->code;
        mf->field       = V4L2_FIELD_NONE;
 
@@ -1001,17 +925,42 @@ static int mt9t112_s_fmt(struct v4l2_subdev *sd,
                         struct v4l2_mbus_framefmt *mf)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct mt9t112_priv *priv = to_mt9t112(client);
+       struct v4l2_rect rect = {
+               .width = mf->width,
+               .height = mf->height,
+               .left = priv->frame.left,
+               .top = priv->frame.top,
+       };
+       int ret;
+
+       ret = mt9t112_set_params(priv, &rect, mf->code);
+
+       if (!ret)
+               mf->colorspace = priv->format->colorspace;
 
-       /* TODO: set colorspace */
-       return mt9t112_set_params(client, mf->width, mf->height, mf->code);
+       return ret;
 }
 
 static int mt9t112_try_fmt(struct v4l2_subdev *sd,
                           struct v4l2_mbus_framefmt *mf)
 {
-       mt9t112_frame_check(&mf->width, &mf->height);
+       unsigned int top, left;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(mt9t112_cfmts); i++)
+               if (mt9t112_cfmts[i].code == mf->code)
+                       break;
+
+       if (i == ARRAY_SIZE(mt9t112_cfmts)) {
+               mf->code = V4L2_MBUS_FMT_UYVY8_2X8;
+               mf->colorspace = V4L2_COLORSPACE_JPEG;
+       } else {
+               mf->colorspace  = mt9t112_cfmts[i].colorspace;
+       }
+
+       mt9t112_frame_check(&mf->width, &mf->height, &left, &top);
 
-       /* TODO: set colorspace */
        mf->field = V4L2_FIELD_NONE;
 
        return 0;
@@ -1024,6 +973,35 @@ static int mt9t112_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
                return -EINVAL;
 
        *code = mt9t112_cfmts[index].code;
+
+       return 0;
+}
+
+static int mt9t112_g_mbus_config(struct v4l2_subdev *sd,
+                                struct v4l2_mbus_config *cfg)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+       cfg->flags = V4L2_MBUS_MASTER | V4L2_MBUS_VSYNC_ACTIVE_HIGH |
+               V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_DATA_ACTIVE_HIGH |
+               V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_PCLK_SAMPLE_FALLING;
+       cfg->type = V4L2_MBUS_PARALLEL;
+       cfg->flags = soc_camera_apply_board_flags(icl, cfg);
+
+       return 0;
+}
+
+static int mt9t112_s_mbus_config(struct v4l2_subdev *sd,
+                                const struct v4l2_mbus_config *cfg)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+       struct mt9t112_priv *priv = to_mt9t112(client);
+
+       if (soc_camera_apply_board_flags(icl, cfg) & V4L2_MBUS_PCLK_SAMPLE_RISING)
+               priv->flags |= PCLK_RISING;
+
        return 0;
 }
 
@@ -1036,31 +1014,24 @@ static struct v4l2_subdev_video_ops mt9t112_subdev_video_ops = {
        .g_crop         = mt9t112_g_crop,
        .s_crop         = mt9t112_s_crop,
        .enum_mbus_fmt  = mt9t112_enum_fmt,
+       .g_mbus_config  = mt9t112_g_mbus_config,
+       .s_mbus_config  = mt9t112_s_mbus_config,
 };
 
 /************************************************************************
-
-
                        i2c driver
-
-
 ************************************************************************/
 static struct v4l2_subdev_ops mt9t112_subdev_ops = {
        .core   = &mt9t112_subdev_core_ops,
        .video  = &mt9t112_subdev_video_ops,
 };
 
-static int mt9t112_camera_probe(struct soc_camera_device *icd,
-                               struct i2c_client *client)
+static int mt9t112_camera_probe(struct i2c_client *client)
 {
        struct mt9t112_priv *priv = to_mt9t112(client);
        const char          *devname;
        int                  chipid;
 
-       /* We must have a parent by now. And it cannot be a wrong one. */
-       BUG_ON(!icd->parent ||
-              to_soc_camera_host(icd->parent)->nr != icd->iface);
-
        /*
         * check and show chip ID
         */
@@ -1088,20 +1059,21 @@ static int mt9t112_camera_probe(struct soc_camera_device *icd,
 static int mt9t112_probe(struct i2c_client *client,
                         const struct i2c_device_id *did)
 {
-       struct mt9t112_priv        *priv;
-       struct soc_camera_device   *icd = client->dev.platform_data;
-       struct soc_camera_link     *icl;
-       int                         ret;
+       struct mt9t112_priv *priv;
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+       struct v4l2_rect rect = {
+               .width = VGA_WIDTH,
+               .height = VGA_HEIGHT,
+               .left = (MAX_WIDTH - VGA_WIDTH) / 2,
+               .top = (MAX_HEIGHT - VGA_HEIGHT) / 2,
+       };
+       int ret;
 
-       if (!icd) {
-               dev_err(&client->dev, "mt9t112: missing soc-camera data!\n");
+       if (!icl || !icl->priv) {
+               dev_err(&client->dev, "mt9t112: missing platform data!\n");
                return -EINVAL;
        }
 
-       icl = to_soc_camera_link(icd);
-       if (!icl || !icl->priv)
-               return -EINVAL;
-
        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
        if (!priv)
                return -ENOMEM;
@@ -1110,13 +1082,12 @@ static int mt9t112_probe(struct i2c_client *client,
 
        v4l2_i2c_subdev_init(&priv->subdev, client, &mt9t112_subdev_ops);
 
-       icd->ops = &mt9t112_ops;
-
-       ret = mt9t112_camera_probe(icd, client);
-       if (ret) {
-               icd->ops = NULL;
+       ret = mt9t112_camera_probe(client);
+       if (ret)
                kfree(priv);
-       }
+
+       /* Cannot fail: using the default supported pixel code */
+       mt9t112_set_params(priv, &rect, V4L2_MBUS_FMT_UYVY8_2X8);
 
        return ret;
 }
@@ -1124,9 +1095,7 @@ static int mt9t112_probe(struct i2c_client *client,
 static int mt9t112_remove(struct i2c_client *client)
 {
        struct mt9t112_priv *priv = to_mt9t112(client);
-       struct soc_camera_device *icd = client->dev.platform_data;
 
-       icd->ops = NULL;
        kfree(priv);
        return 0;
 }
@@ -1147,11 +1116,7 @@ static struct i2c_driver mt9t112_i2c_driver = {
 };
 
 /************************************************************************
-
-
                        module function
-
-
 ************************************************************************/
 static int __init mt9t112_module_init(void)
 {
index 51b0fcc..b6a29f7 100644 (file)
 #include <linux/delay.h>
 #include <linux/log2.h>
 
+#include <media/soc_camera.h>
+#include <media/soc_mediabus.h>
 #include <media/v4l2-subdev.h>
 #include <media/v4l2-chip-ident.h>
-#include <media/soc_camera.h>
+#include <media/v4l2-ctrls.h>
 
 /*
  * mt9v022 i2c address 0x48, 0x4c, 0x58, 0x5c
@@ -100,6 +102,17 @@ static const struct mt9v022_datafmt mt9v022_monochrome_fmts[] = {
 
 struct mt9v022 {
        struct v4l2_subdev subdev;
+       struct v4l2_ctrl_handler hdl;
+       struct {
+               /* exposure/auto-exposure cluster */
+               struct v4l2_ctrl *autoexposure;
+               struct v4l2_ctrl *exposure;
+       };
+       struct {
+               /* gain/auto-gain cluster */
+               struct v4l2_ctrl *autogain;
+               struct v4l2_ctrl *gain;
+       };
        struct v4l2_rect rect;  /* Sensor window */
        const struct mt9v022_datafmt *fmt;
        const struct mt9v022_datafmt *fmts;
@@ -178,6 +191,8 @@ static int mt9v022_init(struct i2c_client *client)
                ret = reg_clear(client, MT9V022_BLACK_LEVEL_CALIB_CTRL, 1);
        if (!ret)
                ret = reg_write(client, MT9V022_DIGITAL_TEST_PATTERN, 0);
+       if (!ret)
+               return v4l2_ctrl_handler_setup(&mt9v022->hdl);
 
        return ret;
 }
@@ -199,78 +214,6 @@ static int mt9v022_s_stream(struct v4l2_subdev *sd, int enable)
        return 0;
 }
 
-static int mt9v022_set_bus_param(struct soc_camera_device *icd,
-                                unsigned long flags)
-{
-       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
-       struct mt9v022 *mt9v022 = to_mt9v022(client);
-       struct soc_camera_link *icl = to_soc_camera_link(icd);
-       unsigned int width_flag = flags & SOCAM_DATAWIDTH_MASK;
-       int ret;
-       u16 pixclk = 0;
-
-       /* Only one width bit may be set */
-       if (!is_power_of_2(width_flag))
-               return -EINVAL;
-
-       if (icl->set_bus_param) {
-               ret = icl->set_bus_param(icl, width_flag);
-               if (ret)
-                       return ret;
-       } else {
-               /*
-                * Without board specific bus width settings we only support the
-                * sensors native bus width
-                */
-               if (width_flag != SOCAM_DATAWIDTH_10)
-                       return -EINVAL;
-       }
-
-       flags = soc_camera_apply_sensor_flags(icl, flags);
-
-       if (flags & SOCAM_PCLK_SAMPLE_FALLING)
-               pixclk |= 0x10;
-
-       if (!(flags & SOCAM_HSYNC_ACTIVE_HIGH))
-               pixclk |= 0x1;
-
-       if (!(flags & SOCAM_VSYNC_ACTIVE_HIGH))
-               pixclk |= 0x2;
-
-       ret = reg_write(client, MT9V022_PIXCLK_FV_LV, pixclk);
-       if (ret < 0)
-               return ret;
-
-       if (!(flags & SOCAM_MASTER))
-               mt9v022->chip_control &= ~0x8;
-
-       ret = reg_write(client, MT9V022_CHIP_CONTROL, mt9v022->chip_control);
-       if (ret < 0)
-               return ret;
-
-       dev_dbg(&client->dev, "Calculated pixclk 0x%x, chip control 0x%x\n",
-               pixclk, mt9v022->chip_control);
-
-       return 0;
-}
-
-static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd)
-{
-       struct soc_camera_link *icl = to_soc_camera_link(icd);
-       unsigned int flags = SOCAM_MASTER | SOCAM_SLAVE |
-               SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING |
-               SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_LOW |
-               SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW |
-               SOCAM_DATA_ACTIVE_HIGH;
-
-       if (icl->query_bus_param)
-               flags |= icl->query_bus_param(icl) & SOCAM_DATAWIDTH_MASK;
-       else
-               flags |= SOCAM_DATAWIDTH_10;
-
-       return soc_camera_apply_sensor_flags(icl, flags);
-}
-
 static int mt9v022_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
@@ -389,7 +332,7 @@ static int mt9v022_s_fmt(struct v4l2_subdev *sd,
 
        /*
         * The caller provides a supported format, as verified per call to
-        * icd->try_fmt(), datawidth is from our supported format list
+        * .try_mbus_fmt(), datawidth is from our supported format list
         */
        switch (mf->code) {
        case V4L2_MBUS_FMT_Y8_1X8:
@@ -502,236 +445,131 @@ static int mt9v022_s_register(struct v4l2_subdev *sd,
 }
 #endif
 
-static const struct v4l2_queryctrl mt9v022_controls[] = {
-       {
-               .id             = V4L2_CID_VFLIP,
-               .type           = V4L2_CTRL_TYPE_BOOLEAN,
-               .name           = "Flip Vertically",
-               .minimum        = 0,
-               .maximum        = 1,
-               .step           = 1,
-               .default_value  = 0,
-       }, {
-               .id             = V4L2_CID_HFLIP,
-               .type           = V4L2_CTRL_TYPE_BOOLEAN,
-               .name           = "Flip Horizontally",
-               .minimum        = 0,
-               .maximum        = 1,
-               .step           = 1,
-               .default_value  = 0,
-       }, {
-               .id             = V4L2_CID_GAIN,
-               .type           = V4L2_CTRL_TYPE_INTEGER,
-               .name           = "Analog Gain",
-               .minimum        = 64,
-               .maximum        = 127,
-               .step           = 1,
-               .default_value  = 64,
-               .flags          = V4L2_CTRL_FLAG_SLIDER,
-       }, {
-               .id             = V4L2_CID_EXPOSURE,
-               .type           = V4L2_CTRL_TYPE_INTEGER,
-               .name           = "Exposure",
-               .minimum        = 1,
-               .maximum        = 255,
-               .step           = 1,
-               .default_value  = 255,
-               .flags          = V4L2_CTRL_FLAG_SLIDER,
-       }, {
-               .id             = V4L2_CID_AUTOGAIN,
-               .type           = V4L2_CTRL_TYPE_BOOLEAN,
-               .name           = "Automatic Gain",
-               .minimum        = 0,
-               .maximum        = 1,
-               .step           = 1,
-               .default_value  = 1,
-       }, {
-               .id             = V4L2_CID_EXPOSURE_AUTO,
-               .type           = V4L2_CTRL_TYPE_BOOLEAN,
-               .name           = "Automatic Exposure",
-               .minimum        = 0,
-               .maximum        = 1,
-               .step           = 1,
-               .default_value  = 1,
-       }
-};
-
-static struct soc_camera_ops mt9v022_ops = {
-       .set_bus_param          = mt9v022_set_bus_param,
-       .query_bus_param        = mt9v022_query_bus_param,
-       .controls               = mt9v022_controls,
-       .num_controls           = ARRAY_SIZE(mt9v022_controls),
-};
-
-static int mt9v022_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+static int mt9v022_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
 {
+       struct mt9v022 *mt9v022 = container_of(ctrl->handler,
+                                              struct mt9v022, hdl);
+       struct v4l2_subdev *sd = &mt9v022->subdev;
        struct i2c_client *client = v4l2_get_subdevdata(sd);
-       const struct v4l2_queryctrl *qctrl;
+       struct v4l2_ctrl *gain = mt9v022->gain;
+       struct v4l2_ctrl *exp = mt9v022->exposure;
        unsigned long range;
        int data;
 
-       qctrl = soc_camera_find_qctrl(&mt9v022_ops, ctrl->id);
-
        switch (ctrl->id) {
-       case V4L2_CID_VFLIP:
-               data = reg_read(client, MT9V022_READ_MODE);
-               if (data < 0)
-                       return -EIO;
-               ctrl->value = !!(data & 0x10);
-               break;
-       case V4L2_CID_HFLIP:
-               data = reg_read(client, MT9V022_READ_MODE);
-               if (data < 0)
-                       return -EIO;
-               ctrl->value = !!(data & 0x20);
-               break;
-       case V4L2_CID_EXPOSURE_AUTO:
-               data = reg_read(client, MT9V022_AEC_AGC_ENABLE);
-               if (data < 0)
-                       return -EIO;
-               ctrl->value = !!(data & 0x1);
-               break;
        case V4L2_CID_AUTOGAIN:
-               data = reg_read(client, MT9V022_AEC_AGC_ENABLE);
-               if (data < 0)
-                       return -EIO;
-               ctrl->value = !!(data & 0x2);
-               break;
-       case V4L2_CID_GAIN:
                data = reg_read(client, MT9V022_ANALOG_GAIN);
                if (data < 0)
                        return -EIO;
 
-               range = qctrl->maximum - qctrl->minimum;
-               ctrl->value = ((data - 16) * range + 24) / 48 + qctrl->minimum;
-
-               break;
-       case V4L2_CID_EXPOSURE:
+               range = gain->maximum - gain->minimum;
+               gain->val = ((data - 16) * range + 24) / 48 + gain->minimum;
+               return 0;
+       case V4L2_CID_EXPOSURE_AUTO:
                data = reg_read(client, MT9V022_TOTAL_SHUTTER_WIDTH);
                if (data < 0)
                        return -EIO;
 
-               range = qctrl->maximum - qctrl->minimum;
-               ctrl->value = ((data - 1) * range + 239) / 479 + qctrl->minimum;
-
-               break;
+               range = exp->maximum - exp->minimum;
+               exp->val = ((data - 1) * range + 239) / 479 + exp->minimum;
+               return 0;
        }
-       return 0;
+       return -EINVAL;
 }
 
-static int mt9v022_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+static int mt9v022_s_ctrl(struct v4l2_ctrl *ctrl)
 {
-       int data;
+       struct mt9v022 *mt9v022 = container_of(ctrl->handler,
+                                              struct mt9v022, hdl);
+       struct v4l2_subdev *sd = &mt9v022->subdev;
        struct i2c_client *client = v4l2_get_subdevdata(sd);
-       const struct v4l2_queryctrl *qctrl;
-
-       qctrl = soc_camera_find_qctrl(&mt9v022_ops, ctrl->id);
-       if (!qctrl)
-               return -EINVAL;
+       int data;
 
        switch (ctrl->id) {
        case V4L2_CID_VFLIP:
-               if (ctrl->value)
+               if (ctrl->val)
                        data = reg_set(client, MT9V022_READ_MODE, 0x10);
                else
                        data = reg_clear(client, MT9V022_READ_MODE, 0x10);
                if (data < 0)
                        return -EIO;
-               break;
+               return 0;
        case V4L2_CID_HFLIP:
-               if (ctrl->value)
+               if (ctrl->val)
                        data = reg_set(client, MT9V022_READ_MODE, 0x20);
                else
                        data = reg_clear(client, MT9V022_READ_MODE, 0x20);
                if (data < 0)
                        return -EIO;
-               break;
-       case V4L2_CID_GAIN:
-               /* mt9v022 has minimum == default */
-               if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum)
-                       return -EINVAL;
-               else {
-                       unsigned long range = qctrl->maximum - qctrl->minimum;
+               return 0;
+       case V4L2_CID_AUTOGAIN:
+               if (ctrl->val) {
+                       if (reg_set(client, MT9V022_AEC_AGC_ENABLE, 0x2) < 0)
+                               return -EIO;
+               } else {
+                       struct v4l2_ctrl *gain = mt9v022->gain;
+                       /* mt9v022 has minimum == default */
+                       unsigned long range = gain->maximum - gain->minimum;
                        /* Valid values 16 to 64, 32 to 64 must be even. */
-                       unsigned long gain = ((ctrl->value - qctrl->minimum) *
+                       unsigned long gain_val = ((gain->val - gain->minimum) *
                                              48 + range / 2) / range + 16;
-                       if (gain >= 32)
-                               gain &= ~1;
+
+                       if (gain_val >= 32)
+                               gain_val &= ~1;
+
                        /*
                         * The user wants to set gain manually, hope, she
                         * knows, what she's doing... Switch AGC off.
                         */
-
                        if (reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x2) < 0)
                                return -EIO;
 
                        dev_dbg(&client->dev, "Setting gain from %d to %lu\n",
-                               reg_read(client, MT9V022_ANALOG_GAIN), gain);
-                       if (reg_write(client, MT9V022_ANALOG_GAIN, gain) < 0)
+                               reg_read(client, MT9V022_ANALOG_GAIN), gain_val);
+                       if (reg_write(client, MT9V022_ANALOG_GAIN, gain_val) < 0)
                                return -EIO;
                }
-               break;
-       case V4L2_CID_EXPOSURE:
-               /* mt9v022 has maximum == default */
-               if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum)
-                       return -EINVAL;
-               else {
-                       unsigned long range = qctrl->maximum - qctrl->minimum;
-                       unsigned long shutter = ((ctrl->value - qctrl->minimum) *
-                                                479 + range / 2) / range + 1;
+               return 0;
+       case V4L2_CID_EXPOSURE_AUTO:
+               if (ctrl->val == V4L2_EXPOSURE_AUTO) {
+                       data = reg_set(client, MT9V022_AEC_AGC_ENABLE, 0x1);
+               } else {
+                       struct v4l2_ctrl *exp = mt9v022->exposure;
+                       unsigned long range = exp->maximum - exp->minimum;
+                       unsigned long shutter = ((exp->val - exp->minimum) *
+                                       479 + range / 2) / range + 1;
+
                        /*
                         * The user wants to set shutter width manually, hope,
                         * she knows, what she's doing... Switch AEC off.
                         */
-
-                       if (reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x1) < 0)
+                       data = reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x1);
+                       if (data < 0)
                                return -EIO;
-
                        dev_dbg(&client->dev, "Shutter width from %d to %lu\n",
-                               reg_read(client, MT9V022_TOTAL_SHUTTER_WIDTH),
-                               shutter);
+                                       reg_read(client, MT9V022_TOTAL_SHUTTER_WIDTH),
+                                       shutter);
                        if (reg_write(client, MT9V022_TOTAL_SHUTTER_WIDTH,
-                                     shutter) < 0)
+                                               shutter) < 0)
                                return -EIO;
                }
-               break;
-       case V4L2_CID_AUTOGAIN:
-               if (ctrl->value)
-                       data = reg_set(client, MT9V022_AEC_AGC_ENABLE, 0x2);
-               else
-                       data = reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x2);
-               if (data < 0)
-                       return -EIO;
-               break;
-       case V4L2_CID_EXPOSURE_AUTO:
-               if (ctrl->value)
-                       data = reg_set(client, MT9V022_AEC_AGC_ENABLE, 0x1);
-               else
-                       data = reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x1);
-               if (data < 0)
-                       return -EIO;
-               break;
+               return 0;
        }
-       return 0;
+       return -EINVAL;
 }
 
 /*
  * Interface active, can use i2c. If it fails, it can indeed mean, that
  * this wasn't our capture interface, so, we wait for the right one
  */
-static int mt9v022_video_probe(struct soc_camera_device *icd,
-                              struct i2c_client *client)
+static int mt9v022_video_probe(struct i2c_client *client)
 {
        struct mt9v022 *mt9v022 = to_mt9v022(client);
-       struct soc_camera_link *icl = to_soc_camera_link(icd);
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
        s32 data;
        int ret;
        unsigned long flags;
 
-       /* We must have a parent by now. And it cannot be a wrong one. */
-       BUG_ON(!icd->parent ||
-              to_soc_camera_host(icd->parent)->nr != icd->iface);
-
        /* Read out the chip version register */
        data = reg_read(client, MT9V022_CHIP_VERSION);
 
@@ -805,16 +643,6 @@ ei2c:
        return ret;
 }
 
-static void mt9v022_video_remove(struct soc_camera_device *icd)
-{
-       struct soc_camera_link *icl = to_soc_camera_link(icd);
-
-       dev_dbg(icd->pdev, "Video removed: %p, %p\n",
-               icd->parent, icd->vdev);
-       if (icl->free_bus)
-               icl->free_bus(icl);
-}
-
 static int mt9v022_g_skip_top_lines(struct v4l2_subdev *sd, u32 *lines)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
@@ -825,9 +653,12 @@ static int mt9v022_g_skip_top_lines(struct v4l2_subdev *sd, u32 *lines)
        return 0;
 }
 
+static const struct v4l2_ctrl_ops mt9v022_ctrl_ops = {
+       .g_volatile_ctrl = mt9v022_g_volatile_ctrl,
+       .s_ctrl = mt9v022_s_ctrl,
+};
+
 static struct v4l2_subdev_core_ops mt9v022_subdev_core_ops = {
-       .g_ctrl         = mt9v022_g_ctrl,
-       .s_ctrl         = mt9v022_s_ctrl,
        .g_chip_ident   = mt9v022_g_chip_ident,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
        .g_register     = mt9v022_g_register,
@@ -848,6 +679,72 @@ static int mt9v022_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
        return 0;
 }
 
+static int mt9v022_g_mbus_config(struct v4l2_subdev *sd,
+                               struct v4l2_mbus_config *cfg)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+       cfg->flags = V4L2_MBUS_MASTER | V4L2_MBUS_SLAVE |
+               V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_PCLK_SAMPLE_FALLING |
+               V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_LOW |
+               V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_LOW |
+               V4L2_MBUS_DATA_ACTIVE_HIGH;
+       cfg->type = V4L2_MBUS_PARALLEL;
+       cfg->flags = soc_camera_apply_board_flags(icl, cfg);
+
+       return 0;
+}
+
+static int mt9v022_s_mbus_config(struct v4l2_subdev *sd,
+                                const struct v4l2_mbus_config *cfg)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+       struct mt9v022 *mt9v022 = to_mt9v022(client);
+       unsigned long flags = soc_camera_apply_board_flags(icl, cfg);
+       unsigned int bps = soc_mbus_get_fmtdesc(mt9v022->fmt->code)->bits_per_sample;
+       int ret;
+       u16 pixclk = 0;
+
+       if (icl->set_bus_param) {
+               ret = icl->set_bus_param(icl, 1 << (bps - 1));
+               if (ret)
+                       return ret;
+       } else if (bps != 10) {
+               /*
+                * Without board specific bus width settings we only support the
+                * sensors native bus width
+                */
+               return -EINVAL;
+       }
+
+       if (flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
+               pixclk |= 0x10;
+
+       if (!(flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH))
+               pixclk |= 0x1;
+
+       if (!(flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH))
+               pixclk |= 0x2;
+
+       ret = reg_write(client, MT9V022_PIXCLK_FV_LV, pixclk);
+       if (ret < 0)
+               return ret;
+
+       if (!(flags & V4L2_MBUS_MASTER))
+               mt9v022->chip_control &= ~0x8;
+
+       ret = reg_write(client, MT9V022_CHIP_CONTROL, mt9v022->chip_control);
+       if (ret < 0)
+               return ret;
+
+       dev_dbg(&client->dev, "Calculated pixclk 0x%x, chip control 0x%x\n",
+               pixclk, mt9v022->chip_control);
+
+       return 0;
+}
+
 static struct v4l2_subdev_video_ops mt9v022_subdev_video_ops = {
        .s_stream       = mt9v022_s_stream,
        .s_mbus_fmt     = mt9v022_s_fmt,
@@ -857,6 +754,8 @@ static struct v4l2_subdev_video_ops mt9v022_subdev_video_ops = {
        .g_crop         = mt9v022_g_crop,
        .cropcap        = mt9v022_cropcap,
        .enum_mbus_fmt  = mt9v022_enum_fmt,
+       .g_mbus_config  = mt9v022_g_mbus_config,
+       .s_mbus_config  = mt9v022_s_mbus_config,
 };
 
 static struct v4l2_subdev_sensor_ops mt9v022_subdev_sensor_ops = {
@@ -873,17 +772,10 @@ static int mt9v022_probe(struct i2c_client *client,
                         const struct i2c_device_id *did)
 {
        struct mt9v022 *mt9v022;
-       struct soc_camera_device *icd = client->dev.platform_data;
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
        struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
-       struct soc_camera_link *icl;
        int ret;
 
-       if (!icd) {
-               dev_err(&client->dev, "MT9V022: missing soc-camera data!\n");
-               return -EINVAL;
-       }
-
-       icl = to_soc_camera_link(icd);
        if (!icl) {
                dev_err(&client->dev, "MT9V022 driver needs platform data\n");
                return -EINVAL;
@@ -900,10 +792,39 @@ static int mt9v022_probe(struct i2c_client *client,
                return -ENOMEM;
 
        v4l2_i2c_subdev_init(&mt9v022->subdev, client, &mt9v022_subdev_ops);
+       v4l2_ctrl_handler_init(&mt9v022->hdl, 6);
+       v4l2_ctrl_new_std(&mt9v022->hdl, &mt9v022_ctrl_ops,
+                       V4L2_CID_VFLIP, 0, 1, 1, 0);
+       v4l2_ctrl_new_std(&mt9v022->hdl, &mt9v022_ctrl_ops,
+                       V4L2_CID_HFLIP, 0, 1, 1, 0);
+       mt9v022->autogain = v4l2_ctrl_new_std(&mt9v022->hdl, &mt9v022_ctrl_ops,
+                       V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
+       mt9v022->gain = v4l2_ctrl_new_std(&mt9v022->hdl, &mt9v022_ctrl_ops,
+                       V4L2_CID_GAIN, 0, 127, 1, 64);
+
+       /*
+        * Simulated autoexposure. If enabled, we calculate shutter width
+        * ourselves in the driver based on vertical blanking and frame width
+        */
+       mt9v022->autoexposure = v4l2_ctrl_new_std_menu(&mt9v022->hdl,
+                       &mt9v022_ctrl_ops, V4L2_CID_EXPOSURE_AUTO, 1, 0,
+                       V4L2_EXPOSURE_AUTO);
+       mt9v022->exposure = v4l2_ctrl_new_std(&mt9v022->hdl, &mt9v022_ctrl_ops,
+                       V4L2_CID_EXPOSURE, 1, 255, 1, 255);
+
+       mt9v022->subdev.ctrl_handler = &mt9v022->hdl;
+       if (mt9v022->hdl.error) {
+               int err = mt9v022->hdl.error;
+
+               kfree(mt9v022);
+               return err;
+       }
+       v4l2_ctrl_auto_cluster(2, &mt9v022->autoexposure,
+                               V4L2_EXPOSURE_MANUAL, true);
+       v4l2_ctrl_auto_cluster(2, &mt9v022->autogain, 0, true);
 
        mt9v022->chip_control = MT9V022_CHIP_CONTROL_DEFAULT;
 
-       icd->ops                = &mt9v022_ops;
        /*
         * MT9V022 _really_ corrupts the first read out line.
         * TODO: verify on i.MX31
@@ -914,9 +835,9 @@ static int mt9v022_probe(struct i2c_client *client,
        mt9v022->rect.width     = MT9V022_MAX_WIDTH;
        mt9v022->rect.height    = MT9V022_MAX_HEIGHT;
 
-       ret = mt9v022_video_probe(icd, client);
+       ret = mt9v022_video_probe(client);
        if (ret) {
-               icd->ops = NULL;
+               v4l2_ctrl_handler_free(&mt9v022->hdl);
                kfree(mt9v022);
        }
 
@@ -926,10 +847,12 @@ static int mt9v022_probe(struct i2c_client *client,
 static int mt9v022_remove(struct i2c_client *client)
 {
        struct mt9v022 *mt9v022 = to_mt9v022(client);
-       struct soc_camera_device *icd = client->dev.platform_data;
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
 
-       icd->ops = NULL;
-       mt9v022_video_remove(icd);
+       v4l2_device_unregister_subdev(&mt9v022->subdev);
+       if (icl->free_bus)
+               icl->free_bus(icl);
+       v4l2_ctrl_handler_free(&mt9v022->hdl);
        kfree(mt9v022);
 
        return 0;
index 087db12..18e94c7 100644 (file)
 #define CSI_IRQ_MASK   (CSISR_SFF_OR_INT | CSISR_RFF_OR_INT | \
                        CSISR_STATFF_INT | CSISR_RXFF_INT | CSISR_SOF_INT)
 
-#define CSI_BUS_FLAGS  (SOCAM_MASTER | SOCAM_HSYNC_ACTIVE_HIGH | \
-                       SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW | \
-                       SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING | \
-                       SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATA_ACTIVE_LOW | \
-                       SOCAM_DATAWIDTH_8)
+#define CSI_BUS_FLAGS  (V4L2_MBUS_MASTER | V4L2_MBUS_HSYNC_ACTIVE_HIGH | \
+                       V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_LOW | \
+                       V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_PCLK_SAMPLE_FALLING | \
+                       V4L2_MBUS_DATA_ACTIVE_HIGH | V4L2_MBUS_DATA_ACTIVE_LOW)
 
 #define MAX_VIDEO_MEM 16       /* Video memory limit in megabytes */
 
@@ -490,59 +489,73 @@ static int mx1_camera_set_crop(struct soc_camera_device *icd,
 
 static int mx1_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
 {
+       struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
        struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct mx1_camera_dev *pcdev = ici->priv;
-       unsigned long camera_flags, common_flags;
+       struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
+       unsigned long common_flags;
        unsigned int csicr1;
        int ret;
 
-       camera_flags = icd->ops->query_bus_param(icd);
-
        /* MX1 supports only 8bit buswidth */
-       common_flags = soc_camera_bus_param_compatible(camera_flags,
-                                                      CSI_BUS_FLAGS);
-       if (!common_flags)
-               return -EINVAL;
+       ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
+       if (!ret) {
+               common_flags = soc_mbus_config_compatible(&cfg, CSI_BUS_FLAGS);
+               if (!common_flags) {
+                       dev_warn(icd->parent,
+                                "Flags incompatible: camera 0x%x, host 0x%x\n",
+                                cfg.flags, CSI_BUS_FLAGS);
+                       return -EINVAL;
+               }
+       } else if (ret != -ENOIOCTLCMD) {
+               return ret;
+       } else {
+               common_flags = CSI_BUS_FLAGS;
+       }
 
        /* Make choises, based on platform choice */
-       if ((common_flags & SOCAM_VSYNC_ACTIVE_HIGH) &&
-               (common_flags & SOCAM_VSYNC_ACTIVE_LOW)) {
+       if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) &&
+               (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) {
                        if (!pcdev->pdata ||
                             pcdev->pdata->flags & MX1_CAMERA_VSYNC_HIGH)
-                               common_flags &= ~SOCAM_VSYNC_ACTIVE_LOW;
+                               common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW;
                        else
-                               common_flags &= ~SOCAM_VSYNC_ACTIVE_HIGH;
+                               common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH;
        }
 
-       if ((common_flags & SOCAM_PCLK_SAMPLE_RISING) &&
-               (common_flags & SOCAM_PCLK_SAMPLE_FALLING)) {
+       if ((common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) &&
+               (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)) {
                        if (!pcdev->pdata ||
                             pcdev->pdata->flags & MX1_CAMERA_PCLK_RISING)
-                               common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING;
+                               common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_FALLING;
                        else
-                               common_flags &= ~SOCAM_PCLK_SAMPLE_RISING;
+                               common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_RISING;
        }
 
-       if ((common_flags & SOCAM_DATA_ACTIVE_HIGH) &&
-               (common_flags & SOCAM_DATA_ACTIVE_LOW)) {
+       if ((common_flags & V4L2_MBUS_DATA_ACTIVE_HIGH) &&
+               (common_flags & V4L2_MBUS_DATA_ACTIVE_LOW)) {
                        if (!pcdev->pdata ||
                             pcdev->pdata->flags & MX1_CAMERA_DATA_HIGH)
-                               common_flags &= ~SOCAM_DATA_ACTIVE_LOW;
+                               common_flags &= ~V4L2_MBUS_DATA_ACTIVE_LOW;
                        else
-                               common_flags &= ~SOCAM_DATA_ACTIVE_HIGH;
+                               common_flags &= ~V4L2_MBUS_DATA_ACTIVE_HIGH;
        }
 
-       ret = icd->ops->set_bus_param(icd, common_flags);
-       if (ret < 0)
+       cfg.flags = common_flags;
+       ret = v4l2_subdev_call(sd, video, s_mbus_config, &cfg);
+       if (ret < 0 && ret != -ENOIOCTLCMD) {
+               dev_dbg(icd->parent, "camera s_mbus_config(0x%lx) returned %d\n",
+                       common_flags, ret);
                return ret;
+       }
 
        csicr1 = __raw_readl(pcdev->base + CSICR1);
 
-       if (common_flags & SOCAM_PCLK_SAMPLE_RISING)
+       if (common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING)
                csicr1 |= CSICR1_REDGE;
-       if (common_flags & SOCAM_VSYNC_ACTIVE_HIGH)
+       if (common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH)
                csicr1 |= CSICR1_SOF_POL;
-       if (common_flags & SOCAM_DATA_ACTIVE_LOW)
+       if (common_flags & V4L2_MBUS_DATA_ACTIVE_LOW)
                csicr1 |= CSICR1_DATA_POL;
 
        __raw_writel(csicr1, pcdev->base + CSICR1);
index ec2410c..a803d9e 100644 (file)
@@ -686,16 +686,15 @@ static void mx2_camera_init_videobuf(struct videobuf_queue *q,
                        icd, &icd->video_lock);
 }
 
-#define MX2_BUS_FLAGS  (SOCAM_DATAWIDTH_8 | \
-                       SOCAM_MASTER | \
-                       SOCAM_VSYNC_ACTIVE_HIGH | \
-                       SOCAM_VSYNC_ACTIVE_LOW | \
-                       SOCAM_HSYNC_ACTIVE_HIGH | \
-                       SOCAM_HSYNC_ACTIVE_LOW | \
-                       SOCAM_PCLK_SAMPLE_RISING | \
-                       SOCAM_PCLK_SAMPLE_FALLING | \
-                       SOCAM_DATA_ACTIVE_HIGH | \
-                       SOCAM_DATA_ACTIVE_LOW)
+#define MX2_BUS_FLAGS  (V4L2_MBUS_MASTER | \
+                       V4L2_MBUS_VSYNC_ACTIVE_HIGH | \
+                       V4L2_MBUS_VSYNC_ACTIVE_LOW | \
+                       V4L2_MBUS_HSYNC_ACTIVE_HIGH | \
+                       V4L2_MBUS_HSYNC_ACTIVE_LOW | \
+                       V4L2_MBUS_PCLK_SAMPLE_RISING | \
+                       V4L2_MBUS_PCLK_SAMPLE_FALLING | \
+                       V4L2_MBUS_DATA_ACTIVE_HIGH | \
+                       V4L2_MBUS_DATA_ACTIVE_LOW)
 
 static int mx27_camera_emma_prp_reset(struct mx2_camera_dev *pcdev)
 {
@@ -770,46 +769,59 @@ static void mx27_camera_emma_buf_init(struct soc_camera_device *icd,
 static int mx2_camera_set_bus_param(struct soc_camera_device *icd,
                __u32 pixfmt)
 {
-       struct soc_camera_host *ici =
-               to_soc_camera_host(icd->parent);
+       struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct mx2_camera_dev *pcdev = ici->priv;
-       unsigned long camera_flags, common_flags;
-       int ret = 0;
+       struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
+       unsigned long common_flags;
+       int ret;
        int bytesperline;
        u32 csicr1 = pcdev->csicr1;
 
-       camera_flags = icd->ops->query_bus_param(icd);
-
-       common_flags = soc_camera_bus_param_compatible(camera_flags,
-                               MX2_BUS_FLAGS);
-       if (!common_flags)
-               return -EINVAL;
+       ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
+       if (!ret) {
+               common_flags = soc_mbus_config_compatible(&cfg, MX2_BUS_FLAGS);
+               if (!common_flags) {
+                       dev_warn(icd->parent,
+                                "Flags incompatible: camera 0x%x, host 0x%x\n",
+                                cfg.flags, MX2_BUS_FLAGS);
+                       return -EINVAL;
+               }
+       } else if (ret != -ENOIOCTLCMD) {
+               return ret;
+       } else {
+               common_flags = MX2_BUS_FLAGS;
+       }
 
-       if ((common_flags & SOCAM_HSYNC_ACTIVE_HIGH) &&
-           (common_flags & SOCAM_HSYNC_ACTIVE_LOW)) {
+       if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) &&
+           (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) {
                if (pcdev->platform_flags & MX2_CAMERA_HSYNC_HIGH)
-                       common_flags &= ~SOCAM_HSYNC_ACTIVE_LOW;
+                       common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW;
                else
-                       common_flags &= ~SOCAM_HSYNC_ACTIVE_HIGH;
+                       common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH;
        }
 
-       if ((common_flags & SOCAM_PCLK_SAMPLE_RISING) &&
-           (common_flags & SOCAM_PCLK_SAMPLE_FALLING)) {
+       if ((common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) &&
+           (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)) {
                if (pcdev->platform_flags & MX2_CAMERA_PCLK_SAMPLE_RISING)
-                       common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING;
+                       common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_FALLING;
                else
-                       common_flags &= ~SOCAM_PCLK_SAMPLE_RISING;
+                       common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_RISING;
        }
 
-       ret = icd->ops->set_bus_param(icd, common_flags);
-       if (ret < 0)
+       cfg.flags = common_flags;
+       ret = v4l2_subdev_call(sd, video, s_mbus_config, &cfg);
+       if (ret < 0 && ret != -ENOIOCTLCMD) {
+               dev_dbg(icd->parent, "camera s_mbus_config(0x%lx) returned %d\n",
+                       common_flags, ret);
                return ret;
+       }
 
-       if (common_flags & SOCAM_PCLK_SAMPLE_RISING)
+       if (common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING)
                csicr1 |= CSICR1_REDGE;
-       if (common_flags & SOCAM_VSYNC_ACTIVE_HIGH)
+       if (common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH)
                csicr1 |= CSICR1_SOF_POL;
-       if (common_flags & SOCAM_HSYNC_ACTIVE_HIGH)
+       if (common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH)
                csicr1 |= CSICR1_HSYNC_POL;
        if (pcdev->platform_flags & MX2_CAMERA_SWAP16)
                csicr1 |= CSICR1_SWAP16_EN;
index c8e958a..f96f92f 100644 (file)
@@ -109,10 +109,12 @@ struct mx3_camera_dev {
 
        unsigned long           platform_flags;
        unsigned long           mclk;
+       u16                     width_flags;    /* max 15 bits */
 
        struct list_head        capture;
        spinlock_t              lock;           /* Protects video buffer lists */
        struct mx3_camera_buffer *active;
+       size_t                  buf_total;
        struct vb2_alloc_ctx    *alloc_ctx;
        enum v4l2_field         field;
        int                     sequence;
@@ -190,79 +192,53 @@ static void mx3_cam_dma_done(void *arg)
  * Calculate the __buffer__ (not data) size and number of buffers.
  */
 static int mx3_videobuf_setup(struct vb2_queue *vq,
+                       const struct v4l2_format *fmt,
                        unsigned int *count, unsigned int *num_planes,
                        unsigned int sizes[], void *alloc_ctxs[])
 {
        struct soc_camera_device *icd = soc_camera_from_vb2q(vq);
        struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct mx3_camera_dev *mx3_cam = ici->priv;
-       int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
-                                               icd->current_fmt->host_fmt);
-
-       if (bytes_per_line < 0)
-               return bytes_per_line;
+       int bytes_per_line;
+       unsigned int height;
 
        if (!mx3_cam->idmac_channel[0])
                return -EINVAL;
 
-       *num_planes = 1;
-
-       mx3_cam->sequence = 0;
-       sizes[0] = bytes_per_line * icd->user_height;
-       alloc_ctxs[0] = mx3_cam->alloc_ctx;
-
-       if (!*count)
-               *count = 32;
-
-       if (sizes[0] * *count > MAX_VIDEO_MEM * 1024 * 1024)
-               *count = MAX_VIDEO_MEM * 1024 * 1024 / sizes[0];
-
-       return 0;
-}
-
-static int mx3_videobuf_prepare(struct vb2_buffer *vb)
-{
-       struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue);
-       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
-       struct mx3_camera_dev *mx3_cam = ici->priv;
-       struct idmac_channel *ichan = mx3_cam->idmac_channel[0];
-       struct scatterlist *sg;
-       struct mx3_camera_buffer *buf;
-       size_t new_size;
-       int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
+       if (fmt) {
+               const struct soc_camera_format_xlate *xlate = soc_camera_xlate_by_fourcc(icd,
+                                                               fmt->fmt.pix.pixelformat);
+               if (!xlate)
+                       return -EINVAL;
+               bytes_per_line = soc_mbus_bytes_per_line(fmt->fmt.pix.width,
+                                                        xlate->host_fmt);
+               height = fmt->fmt.pix.height;
+       } else {
+               /* Called from VIDIOC_REQBUFS or in compatibility mode */
+               bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
                                                icd->current_fmt->host_fmt);
-
+               height = icd->user_height;
+       }
        if (bytes_per_line < 0)
                return bytes_per_line;
 
-       buf = to_mx3_vb(vb);
-       sg = &buf->sg;
-
-       new_size = bytes_per_line * icd->user_height;
+       sizes[0] = bytes_per_line * height;
 
-       if (vb2_plane_size(vb, 0) < new_size) {
-               dev_err(icd->parent, "Buffer too small (%lu < %zu)\n",
-                       vb2_plane_size(vb, 0), new_size);
-               return -ENOBUFS;
-       }
+       alloc_ctxs[0] = mx3_cam->alloc_ctx;
 
-       if (buf->state == CSI_BUF_NEEDS_INIT) {
-               sg_dma_address(sg)      = vb2_dma_contig_plane_dma_addr(vb, 0);
-               sg_dma_len(sg)          = new_size;
+       if (!vq->num_buffers)
+               mx3_cam->sequence = 0;
 
-               buf->txd = ichan->dma_chan.device->device_prep_slave_sg(
-                       &ichan->dma_chan, sg, 1, DMA_FROM_DEVICE,
-                       DMA_PREP_INTERRUPT);
-               if (!buf->txd)
-                       return -EIO;
-
-               buf->txd->callback_param        = buf->txd;
-               buf->txd->callback              = mx3_cam_dma_done;
+       if (!*count)
+               *count = 2;
 
-               buf->state = CSI_BUF_PREPARED;
-       }
+       /* If *num_planes != 0, we have already verified *count. */
+       if (!*num_planes &&
+           sizes[0] * *count + mx3_cam->buf_total > MAX_VIDEO_MEM * 1024 * 1024)
+               *count = (MAX_VIDEO_MEM * 1024 * 1024 - mx3_cam->buf_total) /
+                       sizes[0];
 
-       vb2_set_plane_payload(vb, 0, new_size);
+       *num_planes = 1;
 
        return 0;
 }
@@ -286,28 +262,58 @@ static void mx3_videobuf_queue(struct vb2_buffer *vb)
        struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct mx3_camera_dev *mx3_cam = ici->priv;
        struct mx3_camera_buffer *buf = to_mx3_vb(vb);
-       struct dma_async_tx_descriptor *txd = buf->txd;
-       struct idmac_channel *ichan = to_idmac_chan(txd->chan);
+       struct scatterlist *sg = &buf->sg;
+       struct dma_async_tx_descriptor *txd;
+       struct idmac_channel *ichan = mx3_cam->idmac_channel[0];
        struct idmac_video_param *video = &ichan->params.video;
-       dma_cookie_t cookie;
-       u32 fourcc = icd->current_fmt->host_fmt->fourcc;
+       const struct soc_mbus_pixelfmt *host_fmt = icd->current_fmt->host_fmt;
+       int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, host_fmt);
        unsigned long flags;
+       dma_cookie_t cookie;
+       size_t new_size;
+
+       BUG_ON(bytes_per_line <= 0);
+
+       new_size = bytes_per_line * icd->user_height;
+
+       if (vb2_plane_size(vb, 0) < new_size) {
+               dev_err(icd->parent, "Buffer #%d too small (%lu < %zu)\n",
+                       vb->v4l2_buf.index, vb2_plane_size(vb, 0), new_size);
+               goto error;
+       }
+
+       if (buf->state == CSI_BUF_NEEDS_INIT) {
+               sg_dma_address(sg)      = vb2_dma_contig_plane_dma_addr(vb, 0);
+               sg_dma_len(sg)          = new_size;
+
+               txd = ichan->dma_chan.device->device_prep_slave_sg(
+                       &ichan->dma_chan, sg, 1, DMA_FROM_DEVICE,
+                       DMA_PREP_INTERRUPT);
+               if (!txd)
+                       goto error;
+
+               txd->callback_param     = txd;
+               txd->callback           = mx3_cam_dma_done;
+
+               buf->state              = CSI_BUF_PREPARED;
+               buf->txd                = txd;
+       } else {
+               txd = buf->txd;
+       }
+
+       vb2_set_plane_payload(vb, 0, new_size);
 
        /* This is the configuration of one sg-element */
-       video->out_pixel_fmt    = fourcc_to_ipu_pix(fourcc);
+       video->out_pixel_fmt = fourcc_to_ipu_pix(host_fmt->fourcc);
 
        if (video->out_pixel_fmt == IPU_PIX_FMT_GENERIC) {
                /*
-                * If the IPU DMA channel is configured to transport
-                * generic 8-bit data, we have to set up correctly the
-                * geometry parameters upon the current pixel format.
-                * So, since the DMA horizontal parameters are expressed
-                * in bytes not pixels, convert these in the right unit.
+                * If the IPU DMA channel is configured to transfer generic
+                * 8-bit data, we have to set up the geometry parameters
+                * correctly, according to the current pixel format. The DMA
+                * horizontal parameters in this case are expressed in bytes,
+                * not in pixels.
                 */
-               int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
-                                               icd->current_fmt->host_fmt);
-               BUG_ON(bytes_per_line <= 0);
-
                video->out_width        = bytes_per_line;
                video->out_height       = icd->user_height;
                video->out_stride       = bytes_per_line;
@@ -351,6 +357,7 @@ static void mx3_videobuf_queue(struct vb2_buffer *vb)
                mx3_cam->active = NULL;
 
        spin_unlock_irqrestore(&mx3_cam->lock, flags);
+error:
        vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
 }
 
@@ -384,17 +391,24 @@ static void mx3_videobuf_release(struct vb2_buffer *vb)
        }
 
        spin_unlock_irqrestore(&mx3_cam->lock, flags);
+
+       mx3_cam->buf_total -= vb2_plane_size(vb, 0);
 }
 
 static int mx3_videobuf_init(struct vb2_buffer *vb)
 {
+       struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+       struct mx3_camera_dev *mx3_cam = ici->priv;
        struct mx3_camera_buffer *buf = to_mx3_vb(vb);
+
        /* This is for locking debugging only */
        INIT_LIST_HEAD(&buf->queue);
        sg_init_table(&buf->sg, 1);
 
        buf->state = CSI_BUF_NEEDS_INIT;
-       buf->txd = NULL;
+
+       mx3_cam->buf_total += vb2_plane_size(vb, 0);
 
        return 0;
 }
@@ -405,13 +419,12 @@ static int mx3_stop_streaming(struct vb2_queue *q)
        struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct mx3_camera_dev *mx3_cam = ici->priv;
        struct idmac_channel *ichan = mx3_cam->idmac_channel[0];
-       struct dma_chan *chan;
        struct mx3_camera_buffer *buf, *tmp;
        unsigned long flags;
 
        if (ichan) {
-               chan = &ichan->dma_chan;
-               chan->device->device_control(chan, DMA_TERMINATE_ALL, 0);
+               struct dma_chan *chan = &ichan->dma_chan;
+               chan->device->device_control(chan, DMA_PAUSE, 0);
        }
 
        spin_lock_irqsave(&mx3_cam->lock, flags);
@@ -419,8 +432,8 @@ static int mx3_stop_streaming(struct vb2_queue *q)
        mx3_cam->active = NULL;
 
        list_for_each_entry_safe(buf, tmp, &mx3_cam->capture, queue) {
-               buf->state = CSI_BUF_NEEDS_INIT;
                list_del_init(&buf->queue);
+               vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
        }
 
        spin_unlock_irqrestore(&mx3_cam->lock, flags);
@@ -430,7 +443,6 @@ static int mx3_stop_streaming(struct vb2_queue *q)
 
 static struct vb2_ops mx3_videobuf_ops = {
        .queue_setup    = mx3_videobuf_setup,
-       .buf_prepare    = mx3_videobuf_prepare,
        .buf_queue      = mx3_videobuf_queue,
        .buf_cleanup    = mx3_videobuf_release,
        .buf_init       = mx3_videobuf_init,
@@ -514,6 +526,7 @@ static int mx3_camera_add_device(struct soc_camera_device *icd)
 
        mx3_camera_activate(mx3_cam, icd);
 
+       mx3_cam->buf_total = 0;
        mx3_cam->icd = icd;
 
        dev_info(icd->parent, "MX3 Camera driver attached to camera %d\n",
@@ -548,58 +561,27 @@ static int test_platform_param(struct mx3_camera_dev *mx3_cam,
                               unsigned char buswidth, unsigned long *flags)
 {
        /*
+        * If requested data width is supported by the platform, use it or any
+        * possible lower value - i.MX31 is smart enough to shift bits
+        */
+       if (buswidth > fls(mx3_cam->width_flags))
+               return -EINVAL;
+
+       /*
         * Platform specified synchronization and pixel clock polarities are
         * only a recommendation and are only used during probing. MX3x
         * camera interface only works in master mode, i.e., uses HSYNC and
         * VSYNC signals from the sensor
         */
-       *flags = SOCAM_MASTER |
-               SOCAM_HSYNC_ACTIVE_HIGH |
-               SOCAM_HSYNC_ACTIVE_LOW |
-               SOCAM_VSYNC_ACTIVE_HIGH |
-               SOCAM_VSYNC_ACTIVE_LOW |
-               SOCAM_PCLK_SAMPLE_RISING |
-               SOCAM_PCLK_SAMPLE_FALLING |
-               SOCAM_DATA_ACTIVE_HIGH |
-               SOCAM_DATA_ACTIVE_LOW;
-
-       /*
-        * If requested data width is supported by the platform, use it or any
-        * possible lower value - i.MX31 is smart enough to schift bits
-        */
-       if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_15)
-               *flags |= SOCAM_DATAWIDTH_15 | SOCAM_DATAWIDTH_10 |
-                       SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_4;
-       else if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_10)
-               *flags |= SOCAM_DATAWIDTH_10 | SOCAM_DATAWIDTH_8 |
-                       SOCAM_DATAWIDTH_4;
-       else if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_8)
-               *flags |= SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_4;
-       else if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_4)
-               *flags |= SOCAM_DATAWIDTH_4;
-
-       switch (buswidth) {
-       case 15:
-               if (!(*flags & SOCAM_DATAWIDTH_15))
-                       return -EINVAL;
-               break;
-       case 10:
-               if (!(*flags & SOCAM_DATAWIDTH_10))
-                       return -EINVAL;
-               break;
-       case 8:
-               if (!(*flags & SOCAM_DATAWIDTH_8))
-                       return -EINVAL;
-               break;
-       case 4:
-               if (!(*flags & SOCAM_DATAWIDTH_4))
-                       return -EINVAL;
-               break;
-       default:
-               dev_warn(mx3_cam->soc_host.v4l2_dev.dev,
-                        "Unsupported bus width %d\n", buswidth);
-               return -EINVAL;
-       }
+       *flags = V4L2_MBUS_MASTER |
+               V4L2_MBUS_HSYNC_ACTIVE_HIGH |
+               V4L2_MBUS_HSYNC_ACTIVE_LOW |
+               V4L2_MBUS_VSYNC_ACTIVE_HIGH |
+               V4L2_MBUS_VSYNC_ACTIVE_LOW |
+               V4L2_MBUS_PCLK_SAMPLE_RISING |
+               V4L2_MBUS_PCLK_SAMPLE_FALLING |
+               V4L2_MBUS_DATA_ACTIVE_HIGH |
+               V4L2_MBUS_DATA_ACTIVE_LOW;
 
        return 0;
 }
@@ -607,9 +589,11 @@ static int test_platform_param(struct mx3_camera_dev *mx3_cam,
 static int mx3_camera_try_bus_param(struct soc_camera_device *icd,
                                    const unsigned int depth)
 {
+       struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
        struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct mx3_camera_dev *mx3_cam = ici->priv;
-       unsigned long bus_flags, camera_flags;
+       struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
+       unsigned long bus_flags, common_flags;
        int ret = test_platform_param(mx3_cam, depth, &bus_flags);
 
        dev_dbg(icd->parent, "request bus width %d bit: %d\n", depth, ret);
@@ -617,15 +601,21 @@ static int mx3_camera_try_bus_param(struct soc_camera_device *icd,
        if (ret < 0)
                return ret;
 
-       camera_flags = icd->ops->query_bus_param(icd);
-
-       ret = soc_camera_bus_param_compatible(camera_flags, bus_flags);
-       if (ret < 0)
-               dev_warn(icd->parent,
-                        "Flags incompatible: camera %lx, host %lx\n",
-                        camera_flags, bus_flags);
+       ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
+       if (!ret) {
+               common_flags = soc_mbus_config_compatible(&cfg,
+                                                         bus_flags);
+               if (!common_flags) {
+                       dev_warn(icd->parent,
+                                "Flags incompatible: camera 0x%x, host 0x%lx\n",
+                                cfg.flags, bus_flags);
+                       return -EINVAL;
+               }
+       } else if (ret != -ENOIOCTLCMD) {
+               return ret;
+       }
 
-       return ret;
+       return 0;
 }
 
 static bool chan_filter(struct dma_chan *chan, void *arg)
@@ -994,9 +984,11 @@ static int mx3_camera_querycap(struct soc_camera_host *ici,
 
 static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
 {
+       struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
        struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct mx3_camera_dev *mx3_cam = ici->priv;
-       unsigned long bus_flags, camera_flags, common_flags;
+       struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
+       unsigned long bus_flags, common_flags;
        u32 dw, sens_conf;
        const struct soc_mbus_pixelfmt *fmt;
        int buswidth;
@@ -1008,83 +1000,76 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
        if (!fmt)
                return -EINVAL;
 
-       buswidth = fmt->bits_per_sample;
-       ret = test_platform_param(mx3_cam, buswidth, &bus_flags);
-
        xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
        if (!xlate) {
                dev_warn(dev, "Format %x not found\n", pixfmt);
                return -EINVAL;
        }
 
+       buswidth = fmt->bits_per_sample;
+       ret = test_platform_param(mx3_cam, buswidth, &bus_flags);
+
        dev_dbg(dev, "requested bus width %d bit: %d\n", buswidth, ret);
 
        if (ret < 0)
                return ret;
 
-       camera_flags = icd->ops->query_bus_param(icd);
-
-       common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags);
-       dev_dbg(dev, "Flags cam: 0x%lx host: 0x%lx common: 0x%lx\n",
-               camera_flags, bus_flags, common_flags);
-       if (!common_flags) {
-               dev_dbg(dev, "no common flags");
-               return -EINVAL;
+       ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
+       if (!ret) {
+               common_flags = soc_mbus_config_compatible(&cfg,
+                                                         bus_flags);
+               if (!common_flags) {
+                       dev_warn(icd->parent,
+                                "Flags incompatible: camera 0x%x, host 0x%lx\n",
+                                cfg.flags, bus_flags);
+                       return -EINVAL;
+               }
+       } else if (ret != -ENOIOCTLCMD) {
+               return ret;
+       } else {
+               common_flags = bus_flags;
        }
 
+       dev_dbg(dev, "Flags cam: 0x%x host: 0x%lx common: 0x%lx\n",
+               cfg.flags, bus_flags, common_flags);
+
        /* Make choices, based on platform preferences */
-       if ((common_flags & SOCAM_HSYNC_ACTIVE_HIGH) &&
-           (common_flags & SOCAM_HSYNC_ACTIVE_LOW)) {
+       if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) &&
+           (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) {
                if (mx3_cam->platform_flags & MX3_CAMERA_HSP)
-                       common_flags &= ~SOCAM_HSYNC_ACTIVE_HIGH;
+                       common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH;
                else
-                       common_flags &= ~SOCAM_HSYNC_ACTIVE_LOW;
+                       common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW;
        }
 
-       if ((common_flags & SOCAM_VSYNC_ACTIVE_HIGH) &&
-           (common_flags & SOCAM_VSYNC_ACTIVE_LOW)) {
+       if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) &&
+           (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) {
                if (mx3_cam->platform_flags & MX3_CAMERA_VSP)
-                       common_flags &= ~SOCAM_VSYNC_ACTIVE_HIGH;
+                       common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH;
                else
-                       common_flags &= ~SOCAM_VSYNC_ACTIVE_LOW;
+                       common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW;
        }
 
-       if ((common_flags & SOCAM_DATA_ACTIVE_HIGH) &&
-           (common_flags & SOCAM_DATA_ACTIVE_LOW)) {
+       if ((common_flags & V4L2_MBUS_DATA_ACTIVE_HIGH) &&
+           (common_flags & V4L2_MBUS_DATA_ACTIVE_LOW)) {
                if (mx3_cam->platform_flags & MX3_CAMERA_DP)
-                       common_flags &= ~SOCAM_DATA_ACTIVE_HIGH;
+                       common_flags &= ~V4L2_MBUS_DATA_ACTIVE_HIGH;
                else
-                       common_flags &= ~SOCAM_DATA_ACTIVE_LOW;
+                       common_flags &= ~V4L2_MBUS_DATA_ACTIVE_LOW;
        }
 
-       if ((common_flags & SOCAM_PCLK_SAMPLE_RISING) &&
-           (common_flags & SOCAM_PCLK_SAMPLE_FALLING)) {
+       if ((common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) &&
+           (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)) {
                if (mx3_cam->platform_flags & MX3_CAMERA_PCP)
-                       common_flags &= ~SOCAM_PCLK_SAMPLE_RISING;
+                       common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_RISING;
                else
-                       common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING;
+                       common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_FALLING;
        }
 
-       /*
-        * Make the camera work in widest common mode, we'll take care of
-        * the rest
-        */
-       if (common_flags & SOCAM_DATAWIDTH_15)
-               common_flags = (common_flags & ~SOCAM_DATAWIDTH_MASK) |
-                       SOCAM_DATAWIDTH_15;
-       else if (common_flags & SOCAM_DATAWIDTH_10)
-               common_flags = (common_flags & ~SOCAM_DATAWIDTH_MASK) |
-                       SOCAM_DATAWIDTH_10;
-       else if (common_flags & SOCAM_DATAWIDTH_8)
-               common_flags = (common_flags & ~SOCAM_DATAWIDTH_MASK) |
-                       SOCAM_DATAWIDTH_8;
-       else
-               common_flags = (common_flags & ~SOCAM_DATAWIDTH_MASK) |
-                       SOCAM_DATAWIDTH_4;
-
-       ret = icd->ops->set_bus_param(icd, common_flags);
-       if (ret < 0) {
-               dev_dbg(dev, "camera set_bus_param(%lx) returned %d\n",
+       cfg.flags = common_flags;
+       ret = v4l2_subdev_call(sd, video, s_mbus_config, &cfg);
+       if (ret < 0 && ret != -ENOIOCTLCMD) {
+               dev_dbg(dev, "camera s_mbus_config(0x%lx) returned %d\n",
                        common_flags, ret);
                return ret;
        }
@@ -1108,13 +1093,13 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
        /* This has been set in mx3_camera_activate(), but we clear it above */
        sens_conf |= CSI_SENS_CONF_DATA_FMT_BAYER;
 
-       if (common_flags & SOCAM_PCLK_SAMPLE_FALLING)
+       if (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
                sens_conf |= 1 << CSI_SENS_CONF_PIX_CLK_POL_SHIFT;
-       if (common_flags & SOCAM_HSYNC_ACTIVE_LOW)
+       if (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
                sens_conf |= 1 << CSI_SENS_CONF_HSYNC_POL_SHIFT;
-       if (common_flags & SOCAM_VSYNC_ACTIVE_LOW)
+       if (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
                sens_conf |= 1 << CSI_SENS_CONF_VSYNC_POL_SHIFT;
-       if (common_flags & SOCAM_DATA_ACTIVE_LOW)
+       if (common_flags & V4L2_MBUS_DATA_ACTIVE_LOW)
                sens_conf |= 1 << CSI_SENS_CONF_DATA_POL_SHIFT;
 
        /* Just do what we're asked to do */
@@ -1199,6 +1184,14 @@ static int __devinit mx3_camera_probe(struct platform_device *pdev)
                         "data widths, using default 8 bit\n");
                mx3_cam->platform_flags |= MX3_CAMERA_DATAWIDTH_8;
        }
+       if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_4)
+               mx3_cam->width_flags = 1 << 3;
+       if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_8)
+               mx3_cam->width_flags |= 1 << 7;
+       if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_10)
+               mx3_cam->width_flags |= 1 << 9;
+       if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_15)
+               mx3_cam->width_flags |= 1 << 14;
 
        mx3_cam->mclk = mx3_cam->pdata->mclk_10khz * 10000;
        if (!mx3_cam->mclk) {
@@ -1281,8 +1274,6 @@ static int __devexit mx3_camera_remove(struct platform_device *pdev)
 
        dmaengine_put();
 
-       dev_info(&pdev->dev, "i.MX3x Camera driver unloaded\n");
-
        return 0;
 }
 
index 30d8896..9c5c19f 100644 (file)
@@ -833,6 +833,15 @@ static void omap_vout_buffer_release(struct videobuf_queue *q,
 /*
  *  File operations
  */
+static unsigned int omap_vout_poll(struct file *file,
+                                  struct poll_table_struct *wait)
+{
+       struct omap_vout_device *vout = file->private_data;
+       struct videobuf_queue *q = &vout->vbq;
+
+       return videobuf_poll_stream(file, q, wait);
+}
+
 static void omap_vout_vm_open(struct vm_area_struct *vma)
 {
        struct omap_vout_device *vout = vma->vm_private_data;
@@ -1861,6 +1870,7 @@ static const struct v4l2_ioctl_ops vout_ioctl_ops = {
 
 static const struct v4l2_file_operations omap_vout_fops = {
        .owner          = THIS_MODULE,
+       .poll           = omap_vout_poll,
        .unlocked_ioctl = video_ioctl2,
        .mmap           = omap_vout_mmap,
        .open           = omap_vout_open,
index 8a947e6..e87ae2f 100644 (file)
 /* end of OMAP1 Camera Interface registers */
 
 
-#define SOCAM_BUS_FLAGS        (SOCAM_MASTER | \
-                       SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH | \
-                       SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING | \
-                       SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATAWIDTH_8)
+#define SOCAM_BUS_FLAGS        (V4L2_MBUS_MASTER | \
+                       V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_HIGH | \
+                       V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_PCLK_SAMPLE_FALLING | \
+                       V4L2_MBUS_DATA_ACTIVE_HIGH)
 
 
 #define FIFO_SIZE              ((THRESHOLD_MASK >> THRESHOLD_SHIFT) + 1)
@@ -1438,41 +1438,55 @@ static int omap1_cam_querycap(struct soc_camera_host *ici,
 static int omap1_cam_set_bus_param(struct soc_camera_device *icd,
                __u32 pixfmt)
 {
+       struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
        struct device *dev = icd->parent;
        struct soc_camera_host *ici = to_soc_camera_host(dev);
        struct omap1_cam_dev *pcdev = ici->priv;
        const struct soc_camera_format_xlate *xlate;
        const struct soc_mbus_pixelfmt *fmt;
-       unsigned long camera_flags, common_flags;
+       struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
+       unsigned long common_flags;
        u32 ctrlclock, mode;
        int ret;
 
-       camera_flags = icd->ops->query_bus_param(icd);
-
-       common_flags = soc_camera_bus_param_compatible(camera_flags,
-                       SOCAM_BUS_FLAGS);
-       if (!common_flags)
-               return -EINVAL;
+       ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
+       if (!ret) {
+               common_flags = soc_mbus_config_compatible(&cfg, SOCAM_BUS_FLAGS);
+               if (!common_flags) {
+                       dev_warn(dev,
+                                "Flags incompatible: camera 0x%x, host 0x%x\n",
+                                cfg.flags, SOCAM_BUS_FLAGS);
+                       return -EINVAL;
+               }
+       } else if (ret != -ENOIOCTLCMD) {
+               return ret;
+       } else {
+               common_flags = SOCAM_BUS_FLAGS;
+       }
 
        /* Make choices, possibly based on platform configuration */
-       if ((common_flags & SOCAM_PCLK_SAMPLE_RISING) &&
-                       (common_flags & SOCAM_PCLK_SAMPLE_FALLING)) {
+       if ((common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) &&
+                       (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)) {
                if (!pcdev->pdata ||
                                pcdev->pdata->flags & OMAP1_CAMERA_LCLK_RISING)
-                       common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING;
+                       common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_FALLING;
                else
-                       common_flags &= ~SOCAM_PCLK_SAMPLE_RISING;
+                       common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_RISING;
        }
 
-       ret = icd->ops->set_bus_param(icd, common_flags);
-       if (ret < 0)
+       cfg.flags = common_flags;
+       ret = v4l2_subdev_call(sd, video, s_mbus_config, &cfg);
+       if (ret < 0 && ret != -ENOIOCTLCMD) {
+               dev_dbg(dev, "camera s_mbus_config(0x%lx) returned %d\n",
+                       common_flags, ret);
                return ret;
+       }
 
        ctrlclock = CAM_READ_CACHE(pcdev, CTRLCLOCK);
        if (ctrlclock & LCLK_EN)
                CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock & ~LCLK_EN);
 
-       if (common_flags & SOCAM_PCLK_SAMPLE_RISING) {
+       if (common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) {
                dev_dbg(dev, "CTRLCLOCK_REG |= POLCLK\n");
                ctrlclock |= POLCLK;
        } else {
@@ -1565,10 +1579,10 @@ static int __init omap1_cam_probe(struct platform_device *pdev)
        pcdev->clk = clk;
 
        pcdev->pdata = pdev->dev.platform_data;
-       pcdev->pflags = pcdev->pdata->flags;
-
-       if (pcdev->pdata)
+       if (pcdev->pdata) {
+               pcdev->pflags = pcdev->pdata->flags;
                pcdev->camexclk = pcdev->pdata->camexclk_khz * 1000;
+       }
 
        switch (pcdev->camexclk) {
        case 6000000:
@@ -1578,6 +1592,7 @@ static int __init omap1_cam_probe(struct platform_device *pdev)
        case 24000000:
                break;
        default:
+               /* pcdev->camexclk != 0 => pcdev->pdata != NULL */
                dev_warn(&pdev->dev,
                                "Incorrect sensor clock frequency %ld kHz, "
                                "should be one of 0, 6, 8, 9.6, 12 or 24 MHz, "
@@ -1585,8 +1600,7 @@ static int __init omap1_cam_probe(struct platform_device *pdev)
                                pcdev->pdata->camexclk_khz);
                pcdev->camexclk = 0;
        case 0:
-               dev_info(&pdev->dev,
-                               "Not providing sensor clock\n");
+               dev_info(&pdev->dev, "Not providing sensor clock\n");
        }
 
        INIT_LIST_HEAD(&pcdev->capture);
@@ -1716,5 +1730,5 @@ MODULE_PARM_DESC(sg_mode, "videobuf mode, 0: dma-contig (default), 1: dma-sg");
 MODULE_DESCRIPTION("OMAP1 Camera Interface driver");
 MODULE_AUTHOR("Janusz Krzysztofik <jkrzyszt@tis.icnet.pl>");
 MODULE_LICENSE("GPL v2");
-MODULE_LICENSE(DRIVER_VERSION);
+MODULE_VERSION(DRIVER_VERSION);
 MODULE_ALIAS("platform:" DRIVER_NAME);
index 678e125..b818cac 100644 (file)
@@ -1704,6 +1704,7 @@ static int isp_register_entities(struct isp_device *isp)
        isp->media_dev.dev = isp->dev;
        strlcpy(isp->media_dev.model, "TI OMAP3 ISP",
                sizeof(isp->media_dev.model));
+       isp->media_dev.hw_revision = isp->revision;
        isp->media_dev.link_notify = isp_pipeline_link_notify;
        ret = media_device_register(&isp->media_dev);
        if (ret < 0) {
@@ -2210,6 +2211,8 @@ error:
        regulator_put(isp->isp_csiphy2.vdd);
        regulator_put(isp->isp_csiphy1.vdd);
        platform_set_drvdata(pdev, NULL);
+
+       mutex_destroy(&isp->isp_mutex);
        kfree(isp);
 
        return ret;
index 253fdcc..b0b0fa5 100644 (file)
@@ -1836,7 +1836,7 @@ ccdc_try_format(struct isp_ccdc_device *ccdc, struct v4l2_subdev_fh *fh,
                 * callers to request an output size bigger than the input size
                 * up to the nearest multiple of 16.
                 */
-               fmt->width = clamp_t(u32, width, 32, (fmt->width + 15) & ~15);
+               fmt->width = clamp_t(u32, width, 32, fmt->width + 15);
                fmt->width &= ~15;
                fmt->height = clamp_t(u32, height, 32, fmt->height);
                break;
@@ -2152,6 +2152,37 @@ static const struct media_entity_operations ccdc_media_ops = {
        .link_setup = ccdc_link_setup,
 };
 
+void omap3isp_ccdc_unregister_entities(struct isp_ccdc_device *ccdc)
+{
+       v4l2_device_unregister_subdev(&ccdc->subdev);
+       omap3isp_video_unregister(&ccdc->video_out);
+}
+
+int omap3isp_ccdc_register_entities(struct isp_ccdc_device *ccdc,
+       struct v4l2_device *vdev)
+{
+       int ret;
+
+       /* Register the subdev and video node. */
+       ret = v4l2_device_register_subdev(vdev, &ccdc->subdev);
+       if (ret < 0)
+               goto error;
+
+       ret = omap3isp_video_register(&ccdc->video_out, vdev);
+       if (ret < 0)
+               goto error;
+
+       return 0;
+
+error:
+       omap3isp_ccdc_unregister_entities(ccdc);
+       return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * ISP CCDC initialisation and cleanup
+ */
+
 /*
  * ccdc_init_entities - Initialize V4L2 subdev and media entity
  * @ccdc: ISP CCDC module
@@ -2193,50 +2224,23 @@ static int ccdc_init_entities(struct isp_ccdc_device *ccdc)
 
        ret = omap3isp_video_init(&ccdc->video_out, "CCDC");
        if (ret < 0)
-               return ret;
+               goto error_video;
 
        /* Connect the CCDC subdev to the video node. */
        ret = media_entity_create_link(&ccdc->subdev.entity, CCDC_PAD_SOURCE_OF,
                        &ccdc->video_out.video.entity, 0, 0);
        if (ret < 0)
-               return ret;
-
-       return 0;
-}
-
-void omap3isp_ccdc_unregister_entities(struct isp_ccdc_device *ccdc)
-{
-       media_entity_cleanup(&ccdc->subdev.entity);
-
-       v4l2_device_unregister_subdev(&ccdc->subdev);
-       omap3isp_video_unregister(&ccdc->video_out);
-}
-
-int omap3isp_ccdc_register_entities(struct isp_ccdc_device *ccdc,
-       struct v4l2_device *vdev)
-{
-       int ret;
-
-       /* Register the subdev and video node. */
-       ret = v4l2_device_register_subdev(vdev, &ccdc->subdev);
-       if (ret < 0)
-               goto error;
-
-       ret = omap3isp_video_register(&ccdc->video_out, vdev);
-       if (ret < 0)
-               goto error;
+               goto error_link;
 
        return 0;
 
-error:
-       omap3isp_ccdc_unregister_entities(ccdc);
+error_link:
+       omap3isp_video_cleanup(&ccdc->video_out);
+error_video:
+       media_entity_cleanup(me);
        return ret;
 }
 
-/* -----------------------------------------------------------------------------
- * ISP CCDC initialisation and cleanup
- */
-
 /*
  * omap3isp_ccdc_init - CCDC module initialization.
  * @dev: Device pointer specific to the OMAP3 ISP.
@@ -2248,6 +2252,7 @@ error:
 int omap3isp_ccdc_init(struct isp_device *isp)
 {
        struct isp_ccdc_device *ccdc = &isp->isp_ccdc;
+       int ret;
 
        spin_lock_init(&ccdc->lock);
        init_waitqueue_head(&ccdc->wait);
@@ -2276,7 +2281,13 @@ int omap3isp_ccdc_init(struct isp_device *isp)
        ccdc->update = OMAP3ISP_CCDC_BLCLAMP;
        ccdc_apply_controls(ccdc);
 
-       return ccdc_init_entities(ccdc);
+       ret = ccdc_init_entities(ccdc);
+       if (ret < 0) {
+               mutex_destroy(&ccdc->ioctl_lock);
+               return ret;
+       }
+
+       return 0;
 }
 
 /*
@@ -2287,6 +2298,9 @@ void omap3isp_ccdc_cleanup(struct isp_device *isp)
 {
        struct isp_ccdc_device *ccdc = &isp->isp_ccdc;
 
+       omap3isp_video_cleanup(&ccdc->video_out);
+       media_entity_cleanup(&ccdc->subdev.entity);
+
        /* Free LSC requests. As the CCDC is stopped there's no active request,
         * so only the pending request and the free queue need to be handled.
         */
@@ -2296,4 +2310,6 @@ void omap3isp_ccdc_cleanup(struct isp_device *isp)
 
        if (ccdc->fpc.fpcaddr != 0)
                omap_iommu_vfree(isp->domain, isp->iommu, ccdc->fpc.fpcaddr);
+
+       mutex_destroy(&ccdc->ioctl_lock);
 }
index fa1d09b..904ca8c 100644 (file)
@@ -1032,6 +1032,48 @@ static const struct media_entity_operations ccp2_media_ops = {
 };
 
 /*
+ * omap3isp_ccp2_unregister_entities - Unregister media entities: subdev
+ * @ccp2: Pointer to ISP CCP2 device
+ */
+void omap3isp_ccp2_unregister_entities(struct isp_ccp2_device *ccp2)
+{
+       v4l2_device_unregister_subdev(&ccp2->subdev);
+       omap3isp_video_unregister(&ccp2->video_in);
+}
+
+/*
+ * omap3isp_ccp2_register_entities - Register the subdev media entity
+ * @ccp2: Pointer to ISP CCP2 device
+ * @vdev: Pointer to v4l device
+ * return negative error code or zero on success
+ */
+
+int omap3isp_ccp2_register_entities(struct isp_ccp2_device *ccp2,
+                                   struct v4l2_device *vdev)
+{
+       int ret;
+
+       /* Register the subdev and video nodes. */
+       ret = v4l2_device_register_subdev(vdev, &ccp2->subdev);
+       if (ret < 0)
+               goto error;
+
+       ret = omap3isp_video_register(&ccp2->video_in, vdev);
+       if (ret < 0)
+               goto error;
+
+       return 0;
+
+error:
+       omap3isp_ccp2_unregister_entities(ccp2);
+       return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * ISP ccp2 initialisation and cleanup
+ */
+
+/*
  * ccp2_init_entities - Initialize ccp2 subdev and media entity.
  * @ccp2: Pointer to ISP CCP2 device
  * return negative error code or zero on success
@@ -1083,72 +1125,23 @@ static int ccp2_init_entities(struct isp_ccp2_device *ccp2)
 
        ret = omap3isp_video_init(&ccp2->video_in, "CCP2");
        if (ret < 0)
-               return ret;
+               goto error_video;
 
        /* Connect the video node to the ccp2 subdev. */
        ret = media_entity_create_link(&ccp2->video_in.video.entity, 0,
                                       &ccp2->subdev.entity, CCP2_PAD_SINK, 0);
        if (ret < 0)
-               return ret;
+               goto error_link;
 
        return 0;
-}
 
-/*
- * omap3isp_ccp2_unregister_entities - Unregister media entities: subdev
- * @ccp2: Pointer to ISP CCP2 device
- */
-void omap3isp_ccp2_unregister_entities(struct isp_ccp2_device *ccp2)
-{
+error_link:
+       omap3isp_video_cleanup(&ccp2->video_in);
+error_video:
        media_entity_cleanup(&ccp2->subdev.entity);
-
-       v4l2_device_unregister_subdev(&ccp2->subdev);
-       omap3isp_video_unregister(&ccp2->video_in);
-}
-
-/*
- * omap3isp_ccp2_register_entities - Register the subdev media entity
- * @ccp2: Pointer to ISP CCP2 device
- * @vdev: Pointer to v4l device
- * return negative error code or zero on success
- */
-
-int omap3isp_ccp2_register_entities(struct isp_ccp2_device *ccp2,
-                                   struct v4l2_device *vdev)
-{
-       int ret;
-
-       /* Register the subdev and video nodes. */
-       ret = v4l2_device_register_subdev(vdev, &ccp2->subdev);
-       if (ret < 0)
-               goto error;
-
-       ret = omap3isp_video_register(&ccp2->video_in, vdev);
-       if (ret < 0)
-               goto error;
-
-       return 0;
-
-error:
-       omap3isp_ccp2_unregister_entities(ccp2);
        return ret;
 }
 
-/* -----------------------------------------------------------------------------
- * ISP ccp2 initialisation and cleanup
- */
-
-/*
- * omap3isp_ccp2_cleanup - CCP2 un-initialization
- * @isp : Pointer to ISP device
- */
-void omap3isp_ccp2_cleanup(struct isp_device *isp)
-{
-       struct isp_ccp2_device *ccp2 = &isp->isp_ccp2;
-
-       regulator_put(ccp2->vdds_csib);
-}
-
 /*
  * omap3isp_ccp2_init - CCP2 initialization.
  * @isp : Pointer to ISP device
@@ -1184,13 +1177,25 @@ int omap3isp_ccp2_init(struct isp_device *isp)
        }
 
        ret = ccp2_init_entities(ccp2);
-       if (ret < 0)
-               goto out;
+       if (ret < 0) {
+               regulator_put(ccp2->vdds_csib);
+               return ret;
+       }
 
        ccp2_reset(ccp2);
-out:
-       if (ret)
-               omap3isp_ccp2_cleanup(isp);
+       return 0;
+}
 
-       return ret;
+/*
+ * omap3isp_ccp2_cleanup - CCP2 un-initialization
+ * @isp : Pointer to ISP device
+ */
+void omap3isp_ccp2_cleanup(struct isp_device *isp)
+{
+       struct isp_ccp2_device *ccp2 = &isp->isp_ccp2;
+
+       omap3isp_video_cleanup(&ccp2->video_in);
+       media_entity_cleanup(&ccp2->subdev.entity);
+
+       regulator_put(ccp2->vdds_csib);
 }
index 69161a6..0c5f1cb 100644 (file)
@@ -1187,6 +1187,37 @@ static const struct media_entity_operations csi2_media_ops = {
        .link_setup = csi2_link_setup,
 };
 
+void omap3isp_csi2_unregister_entities(struct isp_csi2_device *csi2)
+{
+       v4l2_device_unregister_subdev(&csi2->subdev);
+       omap3isp_video_unregister(&csi2->video_out);
+}
+
+int omap3isp_csi2_register_entities(struct isp_csi2_device *csi2,
+                                   struct v4l2_device *vdev)
+{
+       int ret;
+
+       /* Register the subdev and video nodes. */
+       ret = v4l2_device_register_subdev(vdev, &csi2->subdev);
+       if (ret < 0)
+               goto error;
+
+       ret = omap3isp_video_register(&csi2->video_out, vdev);
+       if (ret < 0)
+               goto error;
+
+       return 0;
+
+error:
+       omap3isp_csi2_unregister_entities(csi2);
+       return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * ISP CSI2 initialisation and cleanup
+ */
+
 /*
  * csi2_init_entities - Initialize subdev and media entity.
  * @csi2: Pointer to csi2 structure.
@@ -1228,57 +1259,23 @@ static int csi2_init_entities(struct isp_csi2_device *csi2)
 
        ret = omap3isp_video_init(&csi2->video_out, "CSI2a");
        if (ret < 0)
-               return ret;
+               goto error_video;
 
        /* Connect the CSI2 subdev to the video node. */
        ret = media_entity_create_link(&csi2->subdev.entity, CSI2_PAD_SOURCE,
                                       &csi2->video_out.video.entity, 0, 0);
        if (ret < 0)
-               return ret;
+               goto error_link;
 
        return 0;
-}
 
-void omap3isp_csi2_unregister_entities(struct isp_csi2_device *csi2)
-{
+error_link:
+       omap3isp_video_cleanup(&csi2->video_out);
+error_video:
        media_entity_cleanup(&csi2->subdev.entity);
-
-       v4l2_device_unregister_subdev(&csi2->subdev);
-       omap3isp_video_unregister(&csi2->video_out);
-}
-
-int omap3isp_csi2_register_entities(struct isp_csi2_device *csi2,
-                                   struct v4l2_device *vdev)
-{
-       int ret;
-
-       /* Register the subdev and video nodes. */
-       ret = v4l2_device_register_subdev(vdev, &csi2->subdev);
-       if (ret < 0)
-               goto error;
-
-       ret = omap3isp_video_register(&csi2->video_out, vdev);
-       if (ret < 0)
-               goto error;
-
-       return 0;
-
-error:
-       omap3isp_csi2_unregister_entities(csi2);
        return ret;
 }
 
-/* -----------------------------------------------------------------------------
- * ISP CSI2 initialisation and cleanup
- */
-
-/*
- * omap3isp_csi2_cleanup - Routine for module driver cleanup
- */
-void omap3isp_csi2_cleanup(struct isp_device *isp)
-{
-}
-
 /*
  * omap3isp_csi2_init - Routine for module driver init
  */
@@ -1298,7 +1295,7 @@ int omap3isp_csi2_init(struct isp_device *isp)
 
        ret = csi2_init_entities(csi2a);
        if (ret < 0)
-               goto fail;
+               return ret;
 
        if (isp->revision == ISP_REVISION_15_0) {
                csi2c->isp = isp;
@@ -1311,7 +1308,15 @@ int omap3isp_csi2_init(struct isp_device *isp)
        }
 
        return 0;
-fail:
-       omap3isp_csi2_cleanup(isp);
-       return ret;
+}
+
+/*
+ * omap3isp_csi2_cleanup - Routine for module driver cleanup
+ */
+void omap3isp_csi2_cleanup(struct isp_device *isp)
+{
+       struct isp_csi2_device *csi2a = &isp->isp_csi2a;
+
+       omap3isp_video_cleanup(&csi2a->video_out);
+       media_entity_cleanup(&csi2a->subdev.entity);
 }
index 8068cef..a3c76bf 100644 (file)
@@ -370,5 +370,5 @@ void omap3isp_h3a_aewb_cleanup(struct isp_device *isp)
 {
        kfree(isp->isp_aewb.priv);
        kfree(isp->isp_aewb.recover_priv);
-       omap3isp_stat_free(&isp->isp_aewb);
+       omap3isp_stat_cleanup(&isp->isp_aewb);
 }
index ba54d0a..58e0bc4 100644 (file)
@@ -425,5 +425,5 @@ void omap3isp_h3a_af_cleanup(struct isp_device *isp)
 {
        kfree(isp->isp_af.priv);
        kfree(isp->isp_af.recover_priv);
-       omap3isp_stat_free(&isp->isp_af);
+       omap3isp_stat_cleanup(&isp->isp_af);
 }
index 1743856..1163907 100644 (file)
@@ -516,5 +516,5 @@ void omap3isp_hist_cleanup(struct isp_device *isp)
        if (HIST_USING_DMA(&isp->isp_hist))
                omap_free_dma(isp->isp_hist.dma_ch);
        kfree(isp->isp_hist.priv);
-       omap3isp_stat_free(&isp->isp_hist);
+       omap3isp_stat_cleanup(&isp->isp_hist);
 }
index aba537a..ccb876f 100644 (file)
@@ -76,9 +76,51 @@ static struct omap3isp_prev_csc flr_prev_csc = {
 
 #define DEF_DETECT_CORRECT_VAL 0xe
 
-#define PREV_MIN_WIDTH         64
-#define PREV_MIN_HEIGHT                8
-#define PREV_MAX_HEIGHT                16384
+/*
+ * Margins and image size limits.
+ *
+ * The preview engine crops several rows and columns internally depending on
+ * which filters are enabled. To avoid format changes when the filters are
+ * enabled or disabled (which would prevent them from being turned on or off
+ * during streaming), the driver assumes all the filters are enabled when
+ * computing sink crop and source format limits.
+ *
+ * If a filter is disabled, additional cropping is automatically added at the
+ * preview engine input by the driver to avoid overflow at line and frame end.
+ * This is completely transparent for applications.
+ *
+ * Median filter               4 pixels
+ * Noise filter,
+ * Faulty pixels correction    4 pixels, 4 lines
+ * CFA filter                  4 pixels, 4 lines in Bayer mode
+ *                                       2 lines in other modes
+ * Color suppression           2 pixels
+ * or luma enhancement
+ * -------------------------------------------------------------
+ * Maximum total               14 pixels, 8 lines
+ *
+ * The color suppression and luma enhancement filters are applied after bayer to
+ * YUV conversion. They thus can crop one pixel on the left and one pixel on the
+ * right side of the image without changing the color pattern. When both those
+ * filters are disabled, the driver must crop the two pixels on the same side of
+ * the image to avoid changing the bayer pattern. The left margin is thus set to
+ * 8 pixels and the right margin to 6 pixels.
+ */
+
+#define PREV_MARGIN_LEFT       8
+#define PREV_MARGIN_RIGHT      6
+#define PREV_MARGIN_TOP                4
+#define PREV_MARGIN_BOTTOM     4
+
+#define PREV_MIN_IN_WIDTH      64
+#define PREV_MIN_IN_HEIGHT     8
+#define PREV_MAX_IN_HEIGHT     16384
+
+#define PREV_MIN_OUT_WIDTH     0
+#define PREV_MIN_OUT_HEIGHT    0
+#define PREV_MAX_OUT_WIDTH     1280
+#define PREV_MAX_OUT_WIDTH_ES2 3300
+#define PREV_MAX_OUT_WIDTH_3630        4096
 
 /*
  * Coeficient Tables for the submodules in Preview.
@@ -979,52 +1021,36 @@ static void preview_config_averager(struct isp_prev_device *prev, u8 average)
  * enabled when reporting source pad formats to userspace. If this assumption is
  * not true, rows and columns must be manually cropped at the preview engine
  * input to avoid overflows at the end of lines and frames.
+ *
+ * See the explanation at the PREV_MARGIN_* definitions for more details.
  */
 static void preview_config_input_size(struct isp_prev_device *prev)
 {
        struct isp_device *isp = to_isp_device(prev);
        struct prev_params *params = &prev->params;
-       struct v4l2_mbus_framefmt *format = &prev->formats[PREV_PAD_SINK];
-       unsigned int sph = 0;
-       unsigned int eph = format->width - 1;
-       unsigned int slv = 0;
-       unsigned int elv = format->height - 1;
-
-       if (prev->input == PREVIEW_INPUT_CCDC) {
-               sph += 2;
-               eph -= 2;
+       unsigned int sph = prev->crop.left;
+       unsigned int eph = prev->crop.left + prev->crop.width - 1;
+       unsigned int slv = prev->crop.top;
+       unsigned int elv = prev->crop.top + prev->crop.height - 1;
+
+       if (params->features & PREV_CFA) {
+               sph -= 2;
+               eph += 2;
+               slv -= 2;
+               elv += 2;
        }
-
-       /*
-        * Median filter        4 pixels
-        * Noise filter         4 pixels, 4 lines
-        * or faulty pixels correction
-        * CFA filter           4 pixels, 4 lines in Bayer mode
-        *                                2 lines in other modes
-        * Color suppression    2 pixels
-        * or luma enhancement
-        * -------------------------------------------------------------
-        * Maximum total        14 pixels, 8 lines
-        */
-
-       if (!(params->features & PREV_CFA)) {
-               sph += 2;
-               eph -= 2;
-               slv += 2;
-               elv -= 2;
+       if (params->features & (PREV_DEFECT_COR | PREV_NOISE_FILTER)) {
+               sph -= 2;
+               eph += 2;
+               slv -= 2;
+               elv += 2;
        }
-       if (!(params->features & (PREV_DEFECT_COR | PREV_NOISE_FILTER))) {
-               sph += 2;
-               eph -= 2;
-               slv += 2;
-               elv -= 2;
+       if (params->features & PREV_HORZ_MEDIAN_FILTER) {
+               sph -= 2;
+               eph += 2;
        }
-       if (!(params->features & PREV_HORZ_MEDIAN_FILTER)) {
-               sph += 2;
-               eph -= 2;
-       }
-       if (!(params->features & (PREV_CHROMA_SUPPRESS | PREV_LUMA_ENHANCE)))
-               sph += 2;
+       if (params->features & (PREV_CHROMA_SUPPRESS | PREV_LUMA_ENHANCE))
+               sph -= 2;
 
        isp_reg_writel(isp, (sph << ISPPRV_HORZ_INFO_SPH_SHIFT) | eph,
                       OMAP3_ISP_IOMEM_PREV, ISPPRV_HORZ_INFO);
@@ -1228,7 +1254,6 @@ static void preview_init_params(struct isp_prev_device *prev)
        /* Init values */
        params->contrast = ISPPRV_CONTRAST_DEF * ISPPRV_CONTRAST_UNITS;
        params->brightness = ISPPRV_BRIGHT_DEF * ISPPRV_BRIGHT_UNITS;
-       params->average = NO_AVE;
        params->cfa.format = OMAP3ISP_CFAFMT_BAYER;
        memcpy(params->cfa.table, cfa_coef_table,
               sizeof(params->cfa.table));
@@ -1281,14 +1306,14 @@ static unsigned int preview_max_out_width(struct isp_prev_device *prev)
 
        switch (isp->revision) {
        case ISP_REVISION_1_0:
-               return ISPPRV_MAXOUTPUT_WIDTH;
+               return PREV_MAX_OUT_WIDTH;
 
        case ISP_REVISION_2_0:
        default:
-               return ISPPRV_MAXOUTPUT_WIDTH_ES2;
+               return PREV_MAX_OUT_WIDTH_ES2;
 
        case ISP_REVISION_15_0:
-               return ISPPRV_MAXOUTPUT_WIDTH_3630;
+               return PREV_MAX_OUT_WIDTH_3630;
        }
 }
 
@@ -1296,8 +1321,6 @@ static void preview_configure(struct isp_prev_device *prev)
 {
        struct isp_device *isp = to_isp_device(prev);
        struct v4l2_mbus_framefmt *format;
-       unsigned int max_out_width;
-       unsigned int format_avg;
 
        preview_setup_hw(prev);
 
@@ -1335,10 +1358,7 @@ static void preview_configure(struct isp_prev_device *prev)
                preview_config_outlineoffset(prev,
                                ALIGN(format->width, 0x10) * 2);
 
-       max_out_width = preview_max_out_width(prev);
-
-       format_avg = fls(DIV_ROUND_UP(format->width, max_out_width) - 1);
-       preview_config_averager(prev, format_avg);
+       preview_config_averager(prev, 0);
        preview_config_ycpos(prev, format->code);
 }
 
@@ -1597,6 +1617,16 @@ __preview_get_format(struct isp_prev_device *prev, struct v4l2_subdev_fh *fh,
                return &prev->formats[pad];
 }
 
+static struct v4l2_rect *
+__preview_get_crop(struct isp_prev_device *prev, struct v4l2_subdev_fh *fh,
+                  enum v4l2_subdev_format_whence which)
+{
+       if (which == V4L2_SUBDEV_FORMAT_TRY)
+               return v4l2_subdev_get_try_crop(fh, PREV_PAD_SINK);
+       else
+               return &prev->crop;
+}
+
 /* previewer format descriptions */
 static const unsigned int preview_input_fmts[] = {
        V4L2_MBUS_FMT_SGRBG10_1X10,
@@ -1611,24 +1641,25 @@ static const unsigned int preview_output_fmts[] = {
 };
 
 /*
- * preview_try_format - Handle try format by pad subdev method
- * @prev: ISP preview device
- * @fh : V4L2 subdev file handle
- * @pad: pad num
- * @fmt: pointer to v4l2 format structure
+ * preview_try_format - Validate a format
+ * @prev: ISP preview engine
+ * @fh: V4L2 subdev file handle
+ * @pad: pad number
+ * @fmt: format to be validated
+ * @which: try/active format selector
+ *
+ * Validate and adjust the given format for the given pad based on the preview
+ * engine limits and the format and crop rectangles on other pads.
  */
 static void preview_try_format(struct isp_prev_device *prev,
                               struct v4l2_subdev_fh *fh, unsigned int pad,
                               struct v4l2_mbus_framefmt *fmt,
                               enum v4l2_subdev_format_whence which)
 {
-       struct v4l2_mbus_framefmt *format;
-       unsigned int max_out_width;
        enum v4l2_mbus_pixelcode pixelcode;
+       struct v4l2_rect *crop;
        unsigned int i;
 
-       max_out_width = preview_max_out_width(prev);
-
        switch (pad) {
        case PREV_PAD_SINK:
                /* When reading data from the CCDC, the input size has already
@@ -1641,10 +1672,11 @@ static void preview_try_format(struct isp_prev_device *prev,
                 * filter array interpolation.
                 */
                if (prev->input == PREVIEW_INPUT_MEMORY) {
-                       fmt->width = clamp_t(u32, fmt->width, PREV_MIN_WIDTH,
-                                            max_out_width * 8);
-                       fmt->height = clamp_t(u32, fmt->height, PREV_MIN_HEIGHT,
-                                             PREV_MAX_HEIGHT);
+                       fmt->width = clamp_t(u32, fmt->width, PREV_MIN_IN_WIDTH,
+                                            preview_max_out_width(prev));
+                       fmt->height = clamp_t(u32, fmt->height,
+                                             PREV_MIN_IN_HEIGHT,
+                                             PREV_MAX_IN_HEIGHT);
                }
 
                fmt->colorspace = V4L2_COLORSPACE_SRGB;
@@ -1661,15 +1693,8 @@ static void preview_try_format(struct isp_prev_device *prev,
 
        case PREV_PAD_SOURCE:
                pixelcode = fmt->code;
-               format = __preview_get_format(prev, fh, PREV_PAD_SINK, which);
-               memcpy(fmt, format, sizeof(*fmt));
+               *fmt = *__preview_get_format(prev, fh, PREV_PAD_SINK, which);
 
-               /* The preview module output size is configurable through the
-                * input interface (horizontal and vertical cropping) and the
-                * averager (horizontal scaling by 1/1, 1/2, 1/4 or 1/8). In
-                * spite of this, hardcode the output size to the biggest
-                * possible value for simplicity reasons.
-                */
                switch (pixelcode) {
                case V4L2_MBUS_FMT_YUYV8_1X16:
                case V4L2_MBUS_FMT_UYVY8_1X16:
@@ -1681,31 +1706,14 @@ static void preview_try_format(struct isp_prev_device *prev,
                        break;
                }
 
-               /* The TRM states (12.1.4.7.1.2) that 2 pixels must be cropped
-                * from the left and right sides when the input source is the
-                * CCDC. This seems not to be needed in practice, investigation
-                * is required.
-                */
-               if (prev->input == PREVIEW_INPUT_CCDC)
-                       fmt->width -= 4;
-
-               /* The preview module can output a maximum of 3312 pixels
-                * horizontally due to fixed memory-line sizes. Compute the
-                * horizontal averaging factor accordingly. Note that the limit
-                * applies to the noise filter and CFA interpolation blocks, so
-                * it doesn't take cropping by further blocks into account.
-                *
-                * ES 1.0 hardware revision is limited to 1280 pixels
-                * horizontally.
-                */
-               fmt->width >>= fls(DIV_ROUND_UP(fmt->width, max_out_width) - 1);
-
-               /* Assume that all blocks are enabled and crop pixels and lines
-                * accordingly. See preview_config_input_size() for more
-                * information.
+               /* The preview module output size is configurable through the
+                * averager (horizontal scaling by 1/1, 1/2, 1/4 or 1/8). This
+                * is not supported yet, hardcode the output size to the crop
+                * rectangle size.
                 */
-               fmt->width -= 14;
-               fmt->height -= 8;
+               crop = __preview_get_crop(prev, fh, which);
+               fmt->width = crop->width;
+               fmt->height = crop->height;
 
                fmt->colorspace = V4L2_COLORSPACE_JPEG;
                break;
@@ -1715,6 +1723,49 @@ static void preview_try_format(struct isp_prev_device *prev,
 }
 
 /*
+ * preview_try_crop - Validate a crop rectangle
+ * @prev: ISP preview engine
+ * @sink: format on the sink pad
+ * @crop: crop rectangle to be validated
+ *
+ * The preview engine crops lines and columns for its internal operation,
+ * depending on which filters are enabled. Enforce minimum crop margins to
+ * handle that transparently for userspace.
+ *
+ * See the explanation at the PREV_MARGIN_* definitions for more details.
+ */
+static void preview_try_crop(struct isp_prev_device *prev,
+                            const struct v4l2_mbus_framefmt *sink,
+                            struct v4l2_rect *crop)
+{
+       unsigned int left = PREV_MARGIN_LEFT;
+       unsigned int right = sink->width - PREV_MARGIN_RIGHT;
+       unsigned int top = PREV_MARGIN_TOP;
+       unsigned int bottom = sink->height - PREV_MARGIN_BOTTOM;
+
+       /* When processing data on-the-fly from the CCDC, at least 2 pixels must
+        * be cropped from the left and right sides of the image. As we don't
+        * know which filters will be enabled, increase the left and right
+        * margins by two.
+        */
+       if (prev->input == PREVIEW_INPUT_CCDC) {
+               left += 2;
+               right -= 2;
+       }
+
+       /* Restrict left/top to even values to keep the Bayer pattern. */
+       crop->left &= ~1;
+       crop->top &= ~1;
+
+       crop->left = clamp_t(u32, crop->left, left, right - PREV_MIN_OUT_WIDTH);
+       crop->top = clamp_t(u32, crop->top, top, bottom - PREV_MIN_OUT_HEIGHT);
+       crop->width = clamp_t(u32, crop->width, PREV_MIN_OUT_WIDTH,
+                             right - crop->left);
+       crop->height = clamp_t(u32, crop->height, PREV_MIN_OUT_HEIGHT,
+                              bottom - crop->top);
+}
+
+/*
  * preview_enum_mbus_code - Handle pixel format enumeration
  * @sd     : pointer to v4l2 subdev structure
  * @fh     : V4L2 subdev file handle
@@ -1776,6 +1827,60 @@ static int preview_enum_frame_size(struct v4l2_subdev *sd,
 }
 
 /*
+ * preview_get_crop - Retrieve the crop rectangle on a pad
+ * @sd: ISP preview V4L2 subdevice
+ * @fh: V4L2 subdev file handle
+ * @crop: crop rectangle
+ *
+ * Return 0 on success or a negative error code otherwise.
+ */
+static int preview_get_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+                           struct v4l2_subdev_crop *crop)
+{
+       struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
+
+       /* Cropping is only supported on the sink pad. */
+       if (crop->pad != PREV_PAD_SINK)
+               return -EINVAL;
+
+       crop->rect = *__preview_get_crop(prev, fh, crop->which);
+       return 0;
+}
+
+/*
+ * preview_set_crop - Retrieve the crop rectangle on a pad
+ * @sd: ISP preview V4L2 subdevice
+ * @fh: V4L2 subdev file handle
+ * @crop: crop rectangle
+ *
+ * Return 0 on success or a negative error code otherwise.
+ */
+static int preview_set_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+                           struct v4l2_subdev_crop *crop)
+{
+       struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
+       struct v4l2_mbus_framefmt *format;
+
+       /* Cropping is only supported on the sink pad. */
+       if (crop->pad != PREV_PAD_SINK)
+               return -EINVAL;
+
+       /* The crop rectangle can't be changed while streaming. */
+       if (prev->state != ISP_PIPELINE_STREAM_STOPPED)
+               return -EBUSY;
+
+       format = __preview_get_format(prev, fh, PREV_PAD_SINK, crop->which);
+       preview_try_crop(prev, format, &crop->rect);
+       *__preview_get_crop(prev, fh, crop->which) = crop->rect;
+
+       /* Update the source format. */
+       format = __preview_get_format(prev, fh, PREV_PAD_SOURCE, crop->which);
+       preview_try_format(prev, fh, PREV_PAD_SOURCE, format, crop->which);
+
+       return 0;
+}
+
+/*
  * preview_get_format - Handle get format by pads subdev method
  * @sd : pointer to v4l2 subdev structure
  * @fh : V4L2 subdev file handle
@@ -1808,6 +1913,7 @@ static int preview_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
 {
        struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
        struct v4l2_mbus_framefmt *format;
+       struct v4l2_rect *crop;
 
        format = __preview_get_format(prev, fh, fmt->pad, fmt->which);
        if (format == NULL)
@@ -1818,9 +1924,18 @@ static int preview_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
 
        /* Propagate the format from sink to source */
        if (fmt->pad == PREV_PAD_SINK) {
+               /* Reset the crop rectangle. */
+               crop = __preview_get_crop(prev, fh, fmt->which);
+               crop->left = 0;
+               crop->top = 0;
+               crop->width = fmt->format.width;
+               crop->height = fmt->format.height;
+
+               preview_try_crop(prev, &fmt->format, crop);
+
+               /* Update the source format. */
                format = __preview_get_format(prev, fh, PREV_PAD_SOURCE,
                                              fmt->which);
-               *format = fmt->format;
                preview_try_format(prev, fh, PREV_PAD_SOURCE, format,
                                   fmt->which);
        }
@@ -1869,6 +1984,8 @@ static const struct v4l2_subdev_pad_ops preview_v4l2_pad_ops = {
        .enum_frame_size = preview_enum_frame_size,
        .get_fmt = preview_get_format,
        .set_fmt = preview_set_format,
+       .get_crop = preview_get_crop,
+       .set_crop = preview_set_crop,
 };
 
 /* subdev operations */
@@ -1966,8 +2083,44 @@ static const struct media_entity_operations preview_media_ops = {
        .link_setup = preview_link_setup,
 };
 
+void omap3isp_preview_unregister_entities(struct isp_prev_device *prev)
+{
+       v4l2_device_unregister_subdev(&prev->subdev);
+       omap3isp_video_unregister(&prev->video_in);
+       omap3isp_video_unregister(&prev->video_out);
+}
+
+int omap3isp_preview_register_entities(struct isp_prev_device *prev,
+       struct v4l2_device *vdev)
+{
+       int ret;
+
+       /* Register the subdev and video nodes. */
+       ret = v4l2_device_register_subdev(vdev, &prev->subdev);
+       if (ret < 0)
+               goto error;
+
+       ret = omap3isp_video_register(&prev->video_in, vdev);
+       if (ret < 0)
+               goto error;
+
+       ret = omap3isp_video_register(&prev->video_out, vdev);
+       if (ret < 0)
+               goto error;
+
+       return 0;
+
+error:
+       omap3isp_preview_unregister_entities(prev);
+       return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * ISP previewer initialisation and cleanup
+ */
+
 /*
- * review_init_entities - Initialize subdev and media entity.
+ * preview_init_entities - Initialize subdev and media entity.
  * @prev : Pointer to preview structure
  * return -ENOMEM or zero on success
  */
@@ -2024,69 +2177,34 @@ static int preview_init_entities(struct isp_prev_device *prev)
 
        ret = omap3isp_video_init(&prev->video_in, "preview");
        if (ret < 0)
-               return ret;
+               goto error_video_in;
 
        ret = omap3isp_video_init(&prev->video_out, "preview");
        if (ret < 0)
-               return ret;
+               goto error_video_out;
 
        /* Connect the video nodes to the previewer subdev. */
        ret = media_entity_create_link(&prev->video_in.video.entity, 0,
                        &prev->subdev.entity, PREV_PAD_SINK, 0);
        if (ret < 0)
-               return ret;
+               goto error_link;
 
        ret = media_entity_create_link(&prev->subdev.entity, PREV_PAD_SOURCE,
                        &prev->video_out.video.entity, 0, 0);
        if (ret < 0)
-               return ret;
+               goto error_link;
 
        return 0;
-}
 
-void omap3isp_preview_unregister_entities(struct isp_prev_device *prev)
-{
+error_link:
+       omap3isp_video_cleanup(&prev->video_out);
+error_video_out:
+       omap3isp_video_cleanup(&prev->video_in);
+error_video_in:
        media_entity_cleanup(&prev->subdev.entity);
-
-       v4l2_device_unregister_subdev(&prev->subdev);
-       v4l2_ctrl_handler_free(&prev->ctrls);
-       omap3isp_video_unregister(&prev->video_in);
-       omap3isp_video_unregister(&prev->video_out);
-}
-
-int omap3isp_preview_register_entities(struct isp_prev_device *prev,
-       struct v4l2_device *vdev)
-{
-       int ret;
-
-       /* Register the subdev and video nodes. */
-       ret = v4l2_device_register_subdev(vdev, &prev->subdev);
-       if (ret < 0)
-               goto error;
-
-       ret = omap3isp_video_register(&prev->video_in, vdev);
-       if (ret < 0)
-               goto error;
-
-       ret = omap3isp_video_register(&prev->video_out, vdev);
-       if (ret < 0)
-               goto error;
-
-       return 0;
-
-error:
-       omap3isp_preview_unregister_entities(prev);
        return ret;
 }
 
-/* -----------------------------------------------------------------------------
- * ISP previewer initialisation and cleanup
- */
-
-void omap3isp_preview_cleanup(struct isp_device *isp)
-{
-}
-
 /*
  * isp_preview_init - Previewer initialization.
  * @dev : Pointer to ISP device
@@ -2095,19 +2213,20 @@ void omap3isp_preview_cleanup(struct isp_device *isp)
 int omap3isp_preview_init(struct isp_device *isp)
 {
        struct isp_prev_device *prev = &isp->isp_prev;
-       int ret;
 
        spin_lock_init(&prev->lock);
        init_waitqueue_head(&prev->wait);
        preview_init_params(prev);
 
-       ret = preview_init_entities(prev);
-       if (ret < 0)
-               goto out;
+       return preview_init_entities(prev);
+}
 
-out:
-       if (ret)
-               omap3isp_preview_cleanup(isp);
+void omap3isp_preview_cleanup(struct isp_device *isp)
+{
+       struct isp_prev_device *prev = &isp->isp_prev;
 
-       return ret;
+       v4l2_ctrl_handler_free(&prev->ctrls);
+       omap3isp_video_cleanup(&prev->video_in);
+       omap3isp_video_cleanup(&prev->video_out);
+       media_entity_cleanup(&prev->subdev.entity);
 }
index fa943bd..f54e775 100644 (file)
 #define ISPPRV_CONTRAST_HIGH           0xFF
 #define ISPPRV_CONTRAST_UNITS          0x1
 
-#define NO_AVE                         0x0
-#define AVE_2_PIX                      0x1
-#define AVE_4_PIX                      0x2
-#define AVE_8_PIX                      0x3
-
 /* Features list */
 #define PREV_LUMA_ENHANCE              OMAP3ISP_PREV_LUMAENH
 #define PREV_INVERSE_ALAW              OMAP3ISP_PREV_INVALAW
@@ -106,7 +101,6 @@ enum preview_ycpos_mode {
  * @rgb2ycbcr: RGB to ycbcr parameters.
  * @hmed: Horizontal median filter.
  * @yclimit: YC limits parameters.
- * @average: Downsampling rate for averager.
  * @contrast: Contrast.
  * @brightness: Brightness.
  */
@@ -124,7 +118,6 @@ struct prev_params {
        struct omap3isp_prev_csc rgb2ycbcr;
        struct omap3isp_prev_hmed hmed;
        struct omap3isp_prev_yclimit yclimit;
-       u8 average;
        u8 contrast;
        u8 brightness;
 };
@@ -159,6 +152,7 @@ struct isptables_update {
  * @subdev: V4L2 subdevice
  * @pads: Media entity pads
  * @formats: Active formats at the subdev pad
+ * @crop: Active crop rectangle
  * @input: Module currently connected to the input pad
  * @output: Bitmask of the active output
  * @video_in: Input video entity
@@ -177,6 +171,7 @@ struct isp_prev_device {
        struct v4l2_subdev subdev;
        struct media_pad pads[PREV_PADS_NUM];
        struct v4l2_mbus_framefmt formats[PREV_PADS_NUM];
+       struct v4l2_rect crop;
 
        struct v4l2_ctrl_handler ctrls;
 
index 69f6af6..084ea77 100644 (file)
 #define ISPPRV_YENH_TABLE_ADDR         0x1000
 #define ISPPRV_CFA_TABLE_ADDR          0x1400
 
-#define ISPPRV_MAXOUTPUT_WIDTH         1280
-#define ISPPRV_MAXOUTPUT_WIDTH_ES2     3300
-#define ISPPRV_MAXOUTPUT_WIDTH_3630    4096
 #define ISPRSZ_MIN_OUTPUT              64
 #define ISPRSZ_MAX_OUTPUT              3312
 
index 0bb0f8c..50e593b 100644 (file)
@@ -1608,6 +1608,42 @@ static const struct media_entity_operations resizer_media_ops = {
        .link_setup = resizer_link_setup,
 };
 
+void omap3isp_resizer_unregister_entities(struct isp_res_device *res)
+{
+       v4l2_device_unregister_subdev(&res->subdev);
+       omap3isp_video_unregister(&res->video_in);
+       omap3isp_video_unregister(&res->video_out);
+}
+
+int omap3isp_resizer_register_entities(struct isp_res_device *res,
+                                      struct v4l2_device *vdev)
+{
+       int ret;
+
+       /* Register the subdev and video nodes. */
+       ret = v4l2_device_register_subdev(vdev, &res->subdev);
+       if (ret < 0)
+               goto error;
+
+       ret = omap3isp_video_register(&res->video_in, vdev);
+       if (ret < 0)
+               goto error;
+
+       ret = omap3isp_video_register(&res->video_out, vdev);
+       if (ret < 0)
+               goto error;
+
+       return 0;
+
+error:
+       omap3isp_resizer_unregister_entities(res);
+       return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * ISP resizer initialization and cleanup
+ */
+
 /*
  * resizer_init_entities - Initialize resizer subdev and media entity.
  * @res : Pointer to resizer device structure
@@ -1652,68 +1688,34 @@ static int resizer_init_entities(struct isp_res_device *res)
 
        ret = omap3isp_video_init(&res->video_in, "resizer");
        if (ret < 0)
-               return ret;
+               goto error_video_in;
 
        ret = omap3isp_video_init(&res->video_out, "resizer");
        if (ret < 0)
-               return ret;
+               goto error_video_out;
 
        /* Connect the video nodes to the resizer subdev. */
        ret = media_entity_create_link(&res->video_in.video.entity, 0,
                        &res->subdev.entity, RESZ_PAD_SINK, 0);
        if (ret < 0)
-               return ret;
+               goto error_link;
 
        ret = media_entity_create_link(&res->subdev.entity, RESZ_PAD_SOURCE,
                        &res->video_out.video.entity, 0, 0);
        if (ret < 0)
-               return ret;
+               goto error_link;
 
        return 0;
-}
 
-void omap3isp_resizer_unregister_entities(struct isp_res_device *res)
-{
+error_link:
+       omap3isp_video_cleanup(&res->video_out);
+error_video_out:
+       omap3isp_video_cleanup(&res->video_in);
+error_video_in:
        media_entity_cleanup(&res->subdev.entity);
-
-       v4l2_device_unregister_subdev(&res->subdev);
-       omap3isp_video_unregister(&res->video_in);
-       omap3isp_video_unregister(&res->video_out);
-}
-
-int omap3isp_resizer_register_entities(struct isp_res_device *res,
-                                      struct v4l2_device *vdev)
-{
-       int ret;
-
-       /* Register the subdev and video nodes. */
-       ret = v4l2_device_register_subdev(vdev, &res->subdev);
-       if (ret < 0)
-               goto error;
-
-       ret = omap3isp_video_register(&res->video_in, vdev);
-       if (ret < 0)
-               goto error;
-
-       ret = omap3isp_video_register(&res->video_out, vdev);
-       if (ret < 0)
-               goto error;
-
-       return 0;
-
-error:
-       omap3isp_resizer_unregister_entities(res);
        return ret;
 }
 
-/* -----------------------------------------------------------------------------
- * ISP resizer initialization and cleanup
- */
-
-void omap3isp_resizer_cleanup(struct isp_device *isp)
-{
-}
-
 /*
  * isp_resizer_init - Resizer initialization.
  * @isp : Pointer to ISP device
@@ -1722,17 +1724,17 @@ void omap3isp_resizer_cleanup(struct isp_device *isp)
 int omap3isp_resizer_init(struct isp_device *isp)
 {
        struct isp_res_device *res = &isp->isp_res;
-       int ret;
 
        init_waitqueue_head(&res->wait);
        atomic_set(&res->stopping, 0);
-       ret = resizer_init_entities(res);
-       if (ret < 0)
-               goto out;
+       return resizer_init_entities(res);
+}
 
-out:
-       if (ret)
-               omap3isp_resizer_cleanup(isp);
+void omap3isp_resizer_cleanup(struct isp_device *isp)
+{
+       struct isp_res_device *res = &isp->isp_res;
 
-       return ret;
+       omap3isp_video_cleanup(&res->video_in);
+       omap3isp_video_cleanup(&res->video_out);
+       media_entity_cleanup(&res->subdev.entity);
 }
index 7329055..68d5394 100644 (file)
@@ -1023,24 +1023,6 @@ void omap3isp_stat_dma_isr(struct ispstat *stat)
        __stat_isr(stat, 1);
 }
 
-static int isp_stat_init_entities(struct ispstat *stat, const char *name,
-                                 const struct v4l2_subdev_ops *sd_ops)
-{
-       struct v4l2_subdev *subdev = &stat->subdev;
-       struct media_entity *me = &subdev->entity;
-
-       v4l2_subdev_init(subdev, sd_ops);
-       snprintf(subdev->name, V4L2_SUBDEV_NAME_SIZE, "OMAP3 ISP %s", name);
-       subdev->grp_id = 1 << 16;       /* group ID for isp subdevs */
-       subdev->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE;
-       v4l2_set_subdevdata(subdev, stat);
-
-       stat->pad.flags = MEDIA_PAD_FL_SINK;
-       me->ops = NULL;
-
-       return media_entity_init(me, 1, &stat->pad, 0);
-}
-
 int omap3isp_stat_subscribe_event(struct v4l2_subdev *subdev,
                                  struct v4l2_fh *fh,
                                  struct v4l2_event_subscription *sub)
@@ -1062,7 +1044,6 @@ int omap3isp_stat_unsubscribe_event(struct v4l2_subdev *subdev,
 
 void omap3isp_stat_unregister_entities(struct ispstat *stat)
 {
-       media_entity_cleanup(&stat->subdev.entity);
        v4l2_device_unregister_subdev(&stat->subdev);
 }
 
@@ -1072,21 +1053,50 @@ int omap3isp_stat_register_entities(struct ispstat *stat,
        return v4l2_device_register_subdev(vdev, &stat->subdev);
 }
 
+static int isp_stat_init_entities(struct ispstat *stat, const char *name,
+                                 const struct v4l2_subdev_ops *sd_ops)
+{
+       struct v4l2_subdev *subdev = &stat->subdev;
+       struct media_entity *me = &subdev->entity;
+
+       v4l2_subdev_init(subdev, sd_ops);
+       snprintf(subdev->name, V4L2_SUBDEV_NAME_SIZE, "OMAP3 ISP %s", name);
+       subdev->grp_id = 1 << 16;       /* group ID for isp subdevs */
+       subdev->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE;
+       v4l2_set_subdevdata(subdev, stat);
+
+       stat->pad.flags = MEDIA_PAD_FL_SINK;
+       me->ops = NULL;
+
+       return media_entity_init(me, 1, &stat->pad, 0);
+}
+
 int omap3isp_stat_init(struct ispstat *stat, const char *name,
                       const struct v4l2_subdev_ops *sd_ops)
 {
+       int ret;
+
        stat->buf = kcalloc(STAT_MAX_BUFS, sizeof(*stat->buf), GFP_KERNEL);
        if (!stat->buf)
                return -ENOMEM;
+
        isp_stat_buf_clear(stat);
        mutex_init(&stat->ioctl_lock);
        atomic_set(&stat->buf_err, 0);
 
-       return isp_stat_init_entities(stat, name, sd_ops);
+       ret = isp_stat_init_entities(stat, name, sd_ops);
+       if (ret < 0) {
+               mutex_destroy(&stat->ioctl_lock);
+               kfree(stat->buf);
+       }
+
+       return ret;
 }
 
-void omap3isp_stat_free(struct ispstat *stat)
+void omap3isp_stat_cleanup(struct ispstat *stat)
 {
+       media_entity_cleanup(&stat->subdev.entity);
+       mutex_destroy(&stat->ioctl_lock);
        isp_stat_bufs_free(stat);
        kfree(stat->buf);
 }
index d86da94..9b7c865 100644 (file)
@@ -144,7 +144,7 @@ int omap3isp_stat_request_statistics(struct ispstat *stat,
                                     struct omap3isp_stat_data *data);
 int omap3isp_stat_init(struct ispstat *stat, const char *name,
                       const struct v4l2_subdev_ops *sd_ops);
-void omap3isp_stat_free(struct ispstat *stat);
+void omap3isp_stat_cleanup(struct ispstat *stat);
 int omap3isp_stat_subscribe_event(struct v4l2_subdev *subdev,
                                  struct v4l2_fh *fh,
                                  struct v4l2_event_subscription *sub);
index 0cb8a9f..d100072 100644 (file)
@@ -1325,6 +1325,13 @@ int omap3isp_video_init(struct isp_video *video, const char *name)
        return 0;
 }
 
+void omap3isp_video_cleanup(struct isp_video *video)
+{
+       media_entity_cleanup(&video->video.entity);
+       mutex_destroy(&video->stream_lock);
+       mutex_destroy(&video->mutex);
+}
+
 int omap3isp_video_register(struct isp_video *video, struct v4l2_device *vdev)
 {
        int ret;
@@ -1341,8 +1348,6 @@ int omap3isp_video_register(struct isp_video *video, struct v4l2_device *vdev)
 
 void omap3isp_video_unregister(struct isp_video *video)
 {
-       if (video_is_registered(&video->video)) {
-               media_entity_cleanup(&video->video.entity);
+       if (video_is_registered(&video->video))
                video_unregister_device(&video->video);
-       }
 }
index 53160aa..08cbfa1 100644 (file)
@@ -190,6 +190,7 @@ struct isp_video_fh {
                                container_of(q, struct isp_video_fh, queue)
 
 int omap3isp_video_init(struct isp_video *video, const char *name);
+void omap3isp_video_cleanup(struct isp_video *video);
 int omap3isp_video_register(struct isp_video *video,
                            struct v4l2_device *vdev);
 void omap3isp_video_unregister(struct isp_video *video);
index 9ce2fa0..b5247cb 100644 (file)
 #include <linux/i2c.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
+#include <linux/v4l2-mediabus.h>
 #include <linux/videodev2.h>
+
+#include <media/soc_camera.h>
 #include <media/v4l2-chip-ident.h>
 #include <media/v4l2-subdev.h>
-#include <media/soc_camera.h>
-#include <media/soc_mediabus.h>
+#include <media/v4l2-ctrls.h>
 
 #define VAL_SET(x, mask, rshift, lshift)  \
                ((((x) >> rshift) & mask) << lshift)
@@ -299,12 +301,10 @@ struct ov2640_win_size {
 
 struct ov2640_priv {
        struct v4l2_subdev              subdev;
-       struct ov2640_camera_info       *info;
+       struct v4l2_ctrl_handler        hdl;
        enum v4l2_mbus_pixelcode        cfmt_code;
        const struct ov2640_win_size    *win;
        int                             model;
-       u16                             flag_vflip:1;
-       u16                             flag_hflip:1;
 };
 
 /*
@@ -610,29 +610,6 @@ static enum v4l2_mbus_pixelcode ov2640_codes[] = {
 };
 
 /*
- * Supported controls
- */
-static const struct v4l2_queryctrl ov2640_controls[] = {
-       {
-               .id             = V4L2_CID_VFLIP,
-               .type           = V4L2_CTRL_TYPE_BOOLEAN,
-               .name           = "Flip Vertically",
-               .minimum        = 0,
-               .maximum        = 1,
-               .step           = 1,
-               .default_value  = 0,
-       }, {
-               .id             = V4L2_CID_HFLIP,
-               .type           = V4L2_CTRL_TYPE_BOOLEAN,
-               .name           = "Flip Horizontally",
-               .minimum        = 0,
-               .maximum        = 1,
-               .step           = 1,
-               .default_value  = 0,
-       },
-};
-
-/*
  * General functions
  */
 static struct ov2640_priv *to_ov2640(const struct i2c_client *client)
@@ -701,81 +678,23 @@ static int ov2640_s_stream(struct v4l2_subdev *sd, int enable)
        return 0;
 }
 
-static int ov2640_set_bus_param(struct soc_camera_device *icd,
-                               unsigned long flags)
-{
-       struct soc_camera_link *icl = to_soc_camera_link(icd);
-       unsigned long width_flag = flags & SOCAM_DATAWIDTH_MASK;
-
-       /* Only one width bit may be set */
-       if (!is_power_of_2(width_flag))
-               return -EINVAL;
-
-       if (icl->set_bus_param)
-               return icl->set_bus_param(icl, width_flag);
-
-       /*
-        * Without board specific bus width settings we support only the
-        * sensors native bus width witch are tested working
-        */
-       if (width_flag & (SOCAM_DATAWIDTH_10 | SOCAM_DATAWIDTH_8))
-               return 0;
-
-       return 0;
-}
-
-static unsigned long ov2640_query_bus_param(struct soc_camera_device *icd)
-{
-       struct soc_camera_link *icl = to_soc_camera_link(icd);
-       unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER |
-               SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH |
-               SOCAM_DATA_ACTIVE_HIGH;
-
-       if (icl->query_bus_param)
-               flags |= icl->query_bus_param(icl) & SOCAM_DATAWIDTH_MASK;
-       else
-               flags |= SOCAM_DATAWIDTH_10;
-
-       return soc_camera_apply_sensor_flags(icl, flags);
-}
-
-static int ov2640_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+static int ov2640_s_ctrl(struct v4l2_ctrl *ctrl)
 {
+       struct v4l2_subdev *sd =
+               &container_of(ctrl->handler, struct ov2640_priv, hdl)->subdev;
        struct i2c_client  *client = v4l2_get_subdevdata(sd);
-       struct ov2640_priv *priv = to_ov2640(client);
-
-       switch (ctrl->id) {
-       case V4L2_CID_VFLIP:
-               ctrl->value = priv->flag_vflip;
-               break;
-       case V4L2_CID_HFLIP:
-               ctrl->value = priv->flag_hflip;
-               break;
-       }
-       return 0;
-}
-
-static int ov2640_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
-{
-       struct i2c_client  *client = v4l2_get_subdevdata(sd);
-       struct ov2640_priv *priv = to_ov2640(client);
-       int ret = 0;
        u8 val;
 
        switch (ctrl->id) {
        case V4L2_CID_VFLIP:
-               val = ctrl->value ? REG04_VFLIP_IMG : 0x00;
-               priv->flag_vflip = ctrl->value ? 1 : 0;
-               ret = ov2640_mask_set(client, REG04, REG04_VFLIP_IMG, val);
-               break;
+               val = ctrl->val ? REG04_VFLIP_IMG : 0x00;
+               return ov2640_mask_set(client, REG04, REG04_VFLIP_IMG, val);
        case V4L2_CID_HFLIP:
-               val = ctrl->value ? REG04_HFLIP_IMG : 0x00;
-               priv->flag_hflip = ctrl->value ? 1 : 0;
-               ret = ov2640_mask_set(client, REG04, REG04_HFLIP_IMG, val);
-               break;
+               val = ctrl->val ? REG04_HFLIP_IMG : 0x00;
+               return ov2640_mask_set(client, REG04, REG04_HFLIP_IMG, val);
        }
 
-       return ret;
+       return -EINVAL;
 }
 
 static int ov2640_g_chip_ident(struct v4l2_subdev *sd,
@@ -1023,18 +942,13 @@ static int ov2640_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
        return 0;
 }
 
-static int ov2640_video_probe(struct soc_camera_device *icd,
-                             struct i2c_client *client)
+static int ov2640_video_probe(struct i2c_client *client)
 {
        struct ov2640_priv *priv = to_ov2640(client);
        u8 pid, ver, midh, midl;
        const char *devname;
        int ret;
 
-       /* We must have a parent by now. And it cannot be a wrong one. */
-       BUG_ON(!icd->parent ||
-              to_soc_camera_host(icd->parent)->nr != icd->iface);
-
        /*
         * check and show product ID and manufacturer ID
         */
@@ -1060,22 +974,17 @@ static int ov2640_video_probe(struct soc_camera_device *icd,
                 "%s Product ID %0x:%0x Manufacturer ID %x:%x\n",
                 devname, pid, ver, midh, midl);
 
-       return 0;
+       return v4l2_ctrl_handler_setup(&priv->hdl);
 
 err:
        return ret;
 }
 
-static struct soc_camera_ops ov2640_ops = {
-       .set_bus_param          = ov2640_set_bus_param,
-       .query_bus_param        = ov2640_query_bus_param,
-       .controls               = ov2640_controls,
-       .num_controls           = ARRAY_SIZE(ov2640_controls),
+static const struct v4l2_ctrl_ops ov2640_ctrl_ops = {
+       .s_ctrl = ov2640_s_ctrl,
 };
 
 static struct v4l2_subdev_core_ops ov2640_subdev_core_ops = {
-       .g_ctrl         = ov2640_g_ctrl,
-       .s_ctrl         = ov2640_s_ctrl,
        .g_chip_ident   = ov2640_g_chip_ident,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
        .g_register     = ov2640_g_register,
@@ -1083,6 +992,21 @@ static struct v4l2_subdev_core_ops ov2640_subdev_core_ops = {
 #endif
 };
 
+static int ov2640_g_mbus_config(struct v4l2_subdev *sd,
+                               struct v4l2_mbus_config *cfg)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+       cfg->flags = V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_MASTER |
+               V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_HIGH |
+               V4L2_MBUS_DATA_ACTIVE_HIGH;
+       cfg->type = V4L2_MBUS_PARALLEL;
+       cfg->flags = soc_camera_apply_board_flags(icl, cfg);
+
+       return 0;
+}
+
 static struct v4l2_subdev_video_ops ov2640_subdev_video_ops = {
        .s_stream       = ov2640_s_stream,
        .g_mbus_fmt     = ov2640_g_fmt,
@@ -1091,6 +1015,7 @@ static struct v4l2_subdev_video_ops ov2640_subdev_video_ops = {
        .cropcap        = ov2640_cropcap,
        .g_crop         = ov2640_g_crop,
        .enum_mbus_fmt  = ov2640_enum_fmt,
+       .g_mbus_config  = ov2640_g_mbus_config,
 };
 
 static struct v4l2_subdev_ops ov2640_subdev_ops = {
@@ -1104,18 +1029,11 @@ static struct v4l2_subdev_ops ov2640_subdev_ops = {
 static int ov2640_probe(struct i2c_client *client,
                        const struct i2c_device_id *did)
 {
-       struct ov2640_priv        *priv;
-       struct soc_camera_device  *icd = client->dev.platform_data;
-       struct i2c_adapter        *adapter = to_i2c_adapter(client->dev.parent);
-       struct soc_camera_link    *icl;
-       int                        ret;
-
-       if (!icd) {
-               dev_err(&adapter->dev, "OV2640: missing soc-camera data!\n");
-               return -EINVAL;
-       }
+       struct ov2640_priv      *priv;
+       struct soc_camera_link  *icl = soc_camera_i2c_to_link(client);
+       struct i2c_adapter      *adapter = to_i2c_adapter(client->dev.parent);
+       int                     ret;
 
-       icl = to_soc_camera_link(icd);
        if (!icl) {
                dev_err(&adapter->dev,
                        "OV2640: Missing platform_data for driver\n");
@@ -1135,15 +1053,23 @@ static int ov2640_probe(struct i2c_client *client,
                return -ENOMEM;
        }
 
-       priv->info = icl->priv;
-
        v4l2_i2c_subdev_init(&priv->subdev, client, &ov2640_subdev_ops);
+       v4l2_ctrl_handler_init(&priv->hdl, 2);
+       v4l2_ctrl_new_std(&priv->hdl, &ov2640_ctrl_ops,
+                       V4L2_CID_VFLIP, 0, 1, 1, 0);
+       v4l2_ctrl_new_std(&priv->hdl, &ov2640_ctrl_ops,
+                       V4L2_CID_HFLIP, 0, 1, 1, 0);
+       priv->subdev.ctrl_handler = &priv->hdl;
+       if (priv->hdl.error) {
+               int err = priv->hdl.error;
 
-       icd->ops = &ov2640_ops;
+               kfree(priv);
+               return err;
+       }
 
-       ret = ov2640_video_probe(icd, client);
+       ret = ov2640_video_probe(client);
        if (ret) {
-               icd->ops = NULL;
+               v4l2_ctrl_handler_free(&priv->hdl);
                kfree(priv);
        } else {
                dev_info(&adapter->dev, "OV2640 Probed\n");
@@ -1155,9 +1081,9 @@ static int ov2640_probe(struct i2c_client *client,
 static int ov2640_remove(struct i2c_client *client)
 {
        struct ov2640_priv       *priv = to_ov2640(client);
-       struct soc_camera_device *icd = client->dev.platform_data;
 
-       icd->ops = NULL;
+       v4l2_device_unregister_subdev(&priv->subdev);
+       v4l2_ctrl_handler_free(&priv->hdl);
        kfree(priv);
        return 0;
 }
index 349a4ad..bb37ec8 100644 (file)
  * published by the Free Software Foundation.
  */
 
+#include <linux/bitops.h>
 #include <linux/delay.h>
 #include <linux/i2c.h>
+#include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/videodev2.h>
 #include <linux/module.h>
+#include <linux/v4l2-mediabus.h>
 
 #include <media/soc_camera.h>
-#include <media/soc_mediabus.h>
 #include <media/v4l2-chip-ident.h>
 #include <media/v4l2-subdev.h>
 
@@ -35,7 +37,7 @@
 #define REG_WINDOW_START_Y_LOW         0x3803
 #define REG_WINDOW_WIDTH_HIGH          0x3804
 #define REG_WINDOW_WIDTH_LOW           0x3805
-#define REG_WINDOW_HEIGHT_HIGH                 0x3806
+#define REG_WINDOW_HEIGHT_HIGH         0x3806
 #define REG_WINDOW_HEIGHT_LOW          0x3807
 #define REG_OUT_WIDTH_HIGH             0x3808
 #define REG_OUT_WIDTH_LOW              0x3809
 #define REG_OUT_TOTAL_WIDTH_LOW                0x380d
 #define REG_OUT_TOTAL_HEIGHT_HIGH      0x380e
 #define REG_OUT_TOTAL_HEIGHT_LOW       0x380f
+#define REG_OUTPUT_FORMAT              0x4300
+#define REG_ISP_CTRL_01                        0x5001
+#define REG_AVG_WINDOW_END_X_HIGH      0x5682
+#define REG_AVG_WINDOW_END_X_LOW       0x5683
+#define REG_AVG_WINDOW_END_Y_HIGH      0x5686
+#define REG_AVG_WINDOW_END_Y_LOW       0x5687
+
+/* active pixel array size */
+#define OV5642_SENSOR_SIZE_X   2592
+#define OV5642_SENSOR_SIZE_Y   1944
 
 /*
- * define standard resolution.
- * Works currently only for up to 720 lines
- * eg. 320x240, 640x480, 800x600, 1280x720, 2048x720
+ * About OV5642 resolution, cropping and binning:
+ * This sensor supports it all, at least in the feature description.
+ * Unfortunately, no combination of appropriate registers settings could make
+ * the chip work the intended way. As it works with predefined register lists,
+ * some undocumented registers are presumably changed there to achieve their
+ * goals.
+ * This driver currently only works for resolutions up to 720 lines with a
+ * 1:1 scale. Hopefully these restrictions will be removed in the future.
  */
+#define OV5642_MAX_WIDTH       OV5642_SENSOR_SIZE_X
+#define OV5642_MAX_HEIGHT      720
 
-#define OV5642_WIDTH           1280
-#define OV5642_HEIGHT          720
-#define OV5642_TOTAL_WIDTH     3200
-#define OV5642_TOTAL_HEIGHT    2000
-#define OV5642_SENSOR_SIZE_X   2592
-#define OV5642_SENSOR_SIZE_Y   1944
+/* default sizes */
+#define OV5642_DEFAULT_WIDTH   1280
+#define OV5642_DEFAULT_HEIGHT  OV5642_MAX_HEIGHT
+
+/* minimum extra blanking */
+#define BLANKING_EXTRA_WIDTH           500
+#define BLANKING_EXTRA_HEIGHT          20
+
+/*
+ * the sensor's autoexposure is buggy when setting total_height low.
+ * It tries to expose longer than 1 frame period without taking care of it
+ * and this leads to weird output. So we set 1000 lines as minimum.
+ */
+#define BLANKING_MIN_HEIGHT            1000
 
 struct regval_list {
        u16 reg_num;
@@ -582,6 +609,11 @@ struct ov5642_datafmt {
 struct ov5642 {
        struct v4l2_subdev              subdev;
        const struct ov5642_datafmt     *fmt;
+       struct v4l2_rect                crop_rect;
+
+       /* blanking information */
+       int total_width;
+       int total_height;
 };
 
 static const struct ov5642_datafmt ov5642_colour_fmts[] = {
@@ -642,6 +674,21 @@ static int reg_write(struct i2c_client *client, u16 reg, u8 val)
 
        return 0;
 }
+
+/*
+ * convenience function to write 16 bit register values that are split up
+ * into two consecutive high and low parts
+ */
+static int reg_write16(struct i2c_client *client, u16 reg, u16 val16)
+{
+       int ret;
+
+       ret = reg_write(client, reg, val16 >> 8);
+       if (ret)
+               return ret;
+       return reg_write(client, reg + 1, val16 & 0x00ff);
+}
+
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 static int ov5642_get_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
 {
@@ -685,58 +732,55 @@ static int ov5642_write_array(struct i2c_client *client,
        return 0;
 }
 
-static int ov5642_set_resolution(struct i2c_client *client)
+static int ov5642_set_resolution(struct v4l2_subdev *sd)
 {
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct ov5642 *priv = to_ov5642(client);
+       int width = priv->crop_rect.width;
+       int height = priv->crop_rect.height;
+       int total_width = priv->total_width;
+       int total_height = priv->total_height;
+       int start_x = (OV5642_SENSOR_SIZE_X - width) / 2;
+       int start_y = (OV5642_SENSOR_SIZE_Y - height) / 2;
        int ret;
-       u8 start_x_high = ((OV5642_SENSOR_SIZE_X - OV5642_WIDTH) / 2) >> 8;
-       u8 start_x_low  = ((OV5642_SENSOR_SIZE_X - OV5642_WIDTH) / 2) & 0xff;
-       u8 start_y_high = ((OV5642_SENSOR_SIZE_Y - OV5642_HEIGHT) / 2) >> 8;
-       u8 start_y_low  = ((OV5642_SENSOR_SIZE_Y - OV5642_HEIGHT) / 2) & 0xff;
-
-       u8 width_high   = OV5642_WIDTH  >> 8;
-       u8 width_low    = OV5642_WIDTH  & 0xff;
-       u8 height_high  = OV5642_HEIGHT >> 8;
-       u8 height_low   = OV5642_HEIGHT & 0xff;
-
-       u8 total_width_high  = OV5642_TOTAL_WIDTH  >> 8;
-       u8 total_width_low   = OV5642_TOTAL_WIDTH  & 0xff;
-       u8 total_height_high = OV5642_TOTAL_HEIGHT >> 8;
-       u8 total_height_low  = OV5642_TOTAL_HEIGHT & 0xff;
-
-       ret = reg_write(client, REG_WINDOW_START_X_HIGH, start_x_high);
-       if (!ret)
-               ret = reg_write(client, REG_WINDOW_START_X_LOW, start_x_low);
-       if (!ret)
-               ret = reg_write(client, REG_WINDOW_START_Y_HIGH, start_y_high);
-       if (!ret)
-               ret = reg_write(client, REG_WINDOW_START_Y_LOW, start_y_low);
 
+       /*
+        * This should set the starting point for cropping.
+        * Doesn't work so far.
+        */
+       ret = reg_write16(client, REG_WINDOW_START_X_HIGH, start_x);
        if (!ret)
-               ret = reg_write(client, REG_WINDOW_WIDTH_HIGH, width_high);
-       if (!ret)
-               ret = reg_write(client, REG_WINDOW_WIDTH_LOW , width_low);
-       if (!ret)
-               ret = reg_write(client, REG_WINDOW_HEIGHT_HIGH, height_high);
-       if (!ret)
-               ret = reg_write(client, REG_WINDOW_HEIGHT_LOW,  height_low);
+               ret = reg_write16(client, REG_WINDOW_START_Y_HIGH, start_y);
+       if (!ret) {
+               priv->crop_rect.left = start_x;
+               priv->crop_rect.top = start_y;
+       }
 
        if (!ret)
-               ret = reg_write(client, REG_OUT_WIDTH_HIGH, width_high);
+               ret = reg_write16(client, REG_WINDOW_WIDTH_HIGH, width);
        if (!ret)
-               ret = reg_write(client, REG_OUT_WIDTH_LOW , width_low);
-       if (!ret)
-               ret = reg_write(client, REG_OUT_HEIGHT_HIGH, height_high);
+               ret = reg_write16(client, REG_WINDOW_HEIGHT_HIGH, height);
+       if (ret)
+               return ret;
+       priv->crop_rect.width = width;
+       priv->crop_rect.height = height;
+
+       /* Set the output window size. Only 1:1 scale is supported so far. */
+       ret = reg_write16(client, REG_OUT_WIDTH_HIGH, width);
        if (!ret)
-               ret = reg_write(client, REG_OUT_HEIGHT_LOW,  height_low);
+               ret = reg_write16(client, REG_OUT_HEIGHT_HIGH, height);
 
+       /* Total width = output size + blanking */
        if (!ret)
-               ret = reg_write(client, REG_OUT_TOTAL_WIDTH_HIGH, total_width_high);
+               ret = reg_write16(client, REG_OUT_TOTAL_WIDTH_HIGH, total_width);
        if (!ret)
-               ret = reg_write(client, REG_OUT_TOTAL_WIDTH_LOW, total_width_low);
+               ret = reg_write16(client, REG_OUT_TOTAL_HEIGHT_HIGH, total_height);
+
+       /* Sets the window for AWB calculations */
        if (!ret)
-               ret = reg_write(client, REG_OUT_TOTAL_HEIGHT_HIGH, total_height_high);
+               ret = reg_write16(client, REG_AVG_WINDOW_END_X_HIGH, width);
        if (!ret)
-               ret = reg_write(client, REG_OUT_TOTAL_HEIGHT_LOW,  total_height_low);
+               ret = reg_write16(client, REG_AVG_WINDOW_END_Y_HIGH, height);
 
        return ret;
 }
@@ -744,18 +788,18 @@ static int ov5642_set_resolution(struct i2c_client *client)
 static int ov5642_try_fmt(struct v4l2_subdev *sd,
                          struct v4l2_mbus_framefmt *mf)
 {
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct ov5642 *priv = to_ov5642(client);
        const struct ov5642_datafmt *fmt = ov5642_find_datafmt(mf->code);
 
-       dev_dbg(sd->v4l2_dev->dev, "%s(%u) width: %u heigth: %u\n",
-                       __func__, mf->code, mf->width, mf->height);
+       mf->width = priv->crop_rect.width;
+       mf->height = priv->crop_rect.height;
 
        if (!fmt) {
                mf->code        = ov5642_colour_fmts[0].code;
                mf->colorspace  = ov5642_colour_fmts[0].colorspace;
        }
 
-       mf->width       = OV5642_WIDTH;
-       mf->height      = OV5642_HEIGHT;
        mf->field       = V4L2_FIELD_NONE;
 
        return 0;
@@ -767,20 +811,13 @@ static int ov5642_s_fmt(struct v4l2_subdev *sd,
        struct i2c_client *client = v4l2_get_subdevdata(sd);
        struct ov5642 *priv = to_ov5642(client);
 
-       dev_dbg(sd->v4l2_dev->dev, "%s(%u)\n", __func__, mf->code);
-
        /* MIPI CSI could have changed the format, double-check */
        if (!ov5642_find_datafmt(mf->code))
                return -EINVAL;
 
        ov5642_try_fmt(sd, mf);
-
        priv->fmt = ov5642_find_datafmt(mf->code);
 
-       ov5642_write_array(client, ov5642_default_regs_init);
-       ov5642_set_resolution(client);
-       ov5642_write_array(client, ov5642_default_regs_finalise);
-
        return 0;
 }
 
@@ -794,8 +831,8 @@ static int ov5642_g_fmt(struct v4l2_subdev *sd,
 
        mf->code        = fmt->code;
        mf->colorspace  = fmt->colorspace;
-       mf->width       = OV5642_WIDTH;
-       mf->height      = OV5642_HEIGHT;
+       mf->width       = priv->crop_rect.width;
+       mf->height      = priv->crop_rect.height;
        mf->field       = V4L2_FIELD_NONE;
 
        return 0;
@@ -828,15 +865,44 @@ static int ov5642_g_chip_ident(struct v4l2_subdev *sd,
        return 0;
 }
 
+static int ov5642_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct ov5642 *priv = to_ov5642(client);
+       struct v4l2_rect *rect = &a->c;
+       int ret;
+
+       v4l_bound_align_image(&rect->width, 48, OV5642_MAX_WIDTH, 1,
+                             &rect->height, 32, OV5642_MAX_HEIGHT, 1, 0);
+
+       priv->crop_rect.width   = rect->width;
+       priv->crop_rect.height  = rect->height;
+       priv->total_width       = rect->width + BLANKING_EXTRA_WIDTH;
+       priv->total_height      = max_t(int, rect->height +
+                                                       BLANKING_EXTRA_HEIGHT,
+                                                       BLANKING_MIN_HEIGHT);
+       priv->crop_rect.width           = rect->width;
+       priv->crop_rect.height          = rect->height;
+
+       ret = ov5642_write_array(client, ov5642_default_regs_init);
+       if (!ret)
+               ret = ov5642_set_resolution(sd);
+       if (!ret)
+               ret = ov5642_write_array(client, ov5642_default_regs_finalise);
+
+       return ret;
+}
+
 static int ov5642_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
 {
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct ov5642 *priv = to_ov5642(client);
        struct v4l2_rect *rect = &a->c;
 
-       a->type         = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-       rect->top       = 0;
-       rect->left      = 0;
-       rect->width     = OV5642_WIDTH;
-       rect->height    = OV5642_HEIGHT;
+       if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       *rect = priv->crop_rect;
 
        return 0;
 }
@@ -845,8 +911,8 @@ static int ov5642_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
 {
        a->bounds.left                  = 0;
        a->bounds.top                   = 0;
-       a->bounds.width                 = OV5642_WIDTH;
-       a->bounds.height                = OV5642_HEIGHT;
+       a->bounds.width                 = OV5642_MAX_WIDTH;
+       a->bounds.height                = OV5642_MAX_HEIGHT;
        a->defrect                      = a->bounds;
        a->type                         = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        a->pixelaspect.numerator        = 1;
@@ -855,16 +921,47 @@ static int ov5642_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
        return 0;
 }
 
+static int ov5642_g_mbus_config(struct v4l2_subdev *sd,
+                               struct v4l2_mbus_config *cfg)
+{
+       cfg->type = V4L2_MBUS_CSI2;
+       cfg->flags = V4L2_MBUS_CSI2_2_LANE | V4L2_MBUS_CSI2_CHANNEL_0 |
+                                       V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
+
+       return 0;
+}
+
+static int ov5642_s_power(struct v4l2_subdev *sd, int on)
+{
+       struct i2c_client *client;
+       int ret;
+
+       if (!on)
+               return 0;
+
+       client = v4l2_get_subdevdata(sd);
+       ret = ov5642_write_array(client, ov5642_default_regs_init);
+       if (!ret)
+               ret = ov5642_set_resolution(sd);
+       if (!ret)
+               ret = ov5642_write_array(client, ov5642_default_regs_finalise);
+
+       return ret;
+}
+
 static struct v4l2_subdev_video_ops ov5642_subdev_video_ops = {
        .s_mbus_fmt     = ov5642_s_fmt,
        .g_mbus_fmt     = ov5642_g_fmt,
        .try_mbus_fmt   = ov5642_try_fmt,
        .enum_mbus_fmt  = ov5642_enum_fmt,
+       .s_crop         = ov5642_s_crop,
        .g_crop         = ov5642_g_crop,
        .cropcap        = ov5642_cropcap,
+       .g_mbus_config  = ov5642_g_mbus_config,
 };
 
 static struct v4l2_subdev_core_ops ov5642_subdev_core_ops = {
+       .s_power        = ov5642_s_power,
        .g_chip_ident   = ov5642_g_chip_ident,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
        .g_register     = ov5642_get_register,
@@ -877,28 +974,7 @@ static struct v4l2_subdev_ops ov5642_subdev_ops = {
        .video  = &ov5642_subdev_video_ops,
 };
 
-/*
- * We have to provide soc-camera operations, but we don't have anything to say
- * there. The MIPI CSI2 driver will provide .query_bus_param and .set_bus_param
- */
-static unsigned long soc_ov5642_query_bus_param(struct soc_camera_device *icd)
-{
-       return 0;
-}
-
-static int soc_ov5642_set_bus_param(struct soc_camera_device *icd,
-                                unsigned long flags)
-{
-       return -EINVAL;
-}
-
-static struct soc_camera_ops soc_ov5642_ops = {
-       .query_bus_param        = soc_ov5642_query_bus_param,
-       .set_bus_param          = soc_ov5642_set_bus_param,
-};
-
-static int ov5642_video_probe(struct soc_camera_device *icd,
-                             struct i2c_client *client)
+static int ov5642_video_probe(struct i2c_client *client)
 {
        int ret;
        u8 id_high, id_low;
@@ -929,16 +1005,9 @@ static int ov5642_probe(struct i2c_client *client,
                        const struct i2c_device_id *did)
 {
        struct ov5642 *priv;
-       struct soc_camera_device *icd = client->dev.platform_data;
-       struct soc_camera_link *icl;
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
        int ret;
 
-       if (!icd) {
-               dev_err(&client->dev, "OV5642: missing soc-camera data!\n");
-               return -EINVAL;
-       }
-
-       icl = to_soc_camera_link(icd);
        if (!icl) {
                dev_err(&client->dev, "OV5642: missing platform data!\n");
                return -EINVAL;
@@ -950,17 +1019,24 @@ static int ov5642_probe(struct i2c_client *client,
 
        v4l2_i2c_subdev_init(&priv->subdev, client, &ov5642_subdev_ops);
 
-       icd->ops        = &soc_ov5642_ops;
-       priv->fmt       = &ov5642_colour_fmts[0];
+       priv->fmt               = &ov5642_colour_fmts[0];
+
+       priv->crop_rect.width   = OV5642_DEFAULT_WIDTH;
+       priv->crop_rect.height  = OV5642_DEFAULT_HEIGHT;
+       priv->crop_rect.left    = (OV5642_MAX_WIDTH - OV5642_DEFAULT_WIDTH) / 2;
+       priv->crop_rect.top     = (OV5642_MAX_HEIGHT - OV5642_DEFAULT_HEIGHT) / 2;
+       priv->crop_rect.width   = OV5642_DEFAULT_WIDTH;
+       priv->crop_rect.height  = OV5642_DEFAULT_HEIGHT;
+       priv->total_width = OV5642_DEFAULT_WIDTH + BLANKING_EXTRA_WIDTH;
+       priv->total_height = BLANKING_MIN_HEIGHT;
 
-       ret = ov5642_video_probe(icd, client);
+       ret = ov5642_video_probe(client);
        if (ret < 0)
                goto error;
 
        return 0;
 
 error:
-       icd->ops = NULL;
        kfree(priv);
        return ret;
 }
@@ -968,10 +1044,8 @@ error:
 static int ov5642_remove(struct i2c_client *client)
 {
        struct ov5642 *priv = to_ov5642(client);
-       struct soc_camera_device *icd = client->dev.platform_data;
-       struct soc_camera_link *icl = to_soc_camera_link(icd);
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
 
-       icd->ops = NULL;
        if (icl->free_bus)
                icl->free_bus(icl);
        kfree(priv);
index 456d9ad..d5b0572 100644 (file)
 #include <linux/delay.h>
 #include <linux/i2c.h>
 #include <linux/slab.h>
+#include <linux/v4l2-mediabus.h>
 
 #include <media/soc_camera.h>
 #include <media/v4l2-chip-ident.h>
-
+#include <media/v4l2-ctrls.h>
 
 /* Register definitions */
 #define REG_GAIN               0x00    /* range 00 - 3F */
@@ -177,20 +178,23 @@ struct ov6650_reg {
 
 struct ov6650 {
        struct v4l2_subdev      subdev;
-
-       int                     gain;
-       int                     blue;
-       int                     red;
-       int                     saturation;
-       int                     hue;
-       int                     brightness;
-       int                     exposure;
-       int                     gamma;
-       int                     aec;
-       bool                    vflip;
-       bool                    hflip;
-       bool                    awb;
-       bool                    agc;
+       struct v4l2_ctrl_handler hdl;
+       struct {
+               /* exposure/autoexposure cluster */
+               struct v4l2_ctrl *autoexposure;
+               struct v4l2_ctrl *exposure;
+       };
+       struct {
+               /* gain/autogain cluster */
+               struct v4l2_ctrl *autogain;
+               struct v4l2_ctrl *gain;
+       };
+       struct {
+               /* blue/red/autowhitebalance cluster */
+               struct v4l2_ctrl *autowb;
+               struct v4l2_ctrl *blue;
+               struct v4l2_ctrl *red;
+       };
        bool                    half_scale;     /* scale down output by 2 */
        struct v4l2_rect        rect;           /* sensor cropping window */
        unsigned long           pclk_limit;     /* from host */
@@ -210,126 +214,6 @@ static enum v4l2_mbus_pixelcode ov6650_codes[] = {
        V4L2_MBUS_FMT_Y8_1X8,
 };
 
-static const struct v4l2_queryctrl ov6650_controls[] = {
-       {
-               .id             = V4L2_CID_AUTOGAIN,
-               .type           = V4L2_CTRL_TYPE_BOOLEAN,
-               .name           = "AGC",
-               .minimum        = 0,
-               .maximum        = 1,
-               .step           = 1,
-               .default_value  = 1,
-       },
-       {
-               .id             = V4L2_CID_GAIN,
-               .type           = V4L2_CTRL_TYPE_INTEGER,
-               .name           = "Gain",
-               .minimum        = 0,
-               .maximum        = 0x3f,
-               .step           = 1,
-               .default_value  = DEF_GAIN,
-       },
-       {
-               .id             = V4L2_CID_AUTO_WHITE_BALANCE,
-               .type           = V4L2_CTRL_TYPE_BOOLEAN,
-               .name           = "AWB",
-               .minimum        = 0,
-               .maximum        = 1,
-               .step           = 1,
-               .default_value  = 1,
-       },
-       {
-               .id             = V4L2_CID_BLUE_BALANCE,
-               .type           = V4L2_CTRL_TYPE_INTEGER,
-               .name           = "Blue",
-               .minimum        = 0,
-               .maximum        = 0xff,
-               .step           = 1,
-               .default_value  = DEF_BLUE,
-       },
-       {
-               .id             = V4L2_CID_RED_BALANCE,
-               .type           = V4L2_CTRL_TYPE_INTEGER,
-               .name           = "Red",
-               .minimum        = 0,
-               .maximum        = 0xff,
-               .step           = 1,
-               .default_value  = DEF_RED,
-       },
-       {
-               .id             = V4L2_CID_SATURATION,
-               .type           = V4L2_CTRL_TYPE_INTEGER,
-               .name           = "Saturation",
-               .minimum        = 0,
-               .maximum        = 0xf,
-               .step           = 1,
-               .default_value  = 0x8,
-       },
-       {
-               .id             = V4L2_CID_HUE,
-               .type           = V4L2_CTRL_TYPE_INTEGER,
-               .name           = "Hue",
-               .minimum        = 0,
-               .maximum        = HUE_MASK,
-               .step           = 1,
-               .default_value  = DEF_HUE,
-       },
-       {
-               .id             = V4L2_CID_BRIGHTNESS,
-               .type           = V4L2_CTRL_TYPE_INTEGER,
-               .name           = "Brightness",
-               .minimum        = 0,
-               .maximum        = 0xff,
-               .step           = 1,
-               .default_value  = 0x80,
-       },
-       {
-               .id             = V4L2_CID_EXPOSURE_AUTO,
-               .type           = V4L2_CTRL_TYPE_INTEGER,
-               .name           = "AEC",
-               .minimum        = 0,
-               .maximum        = 3,
-               .step           = 1,
-               .default_value  = 0,
-       },
-       {
-               .id             = V4L2_CID_EXPOSURE,
-               .type           = V4L2_CTRL_TYPE_INTEGER,
-               .name           = "Exposure",
-               .minimum        = 0,
-               .maximum        = 0xff,
-               .step           = 1,
-               .default_value  = DEF_AECH,
-       },
-       {
-               .id             = V4L2_CID_GAMMA,
-               .type           = V4L2_CTRL_TYPE_INTEGER,
-               .name           = "Gamma",
-               .minimum        = 0,
-               .maximum        = 0xff,
-               .step           = 1,
-               .default_value  = 0x12,
-       },
-       {
-               .id             = V4L2_CID_VFLIP,
-               .type           = V4L2_CTRL_TYPE_BOOLEAN,
-               .name           = "Flip Vertically",
-               .minimum        = 0,
-               .maximum        = 1,
-               .step           = 1,
-               .default_value  = 0,
-       },
-       {
-               .id             = V4L2_CID_HFLIP,
-               .type           = V4L2_CTRL_TYPE_BOOLEAN,
-               .name           = "Flip Horizontally",
-               .minimum        = 0,
-               .maximum        = 1,
-               .step           = 1,
-               .default_value  = 0,
-       },
-};
-
 /* read a register */
 static int ov6650_reg_read(struct i2c_client *client, u8 reg, u8 *val)
 {
@@ -419,213 +303,90 @@ static int ov6650_s_stream(struct v4l2_subdev *sd, int enable)
        return 0;
 }
 
-/* Alter bus settings on camera side */
-static int ov6650_set_bus_param(struct soc_camera_device *icd,
-                               unsigned long flags)
-{
-       struct soc_camera_link *icl = to_soc_camera_link(icd);
-       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
-       int ret;
-
-       flags = soc_camera_apply_sensor_flags(icl, flags);
-
-       if (flags & SOCAM_PCLK_SAMPLE_RISING)
-               ret = ov6650_reg_rmw(client, REG_COMJ, COMJ_PCLK_RISING, 0);
-       else
-               ret = ov6650_reg_rmw(client, REG_COMJ, 0, COMJ_PCLK_RISING);
-       if (ret)
-               return ret;
-
-       if (flags & SOCAM_HSYNC_ACTIVE_LOW)
-               ret = ov6650_reg_rmw(client, REG_COMF, COMF_HREF_LOW, 0);
-       else
-               ret = ov6650_reg_rmw(client, REG_COMF, 0, COMF_HREF_LOW);
-       if (ret)
-               return ret;
-
-       if (flags & SOCAM_VSYNC_ACTIVE_HIGH)
-               ret = ov6650_reg_rmw(client, REG_COMJ, COMJ_VSYNC_HIGH, 0);
-       else
-               ret = ov6650_reg_rmw(client, REG_COMJ, 0, COMJ_VSYNC_HIGH);
-
-       return ret;
-}
-
-/* Request bus settings on camera side */
-static unsigned long ov6650_query_bus_param(struct soc_camera_device *icd)
-{
-       struct soc_camera_link *icl = to_soc_camera_link(icd);
-
-       unsigned long flags = SOCAM_MASTER |
-               SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING |
-               SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_LOW |
-               SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW |
-               SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATAWIDTH_8;
-
-       return soc_camera_apply_sensor_flags(icl, flags);
-}
-
 /* Get status of additional camera capabilities */
-static int ov6650_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+static int ov6550_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
 {
+       struct ov6650 *priv = container_of(ctrl->handler, struct ov6650, hdl);
+       struct v4l2_subdev *sd = &priv->subdev;
        struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct ov6650 *priv = to_ov6650(client);
-       uint8_t reg;
-       int ret = 0;
+       uint8_t reg, reg2;
+       int ret;
 
        switch (ctrl->id) {
        case V4L2_CID_AUTOGAIN:
-               ctrl->value = priv->agc;
-               break;
-       case V4L2_CID_GAIN:
-               if (priv->agc) {
-                       ret = ov6650_reg_read(client, REG_GAIN, &reg);
-                       ctrl->value = reg;
-               } else {
-                       ctrl->value = priv->gain;
-               }
-               break;
+               ret = ov6650_reg_read(client, REG_GAIN, &reg);
+               if (!ret)
+                       priv->gain->val = reg;
+               return ret;
        case V4L2_CID_AUTO_WHITE_BALANCE:
-               ctrl->value = priv->awb;
-               break;
-       case V4L2_CID_BLUE_BALANCE:
-               if (priv->awb) {
-                       ret = ov6650_reg_read(client, REG_BLUE, &reg);
-                       ctrl->value = reg;
-               } else {
-                       ctrl->value = priv->blue;
-               }
-               break;
-       case V4L2_CID_RED_BALANCE:
-               if (priv->awb) {
-                       ret = ov6650_reg_read(client, REG_RED, &reg);
-                       ctrl->value = reg;
-               } else {
-                       ctrl->value = priv->red;
+               ret = ov6650_reg_read(client, REG_BLUE, &reg);
+               if (!ret)
+                       ret = ov6650_reg_read(client, REG_RED, &reg2);
+               if (!ret) {
+                       priv->blue->val = reg;
+                       priv->red->val = reg2;
                }
-               break;
-       case V4L2_CID_SATURATION:
-               ctrl->value = priv->saturation;
-               break;
-       case V4L2_CID_HUE:
-               ctrl->value = priv->hue;
-               break;
-       case V4L2_CID_BRIGHTNESS:
-               ctrl->value = priv->brightness;
-               break;
+               return ret;
        case V4L2_CID_EXPOSURE_AUTO:
-               ctrl->value = priv->aec;
-               break;
-       case V4L2_CID_EXPOSURE:
-               if (priv->aec) {
-                       ret = ov6650_reg_read(client, REG_AECH, &reg);
-                       ctrl->value = reg;
-               } else {
-                       ctrl->value = priv->exposure;
-               }
-               break;
-       case V4L2_CID_GAMMA:
-               ctrl->value = priv->gamma;
-               break;
-       case V4L2_CID_VFLIP:
-               ctrl->value = priv->vflip;
-               break;
-       case V4L2_CID_HFLIP:
-               ctrl->value = priv->hflip;
-               break;
+               ret = ov6650_reg_read(client, REG_AECH, &reg);
+               if (!ret)
+                       priv->exposure->val = reg;
+               return ret;
        }
-       return ret;
+       return -EINVAL;
 }
 
 /* Set status of additional camera capabilities */
-static int ov6650_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+static int ov6550_s_ctrl(struct v4l2_ctrl *ctrl)
 {
+       struct ov6650 *priv = container_of(ctrl->handler, struct ov6650, hdl);
+       struct v4l2_subdev *sd = &priv->subdev;
        struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct ov6650 *priv = to_ov6650(client);
-       int ret = 0;
+       int ret;
 
        switch (ctrl->id) {
        case V4L2_CID_AUTOGAIN:
                ret = ov6650_reg_rmw(client, REG_COMB,
-                               ctrl->value ? COMB_AGC : 0, COMB_AGC);
-               if (!ret)
-                       priv->agc = ctrl->value;
-               break;
-       case V4L2_CID_GAIN:
-               ret = ov6650_reg_write(client, REG_GAIN, ctrl->value);
-               if (!ret)
-                       priv->gain = ctrl->value;
-               break;
+                               ctrl->val ? COMB_AGC : 0, COMB_AGC);
+               if (!ret && !ctrl->val)
+                       ret = ov6650_reg_write(client, REG_GAIN, priv->gain->val);
+               return ret;
        case V4L2_CID_AUTO_WHITE_BALANCE:
                ret = ov6650_reg_rmw(client, REG_COMB,
-                               ctrl->value ? COMB_AWB : 0, COMB_AWB);
-               if (!ret)
-                       priv->awb = ctrl->value;
-               break;
-       case V4L2_CID_BLUE_BALANCE:
-               ret = ov6650_reg_write(client, REG_BLUE, ctrl->value);
-               if (!ret)
-                       priv->blue = ctrl->value;
-               break;
-       case V4L2_CID_RED_BALANCE:
-               ret = ov6650_reg_write(client, REG_RED, ctrl->value);
-               if (!ret)
-                       priv->red = ctrl->value;
-               break;
+                               ctrl->val ? COMB_AWB : 0, COMB_AWB);
+               if (!ret && !ctrl->val) {
+                       ret = ov6650_reg_write(client, REG_BLUE, priv->blue->val);
+                       if (!ret)
+                               ret = ov6650_reg_write(client, REG_RED,
+                                                       priv->red->val);
+               }
+               return ret;
        case V4L2_CID_SATURATION:
-               ret = ov6650_reg_rmw(client, REG_SAT, SET_SAT(ctrl->value),
+               return ov6650_reg_rmw(client, REG_SAT, SET_SAT(ctrl->val),
                                SAT_MASK);
-               if (!ret)
-                       priv->saturation = ctrl->value;
-               break;
        case V4L2_CID_HUE:
-               ret = ov6650_reg_rmw(client, REG_HUE, SET_HUE(ctrl->value),
+               return ov6650_reg_rmw(client, REG_HUE, SET_HUE(ctrl->val),
                                HUE_MASK);
-               if (!ret)
-                       priv->hue = ctrl->value;
-               break;
        case V4L2_CID_BRIGHTNESS:
-               ret = ov6650_reg_write(client, REG_BRT, ctrl->value);
-               if (!ret)
-                       priv->brightness = ctrl->value;
-               break;
+               return ov6650_reg_write(client, REG_BRT, ctrl->val);
        case V4L2_CID_EXPOSURE_AUTO:
-               switch (ctrl->value) {
-               case V4L2_EXPOSURE_AUTO:
-                       ret = ov6650_reg_rmw(client, REG_COMB, COMB_AEC, 0);
-                       break;
-               default:
-                       ret = ov6650_reg_rmw(client, REG_COMB, 0, COMB_AEC);
-                       break;
-               }
-               if (!ret)
-                       priv->aec = ctrl->value;
-               break;
-       case V4L2_CID_EXPOSURE:
-               ret = ov6650_reg_write(client, REG_AECH, ctrl->value);
-               if (!ret)
-                       priv->exposure = ctrl->value;
-               break;
+               ret = ov6650_reg_rmw(client, REG_COMB, ctrl->val ==
+                               V4L2_EXPOSURE_AUTO ? COMB_AEC : 0, COMB_AEC);
+               if (!ret && ctrl->val == V4L2_EXPOSURE_MANUAL)
+                       ret = ov6650_reg_write(client, REG_AECH,
+                                               priv->exposure->val);
+               return ret;
        case V4L2_CID_GAMMA:
-               ret = ov6650_reg_write(client, REG_GAM1, ctrl->value);
-               if (!ret)
-                       priv->gamma = ctrl->value;
-               break;
+               return ov6650_reg_write(client, REG_GAM1, ctrl->val);
        case V4L2_CID_VFLIP:
-               ret = ov6650_reg_rmw(client, REG_COMB,
-                               ctrl->value ? COMB_FLIP_V : 0, COMB_FLIP_V);
-               if (!ret)
-                       priv->vflip = ctrl->value;
-               break;
+               return ov6650_reg_rmw(client, REG_COMB,
+                               ctrl->val ? COMB_FLIP_V : 0, COMB_FLIP_V);
        case V4L2_CID_HFLIP:
-               ret = ov6650_reg_rmw(client, REG_COMB,
-                               ctrl->value ? COMB_FLIP_H : 0, COMB_FLIP_H);
-               if (!ret)
-                       priv->hflip = ctrl->value;
-               break;
+               return ov6650_reg_rmw(client, REG_COMB,
+                               ctrl->val ? COMB_FLIP_H : 0, COMB_FLIP_H);
        }
 
-       return ret;
+       return -EINVAL;
 }
 
 /* Get chip identification */
@@ -778,7 +539,7 @@ static u8 to_clkrc(struct v4l2_fract *timeperframe,
 static int ov6650_s_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct soc_camera_device *icd = client->dev.platform_data;
+       struct soc_camera_device *icd = (struct soc_camera_device *)sd->grp_id;
        struct soc_camera_sense *sense = icd->sense;
        struct ov6650 *priv = to_ov6650(client);
        bool half_scale = !is_unscaled_ok(mf->width, mf->height, &priv->rect);
@@ -1057,8 +818,7 @@ static int ov6650_prog_dflt(struct i2c_client *client)
        return ret;
 }
 
-static int ov6650_video_probe(struct soc_camera_device *icd,
-                               struct i2c_client *client)
+static int ov6650_video_probe(struct i2c_client *client)
 {
        u8              pidh, pidl, midh, midl;
        int             ret = 0;
@@ -1094,16 +854,12 @@ static int ov6650_video_probe(struct soc_camera_device *icd,
        return ret;
 }
 
-static struct soc_camera_ops ov6650_ops = {
-       .set_bus_param          = ov6650_set_bus_param,
-       .query_bus_param        = ov6650_query_bus_param,
-       .controls               = ov6650_controls,
-       .num_controls           = ARRAY_SIZE(ov6650_controls),
+static const struct v4l2_ctrl_ops ov6550_ctrl_ops = {
+       .g_volatile_ctrl = ov6550_g_volatile_ctrl,
+       .s_ctrl = ov6550_s_ctrl,
 };
 
 static struct v4l2_subdev_core_ops ov6650_core_ops = {
-       .g_ctrl                 = ov6650_g_ctrl,
-       .s_ctrl                 = ov6650_s_ctrl,
        .g_chip_ident           = ov6650_g_chip_ident,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
        .g_register             = ov6650_get_register,
@@ -1111,6 +867,55 @@ static struct v4l2_subdev_core_ops ov6650_core_ops = {
 #endif
 };
 
+/* Request bus settings on camera side */
+static int ov6650_g_mbus_config(struct v4l2_subdev *sd,
+                               struct v4l2_mbus_config *cfg)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+       cfg->flags = V4L2_MBUS_MASTER |
+               V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_PCLK_SAMPLE_FALLING |
+               V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_LOW |
+               V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_LOW |
+               V4L2_MBUS_DATA_ACTIVE_HIGH;
+       cfg->type = V4L2_MBUS_PARALLEL;
+       cfg->flags = soc_camera_apply_board_flags(icl, cfg);
+
+       return 0;
+}
+
+/* Alter bus settings on camera side */
+static int ov6650_s_mbus_config(struct v4l2_subdev *sd,
+                               const struct v4l2_mbus_config *cfg)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+       unsigned long flags = soc_camera_apply_board_flags(icl, cfg);
+       int ret;
+
+       if (flags & V4L2_MBUS_PCLK_SAMPLE_RISING)
+               ret = ov6650_reg_rmw(client, REG_COMJ, COMJ_PCLK_RISING, 0);
+       else
+               ret = ov6650_reg_rmw(client, REG_COMJ, 0, COMJ_PCLK_RISING);
+       if (ret)
+               return ret;
+
+       if (flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
+               ret = ov6650_reg_rmw(client, REG_COMF, COMF_HREF_LOW, 0);
+       else
+               ret = ov6650_reg_rmw(client, REG_COMF, 0, COMF_HREF_LOW);
+       if (ret)
+               return ret;
+
+       if (flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH)
+               ret = ov6650_reg_rmw(client, REG_COMJ, COMJ_VSYNC_HIGH, 0);
+       else
+               ret = ov6650_reg_rmw(client, REG_COMJ, 0, COMJ_VSYNC_HIGH);
+
+       return ret;
+}
+
 static struct v4l2_subdev_video_ops ov6650_video_ops = {
        .s_stream       = ov6650_s_stream,
        .g_mbus_fmt     = ov6650_g_fmt,
@@ -1122,6 +927,8 @@ static struct v4l2_subdev_video_ops ov6650_video_ops = {
        .s_crop         = ov6650_s_crop,
        .g_parm         = ov6650_g_parm,
        .s_parm         = ov6650_s_parm,
+       .g_mbus_config  = ov6650_g_mbus_config,
+       .s_mbus_config  = ov6650_s_mbus_config,
 };
 
 static struct v4l2_subdev_ops ov6650_subdev_ops = {
@@ -1136,16 +943,9 @@ static int ov6650_probe(struct i2c_client *client,
                        const struct i2c_device_id *did)
 {
        struct ov6650 *priv;
-       struct soc_camera_device *icd = client->dev.platform_data;
-       struct soc_camera_link *icl;
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
        int ret;
 
-       if (!icd) {
-               dev_err(&client->dev, "Missing soc-camera data!\n");
-               return -EINVAL;
-       }
-
-       icl = to_soc_camera_link(icd);
        if (!icl) {
                dev_err(&client->dev, "Missing platform_data for driver\n");
                return -EINVAL;
@@ -1159,8 +959,46 @@ static int ov6650_probe(struct i2c_client *client,
        }
 
        v4l2_i2c_subdev_init(&priv->subdev, client, &ov6650_subdev_ops);
+       v4l2_ctrl_handler_init(&priv->hdl, 13);
+       v4l2_ctrl_new_std(&priv->hdl, &ov6550_ctrl_ops,
+                       V4L2_CID_VFLIP, 0, 1, 1, 0);
+       v4l2_ctrl_new_std(&priv->hdl, &ov6550_ctrl_ops,
+                       V4L2_CID_HFLIP, 0, 1, 1, 0);
+       priv->autogain = v4l2_ctrl_new_std(&priv->hdl, &ov6550_ctrl_ops,
+                       V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
+       priv->gain = v4l2_ctrl_new_std(&priv->hdl, &ov6550_ctrl_ops,
+                       V4L2_CID_GAIN, 0, 0x3f, 1, DEF_GAIN);
+       priv->autowb = v4l2_ctrl_new_std(&priv->hdl, &ov6550_ctrl_ops,
+                       V4L2_CID_AUTO_WHITE_BALANCE, 0, 1, 1, 1);
+       priv->blue = v4l2_ctrl_new_std(&priv->hdl, &ov6550_ctrl_ops,
+                       V4L2_CID_BLUE_BALANCE, 0, 0xff, 1, DEF_BLUE);
+       priv->red = v4l2_ctrl_new_std(&priv->hdl, &ov6550_ctrl_ops,
+                       V4L2_CID_RED_BALANCE, 0, 0xff, 1, DEF_RED);
+       v4l2_ctrl_new_std(&priv->hdl, &ov6550_ctrl_ops,
+                       V4L2_CID_SATURATION, 0, 0xf, 1, 0x8);
+       v4l2_ctrl_new_std(&priv->hdl, &ov6550_ctrl_ops,
+                       V4L2_CID_HUE, 0, HUE_MASK, 1, DEF_HUE);
+       v4l2_ctrl_new_std(&priv->hdl, &ov6550_ctrl_ops,
+                       V4L2_CID_BRIGHTNESS, 0, 0xff, 1, 0x80);
+       priv->autoexposure = v4l2_ctrl_new_std_menu(&priv->hdl,
+                       &ov6550_ctrl_ops, V4L2_CID_EXPOSURE_AUTO,
+                       V4L2_EXPOSURE_MANUAL, 0, V4L2_EXPOSURE_AUTO);
+       priv->exposure = v4l2_ctrl_new_std(&priv->hdl, &ov6550_ctrl_ops,
+                       V4L2_CID_EXPOSURE, 0, 0xff, 1, DEF_AECH);
+       v4l2_ctrl_new_std(&priv->hdl, &ov6550_ctrl_ops,
+                       V4L2_CID_GAMMA, 0, 0xff, 1, 0x12);
+
+       priv->subdev.ctrl_handler = &priv->hdl;
+       if (priv->hdl.error) {
+               int err = priv->hdl.error;
 
-       icd->ops = &ov6650_ops;
+               kfree(priv);
+               return err;
+       }
+       v4l2_ctrl_auto_cluster(2, &priv->autogain, 0, true);
+       v4l2_ctrl_auto_cluster(3, &priv->autowb, 0, true);
+       v4l2_ctrl_auto_cluster(2, &priv->autoexposure,
+                               V4L2_EXPOSURE_MANUAL, true);
 
        priv->rect.left   = DEF_HSTRT << 1;
        priv->rect.top    = DEF_VSTRT << 1;
@@ -1170,10 +1008,12 @@ static int ov6650_probe(struct i2c_client *client,
        priv->code        = V4L2_MBUS_FMT_YUYV8_2X8;
        priv->colorspace  = V4L2_COLORSPACE_JPEG;
 
-       ret = ov6650_video_probe(icd, client);
+       ret = ov6650_video_probe(client);
+       if (!ret)
+               ret = v4l2_ctrl_handler_setup(&priv->hdl);
 
        if (ret) {
-               icd->ops = NULL;
+               v4l2_ctrl_handler_free(&priv->hdl);
                kfree(priv);
        }
 
@@ -1184,6 +1024,8 @@ static int ov6650_remove(struct i2c_client *client)
 {
        struct ov6650 *priv = to_ov6650(client);
 
+       v4l2_device_unregister_subdev(&priv->subdev);
+       v4l2_ctrl_handler_free(&priv->hdl);
        kfree(priv);
        return 0;
 }
index 397870f..9f6ce3d 100644 (file)
 #include <linux/i2c.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
+#include <linux/v4l2-mediabus.h>
 #include <linux/videodev2.h>
+
+#include <media/ov772x.h>
+#include <media/soc_camera.h>
+#include <media/v4l2-ctrls.h>
 #include <media/v4l2-chip-ident.h>
 #include <media/v4l2-subdev.h>
-#include <media/soc_camera.h>
-#include <media/soc_mediabus.h>
-#include <media/ov772x.h>
 
 /*
  * register offset
@@ -400,6 +402,7 @@ struct ov772x_win_size {
 
 struct ov772x_priv {
        struct v4l2_subdev                subdev;
+       struct v4l2_ctrl_handler          hdl;
        struct ov772x_camera_info        *info;
        const struct ov772x_color_format *cfmt;
        const struct ov772x_win_size     *win;
@@ -517,36 +520,6 @@ static const struct ov772x_win_size ov772x_win_qvga = {
        .regs     = ov772x_qvga_regs,
 };
 
-static const struct v4l2_queryctrl ov772x_controls[] = {
-       {
-               .id             = V4L2_CID_VFLIP,
-               .type           = V4L2_CTRL_TYPE_BOOLEAN,
-               .name           = "Flip Vertically",
-               .minimum        = 0,
-               .maximum        = 1,
-               .step           = 1,
-               .default_value  = 0,
-       },
-       {
-               .id             = V4L2_CID_HFLIP,
-               .type           = V4L2_CTRL_TYPE_BOOLEAN,
-               .name           = "Flip Horizontally",
-               .minimum        = 0,
-               .maximum        = 1,
-               .step           = 1,
-               .default_value  = 0,
-       },
-       {
-               .id             = V4L2_CID_BAND_STOP_FILTER,
-               .type           = V4L2_CTRL_TYPE_INTEGER,
-               .name           = "Band-stop filter",
-               .minimum        = 0,
-               .maximum        = 256,
-               .step           = 1,
-               .default_value  = 0,
-       },
-};
-
 /*
  * general function
  */
@@ -620,75 +593,30 @@ static int ov772x_s_stream(struct v4l2_subdev *sd, int enable)
        return 0;
 }
 
-static int ov772x_set_bus_param(struct soc_camera_device *icd,
-                               unsigned long             flags)
-{
-       return 0;
-}
-
-static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd)
-{
-       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
-       struct ov772x_priv *priv = i2c_get_clientdata(client);
-       struct soc_camera_link *icl = to_soc_camera_link(icd);
-       unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER |
-               SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH |
-               SOCAM_DATA_ACTIVE_HIGH;
-
-       if (priv->info->flags & OV772X_FLAG_8BIT)
-               flags |= SOCAM_DATAWIDTH_8;
-       else
-               flags |= SOCAM_DATAWIDTH_10;
-
-       return soc_camera_apply_sensor_flags(icl, flags);
-}
-
-static int ov772x_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
-{
-       struct ov772x_priv *priv = container_of(sd, struct ov772x_priv, subdev);
-
-       switch (ctrl->id) {
-       case V4L2_CID_VFLIP:
-               ctrl->value = priv->flag_vflip;
-               break;
-       case V4L2_CID_HFLIP:
-               ctrl->value = priv->flag_hflip;
-               break;
-       case V4L2_CID_BAND_STOP_FILTER:
-               ctrl->value = priv->band_filter;
-               break;
-       }
-       return 0;
-}
-
-static int ov772x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+static int ov772x_s_ctrl(struct v4l2_ctrl *ctrl)
 {
+       struct ov772x_priv *priv = container_of(ctrl->handler,
+                                               struct ov772x_priv, hdl);
+       struct v4l2_subdev *sd = &priv->subdev;
        struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct ov772x_priv *priv = container_of(sd, struct ov772x_priv, subdev);
        int ret = 0;
        u8 val;
 
        switch (ctrl->id) {
        case V4L2_CID_VFLIP:
-               val = ctrl->value ? VFLIP_IMG : 0x00;
-               priv->flag_vflip = ctrl->value;
+               val = ctrl->val ? VFLIP_IMG : 0x00;
+               priv->flag_vflip = ctrl->val;
                if (priv->info->flags & OV772X_FLAG_VFLIP)
                        val ^= VFLIP_IMG;
-               ret = ov772x_mask_set(client, COM3, VFLIP_IMG, val);
-               break;
+               return ov772x_mask_set(client, COM3, VFLIP_IMG, val);
        case V4L2_CID_HFLIP:
-               val = ctrl->value ? HFLIP_IMG : 0x00;
-               priv->flag_hflip = ctrl->value;
+               val = ctrl->val ? HFLIP_IMG : 0x00;
+               priv->flag_hflip = ctrl->val;
                if (priv->info->flags & OV772X_FLAG_HFLIP)
                        val ^= HFLIP_IMG;
-               ret = ov772x_mask_set(client, COM3, HFLIP_IMG, val);
-               break;
+               return ov772x_mask_set(client, COM3, HFLIP_IMG, val);
        case V4L2_CID_BAND_STOP_FILTER:
-               if ((unsigned)ctrl->value > 256)
-                       ctrl->value = 256;
-               if (ctrl->value == priv->band_filter)
-                       break;
-               if (!ctrl->value) {
+               if (!ctrl->val) {
                        /* Switch the filter off, it is on now */
                        ret = ov772x_mask_set(client, BDBASE, 0xff, 0xff);
                        if (!ret)
@@ -696,7 +624,7 @@ static int ov772x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
                                                      BNDF_ON_OFF, 0);
                } else {
                        /* Switch the filter on, set AEC low limit */
-                       val = 256 - ctrl->value;
+                       val = 256 - ctrl->val;
                        ret = ov772x_mask_set(client, COM8,
                                              BNDF_ON_OFF, BNDF_ON_OFF);
                        if (!ret)
@@ -704,11 +632,11 @@ static int ov772x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
                                                      0xff, val);
                }
                if (!ret)
-                       priv->band_filter = ctrl->value;
-               break;
+                       priv->band_filter = ctrl->val;
+               return ret;
        }
 
-       return ret;
+       return -EINVAL;
 }
 
 static int ov772x_g_chip_ident(struct v4l2_subdev *sd,
@@ -822,13 +750,13 @@ static int ov772x_set_params(struct i2c_client *client, u32 *width, u32 *height,
                        goto ov772x_set_fmt_error;
 
                ret = ov772x_mask_set(client,
-                                     EDGE_TRSHLD, EDGE_THRESHOLD_MASK,
+                                     EDGE_TRSHLD, OV772X_EDGE_THRESHOLD_MASK,
                                      priv->info->edgectrl.threshold);
                if (ret < 0)
                        goto ov772x_set_fmt_error;
 
                ret = ov772x_mask_set(client,
-                                     EDGE_STRNGT, EDGE_STRENGTH_MASK,
+                                     EDGE_STRNGT, OV772X_EDGE_STRENGTH_MASK,
                                      priv->info->edgectrl.strength);
                if (ret < 0)
                        goto ov772x_set_fmt_error;
@@ -840,13 +768,13 @@ static int ov772x_set_params(struct i2c_client *client, u32 *width, u32 *height,
                 * set upper and lower limit
                 */
                ret = ov772x_mask_set(client,
-                                     EDGE_UPPER, EDGE_UPPER_MASK,
+                                     EDGE_UPPER, OV772X_EDGE_UPPER_MASK,
                                      priv->info->edgectrl.upper);
                if (ret < 0)
                        goto ov772x_set_fmt_error;
 
                ret = ov772x_mask_set(client,
-                                     EDGE_LOWER, EDGE_LOWER_MASK,
+                                     EDGE_LOWER, OV772X_EDGE_LOWER_MASK,
                                      priv->info->edgectrl.lower);
                if (ret < 0)
                        goto ov772x_set_fmt_error;
@@ -1025,17 +953,12 @@ static int ov772x_try_fmt(struct v4l2_subdev *sd,
        return 0;
 }
 
-static int ov772x_video_probe(struct soc_camera_device *icd,
-                             struct i2c_client *client)
+static int ov772x_video_probe(struct i2c_client *client)
 {
        struct ov772x_priv *priv = to_ov772x(client);
        u8                  pid, ver;
        const char         *devname;
 
-       /* We must have a parent by now. And it cannot be a wrong one. */
-       BUG_ON(!icd->parent ||
-              to_soc_camera_host(icd->parent)->nr != icd->iface);
-
        /*
         * check and show product ID and manufacturer ID
         */
@@ -1064,20 +987,14 @@ static int ov772x_video_probe(struct soc_camera_device *icd,
                 ver,
                 i2c_smbus_read_byte_data(client, MIDH),
                 i2c_smbus_read_byte_data(client, MIDL));
-
-       return 0;
+       return v4l2_ctrl_handler_setup(&priv->hdl);
 }
 
-static struct soc_camera_ops ov772x_ops = {
-       .set_bus_param          = ov772x_set_bus_param,
-       .query_bus_param        = ov772x_query_bus_param,
-       .controls               = ov772x_controls,
-       .num_controls           = ARRAY_SIZE(ov772x_controls),
+static const struct v4l2_ctrl_ops ov772x_ctrl_ops = {
+       .s_ctrl = ov772x_s_ctrl,
 };
 
 static struct v4l2_subdev_core_ops ov772x_subdev_core_ops = {
-       .g_ctrl         = ov772x_g_ctrl,
-       .s_ctrl         = ov772x_s_ctrl,
        .g_chip_ident   = ov772x_g_chip_ident,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
        .g_register     = ov772x_g_register,
@@ -1095,6 +1012,21 @@ static int ov772x_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
        return 0;
 }
 
+static int ov772x_g_mbus_config(struct v4l2_subdev *sd,
+                               struct v4l2_mbus_config *cfg)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+       cfg->flags = V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_MASTER |
+               V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_HIGH |
+               V4L2_MBUS_DATA_ACTIVE_HIGH;
+       cfg->type = V4L2_MBUS_PARALLEL;
+       cfg->flags = soc_camera_apply_board_flags(icl, cfg);
+
+       return 0;
+}
+
 static struct v4l2_subdev_video_ops ov772x_subdev_video_ops = {
        .s_stream       = ov772x_s_stream,
        .g_mbus_fmt     = ov772x_g_fmt,
@@ -1103,6 +1035,7 @@ static struct v4l2_subdev_video_ops ov772x_subdev_video_ops = {
        .cropcap        = ov772x_cropcap,
        .g_crop         = ov772x_g_crop,
        .enum_mbus_fmt  = ov772x_enum_fmt,
+       .g_mbus_config  = ov772x_g_mbus_config,
 };
 
 static struct v4l2_subdev_ops ov772x_subdev_ops = {
@@ -1117,20 +1050,15 @@ static struct v4l2_subdev_ops ov772x_subdev_ops = {
 static int ov772x_probe(struct i2c_client *client,
                        const struct i2c_device_id *did)
 {
-       struct ov772x_priv        *priv;
-       struct soc_camera_device  *icd = client->dev.platform_data;
-       struct i2c_adapter        *adapter = to_i2c_adapter(client->dev.parent);
-       struct soc_camera_link    *icl;
-       int                        ret;
-
-       if (!icd) {
-               dev_err(&client->dev, "OV772X: missing soc-camera data!\n");
-               return -EINVAL;
-       }
+       struct ov772x_priv      *priv;
+       struct soc_camera_link  *icl = soc_camera_i2c_to_link(client);
+       struct i2c_adapter      *adapter = to_i2c_adapter(client->dev.parent);
+       int                     ret;
 
-       icl = to_soc_camera_link(icd);
-       if (!icl || !icl->priv)
+       if (!icl || !icl->priv) {
+               dev_err(&client->dev, "OV772X: missing platform data!\n");
                return -EINVAL;
+       }
 
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
                dev_err(&adapter->dev,
@@ -1146,12 +1074,24 @@ static int ov772x_probe(struct i2c_client *client,
        priv->info = icl->priv;
 
        v4l2_i2c_subdev_init(&priv->subdev, client, &ov772x_subdev_ops);
+       v4l2_ctrl_handler_init(&priv->hdl, 3);
+       v4l2_ctrl_new_std(&priv->hdl, &ov772x_ctrl_ops,
+                       V4L2_CID_VFLIP, 0, 1, 1, 0);
+       v4l2_ctrl_new_std(&priv->hdl, &ov772x_ctrl_ops,
+                       V4L2_CID_HFLIP, 0, 1, 1, 0);
+       v4l2_ctrl_new_std(&priv->hdl, &ov772x_ctrl_ops,
+                       V4L2_CID_BAND_STOP_FILTER, 0, 256, 1, 0);
+       priv->subdev.ctrl_handler = &priv->hdl;
+       if (priv->hdl.error) {
+               int err = priv->hdl.error;
 
-       icd->ops                = &ov772x_ops;
+               kfree(priv);
+               return err;
+       }
 
-       ret = ov772x_video_probe(icd, client);
+       ret = ov772x_video_probe(client);
        if (ret) {
-               icd->ops = NULL;
+               v4l2_ctrl_handler_free(&priv->hdl);
                kfree(priv);
        }
 
@@ -1161,9 +1101,9 @@ static int ov772x_probe(struct i2c_client *client,
 static int ov772x_remove(struct i2c_client *client)
 {
        struct ov772x_priv *priv = to_ov772x(client);
-       struct soc_camera_device *icd = client->dev.platform_data;
 
-       icd->ops = NULL;
+       v4l2_device_unregister_subdev(&priv->subdev);
+       v4l2_ctrl_handler_free(&priv->hdl);
        kfree(priv);
        return 0;
 }
index 3681a6f..a4f9979 100644 (file)
 #include <linux/i2c.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
+#include <linux/v4l2-mediabus.h>
 #include <linux/videodev2.h>
+
+#include <media/soc_camera.h>
 #include <media/v4l2-chip-ident.h>
 #include <media/v4l2-common.h>
-#include <media/soc_camera.h>
+#include <media/v4l2-ctrls.h>
 
 #include "ov9640.h"
 
@@ -162,27 +165,6 @@ static enum v4l2_mbus_pixelcode ov9640_codes[] = {
        V4L2_MBUS_FMT_RGB565_2X8_LE,
 };
 
-static const struct v4l2_queryctrl ov9640_controls[] = {
-       {
-               .id             = V4L2_CID_VFLIP,
-               .type           = V4L2_CTRL_TYPE_BOOLEAN,
-               .name           = "Flip Vertically",
-               .minimum        = 0,
-               .maximum        = 1,
-               .step           = 1,
-               .default_value  = 0,
-       },
-       {
-               .id             = V4L2_CID_HFLIP,
-               .type           = V4L2_CTRL_TYPE_BOOLEAN,
-               .name           = "Flip Horizontally",
-               .minimum        = 0,
-               .maximum        = 1,
-               .step           = 1,
-               .default_value  = 0,
-       },
-};
-
 /* read a register */
 static int ov9640_reg_read(struct i2c_client *client, u8 reg, u8 *val)
 {
@@ -284,75 +266,25 @@ static int ov9640_s_stream(struct v4l2_subdev *sd, int enable)
        return 0;
 }
 
-/* Alter bus settings on camera side */
-static int ov9640_set_bus_param(struct soc_camera_device *icd,
-                               unsigned long flags)
-{
-       return 0;
-}
-
-/* Request bus settings on camera side */
-static unsigned long ov9640_query_bus_param(struct soc_camera_device *icd)
-{
-       struct soc_camera_link *icl = to_soc_camera_link(icd);
-
-       /*
-        * REVISIT: the camera probably can do 10 bit transfers, but I don't
-        *          have those pins connected on my hardware.
-        */
-       unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER |
-               SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH |
-               SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATAWIDTH_8;
-
-       return soc_camera_apply_sensor_flags(icl, flags);
-}
-
-/* Get status of additional camera capabilities */
-static int ov9640_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
-{
-       struct ov9640_priv *priv = to_ov9640_sensor(sd);
-
-       switch (ctrl->id) {
-       case V4L2_CID_VFLIP:
-               ctrl->value = priv->flag_vflip;
-               break;
-       case V4L2_CID_HFLIP:
-               ctrl->value = priv->flag_hflip;
-               break;
-       }
-       return 0;
-}
-
 /* Set status of additional camera capabilities */
-static int ov9640_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+static int ov9640_s_ctrl(struct v4l2_ctrl *ctrl)
 {
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct ov9640_priv *priv = to_ov9640_sensor(sd);
-
-       int ret = 0;
+       struct ov9640_priv *priv = container_of(ctrl->handler, struct ov9640_priv, hdl);
+       struct i2c_client *client = v4l2_get_subdevdata(&priv->subdev);
 
        switch (ctrl->id) {
        case V4L2_CID_VFLIP:
-               priv->flag_vflip = ctrl->value;
-               if (ctrl->value)
-                       ret = ov9640_reg_rmw(client, OV9640_MVFP,
+               if (ctrl->val)
+                       return ov9640_reg_rmw(client, OV9640_MVFP,
                                                        OV9640_MVFP_V, 0);
-               else
-                       ret = ov9640_reg_rmw(client, OV9640_MVFP,
-                                                       0, OV9640_MVFP_V);
-               break;
+               return ov9640_reg_rmw(client, OV9640_MVFP, 0, OV9640_MVFP_V);
        case V4L2_CID_HFLIP:
-               priv->flag_hflip = ctrl->value;
-               if (ctrl->value)
-                       ret = ov9640_reg_rmw(client, OV9640_MVFP,
+               if (ctrl->val)
+                       return ov9640_reg_rmw(client, OV9640_MVFP,
                                                        OV9640_MVFP_H, 0);
-               else
-                       ret = ov9640_reg_rmw(client, OV9640_MVFP,
-                                                       0, OV9640_MVFP_H);
-               break;
+               return ov9640_reg_rmw(client, OV9640_MVFP, 0, OV9640_MVFP_H);
        }
-
-       return ret;
+       return -EINVAL;
 }
 
 /* Get chip identification */
@@ -646,10 +578,7 @@ static int ov9640_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
        return 0;
 }
 
-
-
-static int ov9640_video_probe(struct soc_camera_device *icd,
-                               struct i2c_client *client)
+static int ov9640_video_probe(struct i2c_client *client)
 {
        struct v4l2_subdev *sd = i2c_get_clientdata(client);
        struct ov9640_priv *priv = to_ov9640_sensor(sd);
@@ -657,29 +586,19 @@ static int ov9640_video_probe(struct soc_camera_device *icd,
        const char      *devname;
        int             ret = 0;
 
-       /* We must have a parent by now. And it cannot be a wrong one. */
-       BUG_ON(!icd->parent ||
-              to_soc_camera_host(icd->parent)->nr != icd->iface);
-
        /*
         * check and show product ID and manufacturer ID
         */
 
        ret = ov9640_reg_read(client, OV9640_PID, &pid);
+       if (!ret)
+               ret = ov9640_reg_read(client, OV9640_VER, &ver);
+       if (!ret)
+               ret = ov9640_reg_read(client, OV9640_MIDH, &midh);
+       if (!ret)
+               ret = ov9640_reg_read(client, OV9640_MIDL, &midl);
        if (ret)
-               goto err;
-
-       ret = ov9640_reg_read(client, OV9640_VER, &ver);
-       if (ret)
-               goto err;
-
-       ret = ov9640_reg_read(client, OV9640_MIDH, &midh);
-       if (ret)
-               goto err;
-
-       ret = ov9640_reg_read(client, OV9640_MIDL, &midl);
-       if (ret)
-               goto err;
+               return ret;
 
        switch (VERSION(pid, ver)) {
        case OV9640_V2:
@@ -693,27 +612,20 @@ static int ov9640_video_probe(struct soc_camera_device *icd,
                break;
        default:
                dev_err(&client->dev, "Product ID error %x:%x\n", pid, ver);
-               ret = -ENODEV;
-               goto err;
+               return -ENODEV;
        }
 
        dev_info(&client->dev, "%s Product ID %0x:%0x Manufacturer ID %x:%x\n",
                 devname, pid, ver, midh, midl);
 
-err:
-       return ret;
+       return v4l2_ctrl_handler_setup(&priv->hdl);
 }
 
-static struct soc_camera_ops ov9640_ops = {
-       .set_bus_param          = ov9640_set_bus_param,
-       .query_bus_param        = ov9640_query_bus_param,
-       .controls               = ov9640_controls,
-       .num_controls           = ARRAY_SIZE(ov9640_controls),
+static const struct v4l2_ctrl_ops ov9640_ctrl_ops = {
+       .s_ctrl = ov9640_s_ctrl,
 };
 
 static struct v4l2_subdev_core_ops ov9640_core_ops = {
-       .g_ctrl                 = ov9640_g_ctrl,
-       .s_ctrl                 = ov9640_s_ctrl,
        .g_chip_ident           = ov9640_g_chip_ident,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
        .g_register             = ov9640_get_register,
@@ -722,6 +634,22 @@ static struct v4l2_subdev_core_ops ov9640_core_ops = {
 
 };
 
+/* Request bus settings on camera side */
+static int ov9640_g_mbus_config(struct v4l2_subdev *sd,
+                               struct v4l2_mbus_config *cfg)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+       cfg->flags = V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_MASTER |
+               V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_HIGH |
+               V4L2_MBUS_DATA_ACTIVE_HIGH;
+       cfg->type = V4L2_MBUS_PARALLEL;
+       cfg->flags = soc_camera_apply_board_flags(icl, cfg);
+
+       return 0;
+}
+
 static struct v4l2_subdev_video_ops ov9640_video_ops = {
        .s_stream       = ov9640_s_stream,
        .s_mbus_fmt     = ov9640_s_fmt,
@@ -729,7 +657,7 @@ static struct v4l2_subdev_video_ops ov9640_video_ops = {
        .enum_mbus_fmt  = ov9640_enum_fmt,
        .cropcap        = ov9640_cropcap,
        .g_crop         = ov9640_g_crop,
-
+       .g_mbus_config  = ov9640_g_mbus_config,
 };
 
 static struct v4l2_subdev_ops ov9640_subdev_ops = {
@@ -744,16 +672,9 @@ static int ov9640_probe(struct i2c_client *client,
                        const struct i2c_device_id *did)
 {
        struct ov9640_priv *priv;
-       struct soc_camera_device *icd   = client->dev.platform_data;
-       struct soc_camera_link *icl;
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
        int ret;
 
-       if (!icd) {
-               dev_err(&client->dev, "Missing soc-camera data!\n");
-               return -EINVAL;
-       }
-
-       icl = to_soc_camera_link(icd);
        if (!icl) {
                dev_err(&client->dev, "Missing platform_data for driver\n");
                return -EINVAL;
@@ -768,12 +689,23 @@ static int ov9640_probe(struct i2c_client *client,
 
        v4l2_i2c_subdev_init(&priv->subdev, client, &ov9640_subdev_ops);
 
-       icd->ops        = &ov9640_ops;
+       v4l2_ctrl_handler_init(&priv->hdl, 2);
+       v4l2_ctrl_new_std(&priv->hdl, &ov9640_ctrl_ops,
+                       V4L2_CID_VFLIP, 0, 1, 1, 0);
+       v4l2_ctrl_new_std(&priv->hdl, &ov9640_ctrl_ops,
+                       V4L2_CID_HFLIP, 0, 1, 1, 0);
+       priv->subdev.ctrl_handler = &priv->hdl;
+       if (priv->hdl.error) {
+               int err = priv->hdl.error;
+
+               kfree(priv);
+               return err;
+       }
 
-       ret = ov9640_video_probe(icd, client);
+       ret = ov9640_video_probe(client);
 
        if (ret) {
-               icd->ops = NULL;
+               v4l2_ctrl_handler_free(&priv->hdl);
                kfree(priv);
        }
 
@@ -785,6 +717,8 @@ static int ov9640_remove(struct i2c_client *client)
        struct v4l2_subdev *sd = i2c_get_clientdata(client);
        struct ov9640_priv *priv = to_ov9640_sensor(sd);
 
+       v4l2_device_unregister_subdev(&priv->subdev);
+       v4l2_ctrl_handler_free(&priv->hdl);
        kfree(priv);
        return 0;
 }
index f8a51b7..6b33a97 100644 (file)
@@ -198,12 +198,10 @@ struct ov9640_reg {
 
 struct ov9640_priv {
        struct v4l2_subdev              subdev;
+       struct v4l2_ctrl_handler        hdl;
 
        int                             model;
        int                             revision;
-
-       bool                            flag_vflip;
-       bool                            flag_hflip;
 };
 
 #endif /* __DRIVERS_MEDIA_VIDEO_OV9640_H__ */
index edd1ffc..d9a9f71 100644 (file)
 #include <linux/module.h>
 #include <linux/i2c.h>
 #include <linux/slab.h>
-#include <media/v4l2-chip-ident.h>
+#include <linux/v4l2-mediabus.h>
+
 #include <media/soc_camera.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-ctrls.h>
 
 #define to_ov9740(sd)          container_of(sd, struct ov9740_priv, subdev)
 
@@ -192,6 +195,7 @@ struct ov9740_reg {
 
 struct ov9740_priv {
        struct v4l2_subdev              subdev;
+       struct v4l2_ctrl_handler        hdl;
 
        int                             ident;
        u16                             model;
@@ -392,27 +396,6 @@ static enum v4l2_mbus_pixelcode ov9740_codes[] = {
        V4L2_MBUS_FMT_YUYV8_2X8,
 };
 
-static const struct v4l2_queryctrl ov9740_controls[] = {
-       {
-               .id             = V4L2_CID_VFLIP,
-               .type           = V4L2_CTRL_TYPE_BOOLEAN,
-               .name           = "Flip Vertically",
-               .minimum        = 0,
-               .maximum        = 1,
-               .step           = 1,
-               .default_value  = 0,
-       },
-       {
-               .id             = V4L2_CID_HFLIP,
-               .type           = V4L2_CTRL_TYPE_BOOLEAN,
-               .name           = "Flip Horizontally",
-               .minimum        = 0,
-               .maximum        = 1,
-               .step           = 1,
-               .default_value  = 0,
-       },
-};
-
 /* read a register */
 static int ov9740_reg_read(struct i2c_client *client, u16 reg, u8 *val)
 {
@@ -560,25 +543,6 @@ static int ov9740_s_stream(struct v4l2_subdev *sd, int enable)
        return ret;
 }
 
-/* Alter bus settings on camera side */
-static int ov9740_set_bus_param(struct soc_camera_device *icd,
-                               unsigned long flags)
-{
-       return 0;
-}
-
-/* Request bus settings on camera side */
-static unsigned long ov9740_query_bus_param(struct soc_camera_device *icd)
-{
-       struct soc_camera_link *icl = to_soc_camera_link(icd);
-
-       unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER |
-               SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH |
-               SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATAWIDTH_8;
-
-       return soc_camera_apply_sensor_flags(icl, flags);
-}
-
 /* select nearest higher resolution for capture */
 static void ov9740_res_roundup(u32 *width, u32 *height)
 {
@@ -788,36 +752,18 @@ static int ov9740_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
        return 0;
 }
 
-/* Get status of additional camera capabilities */
-static int ov9740_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
-{
-       struct ov9740_priv *priv = to_ov9740(sd);
-
-       switch (ctrl->id) {
-       case V4L2_CID_VFLIP:
-               ctrl->value = priv->flag_vflip;
-               break;
-       case V4L2_CID_HFLIP:
-               ctrl->value = priv->flag_hflip;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
 /* Set status of additional camera capabilities */
-static int ov9740_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+static int ov9740_s_ctrl(struct v4l2_ctrl *ctrl)
 {
-       struct ov9740_priv *priv = to_ov9740(sd);
+       struct ov9740_priv *priv =
+               container_of(ctrl->handler, struct ov9740_priv, hdl);
 
        switch (ctrl->id) {
        case V4L2_CID_VFLIP:
-               priv->flag_vflip = ctrl->value;
+               priv->flag_vflip = ctrl->val;
                break;
        case V4L2_CID_HFLIP:
-               priv->flag_hflip = ctrl->value;
+               priv->flag_hflip = ctrl->val;
                break;
        default:
                return -EINVAL;
@@ -890,18 +836,13 @@ static int ov9740_set_register(struct v4l2_subdev *sd,
 }
 #endif
 
-static int ov9740_video_probe(struct soc_camera_device *icd,
-                             struct i2c_client *client)
+static int ov9740_video_probe(struct i2c_client *client)
 {
        struct v4l2_subdev *sd = i2c_get_clientdata(client);
        struct ov9740_priv *priv = to_ov9740(sd);
        u8 modelhi, modello;
        int ret;
 
-       /* We must have a parent by now. And it cannot be a wrong one. */
-       BUG_ON(!icd->parent ||
-              to_soc_camera_host(icd->parent)->nr != icd->iface);
-
        /*
         * check and show product ID and manufacturer ID
         */
@@ -942,25 +883,33 @@ err:
        return ret;
 }
 
-static struct soc_camera_ops ov9740_ops = {
-       .set_bus_param          = ov9740_set_bus_param,
-       .query_bus_param        = ov9740_query_bus_param,
-       .controls               = ov9740_controls,
-       .num_controls           = ARRAY_SIZE(ov9740_controls),
-};
+/* Request bus settings on camera side */
+static int ov9740_g_mbus_config(struct v4l2_subdev *sd,
+                               struct v4l2_mbus_config *cfg)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+       cfg->flags = V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_MASTER |
+               V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_HIGH |
+               V4L2_MBUS_DATA_ACTIVE_HIGH;
+       cfg->type = V4L2_MBUS_PARALLEL;
+       cfg->flags = soc_camera_apply_board_flags(icl, cfg);
+
+       return 0;
+}
 
 static struct v4l2_subdev_video_ops ov9740_video_ops = {
-       .s_stream               = ov9740_s_stream,
-       .s_mbus_fmt             = ov9740_s_fmt,
-       .try_mbus_fmt           = ov9740_try_fmt,
-       .enum_mbus_fmt          = ov9740_enum_fmt,
-       .cropcap                = ov9740_cropcap,
-       .g_crop                 = ov9740_g_crop,
+       .s_stream       = ov9740_s_stream,
+       .s_mbus_fmt     = ov9740_s_fmt,
+       .try_mbus_fmt   = ov9740_try_fmt,
+       .enum_mbus_fmt  = ov9740_enum_fmt,
+       .cropcap        = ov9740_cropcap,
+       .g_crop         = ov9740_g_crop,
+       .g_mbus_config  = ov9740_g_mbus_config,
 };
 
 static struct v4l2_subdev_core_ops ov9740_core_ops = {
-       .g_ctrl                 = ov9740_g_ctrl,
-       .s_ctrl                 = ov9740_s_ctrl,
        .g_chip_ident           = ov9740_g_chip_ident,
        .s_power                = ov9740_s_power,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
@@ -974,6 +923,10 @@ static struct v4l2_subdev_ops ov9740_subdev_ops = {
        .video                  = &ov9740_video_ops,
 };
 
+static const struct v4l2_ctrl_ops ov9740_ctrl_ops = {
+       .s_ctrl = ov9740_s_ctrl,
+};
+
 /*
  * i2c_driver function
  */
@@ -981,16 +934,9 @@ static int ov9740_probe(struct i2c_client *client,
                        const struct i2c_device_id *did)
 {
        struct ov9740_priv *priv;
-       struct soc_camera_device *icd   = client->dev.platform_data;
-       struct soc_camera_link *icl;
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
        int ret;
 
-       if (!icd) {
-               dev_err(&client->dev, "Missing soc-camera data!\n");
-               return -EINVAL;
-       }
-
-       icl = to_soc_camera_link(icd);
        if (!icl) {
                dev_err(&client->dev, "Missing platform_data for driver\n");
                return -EINVAL;
@@ -1003,12 +949,24 @@ static int ov9740_probe(struct i2c_client *client,
        }
 
        v4l2_i2c_subdev_init(&priv->subdev, client, &ov9740_subdev_ops);
+       v4l2_ctrl_handler_init(&priv->hdl, 13);
+       v4l2_ctrl_new_std(&priv->hdl, &ov9740_ctrl_ops,
+                       V4L2_CID_VFLIP, 0, 1, 1, 0);
+       v4l2_ctrl_new_std(&priv->hdl, &ov9740_ctrl_ops,
+                       V4L2_CID_HFLIP, 0, 1, 1, 0);
+       priv->subdev.ctrl_handler = &priv->hdl;
+       if (priv->hdl.error) {
+               int err = priv->hdl.error;
 
-       icd->ops = &ov9740_ops;
+               kfree(priv);
+               return err;
+       }
 
-       ret = ov9740_video_probe(icd, client);
+       ret = ov9740_video_probe(client);
+       if (!ret)
+               ret = v4l2_ctrl_handler_setup(&priv->hdl);
        if (ret < 0) {
-               icd->ops = NULL;
+               v4l2_ctrl_handler_free(&priv->hdl);
                kfree(priv);
        }
 
@@ -1019,8 +977,9 @@ static int ov9740_remove(struct i2c_client *client)
 {
        struct ov9740_priv *priv = i2c_get_clientdata(client);
 
+       v4l2_device_unregister_subdev(&priv->subdev);
+       v4l2_ctrl_handler_free(&priv->hdl);
        kfree(priv);
-
        return 0;
 }
 
index 360be22..01ff643 100644 (file)
@@ -744,9 +744,9 @@ static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma)
 /***************************************************************************/
 /* Videobuf2 operations */
 
-static int queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
-                               unsigned int *nplanes, unsigned int sizes[],
-                               void *alloc_ctxs[])
+static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+                               unsigned int *nbuffers, unsigned int *nplanes,
+                               unsigned int sizes[], void *alloc_ctxs[])
 {
        struct pwc_device *pdev = vb2_get_drv_priv(vq);
 
index d07df22..79fb22c 100644 (file)
@@ -214,6 +214,7 @@ struct pxa_camera_dev {
        unsigned long           ciclk;
        unsigned long           mclk;
        u32                     mclk_divisor;
+       u16                     width_flags;    /* max 10 bits */
 
        struct list_head        capture;
 
@@ -1020,37 +1021,20 @@ static int test_platform_param(struct pxa_camera_dev *pcdev,
         * quick capture interface supports both.
         */
        *flags = (pcdev->platform_flags & PXA_CAMERA_MASTER ?
-                 SOCAM_MASTER : SOCAM_SLAVE) |
-               SOCAM_HSYNC_ACTIVE_HIGH |
-               SOCAM_HSYNC_ACTIVE_LOW |
-               SOCAM_VSYNC_ACTIVE_HIGH |
-               SOCAM_VSYNC_ACTIVE_LOW |
-               SOCAM_DATA_ACTIVE_HIGH |
-               SOCAM_PCLK_SAMPLE_RISING |
-               SOCAM_PCLK_SAMPLE_FALLING;
+                 V4L2_MBUS_MASTER : V4L2_MBUS_SLAVE) |
+               V4L2_MBUS_HSYNC_ACTIVE_HIGH |
+               V4L2_MBUS_HSYNC_ACTIVE_LOW |
+               V4L2_MBUS_VSYNC_ACTIVE_HIGH |
+               V4L2_MBUS_VSYNC_ACTIVE_LOW |
+               V4L2_MBUS_DATA_ACTIVE_HIGH |
+               V4L2_MBUS_PCLK_SAMPLE_RISING |
+               V4L2_MBUS_PCLK_SAMPLE_FALLING;
 
        /* If requested data width is supported by the platform, use it */
-       switch (buswidth) {
-       case 10:
-               if (!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_10))
-                       return -EINVAL;
-               *flags |= SOCAM_DATAWIDTH_10;
-               break;
-       case 9:
-               if (!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_9))
-                       return -EINVAL;
-               *flags |= SOCAM_DATAWIDTH_9;
-               break;
-       case 8:
-               if (!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_8))
-                       return -EINVAL;
-               *flags |= SOCAM_DATAWIDTH_8;
-               break;
-       default:
-               return -EINVAL;
-       }
+       if ((1 << (buswidth - 1)) & pcdev->width_flags)
+               return 0;
 
-       return 0;
+       return -EINVAL;
 }
 
 static void pxa_camera_setup_cicr(struct soc_camera_device *icd,
@@ -1070,12 +1054,12 @@ static void pxa_camera_setup_cicr(struct soc_camera_device *icd,
         * Datawidth is now guaranteed to be equal to one of the three values.
         * We fix bit-per-pixel equal to data-width...
         */
-       switch (flags & SOCAM_DATAWIDTH_MASK) {
-       case SOCAM_DATAWIDTH_10:
+       switch (icd->current_fmt->host_fmt->bits_per_sample) {
+       case 10:
                dw = 4;
                bpp = 0x40;
                break;
-       case SOCAM_DATAWIDTH_9:
+       case 9:
                dw = 3;
                bpp = 0x20;
                break;
@@ -1084,7 +1068,7 @@ static void pxa_camera_setup_cicr(struct soc_camera_device *icd,
                 * Actually it can only be 8 now,
                 * default is just to silence compiler warnings
                 */
-       case SOCAM_DATAWIDTH_8:
+       case 8:
                dw = 2;
                bpp = 0;
        }
@@ -1093,11 +1077,11 @@ static void pxa_camera_setup_cicr(struct soc_camera_device *icd,
                cicr4 |= CICR4_PCLK_EN;
        if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN)
                cicr4 |= CICR4_MCLK_EN;
-       if (flags & SOCAM_PCLK_SAMPLE_FALLING)
+       if (flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
                cicr4 |= CICR4_PCP;
-       if (flags & SOCAM_HSYNC_ACTIVE_LOW)
+       if (flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
                cicr4 |= CICR4_HSP;
-       if (flags & SOCAM_VSYNC_ACTIVE_LOW)
+       if (flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
                cicr4 |= CICR4_VSP;
 
        cicr0 = __raw_readl(pcdev->base + CICR0);
@@ -1151,9 +1135,11 @@ static void pxa_camera_setup_cicr(struct soc_camera_device *icd,
 
 static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
 {
+       struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
        struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct pxa_camera_dev *pcdev = ici->priv;
-       unsigned long bus_flags, camera_flags, common_flags;
+       struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
+       unsigned long bus_flags, common_flags;
        int ret;
        struct pxa_cam *cam = icd->host_priv;
 
@@ -1162,44 +1148,58 @@ static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
        if (ret < 0)
                return ret;
 
-       camera_flags = icd->ops->query_bus_param(icd);
-
-       common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags);
-       if (!common_flags)
-               return -EINVAL;
+       ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
+       if (!ret) {
+               common_flags = soc_mbus_config_compatible(&cfg,
+                                                         bus_flags);
+               if (!common_flags) {
+                       dev_warn(icd->parent,
+                                "Flags incompatible: camera 0x%x, host 0x%lx\n",
+                                cfg.flags, bus_flags);
+                       return -EINVAL;
+               }
+       } else if (ret != -ENOIOCTLCMD) {
+               return ret;
+       } else {
+               common_flags = bus_flags;
+       }
 
        pcdev->channels = 1;
 
        /* Make choises, based on platform preferences */
-       if ((common_flags & SOCAM_HSYNC_ACTIVE_HIGH) &&
-           (common_flags & SOCAM_HSYNC_ACTIVE_LOW)) {
+       if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) &&
+           (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) {
                if (pcdev->platform_flags & PXA_CAMERA_HSP)
-                       common_flags &= ~SOCAM_HSYNC_ACTIVE_HIGH;
+                       common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH;
                else
-                       common_flags &= ~SOCAM_HSYNC_ACTIVE_LOW;
+                       common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW;
        }
 
-       if ((common_flags & SOCAM_VSYNC_ACTIVE_HIGH) &&
-           (common_flags & SOCAM_VSYNC_ACTIVE_LOW)) {
+       if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) &&
+           (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) {
                if (pcdev->platform_flags & PXA_CAMERA_VSP)
-                       common_flags &= ~SOCAM_VSYNC_ACTIVE_HIGH;
+                       common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH;
                else
-                       common_flags &= ~SOCAM_VSYNC_ACTIVE_LOW;
+                       common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW;
        }
 
-       if ((common_flags & SOCAM_PCLK_SAMPLE_RISING) &&
-           (common_flags & SOCAM_PCLK_SAMPLE_FALLING)) {
+       if ((common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) &&
+           (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)) {
                if (pcdev->platform_flags & PXA_CAMERA_PCP)
-                       common_flags &= ~SOCAM_PCLK_SAMPLE_RISING;
+                       common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_RISING;
                else
-                       common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING;
+                       common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_FALLING;
        }
 
-       cam->flags = common_flags;
-
-       ret = icd->ops->set_bus_param(icd, common_flags);
-       if (ret < 0)
+       cfg.flags = common_flags;
+       ret = v4l2_subdev_call(sd, video, s_mbus_config, &cfg);
+       if (ret < 0 && ret != -ENOIOCTLCMD) {
+               dev_dbg(icd->parent, "camera s_mbus_config(0x%lx) returned %d\n",
+                       common_flags, ret);
                return ret;
+       }
+
+       cam->flags = common_flags;
 
        pxa_camera_setup_cicr(icd, common_flags, pixfmt);
 
@@ -1209,17 +1209,31 @@ static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
 static int pxa_camera_try_bus_param(struct soc_camera_device *icd,
                                    unsigned char buswidth)
 {
+       struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
        struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct pxa_camera_dev *pcdev = ici->priv;
-       unsigned long bus_flags, camera_flags;
+       struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
+       unsigned long bus_flags, common_flags;
        int ret = test_platform_param(pcdev, buswidth, &bus_flags);
 
        if (ret < 0)
                return ret;
 
-       camera_flags = icd->ops->query_bus_param(icd);
+       ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
+       if (!ret) {
+               common_flags = soc_mbus_config_compatible(&cfg,
+                                                         bus_flags);
+               if (!common_flags) {
+                       dev_warn(icd->parent,
+                                "Flags incompatible: camera 0x%x, host 0x%lx\n",
+                                cfg.flags, bus_flags);
+                       return -EINVAL;
+               }
+       } else if (ret == -ENOIOCTLCMD) {
+               ret = 0;
+       }
 
-       return soc_camera_bus_param_compatible(camera_flags, bus_flags) ? 0 : -EINVAL;
+       return ret;
 }
 
 static const struct soc_mbus_pixelfmt pxa_camera_formats[] = {
@@ -1687,6 +1701,12 @@ static int __devinit pxa_camera_probe(struct platform_device *pdev)
                         "data widths, using default 10 bit\n");
                pcdev->platform_flags |= PXA_CAMERA_DATAWIDTH_10;
        }
+       if (pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_8)
+               pcdev->width_flags = 1 << 7;
+       if (pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_9)
+               pcdev->width_flags |= 1 << 8;
+       if (pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_10)
+               pcdev->width_flags |= 1 << 9;
        pcdev->mclk = pcdev->pdata->mclk_10khz * 10000;
        if (!pcdev->mclk) {
                dev_warn(&pdev->dev,
index 847ccc0..6afc616 100644 (file)
 #include <linux/delay.h>
 #include <linux/i2c.h>
 #include <linux/slab.h>
+#include <linux/v4l2-mediabus.h>
 #include <linux/videodev2.h>
 
 #include <media/rj54n1cb0c.h>
 #include <media/soc_camera.h>
-#include <media/soc_mediabus.h>
 #include <media/v4l2-subdev.h>
 #include <media/v4l2-chip-ident.h>
+#include <media/v4l2-ctrls.h>
 
 #define RJ54N1_DEV_CODE                        0x0400
 #define RJ54N1_DEV_CODE2               0x0401
@@ -148,6 +149,7 @@ struct rj54n1_clock_div {
 
 struct rj54n1 {
        struct v4l2_subdev subdev;
+       struct v4l2_ctrl_handler hdl;
        struct rj54n1_clock_div clk_div;
        const struct rj54n1_datafmt *fmt;
        struct v4l2_rect rect;  /* Sensor window */
@@ -499,31 +501,6 @@ static int rj54n1_s_stream(struct v4l2_subdev *sd, int enable)
        return reg_set(client, RJ54N1_STILL_CONTROL, (!enable) << 7, 0x80);
 }
 
-static int rj54n1_set_bus_param(struct soc_camera_device *icd,
-                               unsigned long flags)
-{
-       struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       /* Figures 2.5-1 to 2.5-3 - default falling pixclk edge */
-
-       if (flags & SOCAM_PCLK_SAMPLE_RISING)
-               return reg_write(client, RJ54N1_OUT_SIGPO, 1 << 4);
-       else
-               return reg_write(client, RJ54N1_OUT_SIGPO, 0);
-}
-
-static unsigned long rj54n1_query_bus_param(struct soc_camera_device *icd)
-{
-       struct soc_camera_link *icl = to_soc_camera_link(icd);
-       const unsigned long flags =
-               SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING |
-               SOCAM_MASTER | SOCAM_DATAWIDTH_8 |
-               SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH |
-               SOCAM_DATA_ACTIVE_HIGH;
-
-       return soc_camera_apply_sensor_flags(icl, flags);
-}
-
 static int rj54n1_set_rect(struct i2c_client *client,
                           u16 reg_x, u16 reg_y, u16 reg_xy,
                           u32 width, u32 height)
@@ -1202,134 +1179,51 @@ static int rj54n1_s_register(struct v4l2_subdev *sd,
 }
 #endif
 
-static const struct v4l2_queryctrl rj54n1_controls[] = {
-       {
-               .id             = V4L2_CID_VFLIP,
-               .type           = V4L2_CTRL_TYPE_BOOLEAN,
-               .name           = "Flip Vertically",
-               .minimum        = 0,
-               .maximum        = 1,
-               .step           = 1,
-               .default_value  = 0,
-       }, {
-               .id             = V4L2_CID_HFLIP,
-               .type           = V4L2_CTRL_TYPE_BOOLEAN,
-               .name           = "Flip Horizontally",
-               .minimum        = 0,
-               .maximum        = 1,
-               .step           = 1,
-               .default_value  = 0,
-       }, {
-               .id             = V4L2_CID_GAIN,
-               .type           = V4L2_CTRL_TYPE_INTEGER,
-               .name           = "Gain",
-               .minimum        = 0,
-               .maximum        = 127,
-               .step           = 1,
-               .default_value  = 66,
-               .flags          = V4L2_CTRL_FLAG_SLIDER,
-       }, {
-               .id             = V4L2_CID_AUTO_WHITE_BALANCE,
-               .type           = V4L2_CTRL_TYPE_BOOLEAN,
-               .name           = "Auto white balance",
-               .minimum        = 0,
-               .maximum        = 1,
-               .step           = 1,
-               .default_value  = 1,
-       },
-};
-
-static struct soc_camera_ops rj54n1_ops = {
-       .set_bus_param          = rj54n1_set_bus_param,
-       .query_bus_param        = rj54n1_query_bus_param,
-       .controls               = rj54n1_controls,
-       .num_controls           = ARRAY_SIZE(rj54n1_controls),
-};
-
-static int rj54n1_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+static int rj54n1_s_ctrl(struct v4l2_ctrl *ctrl)
 {
+       struct rj54n1 *rj54n1 = container_of(ctrl->handler, struct rj54n1, hdl);
+       struct v4l2_subdev *sd = &rj54n1->subdev;
        struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct rj54n1 *rj54n1 = to_rj54n1(client);
        int data;
 
        switch (ctrl->id) {
        case V4L2_CID_VFLIP:
-               data = reg_read(client, RJ54N1_MIRROR_STILL_MODE);
-               if (data < 0)
-                       return -EIO;
-               ctrl->value = !(data & 1);
-               break;
-       case V4L2_CID_HFLIP:
-               data = reg_read(client, RJ54N1_MIRROR_STILL_MODE);
-               if (data < 0)
-                       return -EIO;
-               ctrl->value = !(data & 2);
-               break;
-       case V4L2_CID_GAIN:
-               data = reg_read(client, RJ54N1_Y_GAIN);
-               if (data < 0)
-                       return -EIO;
-
-               ctrl->value = data / 2;
-               break;
-       case V4L2_CID_AUTO_WHITE_BALANCE:
-               ctrl->value = rj54n1->auto_wb;
-               break;
-       }
-
-       return 0;
-}
-
-static int rj54n1_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
-{
-       int data;
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct rj54n1 *rj54n1 = to_rj54n1(client);
-       const struct v4l2_queryctrl *qctrl;
-
-       qctrl = soc_camera_find_qctrl(&rj54n1_ops, ctrl->id);
-       if (!qctrl)
-               return -EINVAL;
-
-       switch (ctrl->id) {
-       case V4L2_CID_VFLIP:
-               if (ctrl->value)
+               if (ctrl->val)
                        data = reg_set(client, RJ54N1_MIRROR_STILL_MODE, 0, 1);
                else
                        data = reg_set(client, RJ54N1_MIRROR_STILL_MODE, 1, 1);
                if (data < 0)
                        return -EIO;
-               break;
+               return 0;
        case V4L2_CID_HFLIP:
-               if (ctrl->value)
+               if (ctrl->val)
                        data = reg_set(client, RJ54N1_MIRROR_STILL_MODE, 0, 2);
                else
                        data = reg_set(client, RJ54N1_MIRROR_STILL_MODE, 2, 2);
                if (data < 0)
                        return -EIO;
-               break;
+               return 0;
        case V4L2_CID_GAIN:
-               if (ctrl->value > qctrl->maximum ||
-                   ctrl->value < qctrl->minimum)
-                       return -EINVAL;
-               else if (reg_write(client, RJ54N1_Y_GAIN, ctrl->value * 2) < 0)
+               if (reg_write(client, RJ54N1_Y_GAIN, ctrl->val * 2) < 0)
                        return -EIO;
-               break;
+               return 0;
        case V4L2_CID_AUTO_WHITE_BALANCE:
                /* Auto WB area - whole image */
-               if (reg_set(client, RJ54N1_WB_SEL_WEIGHT_I, ctrl->value << 7,
+               if (reg_set(client, RJ54N1_WB_SEL_WEIGHT_I, ctrl->val << 7,
                            0x80) < 0)
                        return -EIO;
-               rj54n1->auto_wb = ctrl->value;
-               break;
+               rj54n1->auto_wb = ctrl->val;
+               return 0;
        }
 
-       return 0;
+       return -EINVAL;
 }
 
+static const struct v4l2_ctrl_ops rj54n1_ctrl_ops = {
+       .s_ctrl = rj54n1_s_ctrl,
+};
+
 static struct v4l2_subdev_core_ops rj54n1_subdev_core_ops = {
-       .g_ctrl         = rj54n1_g_ctrl,
-       .s_ctrl         = rj54n1_s_ctrl,
        .g_chip_ident   = rj54n1_g_chip_ident,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
        .g_register     = rj54n1_g_register,
@@ -1337,6 +1231,36 @@ static struct v4l2_subdev_core_ops rj54n1_subdev_core_ops = {
 #endif
 };
 
+static int rj54n1_g_mbus_config(struct v4l2_subdev *sd,
+                               struct v4l2_mbus_config *cfg)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+       cfg->flags =
+               V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_PCLK_SAMPLE_FALLING |
+               V4L2_MBUS_MASTER | V4L2_MBUS_DATA_ACTIVE_HIGH |
+               V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_HIGH;
+       cfg->type = V4L2_MBUS_PARALLEL;
+       cfg->flags = soc_camera_apply_board_flags(icl, cfg);
+
+       return 0;
+}
+
+static int rj54n1_s_mbus_config(struct v4l2_subdev *sd,
+                               const struct v4l2_mbus_config *cfg)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+       /* Figures 2.5-1 to 2.5-3 - default falling pixclk edge */
+       if (soc_camera_apply_board_flags(icl, cfg) &
+           V4L2_MBUS_PCLK_SAMPLE_RISING)
+               return reg_write(client, RJ54N1_OUT_SIGPO, 1 << 4);
+       else
+               return reg_write(client, RJ54N1_OUT_SIGPO, 0);
+}
+
 static struct v4l2_subdev_video_ops rj54n1_subdev_video_ops = {
        .s_stream       = rj54n1_s_stream,
        .s_mbus_fmt     = rj54n1_s_fmt,
@@ -1346,6 +1270,8 @@ static struct v4l2_subdev_video_ops rj54n1_subdev_video_ops = {
        .g_crop         = rj54n1_g_crop,
        .s_crop         = rj54n1_s_crop,
        .cropcap        = rj54n1_cropcap,
+       .g_mbus_config  = rj54n1_g_mbus_config,
+       .s_mbus_config  = rj54n1_s_mbus_config,
 };
 
 static struct v4l2_subdev_ops rj54n1_subdev_ops = {
@@ -1357,17 +1283,12 @@ static struct v4l2_subdev_ops rj54n1_subdev_ops = {
  * Interface active, can use i2c. If it fails, it can indeed mean, that
  * this wasn't our capture interface, so, we wait for the right one
  */
-static int rj54n1_video_probe(struct soc_camera_device *icd,
-                             struct i2c_client *client,
+static int rj54n1_video_probe(struct i2c_client *client,
                              struct rj54n1_pdata *priv)
 {
        int data1, data2;
        int ret;
 
-       /* We must have a parent by now. And it cannot be a wrong one. */
-       BUG_ON(!icd->parent ||
-              to_soc_camera_host(icd->parent)->nr != icd->iface);
-
        /* Read out the chip version register */
        data1 = reg_read(client, RJ54N1_DEV_CODE);
        data2 = reg_read(client, RJ54N1_DEV_CODE2);
@@ -1395,18 +1316,11 @@ static int rj54n1_probe(struct i2c_client *client,
                        const struct i2c_device_id *did)
 {
        struct rj54n1 *rj54n1;
-       struct soc_camera_device *icd = client->dev.platform_data;
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
        struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
-       struct soc_camera_link *icl;
        struct rj54n1_pdata *rj54n1_priv;
        int ret;
 
-       if (!icd) {
-               dev_err(&client->dev, "RJ54N1CB0C: missing soc-camera data!\n");
-               return -EINVAL;
-       }
-
-       icl = to_soc_camera_link(icd);
        if (!icl || !icl->priv) {
                dev_err(&client->dev, "RJ54N1CB0C: missing platform data!\n");
                return -EINVAL;
@@ -1425,8 +1339,22 @@ static int rj54n1_probe(struct i2c_client *client,
                return -ENOMEM;
 
        v4l2_i2c_subdev_init(&rj54n1->subdev, client, &rj54n1_subdev_ops);
+       v4l2_ctrl_handler_init(&rj54n1->hdl, 4);
+       v4l2_ctrl_new_std(&rj54n1->hdl, &rj54n1_ctrl_ops,
+                       V4L2_CID_VFLIP, 0, 1, 1, 0);
+       v4l2_ctrl_new_std(&rj54n1->hdl, &rj54n1_ctrl_ops,
+                       V4L2_CID_HFLIP, 0, 1, 1, 0);
+       v4l2_ctrl_new_std(&rj54n1->hdl, &rj54n1_ctrl_ops,
+                       V4L2_CID_GAIN, 0, 127, 1, 66);
+       v4l2_ctrl_new_std(&rj54n1->hdl, &rj54n1_ctrl_ops,
+                       V4L2_CID_AUTO_WHITE_BALANCE, 0, 1, 1, 1);
+       rj54n1->subdev.ctrl_handler = &rj54n1->hdl;
+       if (rj54n1->hdl.error) {
+               int err = rj54n1->hdl.error;
 
-       icd->ops                = &rj54n1_ops;
+               kfree(rj54n1);
+               return err;
+       }
 
        rj54n1->clk_div         = clk_div;
        rj54n1->rect.left       = RJ54N1_COLUMN_SKIP;
@@ -1440,25 +1368,24 @@ static int rj54n1_probe(struct i2c_client *client,
        rj54n1->tgclk_mhz       = (rj54n1_priv->mclk_freq / PLL_L * PLL_N) /
                (clk_div.ratio_tg + 1) / (clk_div.ratio_t + 1);
 
-       ret = rj54n1_video_probe(icd, client, rj54n1_priv);
+       ret = rj54n1_video_probe(client, rj54n1_priv);
        if (ret < 0) {
-               icd->ops = NULL;
+               v4l2_ctrl_handler_free(&rj54n1->hdl);
                kfree(rj54n1);
                return ret;
        }
-
-       return ret;
+       return v4l2_ctrl_handler_setup(&rj54n1->hdl);
 }
 
 static int rj54n1_remove(struct i2c_client *client)
 {
        struct rj54n1 *rj54n1 = to_rj54n1(client);
-       struct soc_camera_device *icd = client->dev.platform_data;
-       struct soc_camera_link *icl = to_soc_camera_link(icd);
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
 
-       icd->ops = NULL;
+       v4l2_device_unregister_subdev(&rj54n1->subdev);
        if (icl->free_bus)
                icl->free_bus(icl);
+       v4l2_ctrl_handler_free(&rj54n1->hdl);
        kfree(rj54n1);
 
        return 0;
diff --git a/drivers/media/video/s5k6aa.c b/drivers/media/video/s5k6aa.c
new file mode 100644 (file)
index 0000000..2446736
--- /dev/null
@@ -0,0 +1,1680 @@
+/*
+ * Driver for Samsung S5K6AAFX SXGA 1/6" 1.3M CMOS Image Sensor
+ * with embedded SoC ISP.
+ *
+ * Copyright (C) 2011, Samsung Electronics Co., Ltd.
+ * Sylwester Nawrocki <s.nawrocki@samsung.com>
+ *
+ * Based on a driver authored by Dongsoo Nathaniel Kim.
+ * Copyright (C) 2009, Dongsoo Nathaniel Kim <dongsoo45.kim@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/media.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+
+#include <media/media-entity.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include <media/v4l2-mediabus.h>
+#include <media/s5k6aa.h>
+
+static int debug;
+module_param(debug, int, 0644);
+
+#define DRIVER_NAME                    "S5K6AA"
+
+/* The token to indicate array termination */
+#define S5K6AA_TERM                    0xffff
+#define S5K6AA_OUT_WIDTH_DEF           640
+#define S5K6AA_OUT_HEIGHT_DEF          480
+#define S5K6AA_WIN_WIDTH_MAX           1280
+#define S5K6AA_WIN_HEIGHT_MAX          1024
+#define S5K6AA_WIN_WIDTH_MIN           8
+#define S5K6AA_WIN_HEIGHT_MIN          8
+
+/*
+ * H/W register Interface (0xD0000000 - 0xD0000FFF)
+ */
+#define AHB_MSB_ADDR_PTR               0xfcfc
+#define GEN_REG_OFFSH                  0xd000
+#define REG_CMDWR_ADDRH                        0x0028
+#define REG_CMDWR_ADDRL                        0x002a
+#define REG_CMDRD_ADDRH                        0x002c
+#define REG_CMDRD_ADDRL                        0x002e
+#define REG_CMDBUF0_ADDR               0x0f12
+#define REG_CMDBUF1_ADDR               0x0f10
+
+/*
+ * Host S/W Register interface (0x70000000 - 0x70002000)
+ * The value of the two most significant address bytes is 0x7000,
+ * (HOST_SWIF_OFFS_H). The register addresses below specify 2 LSBs.
+ */
+#define HOST_SWIF_OFFSH                        0x7000
+
+/* Initialization parameters */
+/* Master clock frequency in KHz */
+#define REG_I_INCLK_FREQ_L             0x01b8
+#define REG_I_INCLK_FREQ_H             0x01ba
+#define  MIN_MCLK_FREQ_KHZ             6000U
+#define  MAX_MCLK_FREQ_KHZ             27000U
+#define REG_I_USE_NPVI_CLOCKS          0x01c6
+#define REG_I_USE_NMIPI_CLOCKS         0x01c8
+
+/* Clock configurations, n = 0..2. REG_I_* frequency unit is 4 kHz. */
+#define REG_I_OPCLK_4KHZ(n)            ((n) * 6 + 0x01cc)
+#define REG_I_MIN_OUTRATE_4KHZ(n)      ((n) * 6 + 0x01ce)
+#define REG_I_MAX_OUTRATE_4KHZ(n)      ((n) * 6 + 0x01d0)
+#define  SYS_PLL_OUT_FREQ              (48000000 / 4000)
+#define  PCLK_FREQ_MIN                 (24000000 / 4000)
+#define  PCLK_FREQ_MAX                 (48000000 / 4000)
+#define REG_I_INIT_PARAMS_UPDATED      0x01e0
+#define REG_I_ERROR_INFO               0x01e2
+
+/* General purpose parameters */
+#define REG_USER_BRIGHTNESS            0x01e4
+#define REG_USER_CONTRAST              0x01e6
+#define REG_USER_SATURATION            0x01e8
+#define REG_USER_SHARPBLUR             0x01ea
+
+#define REG_G_SPEC_EFFECTS             0x01ee
+#define REG_G_ENABLE_PREV              0x01f0
+#define REG_G_ENABLE_PREV_CHG          0x01f2
+#define REG_G_NEW_CFG_SYNC             0x01f8
+#define REG_G_PREVZOOM_IN_WIDTH                0x020a
+#define REG_G_PREVZOOM_IN_HEIGHT       0x020c
+#define REG_G_PREVZOOM_IN_XOFFS                0x020e
+#define REG_G_PREVZOOM_IN_YOFFS                0x0210
+#define REG_G_INPUTS_CHANGE_REQ                0x021a
+#define REG_G_ACTIVE_PREV_CFG          0x021c
+#define REG_G_PREV_CFG_CHG             0x021e
+#define REG_G_PREV_OPEN_AFTER_CH       0x0220
+#define REG_G_PREV_CFG_ERROR           0x0222
+
+/* Preview control section. n = 0...4. */
+#define PREG(n, x)                     ((n) * 0x26 + x)
+#define REG_P_OUT_WIDTH(n)             PREG(n, 0x0242)
+#define REG_P_OUT_HEIGHT(n)            PREG(n, 0x0244)
+#define REG_P_FMT(n)                   PREG(n, 0x0246)
+#define REG_P_MAX_OUT_RATE(n)          PREG(n, 0x0248)
+#define REG_P_MIN_OUT_RATE(n)          PREG(n, 0x024a)
+#define REG_P_PVI_MASK(n)              PREG(n, 0x024c)
+#define REG_P_CLK_INDEX(n)             PREG(n, 0x024e)
+#define REG_P_FR_RATE_TYPE(n)          PREG(n, 0x0250)
+#define  FR_RATE_DYNAMIC               0
+#define  FR_RATE_FIXED                 1
+#define  FR_RATE_FIXED_ACCURATE                2
+#define REG_P_FR_RATE_Q_TYPE(n)                PREG(n, 0x0252)
+#define  FR_RATE_Q_BEST_FRRATE         1 /* Binning enabled */
+#define  FR_RATE_Q_BEST_QUALITY                2 /* Binning disabled */
+/* Frame period in 0.1 ms units */
+#define REG_P_MAX_FR_TIME(n)           PREG(n, 0x0254)
+#define REG_P_MIN_FR_TIME(n)           PREG(n, 0x0256)
+/* Conversion to REG_P_[MAX/MIN]_FR_TIME value; __t: time in us */
+#define  US_TO_FR_TIME(__t)            ((__t) / 100)
+#define  S5K6AA_MIN_FR_TIME            33300  /* us */
+#define  S5K6AA_MAX_FR_TIME            650000 /* us */
+#define  S5K6AA_MAX_HIGHRES_FR_TIME    666    /* x100 us */
+/* The below 5 registers are for "device correction" values */
+#define REG_P_COLORTEMP(n)             PREG(n, 0x025e)
+#define REG_P_PREV_MIRROR(n)           PREG(n, 0x0262)
+
+/* Extended image property controls */
+/* Exposure time in 10 us units */
+#define REG_SF_USR_EXPOSURE_L          0x03c6
+#define REG_SF_USR_EXPOSURE_H          0x03c8
+#define REG_SF_USR_EXPOSURE_CHG                0x03ca
+#define REG_SF_USR_TOT_GAIN            0x03cc
+#define REG_SF_USR_TOT_GAIN_CHG                0x03ce
+#define REG_SF_RGAIN                   0x03d0
+#define REG_SF_RGAIN_CHG               0x03d2
+#define REG_SF_GGAIN                   0x03d4
+#define REG_SF_GGAIN_CHG               0x03d6
+#define REG_SF_BGAIN                   0x03d8
+#define REG_SF_BGAIN_CHG               0x03da
+#define REG_SF_FLICKER_QUANT           0x03dc
+#define REG_SF_FLICKER_QUANT_CHG       0x03de
+
+/* Output interface (parallel/MIPI) setup */
+#define REG_OIF_EN_MIPI_LANES          0x03fa
+#define REG_OIF_EN_PACKETS             0x03fc
+#define REG_OIF_CFG_CHG                        0x03fe
+
+/* Auto-algorithms enable mask */
+#define REG_DBG_AUTOALG_EN             0x0400
+#define  AALG_ALL_EN_MASK              (1 << 0)
+#define  AALG_AE_EN_MASK               (1 << 1)
+#define  AALG_DIVLEI_EN_MASK           (1 << 2)
+#define  AALG_WB_EN_MASK               (1 << 3)
+#define  AALG_FLICKER_EN_MASK          (1 << 5)
+#define  AALG_FIT_EN_MASK              (1 << 6)
+#define  AALG_WRHW_EN_MASK             (1 << 7)
+
+/* Firmware revision information */
+#define REG_FW_APIVER                  0x012e
+#define  S5K6AAFX_FW_APIVER            0x0001
+#define REG_FW_REVISION                        0x0130
+
+/* For now we use only one user configuration register set */
+#define S5K6AA_MAX_PRESETS             1
+
+static const char * const s5k6aa_supply_names[] = {
+       "vdd_core",     /* Digital core supply 1.5V (1.4V to 1.6V) */
+       "vdda",         /* Analog power supply 2.8V (2.6V to 3.0V) */
+       "vdd_reg",      /* Regulator input power 1.8V (1.7V to 1.9V)
+                          or 2.8V (2.6V to 3.0) */
+       "vddio",        /* I/O supply 1.8V (1.65V to 1.95V)
+                          or 2.8V (2.5V to 3.1V) */
+};
+#define S5K6AA_NUM_SUPPLIES ARRAY_SIZE(s5k6aa_supply_names)
+
+enum s5k6aa_gpio_id {
+       STBY,
+       RST,
+       GPIO_NUM,
+};
+
+struct s5k6aa_regval {
+       u16 addr;
+       u16 val;
+};
+
+struct s5k6aa_pixfmt {
+       enum v4l2_mbus_pixelcode code;
+       u32 colorspace;
+       /* REG_P_FMT(x) register value */
+       u16 reg_p_fmt;
+};
+
+struct s5k6aa_preset {
+       /* output pixel format and resolution */
+       struct v4l2_mbus_framefmt mbus_fmt;
+       u8 clk_id;
+       u8 index;
+};
+
+struct s5k6aa_ctrls {
+       struct v4l2_ctrl_handler handler;
+       /* Auto / manual white balance cluster */
+       struct v4l2_ctrl *awb;
+       struct v4l2_ctrl *gain_red;
+       struct v4l2_ctrl *gain_blue;
+       struct v4l2_ctrl *gain_green;
+       /* Mirror cluster */
+       struct v4l2_ctrl *hflip;
+       struct v4l2_ctrl *vflip;
+       /* Auto exposure / manual exposure and gain cluster */
+       struct v4l2_ctrl *auto_exp;
+       struct v4l2_ctrl *exposure;
+       struct v4l2_ctrl *gain;
+};
+
+struct s5k6aa_interval {
+       u16 reg_fr_time;
+       struct v4l2_fract interval;
+       /* Maximum rectangle for the interval */
+       struct v4l2_frmsize_discrete size;
+};
+
+struct s5k6aa {
+       struct v4l2_subdev sd;
+       struct media_pad pad;
+
+       enum v4l2_mbus_type bus_type;
+       u8 mipi_lanes;
+
+       int (*s_power)(int enable);
+       struct regulator_bulk_data supplies[S5K6AA_NUM_SUPPLIES];
+       struct s5k6aa_gpio gpio[GPIO_NUM];
+
+       /* external master clock frequency */
+       unsigned long mclk_frequency;
+       /* ISP internal master clock frequency */
+       u16 clk_fop;
+       /* output pixel clock frequency range */
+       u16 pclk_fmin;
+       u16 pclk_fmax;
+
+       unsigned int inv_hflip:1;
+       unsigned int inv_vflip:1;
+
+       /* protects the struct members below */
+       struct mutex lock;
+
+       /* sensor matrix scan window */
+       struct v4l2_rect ccd_rect;
+
+       struct s5k6aa_ctrls ctrls;
+       struct s5k6aa_preset presets[S5K6AA_MAX_PRESETS];
+       struct s5k6aa_preset *preset;
+       const struct s5k6aa_interval *fiv;
+
+       unsigned int streaming:1;
+       unsigned int apply_cfg:1;
+       unsigned int apply_crop:1;
+       unsigned int power;
+};
+
+static struct s5k6aa_regval s5k6aa_analog_config[] = {
+       /* Analog settings */
+       { 0x112a, 0x0000 }, { 0x1132, 0x0000 },
+       { 0x113e, 0x0000 }, { 0x115c, 0x0000 },
+       { 0x1164, 0x0000 }, { 0x1174, 0x0000 },
+       { 0x1178, 0x0000 }, { 0x077a, 0x0000 },
+       { 0x077c, 0x0000 }, { 0x077e, 0x0000 },
+       { 0x0780, 0x0000 }, { 0x0782, 0x0000 },
+       { 0x0784, 0x0000 }, { 0x0786, 0x0000 },
+       { 0x0788, 0x0000 }, { 0x07a2, 0x0000 },
+       { 0x07a4, 0x0000 }, { 0x07a6, 0x0000 },
+       { 0x07a8, 0x0000 }, { 0x07b6, 0x0000 },
+       { 0x07b8, 0x0002 }, { 0x07ba, 0x0004 },
+       { 0x07bc, 0x0004 }, { 0x07be, 0x0005 },
+       { 0x07c0, 0x0005 }, { S5K6AA_TERM, 0 },
+};
+
+/* TODO: Add RGB888 and Bayer format */
+static const struct s5k6aa_pixfmt s5k6aa_formats[] = {
+       { V4L2_MBUS_FMT_YUYV8_2X8,      V4L2_COLORSPACE_JPEG,   5 },
+       /* range 16-240 */
+       { V4L2_MBUS_FMT_YUYV8_2X8,      V4L2_COLORSPACE_REC709, 6 },
+       { V4L2_MBUS_FMT_RGB565_2X8_BE,  V4L2_COLORSPACE_JPEG,   0 },
+};
+
+static const struct s5k6aa_interval s5k6aa_intervals[] = {
+       { 1000, {10000, 1000000}, {1280, 1024} }, /* 10 fps */
+       { 666,  {15000, 1000000}, {1280, 1024} }, /* 15 fps */
+       { 500,  {20000, 1000000}, {1280, 720} },  /* 20 fps */
+       { 400,  {25000, 1000000}, {640, 480} },   /* 25 fps */
+       { 333,  {33300, 1000000}, {640, 480} },   /* 30 fps */
+};
+
+#define S5K6AA_INTERVAL_DEF_INDEX 1 /* 15 fps */
+
+static inline struct v4l2_subdev *ctrl_to_sd(struct v4l2_ctrl *ctrl)
+{
+       return &container_of(ctrl->handler, struct s5k6aa, ctrls.handler)->sd;
+}
+
+static inline struct s5k6aa *to_s5k6aa(struct v4l2_subdev *sd)
+{
+       return container_of(sd, struct s5k6aa, sd);
+}
+
+/* Set initial values for all preview presets */
+static void s5k6aa_presets_data_init(struct s5k6aa *s5k6aa)
+{
+       struct s5k6aa_preset *preset = &s5k6aa->presets[0];
+       int i;
+
+       for (i = 0; i < S5K6AA_MAX_PRESETS; i++) {
+               preset->mbus_fmt.width  = S5K6AA_OUT_WIDTH_DEF;
+               preset->mbus_fmt.height = S5K6AA_OUT_HEIGHT_DEF;
+               preset->mbus_fmt.code   = s5k6aa_formats[0].code;
+               preset->index           = i;
+               preset->clk_id          = 0;
+               preset++;
+       }
+
+       s5k6aa->fiv = &s5k6aa_intervals[S5K6AA_INTERVAL_DEF_INDEX];
+       s5k6aa->preset = &s5k6aa->presets[0];
+}
+
+static int s5k6aa_i2c_read(struct i2c_client *client, u16 addr, u16 *val)
+{
+       u8 wbuf[2] = {addr >> 8, addr & 0xFF};
+       struct i2c_msg msg[2];
+       u8 rbuf[2];
+       int ret;
+
+       msg[0].addr = client->addr;
+       msg[0].flags = 0;
+       msg[0].len = 2;
+       msg[0].buf = wbuf;
+
+       msg[1].addr = client->addr;
+       msg[1].flags = I2C_M_RD;
+       msg[1].len = 2;
+       msg[1].buf = rbuf;
+
+       ret = i2c_transfer(client->adapter, msg, 2);
+       *val = be16_to_cpu(*((u16 *)rbuf));
+
+       v4l2_dbg(3, debug, client, "i2c_read: 0x%04X : 0x%04x\n", addr, *val);
+
+       return ret == 2 ? 0 : ret;
+}
+
+static int s5k6aa_i2c_write(struct i2c_client *client, u16 addr, u16 val)
+{
+       u8 buf[4] = {addr >> 8, addr & 0xFF, val >> 8, val & 0xFF};
+
+       int ret = i2c_master_send(client, buf, 4);
+       v4l2_dbg(3, debug, client, "i2c_write: 0x%04X : 0x%04x\n", addr, val);
+
+       return ret == 4 ? 0 : ret;
+}
+
+/* The command register write, assumes Command_Wr_addH = 0x7000. */
+static int s5k6aa_write(struct i2c_client *c, u16 addr, u16 val)
+{
+       int ret = s5k6aa_i2c_write(c, REG_CMDWR_ADDRL, addr);
+       if (ret)
+               return ret;
+       return s5k6aa_i2c_write(c, REG_CMDBUF0_ADDR, val);
+}
+
+/* The command register read, assumes Command_Rd_addH = 0x7000. */
+static int s5k6aa_read(struct i2c_client *client, u16 addr, u16 *val)
+{
+       int ret = s5k6aa_i2c_write(client, REG_CMDRD_ADDRL, addr);
+       if (ret)
+               return ret;
+       return s5k6aa_i2c_read(client, REG_CMDBUF0_ADDR, val);
+}
+
+static int s5k6aa_write_array(struct v4l2_subdev *sd,
+                             const struct s5k6aa_regval *msg)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       u16 addr_incr = 0;
+       int ret = 0;
+
+       while (msg->addr != S5K6AA_TERM) {
+               if (addr_incr != 2)
+                       ret = s5k6aa_i2c_write(client, REG_CMDWR_ADDRL,
+                                              msg->addr);
+               if (ret)
+                       break;
+               ret = s5k6aa_i2c_write(client, REG_CMDBUF0_ADDR, msg->val);
+               if (ret)
+                       break;
+               /* Assume that msg->addr is always less than 0xfffc */
+               addr_incr = (msg + 1)->addr - msg->addr;
+               msg++;
+       }
+
+       return ret;
+}
+
+/* Configure the AHB high address bytes for GTG registers access */
+static int s5k6aa_set_ahb_address(struct i2c_client *client)
+{
+       int ret = s5k6aa_i2c_write(client, AHB_MSB_ADDR_PTR, GEN_REG_OFFSH);
+       if (ret)
+               return ret;
+       ret = s5k6aa_i2c_write(client, REG_CMDRD_ADDRH, HOST_SWIF_OFFSH);
+       if (ret)
+               return ret;
+       return s5k6aa_i2c_write(client, REG_CMDWR_ADDRH, HOST_SWIF_OFFSH);
+}
+
+/**
+ * s5k6aa_configure_pixel_clock - apply ISP main clock/PLL configuration
+ *
+ * Configure the internal ISP PLL for the required output frequency.
+ * Locking: called with s5k6aa.lock mutex held.
+ */
+static int s5k6aa_configure_pixel_clocks(struct s5k6aa *s5k6aa)
+{
+       struct i2c_client *c = v4l2_get_subdevdata(&s5k6aa->sd);
+       unsigned long fmclk = s5k6aa->mclk_frequency / 1000;
+       u16 status;
+       int ret;
+
+       if (WARN(fmclk < MIN_MCLK_FREQ_KHZ || fmclk > MAX_MCLK_FREQ_KHZ,
+                "Invalid clock frequency: %ld\n", fmclk))
+               return -EINVAL;
+
+       s5k6aa->pclk_fmin = PCLK_FREQ_MIN;
+       s5k6aa->pclk_fmax = PCLK_FREQ_MAX;
+       s5k6aa->clk_fop = SYS_PLL_OUT_FREQ;
+
+       /* External input clock frequency in kHz */
+       ret = s5k6aa_write(c, REG_I_INCLK_FREQ_H, fmclk >> 16);
+       if (!ret)
+               ret = s5k6aa_write(c, REG_I_INCLK_FREQ_L, fmclk & 0xFFFF);
+       if (!ret)
+               ret = s5k6aa_write(c, REG_I_USE_NPVI_CLOCKS, 1);
+       /* Internal PLL frequency */
+       if (!ret)
+               ret = s5k6aa_write(c, REG_I_OPCLK_4KHZ(0), s5k6aa->clk_fop);
+       if (!ret)
+               ret = s5k6aa_write(c, REG_I_MIN_OUTRATE_4KHZ(0),
+                                  s5k6aa->pclk_fmin);
+       if (!ret)
+               ret = s5k6aa_write(c, REG_I_MAX_OUTRATE_4KHZ(0),
+                                  s5k6aa->pclk_fmax);
+       if (!ret)
+               ret = s5k6aa_write(c, REG_I_INIT_PARAMS_UPDATED, 1);
+       if (!ret)
+               ret = s5k6aa_read(c, REG_I_ERROR_INFO, &status);
+
+       return ret ? ret : (status ? -EINVAL : 0);
+}
+
+/* Set horizontal and vertical image flipping */
+static int s5k6aa_set_mirror(struct s5k6aa *s5k6aa, int horiz_flip)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
+       int index = s5k6aa->preset->index;
+
+       unsigned int vflip = s5k6aa->ctrls.vflip->val ^ s5k6aa->inv_vflip;
+       unsigned int flip = (horiz_flip ^ s5k6aa->inv_hflip) | (vflip << 1);
+
+       return s5k6aa_write(client, REG_P_PREV_MIRROR(index), flip);
+}
+
+/* Configure auto/manual white balance and R/G/B gains */
+static int s5k6aa_set_awb(struct s5k6aa *s5k6aa, int awb)
+{
+       struct i2c_client *c = v4l2_get_subdevdata(&s5k6aa->sd);
+       struct s5k6aa_ctrls *ctrls = &s5k6aa->ctrls;
+       u16 reg;
+
+       int ret = s5k6aa_read(c, REG_DBG_AUTOALG_EN, &reg);
+
+       if (!ret && !awb) {
+               ret = s5k6aa_write(c, REG_SF_RGAIN, ctrls->gain_red->val);
+               if (!ret)
+                       ret = s5k6aa_write(c, REG_SF_RGAIN_CHG, 1);
+               if (ret)
+                       return ret;
+
+               ret = s5k6aa_write(c, REG_SF_GGAIN, ctrls->gain_green->val);
+               if (!ret)
+                       ret = s5k6aa_write(c, REG_SF_GGAIN_CHG, 1);
+               if (ret)
+                       return ret;
+
+               ret = s5k6aa_write(c, REG_SF_BGAIN, ctrls->gain_blue->val);
+               if (!ret)
+                       ret = s5k6aa_write(c, REG_SF_BGAIN_CHG, 1);
+       }
+       if (!ret) {
+               reg = awb ? reg | AALG_WB_EN_MASK : reg & ~AALG_WB_EN_MASK;
+               ret = s5k6aa_write(c, REG_DBG_AUTOALG_EN, reg);
+       }
+
+       return ret;
+}
+
+/* Program FW with exposure time, 'exposure' in us units */
+static int s5k6aa_set_user_exposure(struct i2c_client *client, int exposure)
+{
+       unsigned int time = exposure / 10;
+
+       int ret = s5k6aa_write(client, REG_SF_USR_EXPOSURE_L, time & 0xffff);
+       if (!ret)
+               ret = s5k6aa_write(client, REG_SF_USR_EXPOSURE_H, time >> 16);
+       if (ret)
+               return ret;
+       return s5k6aa_write(client, REG_SF_USR_EXPOSURE_CHG, 1);
+}
+
+static int s5k6aa_set_user_gain(struct i2c_client *client, int gain)
+{
+       int ret = s5k6aa_write(client, REG_SF_USR_TOT_GAIN, gain);
+       if (ret)
+               return ret;
+       return s5k6aa_write(client, REG_SF_USR_TOT_GAIN_CHG, 1);
+}
+
+/* Set auto/manual exposure and total gain */
+static int s5k6aa_set_auto_exposure(struct s5k6aa *s5k6aa, int value)
+{
+       struct i2c_client *c = v4l2_get_subdevdata(&s5k6aa->sd);
+       unsigned int exp_time = s5k6aa->ctrls.exposure->val;
+       u16 auto_alg;
+
+       int ret = s5k6aa_read(c, REG_DBG_AUTOALG_EN, &auto_alg);
+       if (ret)
+               return ret;
+
+       v4l2_dbg(1, debug, c, "man_exp: %d, auto_exp: %d, a_alg: 0x%x\n",
+                exp_time, value, auto_alg);
+
+       if (value == V4L2_EXPOSURE_AUTO) {
+               auto_alg |= AALG_AE_EN_MASK | AALG_DIVLEI_EN_MASK;
+       } else {
+               ret = s5k6aa_set_user_exposure(c, exp_time);
+               if (ret)
+                       return ret;
+               ret = s5k6aa_set_user_gain(c, s5k6aa->ctrls.gain->val);
+               if (ret)
+                       return ret;
+               auto_alg &= ~(AALG_AE_EN_MASK | AALG_DIVLEI_EN_MASK);
+       }
+
+       return s5k6aa_write(c, REG_DBG_AUTOALG_EN, auto_alg);
+}
+
+static int s5k6aa_set_anti_flicker(struct s5k6aa *s5k6aa, int value)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
+       u16 auto_alg;
+       int ret;
+
+       ret = s5k6aa_read(client, REG_DBG_AUTOALG_EN, &auto_alg);
+       if (ret)
+               return ret;
+
+       if (value == V4L2_CID_POWER_LINE_FREQUENCY_AUTO) {
+               auto_alg |= AALG_FLICKER_EN_MASK;
+       } else {
+               auto_alg &= ~AALG_FLICKER_EN_MASK;
+               /* The V4L2_CID_LINE_FREQUENCY control values match
+                * the register values */
+               ret = s5k6aa_write(client, REG_SF_FLICKER_QUANT, value);
+               if (ret)
+                       return ret;
+               ret = s5k6aa_write(client, REG_SF_FLICKER_QUANT_CHG, 1);
+               if (ret)
+                       return ret;
+       }
+
+       return s5k6aa_write(client, REG_DBG_AUTOALG_EN, auto_alg);
+}
+
+static int s5k6aa_set_colorfx(struct s5k6aa *s5k6aa, int val)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
+       static const struct v4l2_control colorfx[] = {
+               { V4L2_COLORFX_NONE,     0 },
+               { V4L2_COLORFX_BW,       1 },
+               { V4L2_COLORFX_NEGATIVE, 2 },
+               { V4L2_COLORFX_SEPIA,    3 },
+               { V4L2_COLORFX_SKY_BLUE, 4 },
+               { V4L2_COLORFX_SKETCH,   5 },
+       };
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(colorfx); i++) {
+               if (colorfx[i].id == val)
+                       return s5k6aa_write(client, REG_G_SPEC_EFFECTS,
+                                           colorfx[i].value);
+       }
+       return -EINVAL;
+}
+
+static int s5k6aa_preview_config_status(struct i2c_client *client)
+{
+       u16 error = 0;
+       int ret = s5k6aa_read(client, REG_G_PREV_CFG_ERROR, &error);
+
+       v4l2_dbg(1, debug, client, "error: 0x%x (%d)\n", error, ret);
+       return ret ? ret : (error ? -EINVAL : 0);
+}
+
+static int s5k6aa_get_pixfmt_index(struct s5k6aa *s5k6aa,
+                                  struct v4l2_mbus_framefmt *mf)
+{
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(s5k6aa_formats); i++)
+               if (mf->colorspace == s5k6aa_formats[i].colorspace &&
+                   mf->code == s5k6aa_formats[i].code)
+                       return i;
+       return 0;
+}
+
+static int s5k6aa_set_output_framefmt(struct s5k6aa *s5k6aa,
+                                     struct s5k6aa_preset *preset)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
+       int fmt_index = s5k6aa_get_pixfmt_index(s5k6aa, &preset->mbus_fmt);
+       int ret;
+
+       ret = s5k6aa_write(client, REG_P_OUT_WIDTH(preset->index),
+                          preset->mbus_fmt.width);
+       if (!ret)
+               ret = s5k6aa_write(client, REG_P_OUT_HEIGHT(preset->index),
+                                  preset->mbus_fmt.height);
+       if (!ret)
+               ret = s5k6aa_write(client, REG_P_FMT(preset->index),
+                                  s5k6aa_formats[fmt_index].reg_p_fmt);
+       return ret;
+}
+
+static int s5k6aa_set_input_params(struct s5k6aa *s5k6aa)
+{
+       struct i2c_client *c = v4l2_get_subdevdata(&s5k6aa->sd);
+       struct v4l2_rect *r = &s5k6aa->ccd_rect;
+       int ret;
+
+       ret = s5k6aa_write(c, REG_G_PREVZOOM_IN_WIDTH, r->width);
+       if (!ret)
+               ret = s5k6aa_write(c, REG_G_PREVZOOM_IN_HEIGHT, r->height);
+       if (!ret)
+               ret = s5k6aa_write(c, REG_G_PREVZOOM_IN_XOFFS, r->left);
+       if (!ret)
+               ret = s5k6aa_write(c, REG_G_PREVZOOM_IN_YOFFS, r->top);
+       if (!ret)
+               ret = s5k6aa_write(c, REG_G_INPUTS_CHANGE_REQ, 1);
+       if (!ret)
+               s5k6aa->apply_crop = 0;
+
+       return ret;
+}
+
+/**
+ * s5k6aa_configure_video_bus - configure the video output interface
+ * @bus_type: video bus type: parallel or MIPI-CSI
+ * @nlanes: number of MIPI lanes to be used (MIPI-CSI only)
+ *
+ * Note: Only parallel bus operation has been tested.
+ */
+static int s5k6aa_configure_video_bus(struct s5k6aa *s5k6aa,
+                                     enum v4l2_mbus_type bus_type, int nlanes)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
+       u16 cfg = 0;
+       int ret;
+
+       /*
+        * TODO: The sensor is supposed to support BT.601 and BT.656
+        * but there is nothing indicating how to switch between both
+        * in the datasheet. For now default BT.601 interface is assumed.
+        */
+       if (bus_type == V4L2_MBUS_CSI2)
+               cfg = nlanes;
+       else if (bus_type != V4L2_MBUS_PARALLEL)
+               return -EINVAL;
+
+       ret = s5k6aa_write(client, REG_OIF_EN_MIPI_LANES, cfg);
+       if (ret)
+               return ret;
+       return s5k6aa_write(client, REG_OIF_CFG_CHG, 1);
+}
+
+/* This function should be called when switching to new user configuration set*/
+static int s5k6aa_new_config_sync(struct i2c_client *client, int timeout,
+                                 int cid)
+{
+       unsigned long end = jiffies + msecs_to_jiffies(timeout);
+       u16 reg = 1;
+       int ret;
+
+       ret = s5k6aa_write(client, REG_G_ACTIVE_PREV_CFG, cid);
+       if (!ret)
+               ret = s5k6aa_write(client, REG_G_PREV_CFG_CHG, 1);
+       if (!ret)
+               ret = s5k6aa_write(client, REG_G_NEW_CFG_SYNC, 1);
+       if (timeout == 0)
+               return ret;
+
+       while (ret >= 0 && time_is_after_jiffies(end)) {
+               ret = s5k6aa_read(client, REG_G_NEW_CFG_SYNC, &reg);
+               if (!reg)
+                       return 0;
+               usleep_range(1000, 5000);
+       }
+       return ret ? ret : -ETIMEDOUT;
+}
+
+/**
+ * s5k6aa_set_prev_config - write user preview register set
+ *
+ * Configure output resolution and color fromat, pixel clock
+ * frequency range, device frame rate type and frame period range.
+ */
+static int s5k6aa_set_prev_config(struct s5k6aa *s5k6aa,
+                                 struct s5k6aa_preset *preset)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
+       int idx = preset->index;
+       u16 frame_rate_q;
+       int ret;
+
+       if (s5k6aa->fiv->reg_fr_time >= S5K6AA_MAX_HIGHRES_FR_TIME)
+               frame_rate_q = FR_RATE_Q_BEST_FRRATE;
+       else
+               frame_rate_q = FR_RATE_Q_BEST_QUALITY;
+
+       ret = s5k6aa_set_output_framefmt(s5k6aa, preset);
+       if (!ret)
+               ret = s5k6aa_write(client, REG_P_MAX_OUT_RATE(idx),
+                                  s5k6aa->pclk_fmax);
+       if (!ret)
+               ret = s5k6aa_write(client, REG_P_MIN_OUT_RATE(idx),
+                                  s5k6aa->pclk_fmin);
+       if (!ret)
+               ret = s5k6aa_write(client, REG_P_CLK_INDEX(idx),
+                                  preset->clk_id);
+       if (!ret)
+               ret = s5k6aa_write(client, REG_P_FR_RATE_TYPE(idx),
+                                  FR_RATE_DYNAMIC);
+       if (!ret)
+               ret = s5k6aa_write(client, REG_P_FR_RATE_Q_TYPE(idx),
+                                  frame_rate_q);
+       if (!ret)
+               ret = s5k6aa_write(client, REG_P_MAX_FR_TIME(idx),
+                                  s5k6aa->fiv->reg_fr_time + 33);
+       if (!ret)
+               ret = s5k6aa_write(client, REG_P_MIN_FR_TIME(idx),
+                                  s5k6aa->fiv->reg_fr_time - 33);
+       if (!ret)
+               ret = s5k6aa_new_config_sync(client, 250, idx);
+       if (!ret)
+               ret = s5k6aa_preview_config_status(client);
+       if (!ret)
+               s5k6aa->apply_cfg = 0;
+
+       v4l2_dbg(1, debug, client, "Frame interval: %d +/- 3.3ms. (%d)\n",
+                s5k6aa->fiv->reg_fr_time, ret);
+       return ret;
+}
+
+/**
+ * s5k6aa_initialize_isp - basic ISP MCU initialization
+ *
+ * Configure AHB addresses for registers read/write; configure PLLs for
+ * required output pixel clock. The ISP power supply needs to be already
+ * enabled, with an optional H/W reset.
+ * Locking: called with s5k6aa.lock mutex held.
+ */
+static int s5k6aa_initialize_isp(struct v4l2_subdev *sd)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct s5k6aa *s5k6aa = to_s5k6aa(sd);
+       int ret;
+
+       s5k6aa->apply_crop = 1;
+       s5k6aa->apply_cfg = 1;
+       msleep(100);
+
+       ret = s5k6aa_set_ahb_address(client);
+       if (ret)
+               return ret;
+       ret = s5k6aa_configure_video_bus(s5k6aa, s5k6aa->bus_type,
+                                        s5k6aa->mipi_lanes);
+       if (ret)
+               return ret;
+       ret = s5k6aa_write_array(sd, s5k6aa_analog_config);
+       if (ret)
+               return ret;
+       msleep(20);
+
+       return s5k6aa_configure_pixel_clocks(s5k6aa);
+}
+
+static int s5k6aa_gpio_set_value(struct s5k6aa *priv, int id, u32 val)
+{
+       if (!gpio_is_valid(priv->gpio[id].gpio))
+               return 0;
+       gpio_set_value(priv->gpio[id].gpio, !!val);
+       return 1;
+}
+
+static int s5k6aa_gpio_assert(struct s5k6aa *priv, int id)
+{
+       return s5k6aa_gpio_set_value(priv, id, priv->gpio[id].level);
+}
+
+static int s5k6aa_gpio_deassert(struct s5k6aa *priv, int id)
+{
+       return s5k6aa_gpio_set_value(priv, id, !priv->gpio[id].level);
+}
+
+static int __s5k6aa_power_on(struct s5k6aa *s5k6aa)
+{
+       int ret;
+
+       ret = regulator_bulk_enable(S5K6AA_NUM_SUPPLIES, s5k6aa->supplies);
+       if (ret)
+               return ret;
+       if (s5k6aa_gpio_deassert(s5k6aa, STBY))
+               usleep_range(150, 200);
+
+       if (s5k6aa->s_power)
+               ret = s5k6aa->s_power(1);
+       usleep_range(4000, 4000);
+
+       if (s5k6aa_gpio_deassert(s5k6aa, RST))
+               msleep(20);
+
+       return ret;
+}
+
+static int __s5k6aa_power_off(struct s5k6aa *s5k6aa)
+{
+       int ret;
+
+       if (s5k6aa_gpio_assert(s5k6aa, RST))
+               usleep_range(100, 150);
+
+       if (s5k6aa->s_power) {
+               ret = s5k6aa->s_power(0);
+               if (ret)
+                       return ret;
+       }
+       if (s5k6aa_gpio_assert(s5k6aa, STBY))
+               usleep_range(50, 100);
+       s5k6aa->streaming = 0;
+
+       return regulator_bulk_disable(S5K6AA_NUM_SUPPLIES, s5k6aa->supplies);
+}
+
+/*
+ * V4L2 subdev core and video operations
+ */
+static int s5k6aa_set_power(struct v4l2_subdev *sd, int on)
+{
+       struct s5k6aa *s5k6aa = to_s5k6aa(sd);
+       int ret = 0;
+
+       mutex_lock(&s5k6aa->lock);
+
+       if (!on == s5k6aa->power) {
+               if (on) {
+                       ret = __s5k6aa_power_on(s5k6aa);
+                       if (!ret)
+                               ret = s5k6aa_initialize_isp(sd);
+               } else {
+                       ret = __s5k6aa_power_off(s5k6aa);
+               }
+
+               if (!ret)
+                       s5k6aa->power += on ? 1 : -1;
+       }
+
+       mutex_unlock(&s5k6aa->lock);
+
+       if (!on || ret || s5k6aa->power != 1)
+               return ret;
+
+       return v4l2_ctrl_handler_setup(sd->ctrl_handler);
+}
+
+static int __s5k6aa_stream(struct s5k6aa *s5k6aa, int enable)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
+       int ret = 0;
+
+       ret = s5k6aa_write(client, REG_G_ENABLE_PREV, enable);
+       if (!ret)
+               ret = s5k6aa_write(client, REG_G_ENABLE_PREV_CHG, 1);
+       if (!ret)
+               s5k6aa->streaming = enable;
+
+       return ret;
+}
+
+static int s5k6aa_s_stream(struct v4l2_subdev *sd, int on)
+{
+       struct s5k6aa *s5k6aa = to_s5k6aa(sd);
+       int ret = 0;
+
+       mutex_lock(&s5k6aa->lock);
+
+       if (s5k6aa->streaming == !on) {
+               if (!ret && s5k6aa->apply_cfg)
+                       ret = s5k6aa_set_prev_config(s5k6aa, s5k6aa->preset);
+               if (s5k6aa->apply_crop)
+                       ret = s5k6aa_set_input_params(s5k6aa);
+               if (!ret)
+                       ret = __s5k6aa_stream(s5k6aa, !!on);
+       }
+       mutex_unlock(&s5k6aa->lock);
+
+       return ret;
+}
+
+static int s5k6aa_g_frame_interval(struct v4l2_subdev *sd,
+                                  struct v4l2_subdev_frame_interval *fi)
+{
+       struct s5k6aa *s5k6aa = to_s5k6aa(sd);
+
+       mutex_lock(&s5k6aa->lock);
+       fi->interval = s5k6aa->fiv->interval;
+       mutex_unlock(&s5k6aa->lock);
+
+       return 0;
+}
+
+static int __s5k6aa_set_frame_interval(struct s5k6aa *s5k6aa,
+                                      struct v4l2_subdev_frame_interval *fi)
+{
+       struct v4l2_mbus_framefmt *mbus_fmt = &s5k6aa->preset->mbus_fmt;
+       const struct s5k6aa_interval *fiv = &s5k6aa_intervals[0];
+       unsigned int err, min_err = UINT_MAX;
+       unsigned int i, fr_time;
+
+       if (fi->interval.denominator == 0)
+               return -EINVAL;
+
+       fr_time = fi->interval.numerator * 10000 / fi->interval.denominator;
+
+       for (i = 0; i < ARRAY_SIZE(s5k6aa_intervals); i++) {
+               const struct s5k6aa_interval *iv = &s5k6aa_intervals[i];
+
+               if (mbus_fmt->width > iv->size.width ||
+                   mbus_fmt->height > iv->size.height)
+                       continue;
+
+               err = abs(iv->reg_fr_time - fr_time);
+               if (err < min_err) {
+                       fiv = iv;
+                       min_err = err;
+               }
+       }
+       s5k6aa->fiv = fiv;
+
+       v4l2_dbg(1, debug, &s5k6aa->sd, "Changed frame interval to %d us\n",
+                fiv->reg_fr_time * 100);
+       return 0;
+}
+
+static int s5k6aa_s_frame_interval(struct v4l2_subdev *sd,
+                                  struct v4l2_subdev_frame_interval *fi)
+{
+       struct s5k6aa *s5k6aa = to_s5k6aa(sd);
+       int ret;
+
+       v4l2_dbg(1, debug, sd, "Setting %d/%d frame interval\n",
+                fi->interval.numerator, fi->interval.denominator);
+
+       mutex_lock(&s5k6aa->lock);
+       ret = __s5k6aa_set_frame_interval(s5k6aa, fi);
+       s5k6aa->apply_cfg = 1;
+
+       mutex_unlock(&s5k6aa->lock);
+       return ret;
+}
+
+/*
+ * V4L2 subdev pad level and video operations
+ */
+static int s5k6aa_enum_frame_interval(struct v4l2_subdev *sd,
+                             struct v4l2_subdev_fh *fh,
+                             struct v4l2_subdev_frame_interval_enum *fie)
+{
+       struct s5k6aa *s5k6aa = to_s5k6aa(sd);
+       const struct s5k6aa_interval *fi;
+       int ret = 0;
+
+       if (fie->index > ARRAY_SIZE(s5k6aa_intervals))
+               return -EINVAL;
+
+       v4l_bound_align_image(&fie->width, S5K6AA_WIN_WIDTH_MIN,
+                             S5K6AA_WIN_WIDTH_MAX, 1,
+                             &fie->height, S5K6AA_WIN_HEIGHT_MIN,
+                             S5K6AA_WIN_HEIGHT_MAX, 1, 0);
+
+       mutex_lock(&s5k6aa->lock);
+       fi = &s5k6aa_intervals[fie->index];
+       if (fie->width > fi->size.width || fie->height > fi->size.height)
+               ret = -EINVAL;
+       else
+               fie->interval = fi->interval;
+       mutex_unlock(&s5k6aa->lock);
+
+       return ret;
+}
+
+static int s5k6aa_enum_mbus_code(struct v4l2_subdev *sd,
+                                struct v4l2_subdev_fh *fh,
+                                struct v4l2_subdev_mbus_code_enum *code)
+{
+       if (code->index >= ARRAY_SIZE(s5k6aa_formats))
+               return -EINVAL;
+
+       code->code = s5k6aa_formats[code->index].code;
+       return 0;
+}
+
+static int s5k6aa_enum_frame_size(struct v4l2_subdev *sd,
+                                 struct v4l2_subdev_fh *fh,
+                                 struct v4l2_subdev_frame_size_enum *fse)
+{
+       int i = ARRAY_SIZE(s5k6aa_formats);
+
+       if (fse->index > 0)
+               return -EINVAL;
+
+       while (--i)
+               if (fse->code == s5k6aa_formats[i].code)
+                       break;
+
+       fse->code = s5k6aa_formats[i].code;
+       fse->min_width  = S5K6AA_WIN_WIDTH_MIN;
+       fse->max_width  = S5K6AA_WIN_WIDTH_MAX;
+       fse->max_height = S5K6AA_WIN_HEIGHT_MIN;
+       fse->min_height = S5K6AA_WIN_HEIGHT_MAX;
+
+       return 0;
+}
+
+static struct v4l2_rect *
+__s5k6aa_get_crop_rect(struct s5k6aa *s5k6aa, struct v4l2_subdev_fh *fh,
+                      enum v4l2_subdev_format_whence which)
+{
+       if (which == V4L2_SUBDEV_FORMAT_ACTIVE)
+               return &s5k6aa->ccd_rect;
+       if (which == V4L2_SUBDEV_FORMAT_TRY)
+               return v4l2_subdev_get_try_crop(fh, 0);
+
+       return NULL;
+}
+
+static void s5k6aa_try_format(struct s5k6aa *s5k6aa,
+                             struct v4l2_mbus_framefmt *mf)
+{
+       unsigned int index;
+
+       v4l_bound_align_image(&mf->width, S5K6AA_WIN_WIDTH_MIN,
+                             S5K6AA_WIN_WIDTH_MAX, 1,
+                             &mf->height, S5K6AA_WIN_HEIGHT_MIN,
+                             S5K6AA_WIN_HEIGHT_MAX, 1, 0);
+
+       if (mf->colorspace != V4L2_COLORSPACE_JPEG &&
+           mf->colorspace != V4L2_COLORSPACE_REC709)
+               mf->colorspace = V4L2_COLORSPACE_JPEG;
+
+       index = s5k6aa_get_pixfmt_index(s5k6aa, mf);
+
+       mf->colorspace  = s5k6aa_formats[index].colorspace;
+       mf->code        = s5k6aa_formats[index].code;
+       mf->field       = V4L2_FIELD_NONE;
+}
+
+static int s5k6aa_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+                         struct v4l2_subdev_format *fmt)
+{
+       struct s5k6aa *s5k6aa = to_s5k6aa(sd);
+       struct v4l2_mbus_framefmt *mf;
+
+       memset(fmt->reserved, 0, sizeof(fmt->reserved));
+
+       if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
+               mf = v4l2_subdev_get_try_format(fh, 0);
+               fmt->format = *mf;
+               return 0;
+       }
+
+       mutex_lock(&s5k6aa->lock);
+       fmt->format = s5k6aa->preset->mbus_fmt;
+       mutex_unlock(&s5k6aa->lock);
+
+       return 0;
+}
+
+static int s5k6aa_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+                         struct v4l2_subdev_format *fmt)
+{
+       struct s5k6aa *s5k6aa = to_s5k6aa(sd);
+       struct s5k6aa_preset *preset = s5k6aa->preset;
+       struct v4l2_mbus_framefmt *mf;
+       struct v4l2_rect *crop;
+       int ret = 0;
+
+       mutex_lock(&s5k6aa->lock);
+       s5k6aa_try_format(s5k6aa, &fmt->format);
+
+       if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
+               mf = v4l2_subdev_get_try_format(fh, fmt->pad);
+               crop = v4l2_subdev_get_try_crop(fh, 0);
+       } else {
+               if (s5k6aa->streaming) {
+                       ret = -EBUSY;
+               } else {
+                       mf = &preset->mbus_fmt;
+                       crop = &s5k6aa->ccd_rect;
+                       s5k6aa->apply_cfg = 1;
+               }
+       }
+
+       if (ret == 0) {
+               struct v4l2_subdev_frame_interval fiv = {
+                       .interval = {0, 1}
+               };
+
+               *mf = fmt->format;
+               /*
+                * Make sure the crop window is valid, i.e. its size is
+                * greater than the output window, as the ISP supports
+                * only down-scaling.
+                */
+               crop->width = clamp_t(unsigned int, crop->width, mf->width,
+                                     S5K6AA_WIN_WIDTH_MAX);
+               crop->height = clamp_t(unsigned int, crop->height, mf->height,
+                                      S5K6AA_WIN_HEIGHT_MAX);
+               crop->left = clamp_t(unsigned int, crop->left, 0,
+                                    S5K6AA_WIN_WIDTH_MAX - crop->width);
+               crop->top  = clamp_t(unsigned int, crop->top, 0,
+                                    S5K6AA_WIN_HEIGHT_MAX - crop->height);
+
+               /* Reset to minimum possible frame interval */
+               ret = __s5k6aa_set_frame_interval(s5k6aa, &fiv);
+       }
+       mutex_unlock(&s5k6aa->lock);
+
+       return ret;
+}
+
+static int s5k6aa_get_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+                          struct v4l2_subdev_crop *crop)
+{
+       struct s5k6aa *s5k6aa = to_s5k6aa(sd);
+       struct v4l2_rect *rect;
+
+       memset(crop->reserved, 0, sizeof(crop->reserved));
+       mutex_lock(&s5k6aa->lock);
+
+       rect = __s5k6aa_get_crop_rect(s5k6aa, fh, crop->which);
+       if (rect)
+               crop->rect = *rect;
+
+       mutex_unlock(&s5k6aa->lock);
+
+       v4l2_dbg(1, debug, sd, "Current crop rectangle: (%d,%d)/%dx%d\n",
+                rect->left, rect->top, rect->width, rect->height);
+
+       return 0;
+}
+
+static int s5k6aa_set_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+                          struct v4l2_subdev_crop *crop)
+{
+       struct s5k6aa *s5k6aa = to_s5k6aa(sd);
+       struct v4l2_mbus_framefmt *mf;
+       unsigned int max_x, max_y;
+       struct v4l2_rect *crop_r;
+
+       mutex_lock(&s5k6aa->lock);
+       crop_r = __s5k6aa_get_crop_rect(s5k6aa, fh, crop->which);
+
+       if (crop->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
+               mf = &s5k6aa->preset->mbus_fmt;
+               s5k6aa->apply_crop = 1;
+       } else {
+               mf = v4l2_subdev_get_try_format(fh, 0);
+       }
+       v4l_bound_align_image(&crop->rect.width, mf->width,
+                             S5K6AA_WIN_WIDTH_MAX, 1,
+                             &crop->rect.height, mf->height,
+                             S5K6AA_WIN_HEIGHT_MAX, 1, 0);
+
+       max_x = (S5K6AA_WIN_WIDTH_MAX - crop->rect.width) & ~1;
+       max_y = (S5K6AA_WIN_HEIGHT_MAX - crop->rect.height) & ~1;
+
+       crop->rect.left = clamp_t(unsigned int, crop->rect.left, 0, max_x);
+       crop->rect.top  = clamp_t(unsigned int, crop->rect.top, 0, max_y);
+
+       *crop_r = crop->rect;
+
+       mutex_unlock(&s5k6aa->lock);
+
+       v4l2_dbg(1, debug, sd, "Set crop rectangle: (%d,%d)/%dx%d\n",
+                crop_r->left, crop_r->top, crop_r->width, crop_r->height);
+
+       return 0;
+}
+
+static const struct v4l2_subdev_pad_ops s5k6aa_pad_ops = {
+       .enum_mbus_code         = s5k6aa_enum_mbus_code,
+       .enum_frame_size        = s5k6aa_enum_frame_size,
+       .enum_frame_interval    = s5k6aa_enum_frame_interval,
+       .get_fmt                = s5k6aa_get_fmt,
+       .set_fmt                = s5k6aa_set_fmt,
+       .get_crop               = s5k6aa_get_crop,
+       .set_crop               = s5k6aa_set_crop,
+};
+
+static const struct v4l2_subdev_video_ops s5k6aa_video_ops = {
+       .g_frame_interval       = s5k6aa_g_frame_interval,
+       .s_frame_interval       = s5k6aa_s_frame_interval,
+       .s_stream               = s5k6aa_s_stream,
+};
+
+/*
+ * V4L2 subdev controls
+ */
+
+static int s5k6aa_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct v4l2_subdev *sd = ctrl_to_sd(ctrl);
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct s5k6aa *s5k6aa = to_s5k6aa(sd);
+       int idx, err = 0;
+
+       v4l2_dbg(1, debug, sd, "ctrl: 0x%x, value: %d\n", ctrl->id, ctrl->val);
+
+       mutex_lock(&s5k6aa->lock);
+       /*
+        * If the device is not powered up by the host driver do
+        * not apply any controls to H/W at this time. Instead
+        * the controls will be restored right after power-up.
+        */
+       if (s5k6aa->power == 0)
+               goto unlock;
+       idx = s5k6aa->preset->index;
+
+       switch (ctrl->id) {
+       case V4L2_CID_AUTO_WHITE_BALANCE:
+               err = s5k6aa_set_awb(s5k6aa, ctrl->val);
+               break;
+
+       case V4L2_CID_BRIGHTNESS:
+               err = s5k6aa_write(client, REG_USER_BRIGHTNESS, ctrl->val);
+               break;
+
+       case V4L2_CID_COLORFX:
+               err = s5k6aa_set_colorfx(s5k6aa, ctrl->val);
+               break;
+
+       case V4L2_CID_CONTRAST:
+               err = s5k6aa_write(client, REG_USER_CONTRAST, ctrl->val);
+               break;
+
+       case V4L2_CID_EXPOSURE_AUTO:
+               err = s5k6aa_set_auto_exposure(s5k6aa, ctrl->val);
+               break;
+
+       case V4L2_CID_HFLIP:
+               err = s5k6aa_set_mirror(s5k6aa, ctrl->val);
+               if (err)
+                       break;
+               err = s5k6aa_write(client, REG_G_PREV_CFG_CHG, 1);
+               break;
+
+       case V4L2_CID_POWER_LINE_FREQUENCY:
+               err = s5k6aa_set_anti_flicker(s5k6aa, ctrl->val);
+               break;
+
+       case V4L2_CID_SATURATION:
+               err = s5k6aa_write(client, REG_USER_SATURATION, ctrl->val);
+               break;
+
+       case V4L2_CID_SHARPNESS:
+               err = s5k6aa_write(client, REG_USER_SHARPBLUR, ctrl->val);
+               break;
+
+       case V4L2_CID_WHITE_BALANCE_TEMPERATURE:
+               err = s5k6aa_write(client, REG_P_COLORTEMP(idx), ctrl->val);
+               if (err)
+                       break;
+               err = s5k6aa_write(client, REG_G_PREV_CFG_CHG, 1);
+               break;
+       }
+unlock:
+       mutex_unlock(&s5k6aa->lock);
+       return err;
+}
+
+static const struct v4l2_ctrl_ops s5k6aa_ctrl_ops = {
+       .s_ctrl = s5k6aa_s_ctrl,
+};
+
+static int s5k6aa_log_status(struct v4l2_subdev *sd)
+{
+       v4l2_ctrl_handler_log_status(sd->ctrl_handler, sd->name);
+       return 0;
+}
+
+#define V4L2_CID_RED_GAIN      (V4L2_CTRL_CLASS_CAMERA | 0x1001)
+#define V4L2_CID_GREEN_GAIN    (V4L2_CTRL_CLASS_CAMERA | 0x1002)
+#define V4L2_CID_BLUE_GAIN     (V4L2_CTRL_CLASS_CAMERA | 0x1003)
+
+static const struct v4l2_ctrl_config s5k6aa_ctrls[] = {
+       {
+               .ops    = &s5k6aa_ctrl_ops,
+               .id     = V4L2_CID_RED_GAIN,
+               .type   = V4L2_CTRL_TYPE_INTEGER,
+               .name   = "Gain, Red",
+               .min    = 0,
+               .max    = 256,
+               .def    = 127,
+               .step   = 1,
+       }, {
+               .ops    = &s5k6aa_ctrl_ops,
+               .id     = V4L2_CID_GREEN_GAIN,
+               .type   = V4L2_CTRL_TYPE_INTEGER,
+               .name   = "Gain, Green",
+               .min    = 0,
+               .max    = 256,
+               .def    = 127,
+               .step   = 1,
+       }, {
+               .ops    = &s5k6aa_ctrl_ops,
+               .id     = V4L2_CID_BLUE_GAIN,
+               .type   = V4L2_CTRL_TYPE_INTEGER,
+               .name   = "Gain, Blue",
+               .min    = 0,
+               .max    = 256,
+               .def    = 127,
+               .step   = 1,
+       },
+};
+
+static int s5k6aa_initialize_ctrls(struct s5k6aa *s5k6aa)
+{
+       const struct v4l2_ctrl_ops *ops = &s5k6aa_ctrl_ops;
+       struct s5k6aa_ctrls *ctrls = &s5k6aa->ctrls;
+       struct v4l2_ctrl_handler *hdl = &ctrls->handler;
+
+       int ret = v4l2_ctrl_handler_init(hdl, 16);
+       if (ret)
+               return ret;
+       /* Auto white balance cluster */
+       ctrls->awb = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_AUTO_WHITE_BALANCE,
+                                      0, 1, 1, 1);
+       ctrls->gain_red = v4l2_ctrl_new_custom(hdl, &s5k6aa_ctrls[0], NULL);
+       ctrls->gain_green = v4l2_ctrl_new_custom(hdl, &s5k6aa_ctrls[1], NULL);
+       ctrls->gain_blue = v4l2_ctrl_new_custom(hdl, &s5k6aa_ctrls[2], NULL);
+       v4l2_ctrl_auto_cluster(4, &ctrls->awb, 0, false);
+
+       ctrls->hflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_HFLIP, 0, 1, 1, 0);
+       ctrls->vflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_VFLIP, 0, 1, 1, 0);
+       v4l2_ctrl_cluster(2, &ctrls->hflip);
+
+       ctrls->auto_exp = v4l2_ctrl_new_std_menu(hdl, ops,
+                               V4L2_CID_EXPOSURE_AUTO,
+                               V4L2_EXPOSURE_MANUAL, 0, V4L2_EXPOSURE_AUTO);
+       /* Exposure time: x 1 us */
+       ctrls->exposure = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_EXPOSURE,
+                                           0, 6000000U, 1, 100000U);
+       /* Total gain: 256 <=> 1x */
+       ctrls->gain = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_GAIN,
+                                       0, 256, 1, 256);
+       v4l2_ctrl_auto_cluster(3, &ctrls->auto_exp, 0, false);
+
+       v4l2_ctrl_new_std_menu(hdl, ops, V4L2_CID_POWER_LINE_FREQUENCY,
+                              V4L2_CID_POWER_LINE_FREQUENCY_AUTO, 0,
+                              V4L2_CID_POWER_LINE_FREQUENCY_AUTO);
+
+       v4l2_ctrl_new_std_menu(hdl, ops, V4L2_CID_COLORFX,
+                              V4L2_COLORFX_SKY_BLUE, ~0x6f, V4L2_COLORFX_NONE);
+
+       v4l2_ctrl_new_std(hdl, ops, V4L2_CID_WHITE_BALANCE_TEMPERATURE,
+                         0, 256, 1, 0);
+
+       v4l2_ctrl_new_std(hdl, ops, V4L2_CID_SATURATION, -127, 127, 1, 0);
+       v4l2_ctrl_new_std(hdl, ops, V4L2_CID_BRIGHTNESS, -127, 127, 1, 0);
+       v4l2_ctrl_new_std(hdl, ops, V4L2_CID_CONTRAST, -127, 127, 1, 0);
+       v4l2_ctrl_new_std(hdl, ops, V4L2_CID_SHARPNESS, -127, 127, 1, 0);
+
+       if (hdl->error) {
+               ret = hdl->error;
+               v4l2_ctrl_handler_free(hdl);
+               return ret;
+       }
+
+       s5k6aa->sd.ctrl_handler = hdl;
+       return 0;
+}
+
+/*
+ * V4L2 subdev internal operations
+ */
+static int s5k6aa_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+       struct v4l2_mbus_framefmt *format = v4l2_subdev_get_try_format(fh, 0);
+       struct v4l2_rect *crop = v4l2_subdev_get_try_crop(fh, 0);
+
+       format->colorspace = s5k6aa_formats[0].colorspace;
+       format->code = s5k6aa_formats[0].code;
+       format->width = S5K6AA_OUT_WIDTH_DEF;
+       format->height = S5K6AA_OUT_HEIGHT_DEF;
+       format->field = V4L2_FIELD_NONE;
+
+       crop->width = S5K6AA_WIN_WIDTH_MAX;
+       crop->height = S5K6AA_WIN_HEIGHT_MAX;
+       crop->left = 0;
+       crop->top = 0;
+
+       return 0;
+}
+
+int s5k6aa_check_fw_revision(struct s5k6aa *s5k6aa)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
+       u16 api_ver = 0, fw_rev = 0;
+
+       int ret = s5k6aa_set_ahb_address(client);
+
+       if (!ret)
+               ret = s5k6aa_read(client, REG_FW_APIVER, &api_ver);
+       if (!ret)
+               ret = s5k6aa_read(client, REG_FW_REVISION, &fw_rev);
+       if (ret) {
+               v4l2_err(&s5k6aa->sd, "FW revision check failed!\n");
+               return ret;
+       }
+
+       v4l2_info(&s5k6aa->sd, "FW API ver.: 0x%X, FW rev.: 0x%X\n",
+                 api_ver, fw_rev);
+
+       return api_ver == S5K6AAFX_FW_APIVER ? 0 : -ENODEV;
+}
+
+static int s5k6aa_registered(struct v4l2_subdev *sd)
+{
+       struct s5k6aa *s5k6aa = to_s5k6aa(sd);
+       int ret;
+
+       mutex_lock(&s5k6aa->lock);
+       ret = __s5k6aa_power_on(s5k6aa);
+       if (!ret) {
+               msleep(100);
+               ret = s5k6aa_check_fw_revision(s5k6aa);
+               __s5k6aa_power_off(s5k6aa);
+       }
+       mutex_unlock(&s5k6aa->lock);
+
+       return ret;
+}
+
+static const struct v4l2_subdev_internal_ops s5k6aa_subdev_internal_ops = {
+       .registered = s5k6aa_registered,
+       .open = s5k6aa_open,
+};
+
+static const struct v4l2_subdev_core_ops s5k6aa_core_ops = {
+       .s_power = s5k6aa_set_power,
+       .log_status = s5k6aa_log_status,
+};
+
+static const struct v4l2_subdev_ops s5k6aa_subdev_ops = {
+       .core = &s5k6aa_core_ops,
+       .pad = &s5k6aa_pad_ops,
+       .video = &s5k6aa_video_ops,
+};
+
+/*
+ * GPIO setup
+ */
+static int s5k6aa_configure_gpio(int nr, int val, const char *name)
+{
+       unsigned long flags = val ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
+       int ret;
+
+       if (!gpio_is_valid(nr))
+               return 0;
+       ret = gpio_request_one(nr, flags, name);
+       if (!ret)
+               gpio_export(nr, 0);
+       return ret;
+}
+
+static void s5k6aa_free_gpios(struct s5k6aa *s5k6aa)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(s5k6aa->gpio); i++) {
+               if (!gpio_is_valid(s5k6aa->gpio[i].gpio))
+                       continue;
+               gpio_free(s5k6aa->gpio[i].gpio);
+               s5k6aa->gpio[i].gpio = -EINVAL;
+       }
+}
+
+static int s5k6aa_configure_gpios(struct s5k6aa *s5k6aa,
+                                 const struct s5k6aa_platform_data *pdata)
+{
+       const struct s5k6aa_gpio *gpio = &pdata->gpio_stby;
+       int ret;
+
+       s5k6aa->gpio[STBY].gpio = -EINVAL;
+       s5k6aa->gpio[RST].gpio  = -EINVAL;
+
+       ret = s5k6aa_configure_gpio(gpio->gpio, gpio->level, "S5K6AA_STBY");
+       if (ret) {
+               s5k6aa_free_gpios(s5k6aa);
+               return ret;
+       }
+       s5k6aa->gpio[STBY] = *gpio;
+       if (gpio_is_valid(gpio->gpio))
+               gpio_set_value(gpio->gpio, 0);
+
+       gpio = &pdata->gpio_reset;
+       ret = s5k6aa_configure_gpio(gpio->gpio, gpio->level, "S5K6AA_RST");
+       if (ret) {
+               s5k6aa_free_gpios(s5k6aa);
+               return ret;
+       }
+       s5k6aa->gpio[RST] = *gpio;
+       if (gpio_is_valid(gpio->gpio))
+               gpio_set_value(gpio->gpio, 0);
+
+       return 0;
+}
+
+static int s5k6aa_probe(struct i2c_client *client,
+                       const struct i2c_device_id *id)
+{
+       const struct s5k6aa_platform_data *pdata = client->dev.platform_data;
+       struct v4l2_subdev *sd;
+       struct s5k6aa *s5k6aa;
+       int i, ret;
+
+       if (pdata == NULL) {
+               dev_err(&client->dev, "Platform data not specified\n");
+               return -EINVAL;
+       }
+
+       if (pdata->mclk_frequency == 0) {
+               dev_err(&client->dev, "MCLK frequency not specified\n");
+               return -EINVAL;
+       }
+
+       s5k6aa = kzalloc(sizeof(*s5k6aa), GFP_KERNEL);
+       if (!s5k6aa)
+               return -ENOMEM;
+
+       mutex_init(&s5k6aa->lock);
+
+       s5k6aa->mclk_frequency = pdata->mclk_frequency;
+       s5k6aa->bus_type = pdata->bus_type;
+       s5k6aa->mipi_lanes = pdata->nlanes;
+       s5k6aa->s_power = pdata->set_power;
+       s5k6aa->inv_hflip = pdata->horiz_flip;
+       s5k6aa->inv_vflip = pdata->vert_flip;
+
+       sd = &s5k6aa->sd;
+       strlcpy(sd->name, DRIVER_NAME, sizeof(sd->name));
+       v4l2_i2c_subdev_init(sd, client, &s5k6aa_subdev_ops);
+
+       sd->internal_ops = &s5k6aa_subdev_internal_ops;
+       sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+       s5k6aa->pad.flags = MEDIA_PAD_FL_SOURCE;
+       sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR;
+       ret = media_entity_init(&sd->entity, 1, &s5k6aa->pad, 0);
+       if (ret)
+               goto out_err1;
+
+       ret = s5k6aa_configure_gpios(s5k6aa, pdata);
+       if (ret)
+               goto out_err2;
+
+       for (i = 0; i < S5K6AA_NUM_SUPPLIES; i++)
+               s5k6aa->supplies[i].supply = s5k6aa_supply_names[i];
+
+       ret = regulator_bulk_get(&client->dev, S5K6AA_NUM_SUPPLIES,
+                                s5k6aa->supplies);
+       if (ret) {
+               dev_err(&client->dev, "Failed to get regulators\n");
+               goto out_err3;
+       }
+
+       ret = s5k6aa_initialize_ctrls(s5k6aa);
+       if (ret)
+               goto out_err4;
+
+       s5k6aa_presets_data_init(s5k6aa);
+
+       s5k6aa->ccd_rect.width = S5K6AA_WIN_WIDTH_MAX;
+       s5k6aa->ccd_rect.height = S5K6AA_WIN_HEIGHT_MAX;
+       s5k6aa->ccd_rect.left = 0;
+       s5k6aa->ccd_rect.top = 0;
+
+       return 0;
+
+out_err4:
+       regulator_bulk_free(S5K6AA_NUM_SUPPLIES, s5k6aa->supplies);
+out_err3:
+       s5k6aa_free_gpios(s5k6aa);
+out_err2:
+       media_entity_cleanup(&s5k6aa->sd.entity);
+out_err1:
+       kfree(s5k6aa);
+       return ret;
+}
+
+static int s5k6aa_remove(struct i2c_client *client)
+{
+       struct v4l2_subdev *sd = i2c_get_clientdata(client);
+       struct s5k6aa *s5k6aa = to_s5k6aa(sd);
+
+       v4l2_device_unregister_subdev(sd);
+       v4l2_ctrl_handler_free(sd->ctrl_handler);
+       media_entity_cleanup(&sd->entity);
+       regulator_bulk_free(S5K6AA_NUM_SUPPLIES, s5k6aa->supplies);
+       s5k6aa_free_gpios(s5k6aa);
+       kfree(s5k6aa);
+
+       return 0;
+}
+
+static const struct i2c_device_id s5k6aa_id[] = {
+       { DRIVER_NAME, 0 },
+       { },
+};
+MODULE_DEVICE_TABLE(i2c, s5k6aa_id);
+
+
+static struct i2c_driver s5k6aa_i2c_driver = {
+       .driver = {
+               .name = DRIVER_NAME
+       },
+       .probe          = s5k6aa_probe,
+       .remove         = s5k6aa_remove,
+       .id_table       = s5k6aa_id,
+};
+
+static int __init s5k6aa_init(void)
+{
+       return i2c_add_driver(&s5k6aa_i2c_driver);
+}
+
+static void __exit s5k6aa_exit(void)
+{
+       i2c_del_driver(&s5k6aa_i2c_driver);
+}
+
+module_init(s5k6aa_init);
+module_exit(s5k6aa_exit);
+
+MODULE_DESCRIPTION("Samsung S5K6AA(FX) SXGA camera driver");
+MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
+MODULE_LICENSE("GPL");
index 931f469..c8d91b0 100644 (file)
@@ -246,9 +246,9 @@ static unsigned int get_plane_size(struct fimc_frame *fr, unsigned int plane)
        return fr->f_width * fr->f_height * fr->fmt->depth[plane] / 8;
 }
 
-static int queue_setup(struct vb2_queue *vq, unsigned int *num_buffers,
-                      unsigned int *num_planes, unsigned int sizes[],
-                      void *allocators[])
+static int queue_setup(struct vb2_queue *vq,  const struct v4l2_format *pfmt,
+                      unsigned int *num_buffers, unsigned int *num_planes,
+                      unsigned int sizes[], void *allocators[])
 {
        struct fimc_ctx *ctx = vq->drv_priv;
        struct fimc_fmt *fmt = ctx->d_frame.fmt;
index 6c1c9cb..19ca6db 100644 (file)
@@ -670,9 +670,9 @@ static void fimc_job_abort(void *priv)
        fimc_m2m_shutdown(priv);
 }
 
-static int fimc_queue_setup(struct vb2_queue *vq, unsigned int *num_buffers,
-                           unsigned int *num_planes, unsigned int sizes[],
-                           void *allocators[])
+static int fimc_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+                           unsigned int *num_buffers, unsigned int *num_planes,
+                           unsigned int sizes[], void *allocators[])
 {
        struct fimc_ctx *ctx = vb2_get_drv_priv(vq);
        struct fimc_frame *f;
index 5f4da80..f2481a8 100644 (file)
@@ -38,7 +38,7 @@ int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev)
         * into kernel. */
        mfc_debug_enter();
        err = request_firmware((const struct firmware **)&fw_blob,
-                                    "s5pc110-mfc.fw", dev->v4l2_dev.dev);
+                                    "s5p-mfc.fw", dev->v4l2_dev.dev);
        if (err != 0) {
                mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n");
                return -EINVAL;
@@ -116,7 +116,7 @@ int s5p_mfc_reload_firmware(struct s5p_mfc_dev *dev)
         * into kernel. */
        mfc_debug_enter();
        err = request_firmware((const struct firmware **)&fw_blob,
-                                    "s5pc110-mfc.fw", dev->v4l2_dev.dev);
+                                    "s5p-mfc.fw", dev->v4l2_dev.dev);
        if (err != 0) {
                mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n");
                return -EINVAL;
index bfbe084..725634d 100644 (file)
@@ -744,9 +744,10 @@ static const struct v4l2_ioctl_ops s5p_mfc_dec_ioctl_ops = {
        .vidioc_g_crop = vidioc_g_crop,
 };
 
-static int s5p_mfc_queue_setup(struct vb2_queue *vq, unsigned int *buf_count,
-                              unsigned int *plane_count, unsigned int psize[],
-                              void *allocators[])
+static int s5p_mfc_queue_setup(struct vb2_queue *vq,
+                       const struct v4l2_format *fmt, unsigned int *buf_count,
+                       unsigned int *plane_count, unsigned int psize[],
+                       void *allocators[])
 {
        struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
 
index 4c90e53..ecef127 100644 (file)
@@ -1513,8 +1513,9 @@ static int check_vb_with_fmt(struct s5p_mfc_fmt *fmt, struct vb2_buffer *vb)
 }
 
 static int s5p_mfc_queue_setup(struct vb2_queue *vq,
-                      unsigned int *buf_count, unsigned int *plane_count,
-                      unsigned int psize[], void *allocators[])
+                       const struct v4l2_format *fmt,
+                       unsigned int *buf_count, unsigned int *plane_count,
+                       unsigned int psize[], void *allocators[])
 {
        struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
 
index 4917e2c..e16d3a4 100644 (file)
@@ -727,8 +727,8 @@ static const struct v4l2_file_operations mxr_fops = {
        .unlocked_ioctl = video_ioctl2,
 };
 
-static int queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
-       unsigned int *nplanes, unsigned int sizes[],
+static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *pfmt,
+       unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[],
        void *alloc_ctxs[])
 {
        struct mxr_layer *layer = vb2_get_drv_priv(vq);
index bc8d6bb..9b55068 100644 (file)
@@ -843,10 +843,10 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev);
 int saa7134_ir_start(struct saa7134_dev *dev);
 void saa7134_ir_stop(struct saa7134_dev *dev);
 #else
-#define saa7134_input_init1(dev)       (0)
-#define saa7134_input_fini(dev)                (0)
-#define saa7134_input_irq(dev)         (0)
-#define saa7134_probe_i2c_ir(dev)      (0)
-#define saa7134_ir_start(dev)          (0)
-#define saa7134_ir_stop(dev)           (0)
+#define saa7134_input_init1(dev)       ((void)0)
+#define saa7134_input_fini(dev)                ((void)0)
+#define saa7134_input_irq(dev)         ((void)0)
+#define saa7134_probe_i2c_ir(dev)      ((void)0)
+#define saa7134_ir_start(dev)          ((void)0)
+#define saa7134_ir_stop(dev)           ((void)0)
 #endif
index 8615fb8..f390682 100644 (file)
@@ -90,7 +90,6 @@
 struct sh_mobile_ceu_buffer {
        struct vb2_buffer vb; /* v4l buffer must be first */
        struct list_head queue;
-       enum v4l2_mbus_pixelcode code;
 };
 
 struct sh_mobile_ceu_dev {
@@ -100,7 +99,8 @@ struct sh_mobile_ceu_dev {
 
        unsigned int irq;
        void __iomem *base;
-       unsigned long video_limit;
+       size_t video_limit;
+       size_t buf_total;
 
        spinlock_t lock;                /* Protects video buffer lists */
        struct list_head capture;
@@ -121,7 +121,7 @@ struct sh_mobile_ceu_dev {
 };
 
 struct sh_mobile_ceu_cam {
-       /* CEU offsets within scaled by the CEU camera output */
+       /* CEU offsets within the camera output, before the CEU scaler */
        unsigned int ceu_left;
        unsigned int ceu_top;
        /* Client output, as seen by the CEU */
@@ -144,30 +144,6 @@ static struct sh_mobile_ceu_buffer *to_ceu_vb(struct vb2_buffer *vb)
        return container_of(vb, struct sh_mobile_ceu_buffer, vb);
 }
 
-static unsigned long make_bus_param(struct sh_mobile_ceu_dev *pcdev)
-{
-       unsigned long flags;
-
-       flags = SOCAM_MASTER |
-               SOCAM_PCLK_SAMPLE_RISING |
-               SOCAM_HSYNC_ACTIVE_HIGH |
-               SOCAM_HSYNC_ACTIVE_LOW |
-               SOCAM_VSYNC_ACTIVE_HIGH |
-               SOCAM_VSYNC_ACTIVE_LOW |
-               SOCAM_DATA_ACTIVE_HIGH;
-
-       if (pcdev->pdata->flags & SH_CEU_FLAG_USE_8BIT_BUS)
-               flags |= SOCAM_DATAWIDTH_8;
-
-       if (pcdev->pdata->flags & SH_CEU_FLAG_USE_16BIT_BUS)
-               flags |= SOCAM_DATAWIDTH_16;
-
-       if (flags & SOCAM_DATAWIDTH_MASK)
-               return flags;
-
-       return 0;
-}
-
 static void ceu_write(struct sh_mobile_ceu_dev *priv,
                      unsigned long reg_offs, u32 data)
 {
@@ -216,33 +192,61 @@ static int sh_mobile_ceu_soft_reset(struct sh_mobile_ceu_dev *pcdev)
 /*
  *  Videobuf operations
  */
+
+/*
+ * .queue_setup() is called to check, whether the driver can accept the
+ *               requested number of buffers and to fill in plane sizes
+ *               for the current frame format if required
+ */
 static int sh_mobile_ceu_videobuf_setup(struct vb2_queue *vq,
+                       const struct v4l2_format *fmt,
                        unsigned int *count, unsigned int *num_planes,
                        unsigned int sizes[], void *alloc_ctxs[])
 {
        struct soc_camera_device *icd = container_of(vq, struct soc_camera_device, vb2_vidq);
        struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct sh_mobile_ceu_dev *pcdev = ici->priv;
-       int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
-                                               icd->current_fmt->host_fmt);
+       int bytes_per_line;
+       unsigned int height;
 
+       if (fmt) {
+               const struct soc_camera_format_xlate *xlate = soc_camera_xlate_by_fourcc(icd,
+                                                               fmt->fmt.pix.pixelformat);
+               if (!xlate)
+                       return -EINVAL;
+               bytes_per_line = soc_mbus_bytes_per_line(fmt->fmt.pix.width,
+                                                        xlate->host_fmt);
+               height = fmt->fmt.pix.height;
+       } else {
+               /* Called from VIDIOC_REQBUFS or in compatibility mode */
+               bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
+                                               icd->current_fmt->host_fmt);
+               height = icd->user_height;
+       }
        if (bytes_per_line < 0)
                return bytes_per_line;
 
-       *num_planes = 1;
+       sizes[0] = bytes_per_line * height;
 
-       pcdev->sequence = 0;
-       sizes[0] = bytes_per_line * icd->user_height;
        alloc_ctxs[0] = pcdev->alloc_ctx;
 
+       if (!vq->num_buffers)
+               pcdev->sequence = 0;
+
        if (!*count)
                *count = 2;
 
-       if (pcdev->video_limit) {
-               if (PAGE_ALIGN(sizes[0]) * *count > pcdev->video_limit)
-                       *count = pcdev->video_limit / PAGE_ALIGN(sizes[0]);
+       /* If *num_planes != 0, we have already verified *count. */
+       if (pcdev->video_limit && !*num_planes) {
+               size_t size = PAGE_ALIGN(sizes[0]) * *count;
+
+               if (size + pcdev->buf_total > pcdev->video_limit)
+                       *count = (pcdev->video_limit - pcdev->buf_total) /
+                               PAGE_ALIGN(sizes[0]);
        }
 
+       *num_planes = 1;
+
        dev_dbg(icd->parent, "count=%d, size=%u\n", *count, sizes[0]);
 
        return 0;
@@ -267,6 +271,7 @@ static int sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev)
        unsigned long top1, top2;
        unsigned long bottom1, bottom2;
        u32 status;
+       bool planar;
        int ret = 0;
 
        /*
@@ -314,17 +319,29 @@ static int sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev)
 
        phys_addr_top = vb2_dma_contig_plane_dma_addr(pcdev->active, 0);
 
-       ceu_write(pcdev, top1, phys_addr_top);
-       if (V4L2_FIELD_NONE != pcdev->field) {
-               phys_addr_bottom = phys_addr_top + icd->user_width;
-               ceu_write(pcdev, bottom1, phys_addr_bottom);
-       }
-
        switch (icd->current_fmt->host_fmt->fourcc) {
        case V4L2_PIX_FMT_NV12:
        case V4L2_PIX_FMT_NV21:
        case V4L2_PIX_FMT_NV16:
        case V4L2_PIX_FMT_NV61:
+               planar = true;
+               break;
+       default:
+               planar = false;
+       }
+
+       ceu_write(pcdev, top1, phys_addr_top);
+       if (V4L2_FIELD_NONE != pcdev->field) {
+               if (planar)
+                       phys_addr_bottom = phys_addr_top + icd->user_width;
+               else
+                       phys_addr_bottom = phys_addr_top +
+                               soc_mbus_bytes_per_line(icd->user_width,
+                                                       icd->current_fmt->host_fmt);
+               ceu_write(pcdev, bottom1, phys_addr_bottom);
+       }
+
+       if (planar) {
                phys_addr_top += icd->user_width *
                        icd->user_height;
                ceu_write(pcdev, top2, phys_addr_top);
@@ -341,23 +358,40 @@ static int sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev)
 
 static int sh_mobile_ceu_videobuf_prepare(struct vb2_buffer *vb)
 {
+       struct sh_mobile_ceu_buffer *buf = to_ceu_vb(vb);
+
+       /* Added list head initialization on alloc */
+       WARN(!list_empty(&buf->queue), "Buffer %p on queue!\n", vb);
+
+       return 0;
+}
+
+static void sh_mobile_ceu_videobuf_queue(struct vb2_buffer *vb)
+{
        struct soc_camera_device *icd = container_of(vb->vb2_queue, struct soc_camera_device, vb2_vidq);
-       struct sh_mobile_ceu_buffer *buf;
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+       struct sh_mobile_ceu_dev *pcdev = ici->priv;
+       struct sh_mobile_ceu_buffer *buf = to_ceu_vb(vb);
+       unsigned long size;
        int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
                                                icd->current_fmt->host_fmt);
-       unsigned long size;
 
        if (bytes_per_line < 0)
-               return bytes_per_line;
+               goto error;
 
-       buf = to_ceu_vb(vb);
+       size = icd->user_height * bytes_per_line;
+
+       if (vb2_plane_size(vb, 0) < size) {
+               dev_err(icd->parent, "Buffer #%d too small (%lu < %lu)\n",
+                       vb->v4l2_buf.index, vb2_plane_size(vb, 0), size);
+               goto error;
+       }
+
+       vb2_set_plane_payload(vb, 0, size);
 
        dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__,
                vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0));
 
-       /* Added list head initialization on alloc */
-       WARN(!list_empty(&buf->queue), "Buffer %p on queue!\n", vb);
-
 #ifdef DEBUG
        /*
         * This can be useful if you want to see if we actually fill
@@ -367,31 +401,6 @@ static int sh_mobile_ceu_videobuf_prepare(struct vb2_buffer *vb)
                memset(vb2_plane_vaddr(vb, 0), 0xaa, vb2_get_plane_payload(vb, 0));
 #endif
 
-       BUG_ON(NULL == icd->current_fmt);
-
-       size = icd->user_height * bytes_per_line;
-
-       if (vb2_plane_size(vb, 0) < size) {
-               dev_err(icd->parent, "Buffer too small (%lu < %lu)\n",
-                       vb2_plane_size(vb, 0), size);
-               return -ENOBUFS;
-       }
-
-       vb2_set_plane_payload(vb, 0, size);
-
-       return 0;
-}
-
-static void sh_mobile_ceu_videobuf_queue(struct vb2_buffer *vb)
-{
-       struct soc_camera_device *icd = container_of(vb->vb2_queue, struct soc_camera_device, vb2_vidq);
-       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
-       struct sh_mobile_ceu_dev *pcdev = ici->priv;
-       struct sh_mobile_ceu_buffer *buf = to_ceu_vb(vb);
-
-       dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__,
-               vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0));
-
        spin_lock_irq(&pcdev->lock);
        list_add_tail(&buf->queue, &pcdev->capture);
 
@@ -405,6 +414,11 @@ static void sh_mobile_ceu_videobuf_queue(struct vb2_buffer *vb)
                sh_mobile_ceu_capture(pcdev);
        }
        spin_unlock_irq(&pcdev->lock);
+
+       return;
+
+error:
+       vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
 }
 
 static void sh_mobile_ceu_videobuf_release(struct vb2_buffer *vb)
@@ -429,11 +443,23 @@ static void sh_mobile_ceu_videobuf_release(struct vb2_buffer *vb)
        if (buf->queue.next)
                list_del_init(&buf->queue);
 
+       pcdev->buf_total -= PAGE_ALIGN(vb2_plane_size(vb, 0));
+       dev_dbg(icd->parent, "%s() %zu bytes buffers\n", __func__,
+               pcdev->buf_total);
+
        spin_unlock_irq(&pcdev->lock);
 }
 
 static int sh_mobile_ceu_videobuf_init(struct vb2_buffer *vb)
 {
+       struct soc_camera_device *icd = container_of(vb->vb2_queue, struct soc_camera_device, vb2_vidq);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+       struct sh_mobile_ceu_dev *pcdev = ici->priv;
+
+       pcdev->buf_total += PAGE_ALIGN(vb2_plane_size(vb, 0));
+       dev_dbg(icd->parent, "%s() %zu bytes buffers\n", __func__,
+               pcdev->buf_total);
+
        /* This is for locking debugging only */
        INIT_LIST_HEAD(&to_ceu_vb(vb)->queue);
        return 0;
@@ -535,19 +561,29 @@ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd)
 
        pm_runtime_get_sync(ici->v4l2_dev.dev);
 
+       pcdev->buf_total = 0;
+
        ret = sh_mobile_ceu_soft_reset(pcdev);
 
        csi2_sd = find_csi2(pcdev);
+       if (csi2_sd)
+               csi2_sd->grp_id = (long)icd;
 
        ret = v4l2_subdev_call(csi2_sd, core, s_power, 1);
-       if (ret != -ENODEV && ret != -ENOIOCTLCMD && ret < 0) {
+       if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) {
                pm_runtime_put_sync(ici->v4l2_dev.dev);
-       } else {
-               pcdev->icd = icd;
-               ret = 0;
+               return ret;
        }
 
-       return ret;
+       /*
+        * -ENODEV is special: either csi2_sd == NULL or the CSI-2 driver
+        * has not found this soc-camera device among its clients
+        */
+       if (ret == -ENODEV && csi2_sd)
+               csi2_sd->grp_id = 0;
+       pcdev->icd = icd;
+
+       return 0;
 }
 
 /* Called with .video_lock held */
@@ -560,6 +596,8 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd)
        BUG_ON(icd != pcdev->icd);
 
        v4l2_subdev_call(csi2_sd, core, s_power, 0);
+       if (csi2_sd)
+               csi2_sd->grp_id = 0;
        /* disable capture, disable interrupts */
        ceu_write(pcdev, CEIER, 0);
        sh_mobile_ceu_soft_reset(pcdev);
@@ -628,22 +666,22 @@ static void sh_mobile_ceu_set_rect(struct soc_camera_device *icd)
        left_offset     = cam->ceu_left;
        top_offset      = cam->ceu_top;
 
-       /* CEU cropping (CFSZR) is applied _after_ the scaling filter (CFLCR) */
+       WARN_ON(icd->user_width & 3 || icd->user_height & 3);
+
+       width = icd->user_width;
+
        if (pcdev->image_mode) {
                in_width = cam->width;
                if (!pcdev->is_16bit) {
                        in_width *= 2;
                        left_offset *= 2;
                }
-               width = icd->user_width;
-               cdwdr_width = icd->user_width;
+               cdwdr_width = width;
        } else {
-               int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
+               int bytes_per_line = soc_mbus_bytes_per_line(width,
                                                icd->current_fmt->host_fmt);
                unsigned int w_factor;
 
-               width = icd->user_width;
-
                switch (icd->current_fmt->host_fmt->packing) {
                case SOC_MBUS_PACKING_2X8_PADHI:
                        w_factor = 2;
@@ -653,10 +691,10 @@ static void sh_mobile_ceu_set_rect(struct soc_camera_device *icd)
                }
 
                in_width = cam->width * w_factor;
-               left_offset = left_offset * w_factor;
+               left_offset *= w_factor;
 
                if (bytes_per_line < 0)
-                       cdwdr_width = icd->user_width;
+                       cdwdr_width = width;
                else
                        cdwdr_width = bytes_per_line;
        }
@@ -664,7 +702,7 @@ static void sh_mobile_ceu_set_rect(struct soc_camera_device *icd)
        height = icd->user_height;
        in_height = cam->height;
        if (V4L2_FIELD_NONE != pcdev->field) {
-               height /= 2;
+               height = (height / 2) & ~3;
                in_height /= 2;
                top_offset /= 2;
                cdwdr_width *= 2;
@@ -686,6 +724,7 @@ static void sh_mobile_ceu_set_rect(struct soc_camera_device *icd)
 
        ceu_write(pcdev, CAMOR, camor);
        ceu_write(pcdev, CAPWR, (in_height << 16) | in_width);
+       /* CFSZR clipping is applied _after_ the scaling filter (CFLCR) */
        ceu_write(pcdev, CFSZR, (height << 16) | width);
        ceu_write(pcdev, CDWDR, cdwdr_width);
 }
@@ -723,66 +762,93 @@ static void capture_restore(struct sh_mobile_ceu_dev *pcdev, u32 capsr)
                ceu_write(pcdev, CAPSR, capsr);
 }
 
+/* Find the bus subdevice driver, e.g., CSI2 */
+static struct v4l2_subdev *find_bus_subdev(struct sh_mobile_ceu_dev *pcdev,
+                                          struct soc_camera_device *icd)
+{
+       if (pcdev->csi2_pdev) {
+               struct v4l2_subdev *csi2_sd = find_csi2(pcdev);
+               if (csi2_sd && csi2_sd->grp_id == (u32)icd)
+                       return csi2_sd;
+       }
+
+       return soc_camera_to_subdev(icd);
+}
+
+#define CEU_BUS_FLAGS (V4L2_MBUS_MASTER |      \
+               V4L2_MBUS_PCLK_SAMPLE_RISING |  \
+               V4L2_MBUS_HSYNC_ACTIVE_HIGH |   \
+               V4L2_MBUS_HSYNC_ACTIVE_LOW |    \
+               V4L2_MBUS_VSYNC_ACTIVE_HIGH |   \
+               V4L2_MBUS_VSYNC_ACTIVE_LOW |    \
+               V4L2_MBUS_DATA_ACTIVE_HIGH)
+
 /* Capture is not running, no interrupts, no locking needed */
 static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd,
                                       __u32 pixfmt)
 {
        struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct sh_mobile_ceu_dev *pcdev = ici->priv;
-       int ret;
-       unsigned long camera_flags, common_flags, value;
-       int yuv_lineskip;
+       struct v4l2_subdev *sd = find_bus_subdev(pcdev, icd);
        struct sh_mobile_ceu_cam *cam = icd->host_priv;
+       struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
+       unsigned long value, common_flags = CEU_BUS_FLAGS;
        u32 capsr = capture_save_reset(pcdev);
+       unsigned int yuv_lineskip;
+       int ret;
 
-       camera_flags = icd->ops->query_bus_param(icd);
-       common_flags = soc_camera_bus_param_compatible(camera_flags,
-                                                      make_bus_param(pcdev));
-       if (!common_flags)
-               return -EINVAL;
+       /*
+        * If the client doesn't implement g_mbus_config, we just use our
+        * platform data
+        */
+       ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
+       if (!ret) {
+               common_flags = soc_mbus_config_compatible(&cfg,
+                                                         common_flags);
+               if (!common_flags)
+                       return -EINVAL;
+       } else if (ret != -ENOIOCTLCMD) {
+               return ret;
+       }
 
        /* Make choises, based on platform preferences */
-       if ((common_flags & SOCAM_HSYNC_ACTIVE_HIGH) &&
-           (common_flags & SOCAM_HSYNC_ACTIVE_LOW)) {
+       if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) &&
+           (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) {
                if (pcdev->pdata->flags & SH_CEU_FLAG_HSYNC_LOW)
-                       common_flags &= ~SOCAM_HSYNC_ACTIVE_HIGH;
+                       common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH;
                else
-                       common_flags &= ~SOCAM_HSYNC_ACTIVE_LOW;
+                       common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW;
        }
 
-       if ((common_flags & SOCAM_VSYNC_ACTIVE_HIGH) &&
-           (common_flags & SOCAM_VSYNC_ACTIVE_LOW)) {
+       if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) &&
+           (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) {
                if (pcdev->pdata->flags & SH_CEU_FLAG_VSYNC_LOW)
-                       common_flags &= ~SOCAM_VSYNC_ACTIVE_HIGH;
+                       common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH;
                else
-                       common_flags &= ~SOCAM_VSYNC_ACTIVE_LOW;
+                       common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW;
        }
 
-       ret = icd->ops->set_bus_param(icd, common_flags);
-       if (ret < 0)
+       cfg.flags = common_flags;
+       ret = v4l2_subdev_call(sd, video, s_mbus_config, &cfg);
+       if (ret < 0 && ret != -ENOIOCTLCMD)
                return ret;
 
-       switch (common_flags & SOCAM_DATAWIDTH_MASK) {
-       case SOCAM_DATAWIDTH_8:
-               pcdev->is_16bit = 0;
-               break;
-       case SOCAM_DATAWIDTH_16:
+       if (icd->current_fmt->host_fmt->bits_per_sample > 8)
                pcdev->is_16bit = 1;
-               break;
-       default:
-               return -EINVAL;
-       }
+       else
+               pcdev->is_16bit = 0;
 
        ceu_write(pcdev, CRCNTR, 0);
        ceu_write(pcdev, CRCMPR, 0);
 
        value = 0x00000010; /* data fetch by default */
-       yuv_lineskip = 0;
+       yuv_lineskip = 0x10;
 
        switch (icd->current_fmt->host_fmt->fourcc) {
        case V4L2_PIX_FMT_NV12:
        case V4L2_PIX_FMT_NV21:
-               yuv_lineskip = 1; /* skip for NV12/21, no skip for NV16/61 */
+               /* convert 4:2:2 -> 4:2:0 */
+               yuv_lineskip = 0; /* skip for NV12/21, no skip for NV16/61 */
                /* fall-through */
        case V4L2_PIX_FMT_NV16:
        case V4L2_PIX_FMT_NV61:
@@ -808,8 +874,8 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd,
            icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_NV61)
                value ^= 0x00000100; /* swap U, V to change from NV1x->NVx1 */
 
-       value |= common_flags & SOCAM_VSYNC_ACTIVE_LOW ? 1 << 1 : 0;
-       value |= common_flags & SOCAM_HSYNC_ACTIVE_LOW ? 1 << 0 : 0;
+       value |= common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW ? 1 << 1 : 0;
+       value |= common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW ? 1 << 0 : 0;
        value |= pcdev->is_16bit ? 1 << 12 : 0;
 
        /* CSI2 mode */
@@ -852,9 +918,7 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd,
         * using 7 we swap the data bytes to match the incoming order:
         * D0, D1, D2, D3, D4, D5, D6, D7
         */
-       value = 0x00000017;
-       if (yuv_lineskip)
-               value &= ~0x00000010; /* convert 4:2:2 -> 4:2:0 */
+       value = 0x00000007 | yuv_lineskip;
 
        ceu_write(pcdev, CDOCR, value);
        ceu_write(pcdev, CFWCR, 0); /* keep "datafetch firewall" disabled */
@@ -875,13 +939,19 @@ static int sh_mobile_ceu_try_bus_param(struct soc_camera_device *icd,
 {
        struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct sh_mobile_ceu_dev *pcdev = ici->priv;
-       unsigned long camera_flags, common_flags;
+       struct v4l2_subdev *sd = find_bus_subdev(pcdev, icd);
+       unsigned long common_flags = CEU_BUS_FLAGS;
+       struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
+       int ret;
 
-       camera_flags = icd->ops->query_bus_param(icd);
-       common_flags = soc_camera_bus_param_compatible(camera_flags,
-                                                      make_bus_param(pcdev));
-       if (!common_flags || buswidth > 16 ||
-           (buswidth > 8 && !(common_flags & SOCAM_DATAWIDTH_16)))
+       ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
+       if (!ret)
+               common_flags = soc_mbus_config_compatible(&cfg,
+                                                         common_flags);
+       else if (ret != -ENOIOCTLCMD)
+               return ret;
+
+       if (!common_flags || buswidth > 16)
                return -EINVAL;
 
        return 0;
@@ -891,26 +961,26 @@ static const struct soc_mbus_pixelfmt sh_mobile_ceu_formats[] = {
        {
                .fourcc                 = V4L2_PIX_FMT_NV12,
                .name                   = "NV12",
-               .bits_per_sample        = 12,
-               .packing                = SOC_MBUS_PACKING_NONE,
+               .bits_per_sample        = 8,
+               .packing                = SOC_MBUS_PACKING_1_5X8,
                .order                  = SOC_MBUS_ORDER_LE,
        }, {
                .fourcc                 = V4L2_PIX_FMT_NV21,
                .name                   = "NV21",
-               .bits_per_sample        = 12,
-               .packing                = SOC_MBUS_PACKING_NONE,
+               .bits_per_sample        = 8,
+               .packing                = SOC_MBUS_PACKING_1_5X8,
                .order                  = SOC_MBUS_ORDER_LE,
        }, {
                .fourcc                 = V4L2_PIX_FMT_NV16,
                .name                   = "NV16",
-               .bits_per_sample        = 16,
-               .packing                = SOC_MBUS_PACKING_NONE,
+               .bits_per_sample        = 8,
+               .packing                = SOC_MBUS_PACKING_2X8_PADHI,
                .order                  = SOC_MBUS_ORDER_LE,
        }, {
                .fourcc                 = V4L2_PIX_FMT_NV61,
                .name                   = "NV61",
-               .bits_per_sample        = 16,
-               .packing                = SOC_MBUS_PACKING_NONE,
+               .bits_per_sample        = 8,
+               .packing                = SOC_MBUS_PACKING_2X8_PADHI,
                .order                  = SOC_MBUS_ORDER_LE,
        },
 };
@@ -920,6 +990,8 @@ static bool sh_mobile_ceu_packing_supported(const struct soc_mbus_pixelfmt *fmt)
 {
        return  fmt->packing == SOC_MBUS_PACKING_NONE ||
                (fmt->bits_per_sample == 8 &&
+                fmt->packing == SOC_MBUS_PACKING_1_5X8) ||
+               (fmt->bits_per_sample == 8 &&
                 fmt->packing == SOC_MBUS_PACKING_2X8_PADHI) ||
                (fmt->bits_per_sample > 8 &&
                 fmt->packing == SOC_MBUS_PACKING_EXTEND16);
@@ -927,6 +999,38 @@ static bool sh_mobile_ceu_packing_supported(const struct soc_mbus_pixelfmt *fmt)
 
 static int client_g_rect(struct v4l2_subdev *sd, struct v4l2_rect *rect);
 
+static struct soc_camera_device *ctrl_to_icd(struct v4l2_ctrl *ctrl)
+{
+       return container_of(ctrl->handler, struct soc_camera_device,
+                                                       ctrl_handler);
+}
+
+static int sh_mobile_ceu_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct soc_camera_device *icd = ctrl_to_icd(ctrl);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+       struct sh_mobile_ceu_dev *pcdev = ici->priv;
+
+       switch (ctrl->id) {
+       case V4L2_CID_SHARPNESS:
+               switch (icd->current_fmt->host_fmt->fourcc) {
+               case V4L2_PIX_FMT_NV12:
+               case V4L2_PIX_FMT_NV21:
+               case V4L2_PIX_FMT_NV16:
+               case V4L2_PIX_FMT_NV61:
+                       ceu_write(pcdev, CLFCR, !ctrl->val);
+                       return 0;
+               }
+               break;
+       }
+
+       return -EINVAL;
+}
+
+static const struct v4l2_ctrl_ops sh_mobile_ceu_ctrl_ops = {
+       .s_ctrl = sh_mobile_ceu_s_ctrl,
+};
+
 static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, unsigned int idx,
                                     struct soc_camera_format_xlate *xlate)
 {
@@ -952,6 +1056,7 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, unsigned int
        }
 
        if (!pcdev->pdata->csi2) {
+               /* Are there any restrictions in the CSI-2 case? */
                ret = sh_mobile_ceu_try_bus_param(icd, fmt->bits_per_sample);
                if (ret < 0)
                        return 0;
@@ -962,6 +1067,12 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, unsigned int
                struct v4l2_rect rect;
                int shift = 0;
 
+               /* Add our control */
+               v4l2_ctrl_new_std(&icd->ctrl_handler, &sh_mobile_ceu_ctrl_ops,
+                                 V4L2_CID_SHARPNESS, 0, 1, 1, 0);
+               if (icd->ctrl_handler.error)
+                       return icd->ctrl_handler.error;
+
                /* FIXME: subwindow is lost between close / open */
 
                /* Cache current client geometry */
@@ -1004,9 +1115,6 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, unsigned int
                cam->width      = mf.width;
                cam->height     = mf.height;
 
-               cam->width      = mf.width;
-               cam->height     = mf.height;
-
                icd->host_priv = cam;
        } else {
                cam = icd->host_priv;
@@ -1278,6 +1386,7 @@ static int client_s_fmt(struct soc_camera_device *icd,
        unsigned int width = mf->width, height = mf->height, tmp_w, tmp_h;
        unsigned int max_width, max_height;
        struct v4l2_cropcap cap;
+       bool ceu_1to1;
        int ret;
 
        ret = v4l2_device_call_until_err(sd->v4l2_dev, (long)icd, video,
@@ -1287,7 +1396,14 @@ static int client_s_fmt(struct soc_camera_device *icd,
 
        dev_geo(dev, "camera scaled to %ux%u\n", mf->width, mf->height);
 
-       if ((width == mf->width && height == mf->height) || !ceu_can_scale)
+       if (width == mf->width && height == mf->height) {
+               /* Perfect! The client has done it all. */
+               ceu_1to1 = true;
+               goto update_cache;
+       }
+
+       ceu_1to1 = false;
+       if (!ceu_can_scale)
                goto update_cache;
 
        cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
@@ -1327,7 +1443,10 @@ update_cache:
        if (ret < 0)
                return ret;
 
-       update_subrect(cam);
+       if (ceu_1to1)
+               cam->subrect = cam->rect;
+       else
+               update_subrect(cam);
 
        return 0;
 }
@@ -1414,7 +1533,10 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd,
        capsr = capture_save_reset(pcdev);
        dev_dbg(dev, "CAPSR 0x%x, CFLCR 0x%x\n", capsr, pcdev->cflcr);
 
-       /* 1. - 2. Apply iterative camera S_CROP for new input window. */
+       /*
+        * 1. - 2. Apply iterative camera S_CROP for new input window, read back
+        * actual camera rectangle.
+        */
        ret = client_s_crop(icd, a, &cam_crop);
        if (ret < 0)
                return ret;
@@ -1498,8 +1620,9 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd,
                ceu_write(pcdev, CFLCR, cflcr);
        }
 
-       icd->user_width  = out_width;
-       icd->user_height = out_height;
+       icd->user_width  = out_width & ~3;
+       icd->user_height = out_height & ~3;
+       /* Offsets are applied at the CEU scaling filter input */
        cam->ceu_left    = scale_down(rect->left - cam_rect->left, scale_cam_h) & ~1;
        cam->ceu_top     = scale_down(rect->top - cam_rect->top, scale_cam_v) & ~1;
 
@@ -1538,7 +1661,7 @@ static int sh_mobile_ceu_get_crop(struct soc_camera_device *icd,
  * CEU crop, mapped backed onto the client input (subrect).
  */
 static void calculate_client_output(struct soc_camera_device *icd,
-               struct v4l2_pix_format *pix, struct v4l2_mbus_framefmt *mf)
+               const struct v4l2_pix_format *pix, struct v4l2_mbus_framefmt *mf)
 {
        struct sh_mobile_ceu_cam *cam = icd->host_priv;
        struct device *dev = icd->parent;
@@ -1574,8 +1697,8 @@ static void calculate_client_output(struct soc_camera_device *icd,
        dev_geo(dev, "3: scales %u:%u\n", scale_h, scale_v);
 
        /*
-        * 4. Calculate client output window by applying combined scales to real
-        *    input window.
+        * 4. Calculate desired client output window by applying combined scales
+        *    to client (real) input window.
         */
        mf->width       = scale_down(cam->rect.width, scale_h);
        mf->height      = scale_down(cam->rect.height, scale_v);
@@ -1600,8 +1723,6 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd,
        bool image_mode;
        enum v4l2_field field;
 
-       dev_geo(dev, "S_FMT(pix=0x%x, %ux%u)\n", pixfmt, pix->width, pix->height);
-
        switch (pix->field) {
        default:
                pix->field = V4L2_FIELD_NONE;
@@ -1622,8 +1743,8 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd,
                return -EINVAL;
        }
 
-       /* 1.-4. Calculate client output geometry */
-       calculate_client_output(icd, &f->fmt.pix, &mf);
+       /* 1.-4. Calculate desired client output geometry */
+       calculate_client_output(icd, pix, &mf);
        mf.field        = pix->field;
        mf.colorspace   = pix->colorspace;
        mf.code         = xlate->code;
@@ -1639,6 +1760,9 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd,
                image_mode = false;
        }
 
+       dev_geo(dev, "S_FMT(pix=0x%x, fld 0x%x, code 0x%x, %ux%u)\n", pixfmt, mf.field, mf.code,
+               pix->width, pix->height);
+
        dev_geo(dev, "4: request camera output %ux%u\n", mf.width, mf.height);
 
        /* 5. - 9. */
@@ -1700,6 +1824,10 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd,
        pcdev->field = field;
        pcdev->image_mode = image_mode;
 
+       /* CFSZR requirement */
+       pix->width      &= ~3;
+       pix->height     &= ~3;
+
        return 0;
 }
 
@@ -1725,7 +1853,8 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd,
 
        /* FIXME: calculate using depth and bus width */
 
-       v4l_bound_align_image(&pix->width, 2, 2560, 1,
+       /* CFSZR requires height and width to be 4-pixel aligned */
+       v4l_bound_align_image(&pix->width, 2, 2560, 2,
                              &pix->height, 4, 1920, 2, 0);
 
        width = pix->width;
@@ -1778,6 +1907,9 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd,
                        pix->height = height;
        }
 
+       pix->width      &= ~3;
+       pix->height     &= ~3;
+
        dev_geo(icd->parent, "%s(): return %d, fmt 0x%x, %ux%u\n",
                __func__, ret, pix->pixelformat, pix->width, pix->height);
 
@@ -1824,8 +1956,8 @@ static int sh_mobile_ceu_set_livecrop(struct soc_camera_device *icd,
                             out_height != f.fmt.pix.height))
                        ret = -EINVAL;
                if (!ret) {
-                       icd->user_width         = out_width;
-                       icd->user_height        = out_height;
+                       icd->user_width         = out_width & ~3;
+                       icd->user_height        = out_height & ~3;
                        ret = sh_mobile_ceu_set_bus_param(icd,
                                        icd->current_fmt->host_fmt->fourcc);
                }
@@ -1869,55 +2001,6 @@ static int sh_mobile_ceu_init_videobuf(struct vb2_queue *q,
        return vb2_queue_init(q);
 }
 
-static int sh_mobile_ceu_get_ctrl(struct soc_camera_device *icd,
-                                 struct v4l2_control *ctrl)
-{
-       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
-       struct sh_mobile_ceu_dev *pcdev = ici->priv;
-       u32 val;
-
-       switch (ctrl->id) {
-       case V4L2_CID_SHARPNESS:
-               val = ceu_read(pcdev, CLFCR);
-               ctrl->value = val ^ 1;
-               return 0;
-       }
-       return -ENOIOCTLCMD;
-}
-
-static int sh_mobile_ceu_set_ctrl(struct soc_camera_device *icd,
-                                 struct v4l2_control *ctrl)
-{
-       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
-       struct sh_mobile_ceu_dev *pcdev = ici->priv;
-
-       switch (ctrl->id) {
-       case V4L2_CID_SHARPNESS:
-               switch (icd->current_fmt->host_fmt->fourcc) {
-               case V4L2_PIX_FMT_NV12:
-               case V4L2_PIX_FMT_NV21:
-               case V4L2_PIX_FMT_NV16:
-               case V4L2_PIX_FMT_NV61:
-                       ceu_write(pcdev, CLFCR, !ctrl->value);
-                       return 0;
-               }
-               return -EINVAL;
-       }
-       return -ENOIOCTLCMD;
-}
-
-static const struct v4l2_queryctrl sh_mobile_ceu_controls[] = {
-       {
-               .id             = V4L2_CID_SHARPNESS,
-               .type           = V4L2_CTRL_TYPE_BOOLEAN,
-               .name           = "Low-pass filter",
-               .minimum        = 0,
-               .maximum        = 1,
-               .step           = 1,
-               .default_value  = 0,
-       },
-};
-
 static struct soc_camera_host_ops sh_mobile_ceu_host_ops = {
        .owner          = THIS_MODULE,
        .add            = sh_mobile_ceu_add_device,
@@ -1929,14 +2012,10 @@ static struct soc_camera_host_ops sh_mobile_ceu_host_ops = {
        .set_livecrop   = sh_mobile_ceu_set_livecrop,
        .set_fmt        = sh_mobile_ceu_set_fmt,
        .try_fmt        = sh_mobile_ceu_try_fmt,
-       .set_ctrl       = sh_mobile_ceu_set_ctrl,
-       .get_ctrl       = sh_mobile_ceu_get_ctrl,
        .poll           = sh_mobile_ceu_poll,
        .querycap       = sh_mobile_ceu_querycap,
        .set_bus_param  = sh_mobile_ceu_set_bus_param,
        .init_videobuf2 = sh_mobile_ceu_init_videobuf,
-       .controls       = sh_mobile_ceu_controls,
-       .num_controls   = ARRAY_SIZE(sh_mobile_ceu_controls),
 };
 
 struct bus_wait {
index 2893a01..37706eb 100644 (file)
@@ -19,6 +19,7 @@
 #include <media/sh_mobile_ceu.h>
 #include <media/sh_mobile_csi2.h>
 #include <media/soc_camera.h>
+#include <media/soc_mediabus.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-dev.h>
 #include <media/v4l2-device.h>
@@ -35,11 +36,10 @@ struct sh_csi2 {
        struct v4l2_subdev              subdev;
        struct list_head                list;
        unsigned int                    irq;
+       unsigned long                   mipi_flags;
        void __iomem                    *base;
        struct platform_device          *pdev;
        struct sh_csi2_client_config    *client;
-       unsigned long (*query_bus_param)(struct soc_camera_device *);
-       int (*set_bus_param)(struct soc_camera_device *, unsigned long);
 };
 
 static int sh_csi2_try_fmt(struct v4l2_subdev *sd,
@@ -127,9 +127,34 @@ static int sh_csi2_s_fmt(struct v4l2_subdev *sd,
        return 0;
 }
 
+static int sh_csi2_g_mbus_config(struct v4l2_subdev *sd,
+                                struct v4l2_mbus_config *cfg)
+{
+       cfg->flags = V4L2_MBUS_PCLK_SAMPLE_RISING |
+               V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_HIGH |
+               V4L2_MBUS_MASTER | V4L2_MBUS_DATA_ACTIVE_HIGH;
+       cfg->type = V4L2_MBUS_PARALLEL;
+
+       return 0;
+}
+
+static int sh_csi2_s_mbus_config(struct v4l2_subdev *sd,
+                                const struct v4l2_mbus_config *cfg)
+{
+       struct sh_csi2 *priv = container_of(sd, struct sh_csi2, subdev);
+       struct soc_camera_device *icd = (struct soc_camera_device *)sd->grp_id;
+       struct v4l2_subdev *client_sd = soc_camera_to_subdev(icd);
+       struct v4l2_mbus_config client_cfg = {.type = V4L2_MBUS_CSI2,
+                                             .flags = priv->mipi_flags};
+
+       return v4l2_subdev_call(client_sd, video, s_mbus_config, &client_cfg);
+}
+
 static struct v4l2_subdev_video_ops sh_csi2_subdev_video_ops = {
        .s_mbus_fmt     = sh_csi2_s_fmt,
        .try_mbus_fmt   = sh_csi2_try_fmt,
+       .g_mbus_config  = sh_csi2_g_mbus_config,
+       .s_mbus_config  = sh_csi2_s_mbus_config,
 };
 
 static void sh_csi2_hwinit(struct sh_csi2 *priv)
@@ -144,11 +169,21 @@ static void sh_csi2_hwinit(struct sh_csi2 *priv)
        udelay(5);
        iowrite32(0x00000000, priv->base + SH_CSI2_SRST);
 
-       if (priv->client->lanes & 3)
-               tmp |= priv->client->lanes & 3;
-       else
-               /* Default - both lanes */
-               tmp |= 3;
+       switch (pdata->type) {
+       case SH_CSI2C:
+               if (priv->client->lanes == 1)
+                       tmp |= 1;
+               else
+                       /* Default - both lanes */
+                       tmp |= 3;
+               break;
+       case SH_CSI2I:
+               if (!priv->client->lanes || priv->client->lanes > 4)
+                       /* Default - all 4 lanes */
+                       tmp |= 0xf;
+               else
+                       tmp |= (1 << priv->client->lanes) - 1;
+       }
 
        if (priv->client->phy == SH_CSI2_PHY_MAIN)
                tmp |= 0x8000;
@@ -163,38 +198,18 @@ static void sh_csi2_hwinit(struct sh_csi2 *priv)
        iowrite32(tmp, priv->base + SH_CSI2_CHKSUM);
 }
 
-static int sh_csi2_set_bus_param(struct soc_camera_device *icd,
-                                unsigned long flags)
-{
-       return 0;
-}
-
-static unsigned long sh_csi2_query_bus_param(struct soc_camera_device *icd)
-{
-       struct soc_camera_link *icl = to_soc_camera_link(icd);
-       const unsigned long flags = SOCAM_PCLK_SAMPLE_RISING |
-               SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH |
-               SOCAM_MASTER | SOCAM_DATAWIDTH_8 | SOCAM_DATA_ACTIVE_HIGH;
-
-       return soc_camera_apply_sensor_flags(icl, flags);
-}
-
 static int sh_csi2_client_connect(struct sh_csi2 *priv)
 {
        struct sh_csi2_pdata *pdata = priv->pdev->dev.platform_data;
-       struct v4l2_subdev *sd, *csi2_sd = &priv->subdev;
-       struct soc_camera_device *icd = NULL;
+       struct soc_camera_device *icd = (struct soc_camera_device *)priv->subdev.grp_id;
+       struct v4l2_subdev *client_sd = soc_camera_to_subdev(icd);
        struct device *dev = v4l2_get_subdevdata(&priv->subdev);
-       int i;
+       struct v4l2_mbus_config cfg;
+       unsigned long common_flags, csi2_flags;
+       int i, ret;
 
-       v4l2_device_for_each_subdev(sd, csi2_sd->v4l2_dev)
-               if (sd->grp_id) {
-                       icd = (struct soc_camera_device *)sd->grp_id;
-                       break;
-               }
-
-       if (!icd)
-               return -EINVAL;
+       if (priv->client)
+               return -EBUSY;
 
        for (i = 0; i < pdata->num_clients; i++)
                if (&pdata->clients[i].pdev->dev == icd->pdev)
@@ -205,14 +220,41 @@ static int sh_csi2_client_connect(struct sh_csi2 *priv)
        if (i == pdata->num_clients)
                return -ENODEV;
 
-       priv->client = pdata->clients + i;
+       /* Check if we can support this camera */
+       csi2_flags = V4L2_MBUS_CSI2_CONTINUOUS_CLOCK | V4L2_MBUS_CSI2_1_LANE;
+
+       switch (pdata->type) {
+       case SH_CSI2C:
+               if (pdata->clients[i].lanes != 1)
+                       csi2_flags |= V4L2_MBUS_CSI2_2_LANE;
+               break;
+       case SH_CSI2I:
+               switch (pdata->clients[i].lanes) {
+               default:
+                       csi2_flags |= V4L2_MBUS_CSI2_4_LANE;
+               case 3:
+                       csi2_flags |= V4L2_MBUS_CSI2_3_LANE;
+               case 2:
+                       csi2_flags |= V4L2_MBUS_CSI2_2_LANE;
+               }
+       }
 
-       priv->set_bus_param             = icd->ops->set_bus_param;
-       priv->query_bus_param           = icd->ops->query_bus_param;
-       icd->ops->set_bus_param         = sh_csi2_set_bus_param;
-       icd->ops->query_bus_param       = sh_csi2_query_bus_param;
+       cfg.type = V4L2_MBUS_CSI2;
+       ret = v4l2_subdev_call(client_sd, video, g_mbus_config, &cfg);
+       if (ret == -ENOIOCTLCMD)
+               common_flags = csi2_flags;
+       else if (!ret)
+               common_flags = soc_mbus_config_compatible(&cfg,
+                                                         csi2_flags);
+       else
+               common_flags = 0;
 
-       csi2_sd->grp_id = (long)icd;
+       if (!common_flags)
+               return -EINVAL;
+
+       /* All good: camera MIPI configuration supported */
+       priv->mipi_flags = common_flags;
+       priv->client = pdata->clients + i;
 
        pm_runtime_get_sync(dev);
 
@@ -223,16 +265,10 @@ static int sh_csi2_client_connect(struct sh_csi2 *priv)
 
 static void sh_csi2_client_disconnect(struct sh_csi2 *priv)
 {
-       struct soc_camera_device *icd = (struct soc_camera_device *)priv->subdev.grp_id;
+       if (!priv->client)
+               return;
 
        priv->client = NULL;
-       priv->subdev.grp_id = 0;
-
-       /* Driver is about to be unbound */
-       icd->ops->set_bus_param         = priv->set_bus_param;
-       icd->ops->query_bus_param       = priv->query_bus_param;
-       priv->set_bus_param             = NULL;
-       priv->query_bus_param           = NULL;
 
        pm_runtime_put(v4l2_get_subdevdata(&priv->subdev));
 }
index 5bdfe7e..b72580c 100644 (file)
@@ -50,49 +50,65 @@ static LIST_HEAD(hosts);
 static LIST_HEAD(devices);
 static DEFINE_MUTEX(list_lock);                /* Protects the list of hosts */
 
-static int soc_camera_power_set(struct soc_camera_device *icd,
-                               struct soc_camera_link *icl,
-                               int power_on)
+static int soc_camera_power_on(struct soc_camera_device *icd,
+                              struct soc_camera_link *icl)
 {
-       int ret;
-
-       if (power_on) {
-               ret = regulator_bulk_enable(icl->num_regulators,
-                                           icl->regulators);
-               if (ret < 0) {
-                       dev_err(icd->pdev, "Cannot enable regulators\n");
-                       return ret;
-               }
+       struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
+       int ret = regulator_bulk_enable(icl->num_regulators,
+                                       icl->regulators);
+       if (ret < 0) {
+               dev_err(icd->pdev, "Cannot enable regulators\n");
+               return ret;
+       }
 
-               if (icl->power)
-                       ret = icl->power(icd->pdev, power_on);
+       if (icl->power) {
+               ret = icl->power(icd->pdev, 1);
                if (ret < 0) {
                        dev_err(icd->pdev,
                                "Platform failed to power-on the camera.\n");
-
-                       regulator_bulk_disable(icl->num_regulators,
-                                              icl->regulators);
-                       return ret;
+                       goto elinkpwr;
                }
-       } else {
-               ret = 0;
-               if (icl->power)
-                       ret = icl->power(icd->pdev, 0);
+       }
+
+       ret = v4l2_subdev_call(sd, core, s_power, 1);
+       if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
+               goto esdpwr;
+
+       return 0;
+
+esdpwr:
+       if (icl->power)
+               icl->power(icd->pdev, 0);
+elinkpwr:
+       regulator_bulk_disable(icl->num_regulators,
+                              icl->regulators);
+       return ret;
+}
+
+static int soc_camera_power_off(struct soc_camera_device *icd,
+                               struct soc_camera_link *icl)
+{
+       struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
+       int ret = v4l2_subdev_call(sd, core, s_power, 0);
+
+       if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
+               return ret;
+
+       if (icl->power) {
+               ret = icl->power(icd->pdev, 0);
                if (ret < 0) {
                        dev_err(icd->pdev,
                                "Platform failed to power-off the camera.\n");
                        return ret;
                }
-
-               ret = regulator_bulk_disable(icl->num_regulators,
-                                            icl->regulators);
-               if (ret < 0) {
-                       dev_err(icd->pdev, "Cannot disable regulators\n");
-                       return ret;
-               }
        }
 
-       return 0;
+       ret = regulator_bulk_disable(icl->num_regulators,
+                                    icl->regulators);
+       if (ret < 0)
+               dev_err(icd->pdev, "Cannot disable regulators\n");
+
+       return ret;
 }
 
 const struct soc_camera_format_xlate *soc_camera_xlate_by_fourcc(
@@ -108,38 +124,38 @@ const struct soc_camera_format_xlate *soc_camera_xlate_by_fourcc(
 EXPORT_SYMBOL(soc_camera_xlate_by_fourcc);
 
 /**
- * soc_camera_apply_sensor_flags() - apply platform SOCAM_SENSOR_INVERT_* flags
+ * soc_camera_apply_board_flags() - apply platform SOCAM_SENSOR_INVERT_* flags
  * @icl:       camera platform parameters
- * @flags:     flags to be inverted according to platform configuration
+ * @cfg:       media bus configuration
  * @return:    resulting flags
  */
-unsigned long soc_camera_apply_sensor_flags(struct soc_camera_link *icl,
-                                           unsigned long flags)
+unsigned long soc_camera_apply_board_flags(struct soc_camera_link *icl,
+                                          const struct v4l2_mbus_config *cfg)
 {
-       unsigned long f;
+       unsigned long f, flags = cfg->flags;
 
        /* If only one of the two polarities is supported, switch to the opposite */
        if (icl->flags & SOCAM_SENSOR_INVERT_HSYNC) {
-               f = flags & (SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_LOW);
-               if (f == SOCAM_HSYNC_ACTIVE_HIGH || f == SOCAM_HSYNC_ACTIVE_LOW)
-                       flags ^= SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_LOW;
+               f = flags & (V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_LOW);
+               if (f == V4L2_MBUS_HSYNC_ACTIVE_HIGH || f == V4L2_MBUS_HSYNC_ACTIVE_LOW)
+                       flags ^= V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_LOW;
        }
 
        if (icl->flags & SOCAM_SENSOR_INVERT_VSYNC) {
-               f = flags & (SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW);
-               if (f == SOCAM_VSYNC_ACTIVE_HIGH || f == SOCAM_VSYNC_ACTIVE_LOW)
-                       flags ^= SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW;
+               f = flags & (V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_LOW);
+               if (f == V4L2_MBUS_VSYNC_ACTIVE_HIGH || f == V4L2_MBUS_VSYNC_ACTIVE_LOW)
+                       flags ^= V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_LOW;
        }
 
        if (icl->flags & SOCAM_SENSOR_INVERT_PCLK) {
-               f = flags & (SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING);
-               if (f == SOCAM_PCLK_SAMPLE_RISING || f == SOCAM_PCLK_SAMPLE_FALLING)
-                       flags ^= SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING;
+               f = flags & (V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_PCLK_SAMPLE_FALLING);
+               if (f == V4L2_MBUS_PCLK_SAMPLE_RISING || f == V4L2_MBUS_PCLK_SAMPLE_FALLING)
+                       flags ^= V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_PCLK_SAMPLE_FALLING;
        }
 
        return flags;
 }
-EXPORT_SYMBOL(soc_camera_apply_sensor_flags);
+EXPORT_SYMBOL(soc_camera_apply_board_flags);
 
 #define pixfmtstr(x) (x) & 0xff, ((x) >> 8) & 0xff, ((x) >> 16) & 0xff, \
        ((x) >> 24) & 0xff
@@ -233,6 +249,14 @@ static int soc_camera_s_std(struct file *file, void *priv, v4l2_std_id *a)
        return v4l2_subdev_call(sd, core, s_std, *a);
 }
 
+static int soc_camera_g_std(struct file *file, void *priv, v4l2_std_id *a)
+{
+       struct soc_camera_device *icd = file->private_data;
+       struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
+
+       return v4l2_subdev_call(sd, core, g_std, a);
+}
+
 static int soc_camera_enum_fsizes(struct file *file, void *fh,
                                         struct v4l2_frmsizeenum *fsize)
 {
@@ -318,6 +342,32 @@ static int soc_camera_dqbuf(struct file *file, void *priv,
                return vb2_dqbuf(&icd->vb2_vidq, p, file->f_flags & O_NONBLOCK);
 }
 
+static int soc_camera_create_bufs(struct file *file, void *priv,
+                           struct v4l2_create_buffers *create)
+{
+       struct soc_camera_device *icd = file->private_data;
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+
+       /* videobuf2 only */
+       if (ici->ops->init_videobuf)
+               return -EINVAL;
+       else
+               return vb2_create_bufs(&icd->vb2_vidq, create);
+}
+
+static int soc_camera_prepare_buf(struct file *file, void *priv,
+                                 struct v4l2_buffer *b)
+{
+       struct soc_camera_device *icd = file->private_data;
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+
+       /* videobuf2 only */
+       if (ici->ops->init_videobuf)
+               return -EINVAL;
+       else
+               return vb2_prepare_buf(&icd->vb2_vidq, b);
+}
+
 /* Always entered with .video_lock held */
 static int soc_camera_init_user_formats(struct soc_camera_device *icd)
 {
@@ -448,7 +498,7 @@ static int soc_camera_open(struct file *file)
        struct soc_camera_host *ici;
        int ret;
 
-       if (!icd->ops)
+       if (!to_soc_camera_control(icd))
                /* No device driver attached */
                return -ENODEV;
 
@@ -476,7 +526,7 @@ static int soc_camera_open(struct file *file)
                        },
                };
 
-               ret = soc_camera_power_set(icd, icl, 1);
+               ret = soc_camera_power_on(icd, icl);
                if (ret < 0)
                        goto epower;
 
@@ -512,6 +562,7 @@ static int soc_camera_open(struct file *file)
                        if (ret < 0)
                                goto einitvb;
                }
+               v4l2_ctrl_handler_setup(&icd->ctrl_handler);
        }
 
        file->private_data = icd;
@@ -529,7 +580,7 @@ esfmt:
 eresume:
        ici->ops->remove(icd);
 eiciadd:
-       soc_camera_power_set(icd, icl, 0);
+       soc_camera_power_off(icd, icl);
 epower:
        icd->use_count--;
        module_put(ici->ops->owner);
@@ -553,7 +604,7 @@ static int soc_camera_close(struct file *file)
                if (ici->ops->init_videobuf2)
                        vb2_queue_release(&icd->vb2_vidq);
 
-               soc_camera_power_set(icd, icl, 0);
+               soc_camera_power_off(icd, icl);
        }
 
        if (icd->streamer == file)
@@ -781,75 +832,6 @@ static int soc_camera_streamoff(struct file *file, void *priv,
        return 0;
 }
 
-static int soc_camera_queryctrl(struct file *file, void *priv,
-                               struct v4l2_queryctrl *qc)
-{
-       struct soc_camera_device *icd = file->private_data;
-       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
-       int i;
-
-       WARN_ON(priv != file->private_data);
-
-       if (!qc->id)
-               return -EINVAL;
-
-       /* First check host controls */
-       for (i = 0; i < ici->ops->num_controls; i++)
-               if (qc->id == ici->ops->controls[i].id) {
-                       memcpy(qc, &(ici->ops->controls[i]),
-                               sizeof(*qc));
-                       return 0;
-               }
-
-       /* Then device controls */
-       for (i = 0; i < icd->ops->num_controls; i++)
-               if (qc->id == icd->ops->controls[i].id) {
-                       memcpy(qc, &(icd->ops->controls[i]),
-                               sizeof(*qc));
-                       return 0;
-               }
-
-       return -EINVAL;
-}
-
-static int soc_camera_g_ctrl(struct file *file, void *priv,
-                            struct v4l2_control *ctrl)
-{
-       struct soc_camera_device *icd = file->private_data;
-       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
-       struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
-       int ret;
-
-       WARN_ON(priv != file->private_data);
-
-       if (ici->ops->get_ctrl) {
-               ret = ici->ops->get_ctrl(icd, ctrl);
-               if (ret != -ENOIOCTLCMD)
-                       return ret;
-       }
-
-       return v4l2_subdev_call(sd, core, g_ctrl, ctrl);
-}
-
-static int soc_camera_s_ctrl(struct file *file, void *priv,
-                            struct v4l2_control *ctrl)
-{
-       struct soc_camera_device *icd = file->private_data;
-       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
-       struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
-       int ret;
-
-       WARN_ON(priv != file->private_data);
-
-       if (ici->ops->set_ctrl) {
-               ret = ici->ops->set_ctrl(icd, ctrl);
-               if (ret != -ENOIOCTLCMD)
-                       return ret;
-       }
-
-       return v4l2_subdev_call(sd, core, s_ctrl, ctrl);
-}
-
 static int soc_camera_cropcap(struct file *file, void *fh,
                              struct v4l2_cropcap *a)
 {
@@ -1003,7 +985,7 @@ static int soc_camera_init_i2c(struct soc_camera_device *icd,
                goto ei2cga;
        }
 
-       icl->board_info->platform_data = icd;
+       icl->board_info->platform_data = icl;
 
        subdev = v4l2_i2c_new_subdev_board(&ici->v4l2_dev, adap,
                                icl->board_info, NULL);
@@ -1052,12 +1034,29 @@ static int soc_camera_probe(struct soc_camera_device *icd)
 
        dev_info(icd->pdev, "Probing %s\n", dev_name(icd->pdev));
 
+       /*
+        * Currently the subdev with the largest number of controls (13) is
+        * ov6550. So let's pick 16 as a hint for the control handler. Note
+        * that this is a hint only: too large and you waste some memory, too
+        * small and there is a (very) small performance hit when looking up
+        * controls in the internal hash.
+        */
+       ret = v4l2_ctrl_handler_init(&icd->ctrl_handler, 16);
+       if (ret < 0)
+               return ret;
+
        ret = regulator_bulk_get(icd->pdev, icl->num_regulators,
                                 icl->regulators);
        if (ret < 0)
                goto ereg;
 
-       ret = soc_camera_power_set(icd, icl, 1);
+       /*
+        * This will not yet call v4l2_subdev_core_ops::s_power(1), because the
+        * subdevice has not been initialised yet. We'll have to call it once
+        * again after initialisation, even though it shouldn't be needed, we
+        * don't do any IO here.
+        */
+       ret = soc_camera_power_on(icd, icl);
        if (ret < 0)
                goto epower;
 
@@ -1098,6 +1097,7 @@ static int soc_camera_probe(struct soc_camera_device *icd)
                if (!control || !control->driver || !dev_get_drvdata(control) ||
                    !try_module_get(control->driver->owner)) {
                        icl->del_device(icd);
+                       ret = -ENODEV;
                        goto enodrv;
                }
        }
@@ -1105,6 +1105,9 @@ static int soc_camera_probe(struct soc_camera_device *icd)
        sd = soc_camera_to_subdev(icd);
        sd->grp_id = (long)icd;
 
+       if (v4l2_ctrl_add_handler(&icd->ctrl_handler, sd->ctrl_handler))
+               goto ectrl;
+
        /* At this point client .probe() should have run already */
        ret = soc_camera_init_user_formats(icd);
        if (ret < 0)
@@ -1123,6 +1126,10 @@ static int soc_camera_probe(struct soc_camera_device *icd)
        if (ret < 0)
                goto evidstart;
 
+       ret = v4l2_subdev_call(sd, core, s_power, 1);
+       if (ret < 0 && ret != -ENOIOCTLCMD)
+               goto esdpwr;
+
        /* Try to improve our guess of a reasonable window format */
        if (!v4l2_subdev_call(sd, video, g_mbus_fmt, &mf)) {
                icd->user_width         = mf.width;
@@ -1133,16 +1140,19 @@ static int soc_camera_probe(struct soc_camera_device *icd)
 
        ici->ops->remove(icd);
 
-       soc_camera_power_set(icd, icl, 0);
+       soc_camera_power_off(icd, icl);
 
        mutex_unlock(&icd->video_lock);
 
        return 0;
 
+esdpwr:
+       video_unregister_device(icd->vdev);
 evidstart:
        mutex_unlock(&icd->video_lock);
        soc_camera_free_user_formats(icd);
 eiufmt:
+ectrl:
        if (icl->board_info) {
                soc_camera_free_i2c(icd);
        } else {
@@ -1152,13 +1162,15 @@ eiufmt:
 enodrv:
 eadddev:
        video_device_release(icd->vdev);
+       icd->vdev = NULL;
 evdc:
        ici->ops->remove(icd);
 eadd:
-       soc_camera_power_set(icd, icl, 0);
+       soc_camera_power_off(icd, icl);
 epower:
        regulator_bulk_free(icl->num_regulators, icl->regulators);
 ereg:
+       v4l2_ctrl_handler_free(&icd->ctrl_handler);
        return ret;
 }
 
@@ -1173,6 +1185,7 @@ static int soc_camera_remove(struct soc_camera_device *icd)
 
        BUG_ON(!icd->parent);
 
+       v4l2_ctrl_handler_free(&icd->ctrl_handler);
        if (vdev) {
                video_unregister_device(vdev);
                icd->vdev = NULL;
@@ -1363,24 +1376,24 @@ static int soc_camera_device_register(struct soc_camera_device *icd)
 
 static const struct v4l2_ioctl_ops soc_camera_ioctl_ops = {
        .vidioc_querycap         = soc_camera_querycap,
+       .vidioc_try_fmt_vid_cap  = soc_camera_try_fmt_vid_cap,
        .vidioc_g_fmt_vid_cap    = soc_camera_g_fmt_vid_cap,
-       .vidioc_enum_fmt_vid_cap = soc_camera_enum_fmt_vid_cap,
        .vidioc_s_fmt_vid_cap    = soc_camera_s_fmt_vid_cap,
+       .vidioc_enum_fmt_vid_cap = soc_camera_enum_fmt_vid_cap,
        .vidioc_enum_input       = soc_camera_enum_input,
        .vidioc_g_input          = soc_camera_g_input,
        .vidioc_s_input          = soc_camera_s_input,
        .vidioc_s_std            = soc_camera_s_std,
+       .vidioc_g_std            = soc_camera_g_std,
        .vidioc_enum_framesizes  = soc_camera_enum_fsizes,
        .vidioc_reqbufs          = soc_camera_reqbufs,
-       .vidioc_try_fmt_vid_cap  = soc_camera_try_fmt_vid_cap,
        .vidioc_querybuf         = soc_camera_querybuf,
        .vidioc_qbuf             = soc_camera_qbuf,
        .vidioc_dqbuf            = soc_camera_dqbuf,
+       .vidioc_create_bufs      = soc_camera_create_bufs,
+       .vidioc_prepare_buf      = soc_camera_prepare_buf,
        .vidioc_streamon         = soc_camera_streamon,
        .vidioc_streamoff        = soc_camera_streamoff,
-       .vidioc_queryctrl        = soc_camera_queryctrl,
-       .vidioc_g_ctrl           = soc_camera_g_ctrl,
-       .vidioc_s_ctrl           = soc_camera_s_ctrl,
        .vidioc_cropcap          = soc_camera_cropcap,
        .vidioc_g_crop           = soc_camera_g_crop,
        .vidioc_s_crop           = soc_camera_s_crop,
@@ -1409,6 +1422,7 @@ static int video_dev_create(struct soc_camera_device *icd)
        vdev->ioctl_ops         = &soc_camera_ioctl_ops;
        vdev->release           = video_device_release;
        vdev->tvnorms           = V4L2_STD_UNKNOWN;
+       vdev->ctrl_handler      = &icd->ctrl_handler;
        vdev->lock              = &icd->video_lock;
 
        icd->vdev = vdev;
@@ -1427,11 +1441,6 @@ static int soc_camera_video_start(struct soc_camera_device *icd)
        if (!icd->parent)
                return -ENODEV;
 
-       if (!icd->ops ||
-           !icd->ops->query_bus_param ||
-           !icd->ops->set_bus_param)
-               return -EINVAL;
-
        ret = video_register_device(icd->vdev, VFL_TYPE_GRABBER, -1);
        if (ret < 0) {
                dev_err(icd->pdev, "video_register_device failed: %d\n", ret);
index 8069cd6..4402a8a 100644 (file)
@@ -30,32 +30,12 @@ static struct soc_camera_platform_priv *get_priv(struct platform_device *pdev)
        return container_of(subdev, struct soc_camera_platform_priv, subdev);
 }
 
-static struct soc_camera_platform_info *get_info(struct soc_camera_device *icd)
-{
-       struct platform_device *pdev =
-               to_platform_device(to_soc_camera_control(icd));
-       return pdev->dev.platform_data;
-}
-
 static int soc_camera_platform_s_stream(struct v4l2_subdev *sd, int enable)
 {
        struct soc_camera_platform_info *p = v4l2_get_subdevdata(sd);
        return p->set_capture(p, enable);
 }
 
-static int soc_camera_platform_set_bus_param(struct soc_camera_device *icd,
-                                            unsigned long flags)
-{
-       return 0;
-}
-
-static unsigned long
-soc_camera_platform_query_bus_param(struct soc_camera_device *icd)
-{
-       struct soc_camera_platform_info *p = get_info(icd);
-       return p->bus_param;
-}
-
 static int soc_camera_platform_fill_fmt(struct v4l2_subdev *sd,
                                        struct v4l2_mbus_framefmt *mf)
 {
@@ -115,6 +95,17 @@ static int soc_camera_platform_cropcap(struct v4l2_subdev *sd,
        return 0;
 }
 
+static int soc_camera_platform_g_mbus_config(struct v4l2_subdev *sd,
+                                            struct v4l2_mbus_config *cfg)
+{
+       struct soc_camera_platform_info *p = v4l2_get_subdevdata(sd);
+
+       cfg->flags = p->mbus_param;
+       cfg->type = p->mbus_type;
+
+       return 0;
+}
+
 static struct v4l2_subdev_video_ops platform_subdev_video_ops = {
        .s_stream       = soc_camera_platform_s_stream,
        .enum_mbus_fmt  = soc_camera_platform_enum_fmt,
@@ -123,6 +114,7 @@ static struct v4l2_subdev_video_ops platform_subdev_video_ops = {
        .try_mbus_fmt   = soc_camera_platform_fill_fmt,
        .g_mbus_fmt     = soc_camera_platform_fill_fmt,
        .s_mbus_fmt     = soc_camera_platform_fill_fmt,
+       .g_mbus_config  = soc_camera_platform_g_mbus_config,
 };
 
 static struct v4l2_subdev_ops platform_subdev_ops = {
@@ -130,11 +122,6 @@ static struct v4l2_subdev_ops platform_subdev_ops = {
        .video  = &platform_subdev_video_ops,
 };
 
-static struct soc_camera_ops soc_camera_platform_ops = {
-       .set_bus_param          = soc_camera_platform_set_bus_param,
-       .query_bus_param        = soc_camera_platform_query_bus_param,
-};
-
 static int soc_camera_platform_probe(struct platform_device *pdev)
 {
        struct soc_camera_host *ici;
@@ -163,8 +150,6 @@ static int soc_camera_platform_probe(struct platform_device *pdev)
        /* Set the control device reference */
        icd->control = &pdev->dev;
 
-       icd->ops = &soc_camera_platform_ops;
-
        ici = to_soc_camera_host(icd->parent);
 
        v4l2_subdev_init(&priv->subdev, &platform_subdev_ops);
@@ -178,7 +163,6 @@ static int soc_camera_platform_probe(struct platform_device *pdev)
        return ret;
 
 evdrs:
-       icd->ops = NULL;
        platform_set_drvdata(pdev, NULL);
        kfree(priv);
        return ret;
@@ -187,11 +171,10 @@ evdrs:
 static int soc_camera_platform_remove(struct platform_device *pdev)
 {
        struct soc_camera_platform_priv *priv = get_priv(pdev);
-       struct soc_camera_platform_info *p = pdev->dev.platform_data;
-       struct soc_camera_device *icd = p->icd;
+       struct soc_camera_platform_info *p = v4l2_get_subdevdata(&priv->subdev);
 
+       p->icd->control = NULL;
        v4l2_device_unregister_subdev(&priv->subdev);
-       icd->ops = NULL;
        platform_set_drvdata(pdev, NULL);
        kfree(priv);
        return 0;
index bea7c9c..cf7f219 100644 (file)
@@ -383,6 +383,39 @@ const struct soc_mbus_pixelfmt *soc_mbus_get_fmtdesc(
 }
 EXPORT_SYMBOL(soc_mbus_get_fmtdesc);
 
+unsigned int soc_mbus_config_compatible(const struct v4l2_mbus_config *cfg,
+                                       unsigned int flags)
+{
+       unsigned long common_flags;
+       bool hsync = true, vsync = true, pclk, data, mode;
+       bool mipi_lanes, mipi_clock;
+
+       common_flags = cfg->flags & flags;
+
+       switch (cfg->type) {
+       case V4L2_MBUS_PARALLEL:
+               hsync = common_flags & (V4L2_MBUS_HSYNC_ACTIVE_HIGH |
+                                       V4L2_MBUS_HSYNC_ACTIVE_LOW);
+               vsync = common_flags & (V4L2_MBUS_VSYNC_ACTIVE_HIGH |
+                                       V4L2_MBUS_VSYNC_ACTIVE_LOW);
+       case V4L2_MBUS_BT656:
+               pclk = common_flags & (V4L2_MBUS_PCLK_SAMPLE_RISING |
+                                      V4L2_MBUS_PCLK_SAMPLE_FALLING);
+               data = common_flags & (V4L2_MBUS_DATA_ACTIVE_HIGH |
+                                      V4L2_MBUS_DATA_ACTIVE_LOW);
+               mode = common_flags & (V4L2_MBUS_MASTER | V4L2_MBUS_SLAVE);
+               return (!hsync || !vsync || !pclk || !data || !mode) ?
+                       0 : common_flags;
+       case V4L2_MBUS_CSI2:
+               mipi_lanes = common_flags & V4L2_MBUS_CSI2_LANES;
+               mipi_clock = common_flags & (V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK |
+                                            V4L2_MBUS_CSI2_CONTINUOUS_CLOCK);
+               return (!mipi_lanes || !mipi_clock) ? 0 : common_flags;
+       }
+       return 0;
+}
+EXPORT_SYMBOL(soc_mbus_config_compatible);
+
 static int __init soc_mbus_init(void)
 {
        return 0;
index 742482e..a514fa6 100644 (file)
 #include <linux/slab.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
+#include <linux/v4l2-mediabus.h>
 #include <linux/videodev2.h>
-#include <media/v4l2-chip-ident.h>
-#include <media/v4l2-subdev.h>
+
 #include <media/soc_camera.h>
 #include <media/tw9910.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-subdev.h>
 
 #define GET_ID(val)  ((val & 0xF8) >> 3)
 #define GET_REV(val) (val & 0x07)
 #define RTSEL_FIELD 0x06 /* 0110 = FIELD */
 #define RTSEL_RTCO  0x07 /* 0111 = RTCO ( Real Time Control ) */
 
+/* HSYNC start and end are constant for now */
+#define HSYNC_START    0x0260
+#define HSYNC_END      0x0300
+
 /*
  * structure
  */
@@ -220,22 +226,11 @@ struct tw9910_scale_ctrl {
        u16             vscale;
 };
 
-struct tw9910_cropping_ctrl {
-       u16 vdelay;
-       u16 vactive;
-       u16 hdelay;
-       u16 hactive;
-};
-
-struct tw9910_hsync_ctrl {
-       u16 start;
-       u16 end;
-};
-
 struct tw9910_priv {
        struct v4l2_subdev              subdev;
        struct tw9910_video_info        *info;
        const struct tw9910_scale_ctrl  *scale;
+       v4l2_std_id                     norm;
        u32                             revision;
 };
 
@@ -329,11 +324,6 @@ static const struct tw9910_scale_ctrl tw9910_pal_scales[] = {
        },
 };
 
-static const struct tw9910_hsync_ctrl tw9910_hsync_ctrl = {
-       .start = 0x0260,
-       .end   = 0x0300,
-};
-
 /*
  * general function
  */
@@ -378,21 +368,20 @@ static int tw9910_set_scale(struct i2c_client *client,
        return ret;
 }
 
-static int tw9910_set_hsync(struct i2c_client *client,
-                           const struct tw9910_hsync_ctrl *hsync)
+static int tw9910_set_hsync(struct i2c_client *client)
 {
        struct tw9910_priv *priv = to_tw9910(client);
        int ret;
 
        /* bit 10 - 3 */
        ret = i2c_smbus_write_byte_data(client, HSBEGIN,
-                                       (hsync->start & 0x07F8) >> 3);
+                                       (HSYNC_START & 0x07F8) >> 3);
        if (ret < 0)
                return ret;
 
        /* bit 10 - 3 */
        ret = i2c_smbus_write_byte_data(client, HSEND,
-                                       (hsync->end & 0x07F8) >> 3);
+                                       (HSYNC_END & 0x07F8) >> 3);
        if (ret < 0)
                return ret;
 
@@ -400,8 +389,8 @@ static int tw9910_set_hsync(struct i2c_client *client,
        /* bit 2 - 0 */
        if (1 == priv->revision)
                ret = tw9910_mask_set(client, HSLOWCTL, 0x77,
-                                     (hsync->start & 0x0007) << 4 |
-                                     (hsync->end   & 0x0007));
+                                     (HSYNC_START & 0x0007) << 4 |
+                                     (HSYNC_END   & 0x0007));
 
        return ret;
 }
@@ -433,12 +422,11 @@ static int tw9910_power(struct i2c_client *client, int enable)
        return tw9910_mask_set(client, ACNTL2, ACNTL2_PDN_MASK, acntl2);
 }
 
-static const struct tw9910_scale_ctrl*
-tw9910_select_norm(struct soc_camera_device *icd, u32 width, u32 height)
+static const struct tw9910_scale_ctrl *tw9910_select_norm(v4l2_std_id norm,
+                                                         u32 width, u32 height)
 {
        const struct tw9910_scale_ctrl *scale;
        const struct tw9910_scale_ctrl *ret = NULL;
-       v4l2_std_id norm = icd->vdev->current_norm;
        __u32 diff = 0xffffffff, tmp;
        int size, i;
 
@@ -465,7 +453,7 @@ tw9910_select_norm(struct soc_camera_device *icd, u32 width, u32 height)
 }
 
 /*
- * soc_camera_ops function
+ * subdevice operations
  */
 static int tw9910_s_stream(struct v4l2_subdev *sd, int enable)
 {
@@ -507,49 +495,27 @@ static int tw9910_s_stream(struct v4l2_subdev *sd, int enable)
        return tw9910_power(client, enable);
 }
 
-static int tw9910_set_bus_param(struct soc_camera_device *icd,
-                               unsigned long flags)
+static int tw9910_g_std(struct v4l2_subdev *sd, v4l2_std_id *norm)
 {
-       struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
        struct i2c_client *client = v4l2_get_subdevdata(sd);
-       u8 val = VSSL_VVALID | HSSL_DVALID;
+       struct tw9910_priv *priv = to_tw9910(client);
 
-       /*
-        * set OUTCTR1
-        *
-        * We use VVALID and DVALID signals to control VSYNC and HSYNC
-        * outputs, in this mode their polarity is inverted.
-        */
-       if (flags & SOCAM_HSYNC_ACTIVE_LOW)
-               val |= HSP_HI;
+       *norm = priv->norm;
 
-       if (flags & SOCAM_VSYNC_ACTIVE_LOW)
-               val |= VSP_HI;
-
-       return i2c_smbus_write_byte_data(client, OUTCTR1, val);
+       return 0;
 }
 
-static unsigned long tw9910_query_bus_param(struct soc_camera_device *icd)
+static int tw9910_s_std(struct v4l2_subdev *sd, v4l2_std_id norm)
 {
-       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
        struct tw9910_priv *priv = to_tw9910(client);
-       struct soc_camera_link *icl = to_soc_camera_link(icd);
-       unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER |
-               SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH |
-               SOCAM_VSYNC_ACTIVE_LOW  | SOCAM_HSYNC_ACTIVE_LOW  |
-               SOCAM_DATA_ACTIVE_HIGH | priv->info->buswidth;
 
-       return soc_camera_apply_sensor_flags(icl, flags);
-}
-
-static int tw9910_s_std(struct v4l2_subdev *sd, v4l2_std_id norm)
-{
-       int ret = -EINVAL;
+       if (!(norm & (V4L2_STD_NTSC | V4L2_STD_PAL)))
+               return -EINVAL;
 
-       if (norm & (V4L2_STD_NTSC | V4L2_STD_PAL))
-               ret = 0;
+       priv->norm = norm;
 
-       return ret;
+       return 0;
 }
 
 static int tw9910_g_chip_ident(struct v4l2_subdev *sd,
@@ -600,19 +566,17 @@ static int tw9910_s_register(struct v4l2_subdev *sd,
 }
 #endif
 
-static int tw9910_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+static int tw9910_set_frame(struct v4l2_subdev *sd, u32 *width, u32 *height)
 {
-       struct v4l2_rect *rect = &a->c;
        struct i2c_client *client = v4l2_get_subdevdata(sd);
        struct tw9910_priv *priv = to_tw9910(client);
-       struct soc_camera_device *icd = client->dev.platform_data;
-       int                 ret  = -EINVAL;
-       u8                  val;
+       int ret = -EINVAL;
+       u8 val;
 
        /*
         * select suitable norm
         */
-       priv->scale = tw9910_select_norm(icd, rect->width, rect->height);
+       priv->scale = tw9910_select_norm(priv->norm, *width, *height);
        if (!priv->scale)
                goto tw9910_set_fmt_error;
 
@@ -670,14 +634,12 @@ static int tw9910_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
        /*
         * set hsync
         */
-       ret = tw9910_set_hsync(client, &tw9910_hsync_ctrl);
+       ret = tw9910_set_hsync(client);
        if (ret < 0)
                goto tw9910_set_fmt_error;
 
-       rect->width = priv->scale->width;
-       rect->height = priv->scale->height;
-       rect->left = 0;
-       rect->top = 0;
+       *width = priv->scale->width;
+       *height = priv->scale->height;
 
        return ret;
 
@@ -694,25 +656,15 @@ static int tw9910_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
        struct i2c_client *client = v4l2_get_subdevdata(sd);
        struct tw9910_priv *priv = to_tw9910(client);
 
-       if (!priv->scale) {
-               int ret;
-               struct v4l2_crop crop = {
-                       .c = {
-                               .left   = 0,
-                               .top    = 0,
-                               .width  = 640,
-                               .height = 480,
-                       },
-               };
-               ret = tw9910_s_crop(sd, &crop);
-               if (ret < 0)
-                       return ret;
-       }
-
        a->c.left       = 0;
        a->c.top        = 0;
-       a->c.width      = priv->scale->width;
-       a->c.height     = priv->scale->height;
+       if (priv->norm & V4L2_STD_NTSC) {
+               a->c.width      = 640;
+               a->c.height     = 480;
+       } else {
+               a->c.width      = 768;
+               a->c.height     = 576;
+       }
        a->type         = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
        return 0;
@@ -720,14 +672,19 @@ static int tw9910_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
 
 static int tw9910_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
 {
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct tw9910_priv *priv = to_tw9910(client);
+
        a->bounds.left                  = 0;
        a->bounds.top                   = 0;
-       a->bounds.width                 = 768;
-       a->bounds.height                = 576;
-       a->defrect.left                 = 0;
-       a->defrect.top                  = 0;
-       a->defrect.width                = 640;
-       a->defrect.height               = 480;
+       if (priv->norm & V4L2_STD_NTSC) {
+               a->bounds.width         = 640;
+               a->bounds.height        = 480;
+       } else {
+               a->bounds.width         = 768;
+               a->bounds.height        = 576;
+       }
+       a->defrect                      = a->bounds;
        a->type                         = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        a->pixelaspect.numerator        = 1;
        a->pixelaspect.denominator      = 1;
@@ -743,15 +700,8 @@ static int tw9910_g_fmt(struct v4l2_subdev *sd,
 
        if (!priv->scale) {
                int ret;
-               struct v4l2_crop crop = {
-                       .c = {
-                               .left   = 0,
-                               .top    = 0,
-                               .width  = 640,
-                               .height = 480,
-                       },
-               };
-               ret = tw9910_s_crop(sd, &crop);
+               u32 width = 640, height = 480;
+               ret = tw9910_set_frame(sd, &width, &height);
                if (ret < 0)
                        return ret;
        }
@@ -768,17 +718,7 @@ static int tw9910_g_fmt(struct v4l2_subdev *sd,
 static int tw9910_s_fmt(struct v4l2_subdev *sd,
                        struct v4l2_mbus_framefmt *mf)
 {
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct tw9910_priv *priv = to_tw9910(client);
-       /* See tw9910_s_crop() - no proper cropping support */
-       struct v4l2_crop a = {
-               .c = {
-                       .left   = 0,
-                       .top    = 0,
-                       .width  = mf->width,
-                       .height = mf->height,
-               },
-       };
+       u32 width = mf->width, height = mf->height;
        int ret;
 
        WARN_ON(mf->field != V4L2_FIELD_ANY &&
@@ -792,10 +732,10 @@ static int tw9910_s_fmt(struct v4l2_subdev *sd,
 
        mf->colorspace = V4L2_COLORSPACE_JPEG;
 
-       ret = tw9910_s_crop(sd, &a);
+       ret = tw9910_set_frame(sd, &width, &height);
        if (!ret) {
-               mf->width       = priv->scale->width;
-               mf->height      = priv->scale->height;
+               mf->width       = width;
+               mf->height      = height;
        }
        return ret;
 }
@@ -804,7 +744,7 @@ static int tw9910_try_fmt(struct v4l2_subdev *sd,
                          struct v4l2_mbus_framefmt *mf)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct soc_camera_device *icd = client->dev.platform_data;
+       struct tw9910_priv *priv = to_tw9910(client);
        const struct tw9910_scale_ctrl *scale;
 
        if (V4L2_FIELD_ANY == mf->field) {
@@ -820,7 +760,7 @@ static int tw9910_try_fmt(struct v4l2_subdev *sd,
        /*
         * select suitable norm
         */
-       scale = tw9910_select_norm(icd, mf->width, mf->height);
+       scale = tw9910_select_norm(priv->norm, mf->width, mf->height);
        if (!scale)
                return -EINVAL;
 
@@ -830,16 +770,11 @@ static int tw9910_try_fmt(struct v4l2_subdev *sd,
        return 0;
 }
 
-static int tw9910_video_probe(struct soc_camera_device *icd,
-                             struct i2c_client *client)
+static int tw9910_video_probe(struct i2c_client *client)
 {
        struct tw9910_priv *priv = to_tw9910(client);
        s32 id;
 
-       /* We must have a parent by now. And it cannot be a wrong one. */
-       BUG_ON(!icd->parent ||
-              to_soc_camera_host(icd->parent)->nr != icd->iface);
-
        /*
         * tw9910 only use 8 or 16 bit bus width
         */
@@ -868,20 +803,15 @@ static int tw9910_video_probe(struct soc_camera_device *icd,
        dev_info(&client->dev,
                 "tw9910 Product ID %0x:%0x\n", id, priv->revision);
 
-       icd->vdev->tvnorms      = V4L2_STD_NTSC | V4L2_STD_PAL;
-       icd->vdev->current_norm = V4L2_STD_NTSC;
+       priv->norm = V4L2_STD_NTSC;
 
        return 0;
 }
 
-static struct soc_camera_ops tw9910_ops = {
-       .set_bus_param          = tw9910_set_bus_param,
-       .query_bus_param        = tw9910_query_bus_param,
-};
-
 static struct v4l2_subdev_core_ops tw9910_subdev_core_ops = {
        .g_chip_ident   = tw9910_g_chip_ident,
        .s_std          = tw9910_s_std,
+       .g_std          = tw9910_g_std,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
        .g_register     = tw9910_g_register,
        .s_register     = tw9910_s_register,
@@ -898,6 +828,45 @@ static int tw9910_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
        return 0;
 }
 
+static int tw9910_g_mbus_config(struct v4l2_subdev *sd,
+                               struct v4l2_mbus_config *cfg)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+       cfg->flags = V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_MASTER |
+               V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_LOW |
+               V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_LOW |
+               V4L2_MBUS_DATA_ACTIVE_HIGH;
+       cfg->type = V4L2_MBUS_PARALLEL;
+       cfg->flags = soc_camera_apply_board_flags(icl, cfg);
+
+       return 0;
+}
+
+static int tw9910_s_mbus_config(struct v4l2_subdev *sd,
+                               const struct v4l2_mbus_config *cfg)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+       u8 val = VSSL_VVALID | HSSL_DVALID;
+       unsigned long flags = soc_camera_apply_board_flags(icl, cfg);
+
+       /*
+        * set OUTCTR1
+        *
+        * We use VVALID and DVALID signals to control VSYNC and HSYNC
+        * outputs, in this mode their polarity is inverted.
+        */
+       if (flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
+               val |= HSP_HI;
+
+       if (flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
+               val |= VSP_HI;
+
+       return i2c_smbus_write_byte_data(client, OUTCTR1, val);
+}
+
 static struct v4l2_subdev_video_ops tw9910_subdev_video_ops = {
        .s_stream       = tw9910_s_stream,
        .g_mbus_fmt     = tw9910_g_fmt,
@@ -905,8 +874,9 @@ static struct v4l2_subdev_video_ops tw9910_subdev_video_ops = {
        .try_mbus_fmt   = tw9910_try_fmt,
        .cropcap        = tw9910_cropcap,
        .g_crop         = tw9910_g_crop,
-       .s_crop         = tw9910_s_crop,
        .enum_mbus_fmt  = tw9910_enum_fmt,
+       .g_mbus_config  = tw9910_g_mbus_config,
+       .s_mbus_config  = tw9910_s_mbus_config,
 };
 
 static struct v4l2_subdev_ops tw9910_subdev_ops = {
@@ -922,23 +892,18 @@ static int tw9910_probe(struct i2c_client *client,
                        const struct i2c_device_id *did)
 
 {
-       struct tw9910_priv             *priv;
-       struct tw9910_video_info       *info;
-       struct soc_camera_device       *icd = client->dev.platform_data;
-       struct i2c_adapter             *adapter =
+       struct tw9910_priv              *priv;
+       struct tw9910_video_info        *info;
+       struct i2c_adapter              *adapter =
                to_i2c_adapter(client->dev.parent);
-       struct soc_camera_link         *icl;
-       int                             ret;
+       struct soc_camera_link          *icl = soc_camera_i2c_to_link(client);
+       int                             ret;
 
-       if (!icd) {
-               dev_err(&client->dev, "TW9910: missing soc-camera data!\n");
+       if (!icl || !icl->priv) {
+               dev_err(&client->dev, "TW9910: missing platform data!\n");
                return -EINVAL;
        }
 
-       icl = to_soc_camera_link(icd);
-       if (!icl || !icl->priv)
-               return -EINVAL;
-
        info = icl->priv;
 
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
@@ -956,14 +921,9 @@ static int tw9910_probe(struct i2c_client *client,
 
        v4l2_i2c_subdev_init(&priv->subdev, client, &tw9910_subdev_ops);
 
-       icd->ops     = &tw9910_ops;
-       icd->iface   = icl->bus_id;
-
-       ret = tw9910_video_probe(icd, client);
-       if (ret) {
-               icd->ops = NULL;
+       ret = tw9910_video_probe(client);
+       if (ret)
                kfree(priv);
-       }
 
        return ret;
 }
@@ -971,9 +931,7 @@ static int tw9910_probe(struct i2c_client *client,
 static int tw9910_remove(struct i2c_client *client)
 {
        struct tw9910_priv *priv = to_tw9910(client);
-       struct soc_camera_device *icd = client->dev.platform_data;
 
-       icd->ops = NULL;
        kfree(priv);
        return 0;
 }
index 61979b7..c68531b 100644 (file)
@@ -159,11 +159,25 @@ struct v4l2_format32 {
        } fmt;
 };
 
-static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
+/**
+ * struct v4l2_create_buffers32 - VIDIOC_CREATE_BUFS32 argument
+ * @index:     on return, index of the first created buffer
+ * @count:     entry: number of requested buffers,
+ *             return: number of created buffers
+ * @memory:    buffer memory type
+ * @format:    frame format, for which buffers are requested
+ * @reserved:  future extensions
+ */
+struct v4l2_create_buffers32 {
+       __u32                   index;
+       __u32                   count;
+       enum v4l2_memory        memory;
+       struct v4l2_format32    format;
+       __u32                   reserved[8];
+};
+
+static int __get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
 {
-       if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_format32)) ||
-                       get_user(kp->type, &up->type))
-                       return -EFAULT;
        switch (kp->type) {
        case V4L2_BUF_TYPE_VIDEO_CAPTURE:
        case V4L2_BUF_TYPE_VIDEO_OUTPUT:
@@ -192,11 +206,24 @@ static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user
        }
 }
 
-static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
+static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
+{
+       if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_format32)) ||
+                       get_user(kp->type, &up->type))
+                       return -EFAULT;
+       return __get_v4l2_format32(kp, up);
+}
+
+static int get_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up)
+{
+       if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_create_buffers32)) ||
+           copy_from_user(kp, up, offsetof(struct v4l2_create_buffers32, format.fmt)))
+                       return -EFAULT;
+       return __get_v4l2_format32(&kp->format, &up->format);
+}
+
+static int __put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
 {
-       if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32)) ||
-               put_user(kp->type, &up->type))
-               return -EFAULT;
        switch (kp->type) {
        case V4L2_BUF_TYPE_VIDEO_CAPTURE:
        case V4L2_BUF_TYPE_VIDEO_OUTPUT:
@@ -225,6 +252,22 @@ static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user
        }
 }
 
+static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
+{
+       if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32)) ||
+               put_user(kp->type, &up->type))
+               return -EFAULT;
+       return __put_v4l2_format32(kp, up);
+}
+
+static int put_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up)
+{
+       if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_create_buffers32)) ||
+           copy_to_user(up, kp, offsetof(struct v4l2_create_buffers32, format.fmt)))
+                       return -EFAULT;
+       return __put_v4l2_format32(&kp->format, &up->format);
+}
+
 struct v4l2_standard32 {
        __u32                index;
        __u32                id[2]; /* __u64 would get the alignment wrong */
@@ -702,6 +745,8 @@ static int put_v4l2_event32(struct v4l2_event *kp, struct v4l2_event32 __user *u
 #define VIDIOC_S_EXT_CTRLS32    _IOWR('V', 72, struct v4l2_ext_controls32)
 #define VIDIOC_TRY_EXT_CTRLS32  _IOWR('V', 73, struct v4l2_ext_controls32)
 #define        VIDIOC_DQEVENT32        _IOR ('V', 89, struct v4l2_event32)
+#define VIDIOC_CREATE_BUFS32   _IOWR('V', 92, struct v4l2_create_buffers32)
+#define VIDIOC_PREPARE_BUF32   _IOWR('V', 93, struct v4l2_buffer32)
 
 #define VIDIOC_OVERLAY32       _IOW ('V', 14, s32)
 #define VIDIOC_STREAMON32      _IOW ('V', 18, s32)
@@ -721,6 +766,7 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar
                struct v4l2_standard v2s;
                struct v4l2_ext_controls v2ecs;
                struct v4l2_event v2ev;
+               struct v4l2_create_buffers v2crt;
                unsigned long vx;
                int vi;
        } karg;
@@ -751,6 +797,8 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar
        case VIDIOC_S_INPUT32: cmd = VIDIOC_S_INPUT; break;
        case VIDIOC_G_OUTPUT32: cmd = VIDIOC_G_OUTPUT; break;
        case VIDIOC_S_OUTPUT32: cmd = VIDIOC_S_OUTPUT; break;
+       case VIDIOC_CREATE_BUFS32: cmd = VIDIOC_CREATE_BUFS; break;
+       case VIDIOC_PREPARE_BUF32: cmd = VIDIOC_PREPARE_BUF; break;
        }
 
        switch (cmd) {
@@ -775,6 +823,12 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar
                compatible_arg = 0;
                break;
 
+       case VIDIOC_CREATE_BUFS:
+               err = get_v4l2_create32(&karg.v2crt, up);
+               compatible_arg = 0;
+               break;
+
+       case VIDIOC_PREPARE_BUF:
        case VIDIOC_QUERYBUF:
        case VIDIOC_QBUF:
        case VIDIOC_DQBUF:
@@ -860,6 +914,10 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar
                err = put_v4l2_format32(&karg.v2f, up);
                break;
 
+       case VIDIOC_CREATE_BUFS:
+               err = put_v4l2_create32(&karg.v2crt, up);
+               break;
+
        case VIDIOC_QUERYBUF:
        case VIDIOC_QBUF:
        case VIDIOC_DQBUF:
@@ -959,6 +1017,8 @@ long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
        case VIDIOC_DQEVENT32:
        case VIDIOC_SUBSCRIBE_EVENT:
        case VIDIOC_UNSUBSCRIBE_EVENT:
+       case VIDIOC_CREATE_BUFS32:
+       case VIDIOC_PREPARE_BUF32:
                ret = do_video_ioctl(file, cmd, arg);
                break;
 
index fc8666a..5552f81 100644 (file)
@@ -210,6 +210,7 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
                "Disabled",
                "50 Hz",
                "60 Hz",
+               "Auto",
                NULL
        };
        static const char * const camera_exposure_auto[] = {
index e6a2c3b..9fc0ae8 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/types.h>
 #include <linux/ioctl.h>
 #include <linux/i2c.h>
+#include <linux/slab.h>
 #if defined(CONFIG_SPI)
 #include <linux/spi/spi.h>
 #endif
@@ -193,6 +194,13 @@ int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev,
 }
 EXPORT_SYMBOL_GPL(v4l2_device_register_subdev);
 
+static void v4l2_device_release_subdev_node(struct video_device *vdev)
+{
+       struct v4l2_subdev *sd = video_get_drvdata(vdev);
+       sd->devnode = NULL;
+       kfree(vdev);
+}
+
 int v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev)
 {
        struct video_device *vdev;
@@ -206,22 +214,40 @@ int v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev)
                if (!(sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE))
                        continue;
 
-               vdev = &sd->devnode;
+               vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
+               if (!vdev) {
+                       err = -ENOMEM;
+                       goto clean_up;
+               }
+
+               video_set_drvdata(vdev, sd);
                strlcpy(vdev->name, sd->name, sizeof(vdev->name));
                vdev->v4l2_dev = v4l2_dev;
                vdev->fops = &v4l2_subdev_fops;
-               vdev->release = video_device_release_empty;
+               vdev->release = v4l2_device_release_subdev_node;
                vdev->ctrl_handler = sd->ctrl_handler;
                err = __video_register_device(vdev, VFL_TYPE_SUBDEV, -1, 1,
                                              sd->owner);
-               if (err < 0)
-                       return err;
+               if (err < 0) {
+                       kfree(vdev);
+                       goto clean_up;
+               }
 #if defined(CONFIG_MEDIA_CONTROLLER)
                sd->entity.v4l.major = VIDEO_MAJOR;
                sd->entity.v4l.minor = vdev->minor;
 #endif
+               sd->devnode = vdev;
        }
        return 0;
+
+clean_up:
+       list_for_each_entry(sd, &v4l2_dev->subdevs, list) {
+               if (!sd->devnode)
+                       break;
+               video_unregister_device(sd->devnode);
+       }
+
+       return err;
 }
 EXPORT_SYMBOL_GPL(v4l2_device_register_subdev_nodes);
 
@@ -247,7 +273,7 @@ void v4l2_device_unregister_subdev(struct v4l2_subdev *sd)
        if (v4l2_dev->mdev)
                media_device_unregister_entity(&sd->entity);
 #endif
-       video_unregister_device(&sd->devnode);
+       video_unregister_device(sd->devnode);
        module_put(sd->owner);
 }
 EXPORT_SYMBOL_GPL(v4l2_device_unregister_subdev);
index 24fd433..e1da8fc 100644 (file)
@@ -273,6 +273,8 @@ static const char *v4l2_ioctls[] = {
        [_IOC_NR(VIDIOC_DQEVENT)]          = "VIDIOC_DQEVENT",
        [_IOC_NR(VIDIOC_SUBSCRIBE_EVENT)]  = "VIDIOC_SUBSCRIBE_EVENT",
        [_IOC_NR(VIDIOC_UNSUBSCRIBE_EVENT)] = "VIDIOC_UNSUBSCRIBE_EVENT",
+       [_IOC_NR(VIDIOC_CREATE_BUFS)]      = "VIDIOC_CREATE_BUFS",
+       [_IOC_NR(VIDIOC_PREPARE_BUF)]      = "VIDIOC_PREPARE_BUF",
 };
 #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
 
@@ -2104,6 +2106,40 @@ static long __video_do_ioctl(struct file *file,
                dbgarg(cmd, "type=0x%8.8x", sub->type);
                break;
        }
+       case VIDIOC_CREATE_BUFS:
+       {
+               struct v4l2_create_buffers *create = arg;
+
+               if (!ops->vidioc_create_bufs)
+                       break;
+               if (ret_prio) {
+                       ret = ret_prio;
+                       break;
+               }
+               ret = check_fmt(ops, create->format.type);
+               if (ret)
+                       break;
+
+               ret = ops->vidioc_create_bufs(file, fh, create);
+
+               dbgarg(cmd, "count=%d @ %d\n", create->count, create->index);
+               break;
+       }
+       case VIDIOC_PREPARE_BUF:
+       {
+               struct v4l2_buffer *b = arg;
+
+               if (!ops->vidioc_prepare_buf)
+                       break;
+               ret = check_fmt(ops, b->type);
+               if (ret)
+                       break;
+
+               ret = ops->vidioc_prepare_buf(file, fh, b);
+
+               dbgarg(cmd, "index=%d", b->index);
+               break;
+       }
        default:
                if (!ops->vidioc_default)
                        break;
index 3f5c7a3..979e544 100644 (file)
@@ -38,7 +38,8 @@ module_param(debug, int, 0644);
        (((q)->ops->op) ? ((q)->ops->op(args)) : 0)
 
 #define V4L2_BUFFER_STATE_FLAGS        (V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED | \
-                                V4L2_BUF_FLAG_DONE | V4L2_BUF_FLAG_ERROR)
+                                V4L2_BUF_FLAG_DONE | V4L2_BUF_FLAG_ERROR | \
+                                V4L2_BUF_FLAG_PREPARED)
 
 /**
  * __vb2_buf_mem_alloc() - allocate video memory for the given buffer
@@ -109,13 +110,22 @@ static void __vb2_buf_userptr_put(struct vb2_buffer *vb)
  * __setup_offsets() - setup unique offsets ("cookies") for every plane in
  * every buffer on the queue
  */
-static void __setup_offsets(struct vb2_queue *q)
+static void __setup_offsets(struct vb2_queue *q, unsigned int n)
 {
        unsigned int buffer, plane;
        struct vb2_buffer *vb;
-       unsigned long off = 0;
+       unsigned long off;
 
-       for (buffer = 0; buffer < q->num_buffers; ++buffer) {
+       if (q->num_buffers) {
+               struct v4l2_plane *p;
+               vb = q->bufs[q->num_buffers - 1];
+               p = &vb->v4l2_planes[vb->num_planes - 1];
+               off = PAGE_ALIGN(p->m.mem_offset + p->length);
+       } else {
+               off = 0;
+       }
+
+       for (buffer = q->num_buffers; buffer < q->num_buffers + n; ++buffer) {
                vb = q->bufs[buffer];
                if (!vb)
                        continue;
@@ -161,7 +171,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory,
                vb->state = VB2_BUF_STATE_DEQUEUED;
                vb->vb2_queue = q;
                vb->num_planes = num_planes;
-               vb->v4l2_buf.index = buffer;
+               vb->v4l2_buf.index = q->num_buffers + buffer;
                vb->v4l2_buf.type = q->type;
                vb->v4l2_buf.memory = memory;
 
@@ -189,15 +199,13 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory,
                        }
                }
 
-               q->bufs[buffer] = vb;
+               q->bufs[q->num_buffers + buffer] = vb;
        }
 
-       q->num_buffers = buffer;
-
-       __setup_offsets(q);
+       __setup_offsets(q, buffer);
 
        dprintk(1, "Allocated %d buffers, %d plane(s) each\n",
-                       q->num_buffers, num_planes);
+                       buffer, num_planes);
 
        return buffer;
 }
@@ -205,12 +213,13 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory,
 /**
  * __vb2_free_mem() - release all video buffer memory for a given queue
  */
-static void __vb2_free_mem(struct vb2_queue *q)
+static void __vb2_free_mem(struct vb2_queue *q, unsigned int buffers)
 {
        unsigned int buffer;
        struct vb2_buffer *vb;
 
-       for (buffer = 0; buffer < q->num_buffers; ++buffer) {
+       for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
+            ++buffer) {
                vb = q->bufs[buffer];
                if (!vb)
                        continue;
@@ -224,17 +233,18 @@ static void __vb2_free_mem(struct vb2_queue *q)
 }
 
 /**
- * __vb2_queue_free() - free the queue - video memory and related information
- * and return the queue to an uninitialized state. Might be called even if the
- * queue has already been freed.
+ * __vb2_queue_free() - free buffers at the end of the queue - video memory and
+ * related information, if no buffers are left return the queue to an
+ * uninitialized state. Might be called even if the queue has already been freed.
  */
-static void __vb2_queue_free(struct vb2_queue *q)
+static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
 {
        unsigned int buffer;
 
        /* Call driver-provided cleanup function for each buffer, if provided */
        if (q->ops->buf_cleanup) {
-               for (buffer = 0; buffer < q->num_buffers; ++buffer) {
+               for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
+                    ++buffer) {
                        if (NULL == q->bufs[buffer])
                                continue;
                        q->ops->buf_cleanup(q->bufs[buffer]);
@@ -242,23 +252,25 @@ static void __vb2_queue_free(struct vb2_queue *q)
        }
 
        /* Release video buffer memory */
-       __vb2_free_mem(q);
+       __vb2_free_mem(q, buffers);
 
        /* Free videobuf buffers */
-       for (buffer = 0; buffer < q->num_buffers; ++buffer) {
+       for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
+            ++buffer) {
                kfree(q->bufs[buffer]);
                q->bufs[buffer] = NULL;
        }
 
-       q->num_buffers = 0;
-       q->memory = 0;
+       q->num_buffers -= buffers;
+       if (!q->num_buffers)
+               q->memory = 0;
 }
 
 /**
  * __verify_planes_array() - verify that the planes array passed in struct
  * v4l2_buffer from userspace can be safely used
  */
-static int __verify_planes_array(struct vb2_buffer *vb, struct v4l2_buffer *b)
+static int __verify_planes_array(struct vb2_buffer *vb, const struct v4l2_buffer *b)
 {
        /* Is memory for copying plane information present? */
        if (NULL == b->m.planes) {
@@ -318,7 +330,7 @@ static bool __buffers_in_use(struct vb2_queue *q)
 static int __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
 {
        struct vb2_queue *q = vb->vb2_queue;
-       int ret = 0;
+       int ret;
 
        /* Copy back data such as timestamp, flags, input, etc. */
        memcpy(b, &vb->v4l2_buf, offsetof(struct v4l2_buffer, m));
@@ -365,6 +377,9 @@ static int __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
        case VB2_BUF_STATE_DONE:
                b->flags |= V4L2_BUF_FLAG_DONE;
                break;
+       case VB2_BUF_STATE_PREPARED:
+               b->flags |= V4L2_BUF_FLAG_PREPARED;
+               break;
        case VB2_BUF_STATE_DEQUEUED:
                /* nothing */
                break;
@@ -373,7 +388,7 @@ static int __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
        if (__buffer_in_use(q, vb))
                b->flags |= V4L2_BUF_FLAG_MAPPED;
 
-       return ret;
+       return 0;
 }
 
 /**
@@ -459,7 +474,7 @@ static int __verify_mmap_ops(struct vb2_queue *q)
  */
 int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
 {
-       unsigned int num_buffers, num_planes;
+       unsigned int num_buffers, allocated_buffers, num_planes = 0;
        int ret = 0;
 
        if (q->fileio) {
@@ -507,7 +522,7 @@ int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
                        return -EBUSY;
                }
 
-               __vb2_queue_free(q);
+               __vb2_queue_free(q, q->num_buffers);
 
                /*
                 * In case of REQBUFS(0) return immediately without calling
@@ -529,7 +544,7 @@ int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
         * Ask the driver how many buffers and planes per buffer it requires.
         * Driver also sets the size and allocator context for each plane.
         */
-       ret = call_qop(q, queue_setup, q, &num_buffers, &num_planes,
+       ret = call_qop(q, queue_setup, q, NULL, &num_buffers, &num_planes,
                       q->plane_sizes, q->alloc_ctx);
        if (ret)
                return ret;
@@ -541,44 +556,168 @@ int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
                return -ENOMEM;
        }
 
+       allocated_buffers = ret;
+
        /*
         * Check if driver can handle the allocated number of buffers.
         */
-       if (ret < num_buffers) {
-               unsigned int orig_num_buffers;
+       if (allocated_buffers < num_buffers) {
+               num_buffers = allocated_buffers;
 
-               orig_num_buffers = num_buffers = ret;
-               ret = call_qop(q, queue_setup, q, &num_buffers, &num_planes,
-                              q->plane_sizes, q->alloc_ctx);
-               if (ret)
-                       goto free_mem;
+               ret = call_qop(q, queue_setup, q, NULL, &num_buffers,
+                              &num_planes, q->plane_sizes, q->alloc_ctx);
 
-               if (orig_num_buffers < num_buffers) {
+               if (!ret && allocated_buffers < num_buffers)
                        ret = -ENOMEM;
-                       goto free_mem;
-               }
 
                /*
-                * Ok, driver accepted smaller number of buffers.
+                * Either the driver has accepted a smaller number of buffers,
+                * or .queue_setup() returned an error
                 */
-               ret = num_buffers;
+       }
+
+       q->num_buffers = allocated_buffers;
+
+       if (ret < 0) {
+               __vb2_queue_free(q, allocated_buffers);
+               return ret;
        }
 
        /*
         * Return the number of successfully allocated buffers
         * to the userspace.
         */
-       req->count = ret;
+       req->count = allocated_buffers;
 
        return 0;
-
-free_mem:
-       __vb2_queue_free(q);
-       return ret;
 }
 EXPORT_SYMBOL_GPL(vb2_reqbufs);
 
 /**
+ * vb2_create_bufs() - Allocate buffers and any required auxiliary structs
+ * @q:         videobuf2 queue
+ * @create:    creation parameters, passed from userspace to vidioc_create_bufs
+ *             handler in driver
+ *
+ * Should be called from vidioc_create_bufs ioctl handler of a driver.
+ * This function:
+ * 1) verifies parameter sanity
+ * 2) calls the .queue_setup() queue operation
+ * 3) performs any necessary memory allocations
+ *
+ * The return values from this function are intended to be directly returned
+ * from vidioc_create_bufs handler in driver.
+ */
+int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create)
+{
+       unsigned int num_planes = 0, num_buffers, allocated_buffers;
+       int ret = 0;
+
+       if (q->fileio) {
+               dprintk(1, "%s(): file io in progress\n", __func__);
+               return -EBUSY;
+       }
+
+       if (create->memory != V4L2_MEMORY_MMAP
+                       && create->memory != V4L2_MEMORY_USERPTR) {
+               dprintk(1, "%s(): unsupported memory type\n", __func__);
+               return -EINVAL;
+       }
+
+       if (create->format.type != q->type) {
+               dprintk(1, "%s(): requested type is incorrect\n", __func__);
+               return -EINVAL;
+       }
+
+       /*
+        * Make sure all the required memory ops for given memory type
+        * are available.
+        */
+       if (create->memory == V4L2_MEMORY_MMAP && __verify_mmap_ops(q)) {
+               dprintk(1, "%s(): MMAP for current setup unsupported\n", __func__);
+               return -EINVAL;
+       }
+
+       if (create->memory == V4L2_MEMORY_USERPTR && __verify_userptr_ops(q)) {
+               dprintk(1, "%s(): USERPTR for current setup unsupported\n", __func__);
+               return -EINVAL;
+       }
+
+       if (q->num_buffers == VIDEO_MAX_FRAME) {
+               dprintk(1, "%s(): maximum number of buffers already allocated\n",
+                       __func__);
+               return -ENOBUFS;
+       }
+
+       create->index = q->num_buffers;
+
+       if (!q->num_buffers) {
+               memset(q->plane_sizes, 0, sizeof(q->plane_sizes));
+               memset(q->alloc_ctx, 0, sizeof(q->alloc_ctx));
+               q->memory = create->memory;
+       }
+
+       num_buffers = min(create->count, VIDEO_MAX_FRAME - q->num_buffers);
+
+       /*
+        * Ask the driver, whether the requested number of buffers, planes per
+        * buffer and their sizes are acceptable
+        */
+       ret = call_qop(q, queue_setup, q, &create->format, &num_buffers,
+                      &num_planes, q->plane_sizes, q->alloc_ctx);
+       if (ret)
+               return ret;
+
+       /* Finally, allocate buffers and video memory */
+       ret = __vb2_queue_alloc(q, create->memory, num_buffers,
+                               num_planes);
+       if (ret < 0) {
+               dprintk(1, "Memory allocation failed with error: %d\n", ret);
+               return ret;
+       }
+
+       allocated_buffers = ret;
+
+       /*
+        * Check if driver can handle the so far allocated number of buffers.
+        */
+       if (ret < num_buffers) {
+               num_buffers = ret;
+
+               /*
+                * q->num_buffers contains the total number of buffers, that the
+                * queue driver has set up
+                */
+               ret = call_qop(q, queue_setup, q, &create->format, &num_buffers,
+                              &num_planes, q->plane_sizes, q->alloc_ctx);
+
+               if (!ret && allocated_buffers < num_buffers)
+                       ret = -ENOMEM;
+
+               /*
+                * Either the driver has accepted a smaller number of buffers,
+                * or .queue_setup() returned an error
+                */
+       }
+
+       q->num_buffers += allocated_buffers;
+
+       if (ret < 0) {
+               __vb2_queue_free(q, allocated_buffers);
+               return ret;
+       }
+
+       /*
+        * Return the number of successfully allocated buffers
+        * to the userspace.
+        */
+       create->count = allocated_buffers;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(vb2_create_bufs);
+
+/**
  * vb2_plane_vaddr() - Return a kernel virtual address of a given plane
  * @vb:                vb2_buffer to which the plane in question belongs to
  * @plane_no:  plane number for which the address is to be returned
@@ -662,7 +801,7 @@ EXPORT_SYMBOL_GPL(vb2_buffer_done);
  * __fill_vb2_buffer() - fill a vb2_buffer with information provided in
  * a v4l2_buffer by the userspace
  */
-static int __fill_vb2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b,
+static int __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b,
                                struct v4l2_plane *v4l2_planes)
 {
        unsigned int plane;
@@ -726,7 +865,7 @@ static int __fill_vb2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b,
 /**
  * __qbuf_userptr() - handle qbuf of a USERPTR buffer
  */
-static int __qbuf_userptr(struct vb2_buffer *vb, struct v4l2_buffer *b)
+static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b)
 {
        struct v4l2_plane planes[VIDEO_MAX_PLANES];
        struct vb2_queue *q = vb->vb2_queue;
@@ -815,7 +954,7 @@ err:
 /**
  * __qbuf_mmap() - handle qbuf of an MMAP buffer
  */
-static int __qbuf_mmap(struct vb2_buffer *vb, struct v4l2_buffer *b)
+static int __qbuf_mmap(struct vb2_buffer *vb, const struct v4l2_buffer *b)
 {
        return __fill_vb2_buffer(vb, b, vb->v4l2_planes);
 }
@@ -832,6 +971,95 @@ static void __enqueue_in_driver(struct vb2_buffer *vb)
        q->ops->buf_queue(vb);
 }
 
+static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b)
+{
+       struct vb2_queue *q = vb->vb2_queue;
+       int ret;
+
+       switch (q->memory) {
+       case V4L2_MEMORY_MMAP:
+               ret = __qbuf_mmap(vb, b);
+               break;
+       case V4L2_MEMORY_USERPTR:
+               ret = __qbuf_userptr(vb, b);
+               break;
+       default:
+               WARN(1, "Invalid queue type\n");
+               ret = -EINVAL;
+       }
+
+       if (!ret)
+               ret = call_qop(q, buf_prepare, vb);
+       if (ret)
+               dprintk(1, "qbuf: buffer preparation failed: %d\n", ret);
+       else
+               vb->state = VB2_BUF_STATE_PREPARED;
+
+       return ret;
+}
+
+/**
+ * vb2_prepare_buf() - Pass ownership of a buffer from userspace to the kernel
+ * @q:         videobuf2 queue
+ * @b:         buffer structure passed from userspace to vidioc_prepare_buf
+ *             handler in driver
+ *
+ * Should be called from vidioc_prepare_buf ioctl handler of a driver.
+ * This function:
+ * 1) verifies the passed buffer,
+ * 2) calls buf_prepare callback in the driver (if provided), in which
+ *    driver-specific buffer initialization can be performed,
+ *
+ * The return values from this function are intended to be directly returned
+ * from vidioc_prepare_buf handler in driver.
+ */
+int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b)
+{
+       struct vb2_buffer *vb;
+       int ret;
+
+       if (q->fileio) {
+               dprintk(1, "%s(): file io in progress\n", __func__);
+               return -EBUSY;
+       }
+
+       if (b->type != q->type) {
+               dprintk(1, "%s(): invalid buffer type\n", __func__);
+               return -EINVAL;
+       }
+
+       if (b->index >= q->num_buffers) {
+               dprintk(1, "%s(): buffer index out of range\n", __func__);
+               return -EINVAL;
+       }
+
+       vb = q->bufs[b->index];
+       if (NULL == vb) {
+               /* Should never happen */
+               dprintk(1, "%s(): buffer is NULL\n", __func__);
+               return -EINVAL;
+       }
+
+       if (b->memory != q->memory) {
+               dprintk(1, "%s(): invalid memory type\n", __func__);
+               return -EINVAL;
+       }
+
+       if (vb->state != VB2_BUF_STATE_DEQUEUED) {
+               dprintk(1, "%s(): invalid buffer state %d\n", __func__, vb->state);
+               return -EINVAL;
+       }
+
+       ret = __buf_prepare(vb, b);
+       if (ret < 0)
+               return ret;
+
+       __fill_v4l2_buffer(vb, b);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(vb2_prepare_buf);
+
 /**
  * vb2_qbuf() - Queue a buffer from userspace
  * @q:         videobuf2 queue
@@ -841,8 +1069,8 @@ static void __enqueue_in_driver(struct vb2_buffer *vb)
  * Should be called from vidioc_qbuf ioctl handler of a driver.
  * This function:
  * 1) verifies the passed buffer,
- * 2) calls buf_prepare callback in the driver (if provided), in which
- *    driver-specific buffer initialization can be performed,
+ * 2) if necessary, calls buf_prepare callback in the driver (if provided), in
+ *    which driver-specific buffer initialization can be performed,
  * 3) if streaming is on, queues the buffer in driver by the means of buf_queue
  *    callback for processing.
  *
@@ -852,7 +1080,7 @@ static void __enqueue_in_driver(struct vb2_buffer *vb)
 int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
 {
        struct vb2_buffer *vb;
-       int ret = 0;
+       int ret;
 
        if (q->fileio) {
                dprintk(1, "qbuf: file io in progress\n");
@@ -881,29 +1109,18 @@ int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
                return -EINVAL;
        }
 
-       if (vb->state != VB2_BUF_STATE_DEQUEUED) {
+       switch (vb->state) {
+       case VB2_BUF_STATE_DEQUEUED:
+               ret = __buf_prepare(vb, b);
+               if (ret)
+                       return ret;
+       case VB2_BUF_STATE_PREPARED:
+               break;
+       default:
                dprintk(1, "qbuf: buffer already in use\n");
                return -EINVAL;
        }
 
-       if (q->memory == V4L2_MEMORY_MMAP)
-               ret = __qbuf_mmap(vb, b);
-       else if (q->memory == V4L2_MEMORY_USERPTR)
-               ret = __qbuf_userptr(vb, b);
-       else {
-               WARN(1, "Invalid queue type\n");
-               return -EINVAL;
-       }
-
-       if (ret)
-               return ret;
-
-       ret = call_qop(q, buf_prepare, vb);
-       if (ret) {
-               dprintk(1, "qbuf: buffer preparation failed\n");
-               return ret;
-       }
-
        /*
         * Add to the queued buffers list, a buffer will stay on it until
         * dequeued in dqbuf.
@@ -918,6 +1135,9 @@ int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
        if (q->streaming)
                __enqueue_in_driver(vb);
 
+       /* Fill buffer information for the userspace */
+       __fill_v4l2_buffer(vb, b);
+
        dprintk(1, "qbuf of buffer %d succeeded\n", vb->v4l2_buf.index);
        return 0;
 }
@@ -1347,6 +1567,37 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
 }
 EXPORT_SYMBOL_GPL(vb2_mmap);
 
+#ifndef CONFIG_MMU
+unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
+                                   unsigned long addr,
+                                   unsigned long len,
+                                   unsigned long pgoff,
+                                   unsigned long flags)
+{
+       unsigned long off = pgoff << PAGE_SHIFT;
+       struct vb2_buffer *vb;
+       unsigned int buffer, plane;
+       int ret;
+
+       if (q->memory != V4L2_MEMORY_MMAP) {
+               dprintk(1, "Queue is not currently set up for mmap\n");
+               return -EINVAL;
+       }
+
+       /*
+        * Find the plane corresponding to the offset passed by userspace.
+        */
+       ret = __find_plane_by_offset(q, off, &buffer, &plane);
+       if (ret)
+               return ret;
+
+       vb = q->bufs[buffer];
+
+       return (unsigned long)vb2_plane_vaddr(vb, plane);
+}
+EXPORT_SYMBOL_GPL(vb2_get_unmapped_area);
+#endif
+
 static int __vb2_init_fileio(struct vb2_queue *q, int read);
 static int __vb2_cleanup_fileio(struct vb2_queue *q);
 
@@ -1464,7 +1715,7 @@ void vb2_queue_release(struct vb2_queue *q)
 {
        __vb2_cleanup_fileio(q);
        __vb2_queue_cancel(q);
-       __vb2_queue_free(q);
+       __vb2_queue_free(q, q->num_buffers);
 }
 EXPORT_SYMBOL_GPL(vb2_queue_release);
 
index 7cf94c0..7d754fb 100644 (file)
@@ -650,9 +650,9 @@ static void vivi_stop_generating(struct vivi_dev *dev)
 /* ------------------------------------------------------------------
        Videobuf operations
    ------------------------------------------------------------------*/
-static int queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
-                               unsigned int *nplanes, unsigned int sizes[],
-                               void *alloc_ctxs[])
+static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+                               unsigned int *nbuffers, unsigned int *nplanes,
+                               unsigned int sizes[], void *alloc_ctxs[])
 {
        struct vivi_dev *dev = vb2_get_drv_priv(vq);
        unsigned long size;
index d2856b6..720f993 100644 (file)
@@ -913,9 +913,9 @@ request_done:
 }
 
 static void s3cmci_dma_setup(struct s3cmci_host *host,
-                            enum s3c2410_dmasrc source)
+                            enum dma_data_direction source)
 {
-       static enum s3c2410_dmasrc last_source = -1;
+       static enum dma_data_direction last_source = -1;
        static int setup_ok;
 
        if (last_source == source)
@@ -1087,7 +1087,7 @@ static int s3cmci_prepare_dma(struct s3cmci_host *host, struct mmc_data *data)
 
        BUG_ON((data->flags & BOTH_DIR) == BOTH_DIR);
 
-       s3cmci_dma_setup(host, rw ? S3C2410_DMASRC_MEM : S3C2410_DMASRC_HW);
+       s3cmci_dma_setup(host, rw ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
        s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH);
 
        dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
index ddb33cf..7bf1e20 100644 (file)
@@ -1674,6 +1674,9 @@ static int __devinit ps3_gelic_driver_probe(struct ps3_system_bus_device *dev)
        int result;
 
        pr_debug("%s: called\n", __func__);
+
+       udbg_shutdown_ps3gelic();
+
        result = ps3_open_hv_device(dev);
 
        if (result) {
index d3fadfb..a93df6a 100644 (file)
@@ -359,6 +359,12 @@ static inline void *port_priv(struct gelic_port *port)
        return port->priv;
 }
 
+#ifdef CONFIG_PPC_EARLY_DEBUG_PS3GELIC
+extern void udbg_shutdown_ps3gelic(void);
+#else
+static inline void udbg_shutdown_ps3gelic(void) {}
+#endif
+
 extern int gelic_card_set_irq_mask(struct gelic_card *card, u64 mask);
 /* shared netdev ops */
 extern void gelic_card_up(struct gelic_card *card);
index aeec35b..fd85fa2 100644 (file)
@@ -681,9 +681,14 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
        if (p != NULL && l > 0)
                strlcpy(data, p, min((int)l, COMMAND_LINE_SIZE));
 
+       /*
+        * CONFIG_CMDLINE is meant to be a default in case nothing else
+        * managed to set the command line, unless CONFIG_CMDLINE_FORCE
+        * is set in which case we override whatever was found earlier.
+        */
 #ifdef CONFIG_CMDLINE
 #ifndef CONFIG_CMDLINE_FORCE
-       if (p == NULL || l == 0 || (l == 1 && (*p) == 0))
+       if (!((char *)data)[0])
 #endif
                strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
 #endif /* CONFIG_CMDLINE */
index ed5a6d3..cbd5d70 100644 (file)
@@ -310,18 +310,21 @@ static const struct of_dev_auxdata *of_dev_lookup(const struct of_dev_auxdata *l
                                 struct device_node *np)
 {
        struct resource res;
-       if (lookup) {
-               for(; lookup->name != NULL; lookup++) {
-                       if (!of_device_is_compatible(np, lookup->compatible))
-                               continue;
-                       if (of_address_to_resource(np, 0, &res))
-                               continue;
-                       if (res.start != lookup->phys_addr)
-                               continue;
-                       pr_debug("%s: devname=%s\n", np->full_name, lookup->name);
-                       return lookup;
-               }
+
+       if (!lookup)
+               return NULL;
+
+       for(; lookup->name != NULL; lookup++) {
+               if (!of_device_is_compatible(np, lookup->compatible))
+                       continue;
+               if (of_address_to_resource(np, 0, &res))
+                       continue;
+               if (res.start != lookup->phys_addr)
+                       continue;
+               pr_debug("%s: devname=%s\n", np->full_name, lookup->name);
+               return lookup;
        }
+
        return NULL;
 }
 
@@ -329,8 +332,9 @@ static const struct of_dev_auxdata *of_dev_lookup(const struct of_dev_auxdata *l
  * of_platform_bus_create() - Create a device for a node and its children.
  * @bus: device node of the bus to instantiate
  * @matches: match table for bus nodes
- * disallow recursive creation of child buses
+ * @lookup: auxdata table for matching id and platform_data with device nodes
  * @parent: parent for new device, or NULL for top level.
+ * @strict: require compatible property
  *
  * Creates a platform_device for the provided device_node, and optionally
  * recursively create devices for all the child nodes.
index 2c54054..a87e272 100644 (file)
@@ -231,6 +231,7 @@ void pxa2xx_configure_sockets(struct device *dev)
 
        __raw_writel(mecr, MECR);
 }
+EXPORT_SYMBOL(pxa2xx_configure_sockets);
 
 static const char *skt_names[] = {
        "PCMCIA socket 0",
index 4f09506..6e7dcfd 100644 (file)
@@ -12,9 +12,8 @@
 
 #include <linux/module.h>
 
-#include <asm/system.h>
 #include <asm/mach-types.h>
-#include <mach/system.h>
+#include <mach/hardware.h>
 
 int cmx255_pcmcia_init(void);
 int cmx270_pcmcia_init(void);
index 9b43ae9..a5a55da 100644 (file)
@@ -27,7 +27,7 @@
 
 static int dcssblk_open(struct block_device *bdev, fmode_t mode);
 static int dcssblk_release(struct gendisk *disk, fmode_t mode);
-static int dcssblk_make_request(struct request_queue *q, struct bio *bio);
+static void dcssblk_make_request(struct request_queue *q, struct bio *bio);
 static int dcssblk_direct_access(struct block_device *bdev, sector_t secnum,
                                 void **kaddr, unsigned long *pfn);
 
@@ -814,7 +814,7 @@ out:
        return rc;
 }
 
-static int
+static void
 dcssblk_make_request(struct request_queue *q, struct bio *bio)
 {
        struct dcssblk_dev_info *dev_info;
@@ -871,10 +871,9 @@ dcssblk_make_request(struct request_queue *q, struct bio *bio)
                bytes_done += bvec->bv_len;
        }
        bio_endio(bio, 0);
-       return 0;
+       return;
 fail:
        bio_io_error(bio);
-       return 0;
 }
 
 static int
index 1f6a4d8..98f3e4a 100644 (file)
@@ -181,7 +181,7 @@ static unsigned long xpram_highest_page_index(void)
 /*
  * Block device make request function.
  */
-static int xpram_make_request(struct request_queue *q, struct bio *bio)
+static void xpram_make_request(struct request_queue *q, struct bio *bio)
 {
        xpram_device_t *xdev = bio->bi_bdev->bd_disk->private_data;
        struct bio_vec *bvec;
@@ -221,10 +221,9 @@ static int xpram_make_request(struct request_queue *q, struct bio *bio)
        }
        set_bit(BIO_UPTODATE, &bio->bi_flags);
        bio_endio(bio, 0);
-       return 0;
+       return;
 fail:
        bio_io_error(bio);
-       return 0;
 }
 
 static int xpram_getgeo(struct block_device *bdev, struct hd_geometry *geo)
index 63de1c7..049ea90 100644 (file)
@@ -62,7 +62,7 @@
 #include "bnx2fc_constants.h"
 
 #define BNX2FC_NAME            "bnx2fc"
-#define BNX2FC_VERSION         "1.0.8"
+#define BNX2FC_VERSION         "1.0.9"
 
 #define PFX                    "bnx2fc: "
 
 #define REC_RETRY_COUNT                        1
 #define BNX2FC_NUM_ERR_BITS            63
 
+#define BNX2FC_RELOGIN_WAIT_TIME       200
+#define BNX2FC_RELOGIN_WAIT_CNT                10
+
 /* bnx2fc driver uses only one instance of fcoe_percpu_s */
 extern struct fcoe_percpu_s bnx2fc_global;
 
index fd382fe..ce0ce3e 100644 (file)
@@ -268,17 +268,6 @@ void bnx2fc_srr_compl(struct bnx2fc_els_cb_arg *cb_arg)
 
        orig_io_req = cb_arg->aborted_io_req;
        srr_req = cb_arg->io_req;
-       if (test_bit(BNX2FC_FLAG_IO_COMPL, &orig_io_req->req_flags)) {
-               BNX2FC_IO_DBG(srr_req, "srr_compl: xid - 0x%x completed",
-                       orig_io_req->xid);
-               goto srr_compl_done;
-       }
-       if (test_bit(BNX2FC_FLAG_ISSUE_ABTS, &orig_io_req->req_flags)) {
-               BNX2FC_IO_DBG(srr_req, "rec abts in prog "
-                      "orig_io - 0x%x\n",
-                       orig_io_req->xid);
-               goto srr_compl_done;
-       }
        if (test_and_clear_bit(BNX2FC_FLAG_ELS_TIMEOUT, &srr_req->req_flags)) {
                /* SRR timedout */
                BNX2FC_IO_DBG(srr_req, "srr timed out, abort "
@@ -290,6 +279,12 @@ void bnx2fc_srr_compl(struct bnx2fc_els_cb_arg *cb_arg)
                                "failed. issue cleanup\n");
                        bnx2fc_initiate_cleanup(srr_req);
                }
+               if (test_bit(BNX2FC_FLAG_IO_COMPL, &orig_io_req->req_flags) ||
+                   test_bit(BNX2FC_FLAG_ISSUE_ABTS, &orig_io_req->req_flags)) {
+                       BNX2FC_IO_DBG(srr_req, "srr_compl:xid 0x%x flags = %lx",
+                                     orig_io_req->xid, orig_io_req->req_flags);
+                       goto srr_compl_done;
+               }
                orig_io_req->srr_retry++;
                if (orig_io_req->srr_retry <= SRR_RETRY_COUNT) {
                        struct bnx2fc_rport *tgt = orig_io_req->tgt;
@@ -311,6 +306,12 @@ void bnx2fc_srr_compl(struct bnx2fc_els_cb_arg *cb_arg)
                }
                goto srr_compl_done;
        }
+       if (test_bit(BNX2FC_FLAG_IO_COMPL, &orig_io_req->req_flags) ||
+           test_bit(BNX2FC_FLAG_ISSUE_ABTS, &orig_io_req->req_flags)) {
+               BNX2FC_IO_DBG(srr_req, "srr_compl:xid - 0x%x flags = %lx",
+                             orig_io_req->xid, orig_io_req->req_flags);
+               goto srr_compl_done;
+       }
        mp_req = &(srr_req->mp_req);
        fc_hdr = &(mp_req->resp_fc_hdr);
        resp_len = mp_req->resp_len;
index 85bcc4b..8c6156a 100644 (file)
@@ -22,7 +22,7 @@ DEFINE_PER_CPU(struct bnx2fc_percpu_s, bnx2fc_percpu);
 
 #define DRV_MODULE_NAME                "bnx2fc"
 #define DRV_MODULE_VERSION     BNX2FC_VERSION
-#define DRV_MODULE_RELDATE     "Oct 02, 2011"
+#define DRV_MODULE_RELDATE     "Oct 21, 2011"
 
 
 static char version[] __devinitdata =
index 0c64d18..84a78af 100644 (file)
@@ -1103,7 +1103,10 @@ int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd)
        struct fc_rport_libfc_priv *rp = rport->dd_data;
        struct bnx2fc_cmd *io_req;
        struct fc_lport *lport;
+       struct fc_rport_priv *rdata;
        struct bnx2fc_rport *tgt;
+       int logo_issued;
+       int wait_cnt = 0;
        int rc = FAILED;
 
 
@@ -1192,8 +1195,40 @@ int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd)
        } else {
                printk(KERN_ERR PFX "eh_abort: io_req (xid = 0x%x) "
                                "already in abts processing\n", io_req->xid);
+               if (cancel_delayed_work(&io_req->timeout_work))
+                       kref_put(&io_req->refcount,
+                                bnx2fc_cmd_release); /* drop timer hold */
+               bnx2fc_initiate_cleanup(io_req);
+
+               spin_unlock_bh(&tgt->tgt_lock);
+
+               wait_for_completion(&io_req->tm_done);
+
+               spin_lock_bh(&tgt->tgt_lock);
+               io_req->wait_for_comp = 0;
+               rdata = io_req->tgt->rdata;
+               logo_issued = test_and_set_bit(BNX2FC_FLAG_EXPL_LOGO,
+                                              &tgt->flags);
                kref_put(&io_req->refcount, bnx2fc_cmd_release);
                spin_unlock_bh(&tgt->tgt_lock);
+
+               if (!logo_issued) {
+                       BNX2FC_IO_DBG(io_req, "Expl logo - tgt flags = 0x%lx\n",
+                                     tgt->flags);
+                       mutex_lock(&lport->disc.disc_mutex);
+                       lport->tt.rport_logoff(rdata);
+                       mutex_unlock(&lport->disc.disc_mutex);
+                       do {
+                               msleep(BNX2FC_RELOGIN_WAIT_TIME);
+                               /*
+                                * If session not recovered, let SCSI-ml
+                                * escalate error recovery.
+                                */
+                               if (wait_cnt++ > BNX2FC_RELOGIN_WAIT_CNT)
+                                       return FAILED;
+                       } while (!test_bit(BNX2FC_FLAG_SESSION_READY,
+                                          &tgt->flags));
+               }
                return SUCCESS;
        }
        if (rc == FAILED) {
@@ -1275,6 +1310,8 @@ void bnx2fc_process_cleanup_compl(struct bnx2fc_cmd *io_req,
                   io_req->refcount.refcount.counter, io_req->cmd_type);
        bnx2fc_scsi_done(io_req, DID_ERROR);
        kref_put(&io_req->refcount, bnx2fc_cmd_release);
+       if (io_req->wait_for_comp)
+               complete(&io_req->tm_done);
 }
 
 void bnx2fc_process_abts_compl(struct bnx2fc_cmd *io_req,
index 7c05fd9..339ea23 100644 (file)
@@ -441,7 +441,15 @@ int scsi_dh_activate(struct request_queue *q, activate_complete fn, void *data)
 
        spin_lock_irqsave(q->queue_lock, flags);
        sdev = q->queuedata;
-       if (sdev && sdev->scsi_dh_data)
+       if (!sdev) {
+               spin_unlock_irqrestore(q->queue_lock, flags);
+               err = SCSI_DH_NOSYS;
+               if (fn)
+                       fn(data, err);
+               return err;
+       }
+
+       if (sdev->scsi_dh_data)
                scsi_dh = sdev->scsi_dh_data->scsi_dh;
        dev = get_device(&sdev->sdev_gendev);
        if (!scsi_dh || !dev ||
index 627f4b5..fe4df2d 100644 (file)
@@ -507,7 +507,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h)
        int len, k, off, valid_states = 0;
        unsigned char *ucp;
        unsigned err;
-       unsigned long expiry, interval = 1;
+       unsigned long expiry, interval = 1000;
 
        expiry = round_jiffies_up(jiffies + ALUA_FAILOVER_TIMEOUT);
  retry:
@@ -734,6 +734,7 @@ static int alua_bus_attach(struct scsi_device *sdev)
        spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
        sdev->scsi_dh_data = scsi_dh_data;
        spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
+       sdev_printk(KERN_NOTICE, sdev, "%s: Attached\n", ALUA_DH_NAME);
 
        return 0;
 
index 61384ee..cefbe44 100644 (file)
@@ -2347,14 +2347,11 @@ static void fcoe_flogi_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg)
                goto done;
 
        mac = fr_cb(fp)->granted_mac;
-       if (is_zero_ether_addr(mac)) {
-               /* pre-FIP */
-               if (fcoe_ctlr_recv_flogi(fip, lport, fp)) {
-                       fc_frame_free(fp);
-                       return;
-               }
-       }
-       fcoe_update_src_mac(lport, mac);
+       /* pre-FIP */
+       if (is_zero_ether_addr(mac))
+               fcoe_ctlr_recv_flogi(fip, lport, fp);
+       if (!is_zero_ether_addr(mac))
+               fcoe_update_src_mac(lport, mac);
 done:
        fc_lport_flogi_resp(seq, fp, lport);
 }
index 4f7a582..351dc0b 100644 (file)
@@ -286,6 +286,7 @@ static void scsi_host_dev_release(struct device *dev)
 {
        struct Scsi_Host *shost = dev_to_shost(dev);
        struct device *parent = dev->parent;
+       struct request_queue *q;
 
        scsi_proc_hostdir_rm(shost->hostt);
 
@@ -293,9 +294,11 @@ static void scsi_host_dev_release(struct device *dev)
                kthread_stop(shost->ehandler);
        if (shost->work_q)
                destroy_workqueue(shost->work_q);
-       if (shost->uspace_req_q) {
-               kfree(shost->uspace_req_q->queuedata);
-               scsi_free_queue(shost->uspace_req_q);
+       q = shost->uspace_req_q;
+       if (q) {
+               kfree(q->queuedata);
+               q->queuedata = NULL;
+               scsi_free_queue(q);
        }
 
        scsi_destroy_command_freelist(shost);
index 9825ecf..e76107b 100644 (file)
@@ -48,6 +48,7 @@
 #include <linux/bitmap.h>
 #include <linux/atomic.h>
 #include <linux/kthread.h>
+#include <linux/jiffies.h>
 #include "hpsa_cmd.h"
 #include "hpsa.h"
 
@@ -127,6 +128,10 @@ static struct board_type products[] = {
 
 static int number_of_controllers;
 
+static struct list_head hpsa_ctlr_list = LIST_HEAD_INIT(hpsa_ctlr_list);
+static spinlock_t lockup_detector_lock;
+static struct task_struct *hpsa_lockup_detector;
+
 static irqreturn_t do_hpsa_intr_intx(int irq, void *dev_id);
 static irqreturn_t do_hpsa_intr_msi(int irq, void *dev_id);
 static int hpsa_ioctl(struct scsi_device *dev, int cmd, void *arg);
@@ -484,6 +489,7 @@ static struct scsi_host_template hpsa_driver_template = {
 #endif
        .sdev_attrs = hpsa_sdev_attrs,
        .shost_attrs = hpsa_shost_attrs,
+       .max_sectors = 8192,
 };
 
 
@@ -566,16 +572,16 @@ static int hpsa_find_target_lun(struct ctlr_info *h,
         * assumes h->devlock is held
         */
        int i, found = 0;
-       DECLARE_BITMAP(lun_taken, HPSA_MAX_SCSI_DEVS_PER_HBA);
+       DECLARE_BITMAP(lun_taken, HPSA_MAX_DEVICES);
 
-       memset(&lun_taken[0], 0, HPSA_MAX_SCSI_DEVS_PER_HBA >> 3);
+       memset(&lun_taken[0], 0, HPSA_MAX_DEVICES >> 3);
 
        for (i = 0; i < h->ndevices; i++) {
                if (h->dev[i]->bus == bus && h->dev[i]->target != -1)
                        set_bit(h->dev[i]->target, lun_taken);
        }
 
-       for (i = 0; i < HPSA_MAX_SCSI_DEVS_PER_HBA; i++) {
+       for (i = 0; i < HPSA_MAX_DEVICES; i++) {
                if (!test_bit(i, lun_taken)) {
                        /* *bus = 1; */
                        *target = i;
@@ -598,7 +604,7 @@ static int hpsa_scsi_add_entry(struct ctlr_info *h, int hostno,
        unsigned char addr1[8], addr2[8];
        struct hpsa_scsi_dev_t *sd;
 
-       if (n >= HPSA_MAX_SCSI_DEVS_PER_HBA) {
+       if (n >= HPSA_MAX_DEVICES) {
                dev_err(&h->pdev->dev, "too many devices, some will be "
                        "inaccessible.\n");
                return -1;
@@ -673,7 +679,7 @@ static void hpsa_scsi_replace_entry(struct ctlr_info *h, int hostno,
        struct hpsa_scsi_dev_t *removed[], int *nremoved)
 {
        /* assumes h->devlock is held */
-       BUG_ON(entry < 0 || entry >= HPSA_MAX_SCSI_DEVS_PER_HBA);
+       BUG_ON(entry < 0 || entry >= HPSA_MAX_DEVICES);
        removed[*nremoved] = h->dev[entry];
        (*nremoved)++;
 
@@ -702,7 +708,7 @@ static void hpsa_scsi_remove_entry(struct ctlr_info *h, int hostno, int entry,
        int i;
        struct hpsa_scsi_dev_t *sd;
 
-       BUG_ON(entry < 0 || entry >= HPSA_MAX_SCSI_DEVS_PER_HBA);
+       BUG_ON(entry < 0 || entry >= HPSA_MAX_DEVICES);
 
        sd = h->dev[entry];
        removed[*nremoved] = h->dev[entry];
@@ -814,10 +820,8 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno,
        int nadded, nremoved;
        struct Scsi_Host *sh = NULL;
 
-       added = kzalloc(sizeof(*added) * HPSA_MAX_SCSI_DEVS_PER_HBA,
-               GFP_KERNEL);
-       removed = kzalloc(sizeof(*removed) * HPSA_MAX_SCSI_DEVS_PER_HBA,
-               GFP_KERNEL);
+       added = kzalloc(sizeof(*added) * HPSA_MAX_DEVICES, GFP_KERNEL);
+       removed = kzalloc(sizeof(*removed) * HPSA_MAX_DEVICES, GFP_KERNEL);
 
        if (!added || !removed) {
                dev_warn(&h->pdev->dev, "out of memory in "
@@ -1338,6 +1342,22 @@ static inline void hpsa_scsi_do_simple_cmd_core(struct ctlr_info *h,
        wait_for_completion(&wait);
 }
 
+static void hpsa_scsi_do_simple_cmd_core_if_no_lockup(struct ctlr_info *h,
+       struct CommandList *c)
+{
+       unsigned long flags;
+
+       /* If controller lockup detected, fake a hardware error. */
+       spin_lock_irqsave(&h->lock, flags);
+       if (unlikely(h->lockup_detected)) {
+               spin_unlock_irqrestore(&h->lock, flags);
+               c->err_info->CommandStatus = CMD_HARDWARE_ERR;
+       } else {
+               spin_unlock_irqrestore(&h->lock, flags);
+               hpsa_scsi_do_simple_cmd_core(h, c);
+       }
+}
+
 static void hpsa_scsi_do_simple_cmd_with_retry(struct ctlr_info *h,
        struct CommandList *c, int data_direction)
 {
@@ -1735,7 +1755,6 @@ static int add_msa2xxx_enclosure_device(struct ctlr_info *h,
        if (is_scsi_rev_5(h))
                return 0; /* p1210m doesn't need to do this. */
 
-#define MAX_MSA2XXX_ENCLOSURES 32
        if (*nmsa2xxx_enclosures >= MAX_MSA2XXX_ENCLOSURES) {
                dev_warn(&h->pdev->dev, "Maximum number of MSA2XXX "
                        "enclosures exceeded.  Check your hardware "
@@ -1846,8 +1865,7 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
        int raid_ctlr_position;
        DECLARE_BITMAP(lunzerobits, HPSA_MAX_TARGETS_PER_CTLR);
 
-       currentsd = kzalloc(sizeof(*currentsd) * HPSA_MAX_SCSI_DEVS_PER_HBA,
-               GFP_KERNEL);
+       currentsd = kzalloc(sizeof(*currentsd) * HPSA_MAX_DEVICES, GFP_KERNEL);
        physdev_list = kzalloc(reportlunsize, GFP_KERNEL);
        logdev_list = kzalloc(reportlunsize, GFP_KERNEL);
        tmpdevice = kzalloc(sizeof(*tmpdevice), GFP_KERNEL);
@@ -1870,6 +1888,13 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
 
        /* Allocate the per device structures */
        for (i = 0; i < ndevs_to_allocate; i++) {
+               if (i >= HPSA_MAX_DEVICES) {
+                       dev_warn(&h->pdev->dev, "maximum devices (%d) exceeded."
+                               "  %d devices ignored.\n", HPSA_MAX_DEVICES,
+                               ndevs_to_allocate - HPSA_MAX_DEVICES);
+                       break;
+               }
+
                currentsd[i] = kzalloc(sizeof(*currentsd[i]), GFP_KERNEL);
                if (!currentsd[i]) {
                        dev_warn(&h->pdev->dev, "out of memory at %s:%d\n",
@@ -1956,7 +1981,7 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
                default:
                        break;
                }
-               if (ncurrent >= HPSA_MAX_SCSI_DEVS_PER_HBA)
+               if (ncurrent >= HPSA_MAX_DEVICES)
                        break;
        }
        adjust_hpsa_scsi_table(h, hostno, currentsd, ncurrent);
@@ -2048,8 +2073,14 @@ static int hpsa_scsi_queue_command_lck(struct scsi_cmnd *cmd,
        }
        memcpy(scsi3addr, dev->scsi3addr, sizeof(scsi3addr));
 
-       /* Need a lock as this is being allocated from the pool */
        spin_lock_irqsave(&h->lock, flags);
+       if (unlikely(h->lockup_detected)) {
+               spin_unlock_irqrestore(&h->lock, flags);
+               cmd->result = DID_ERROR << 16;
+               done(cmd);
+               return 0;
+       }
+       /* Need a lock as this is being allocated from the pool */
        c = cmd_alloc(h);
        spin_unlock_irqrestore(&h->lock, flags);
        if (c == NULL) {                        /* trouble... */
@@ -2601,7 +2632,7 @@ static int hpsa_passthru_ioctl(struct ctlr_info *h, void __user *argp)
                c->SG[0].Len = iocommand.buf_size;
                c->SG[0].Ext = 0; /* we are not chaining*/
        }
-       hpsa_scsi_do_simple_cmd_core(h, c);
+       hpsa_scsi_do_simple_cmd_core_if_no_lockup(h, c);
        if (iocommand.buf_size > 0)
                hpsa_pci_unmap(h->pdev, c, 1, PCI_DMA_BIDIRECTIONAL);
        check_ioctl_unit_attention(h, c);
@@ -2724,7 +2755,7 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp)
                        c->SG[i].Ext = 0;
                }
        }
-       hpsa_scsi_do_simple_cmd_core(h, c);
+       hpsa_scsi_do_simple_cmd_core_if_no_lockup(h, c);
        if (sg_used)
                hpsa_pci_unmap(h->pdev, c, sg_used, PCI_DMA_BIDIRECTIONAL);
        check_ioctl_unit_attention(h, c);
@@ -2872,6 +2903,8 @@ static void fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
                        c->Request.Timeout = 0;
                        c->Request.CDB[0] = BMIC_WRITE;
                        c->Request.CDB[6] = BMIC_CACHE_FLUSH;
+                       c->Request.CDB[7] = (size >> 8) & 0xFF;
+                       c->Request.CDB[8] = size & 0xFF;
                        break;
                case TEST_UNIT_READY:
                        c->Request.CDBLen = 6;
@@ -3091,6 +3124,7 @@ static irqreturn_t hpsa_intx_discard_completions(int irq, void *dev_id)
        if (interrupt_not_for_us(h))
                return IRQ_NONE;
        spin_lock_irqsave(&h->lock, flags);
+       h->last_intr_timestamp = get_jiffies_64();
        while (interrupt_pending(h)) {
                raw_tag = get_next_completion(h);
                while (raw_tag != FIFO_EMPTY)
@@ -3110,6 +3144,7 @@ static irqreturn_t hpsa_msix_discard_completions(int irq, void *dev_id)
                return IRQ_NONE;
 
        spin_lock_irqsave(&h->lock, flags);
+       h->last_intr_timestamp = get_jiffies_64();
        raw_tag = get_next_completion(h);
        while (raw_tag != FIFO_EMPTY)
                raw_tag = next_command(h);
@@ -3126,6 +3161,7 @@ static irqreturn_t do_hpsa_intr_intx(int irq, void *dev_id)
        if (interrupt_not_for_us(h))
                return IRQ_NONE;
        spin_lock_irqsave(&h->lock, flags);
+       h->last_intr_timestamp = get_jiffies_64();
        while (interrupt_pending(h)) {
                raw_tag = get_next_completion(h);
                while (raw_tag != FIFO_EMPTY) {
@@ -3146,6 +3182,7 @@ static irqreturn_t do_hpsa_intr_msi(int irq, void *dev_id)
        u32 raw_tag;
 
        spin_lock_irqsave(&h->lock, flags);
+       h->last_intr_timestamp = get_jiffies_64();
        raw_tag = get_next_completion(h);
        while (raw_tag != FIFO_EMPTY) {
                if (hpsa_tag_contains_index(raw_tag))
@@ -3300,6 +3337,13 @@ static int hpsa_controller_hard_reset(struct pci_dev *pdev,
                pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
                pmcsr |= PCI_D0;
                pci_write_config_word(pdev, pos + PCI_PM_CTRL, pmcsr);
+
+               /*
+                * The P600 requires a small delay when changing states.
+                * Otherwise we may think the board did not reset and we bail.
+                * This for kdump only and is particular to the P600.
+                */
+               msleep(500);
        }
        return 0;
 }
@@ -4083,6 +4127,149 @@ static void hpsa_undo_allocations_after_kdump_soft_reset(struct ctlr_info *h)
        kfree(h);
 }
 
+static void remove_ctlr_from_lockup_detector_list(struct ctlr_info *h)
+{
+       assert_spin_locked(&lockup_detector_lock);
+       if (!hpsa_lockup_detector)
+               return;
+       if (h->lockup_detected)
+               return; /* already stopped the lockup detector */
+       list_del(&h->lockup_list);
+}
+
+/* Called when controller lockup detected. */
+static void fail_all_cmds_on_list(struct ctlr_info *h, struct list_head *list)
+{
+       struct CommandList *c = NULL;
+
+       assert_spin_locked(&h->lock);
+       /* Mark all outstanding commands as failed and complete them. */
+       while (!list_empty(list)) {
+               c = list_entry(list->next, struct CommandList, list);
+               c->err_info->CommandStatus = CMD_HARDWARE_ERR;
+               finish_cmd(c, c->Header.Tag.lower);
+       }
+}
+
+static void controller_lockup_detected(struct ctlr_info *h)
+{
+       unsigned long flags;
+
+       assert_spin_locked(&lockup_detector_lock);
+       remove_ctlr_from_lockup_detector_list(h);
+       h->access.set_intr_mask(h, HPSA_INTR_OFF);
+       spin_lock_irqsave(&h->lock, flags);
+       h->lockup_detected = readl(h->vaddr + SA5_SCRATCHPAD_OFFSET);
+       spin_unlock_irqrestore(&h->lock, flags);
+       dev_warn(&h->pdev->dev, "Controller lockup detected: 0x%08x\n",
+                       h->lockup_detected);
+       pci_disable_device(h->pdev);
+       spin_lock_irqsave(&h->lock, flags);
+       fail_all_cmds_on_list(h, &h->cmpQ);
+       fail_all_cmds_on_list(h, &h->reqQ);
+       spin_unlock_irqrestore(&h->lock, flags);
+}
+
+#define HEARTBEAT_SAMPLE_INTERVAL (10 * HZ)
+#define HEARTBEAT_CHECK_MINIMUM_INTERVAL (HEARTBEAT_SAMPLE_INTERVAL / 2)
+
+static void detect_controller_lockup(struct ctlr_info *h)
+{
+       u64 now;
+       u32 heartbeat;
+       unsigned long flags;
+
+       assert_spin_locked(&lockup_detector_lock);
+       now = get_jiffies_64();
+       /* If we've received an interrupt recently, we're ok. */
+       if (time_after64(h->last_intr_timestamp +
+                               (HEARTBEAT_CHECK_MINIMUM_INTERVAL), now))
+               return;
+
+       /*
+        * If we've already checked the heartbeat recently, we're ok.
+        * This could happen if someone sends us a signal. We
+        * otherwise don't care about signals in this thread.
+        */
+       if (time_after64(h->last_heartbeat_timestamp +
+                               (HEARTBEAT_CHECK_MINIMUM_INTERVAL), now))
+               return;
+
+       /* If heartbeat has not changed since we last looked, we're not ok. */
+       spin_lock_irqsave(&h->lock, flags);
+       heartbeat = readl(&h->cfgtable->HeartBeat);
+       spin_unlock_irqrestore(&h->lock, flags);
+       if (h->last_heartbeat == heartbeat) {
+               controller_lockup_detected(h);
+               return;
+       }
+
+       /* We're ok. */
+       h->last_heartbeat = heartbeat;
+       h->last_heartbeat_timestamp = now;
+}
+
+static int detect_controller_lockup_thread(void *notused)
+{
+       struct ctlr_info *h;
+       unsigned long flags;
+
+       while (1) {
+               struct list_head *this, *tmp;
+
+               schedule_timeout_interruptible(HEARTBEAT_SAMPLE_INTERVAL);
+               if (kthread_should_stop())
+                       break;
+               spin_lock_irqsave(&lockup_detector_lock, flags);
+               list_for_each_safe(this, tmp, &hpsa_ctlr_list) {
+                       h = list_entry(this, struct ctlr_info, lockup_list);
+                       detect_controller_lockup(h);
+               }
+               spin_unlock_irqrestore(&lockup_detector_lock, flags);
+       }
+       return 0;
+}
+
+static void add_ctlr_to_lockup_detector_list(struct ctlr_info *h)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&lockup_detector_lock, flags);
+       list_add_tail(&h->lockup_list, &hpsa_ctlr_list);
+       spin_unlock_irqrestore(&lockup_detector_lock, flags);
+}
+
+static void start_controller_lockup_detector(struct ctlr_info *h)
+{
+       /* Start the lockup detector thread if not already started */
+       if (!hpsa_lockup_detector) {
+               spin_lock_init(&lockup_detector_lock);
+               hpsa_lockup_detector =
+                       kthread_run(detect_controller_lockup_thread,
+                                               NULL, "hpsa");
+       }
+       if (!hpsa_lockup_detector) {
+               dev_warn(&h->pdev->dev,
+                       "Could not start lockup detector thread\n");
+               return;
+       }
+       add_ctlr_to_lockup_detector_list(h);
+}
+
+static void stop_controller_lockup_detector(struct ctlr_info *h)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&lockup_detector_lock, flags);
+       remove_ctlr_from_lockup_detector_list(h);
+       /* If the list of ctlr's to monitor is empty, stop the thread */
+       if (list_empty(&hpsa_ctlr_list)) {
+               kthread_stop(hpsa_lockup_detector);
+               hpsa_lockup_detector = NULL;
+       }
+       spin_unlock_irqrestore(&lockup_detector_lock, flags);
+}
+
 static int __devinit hpsa_init_one(struct pci_dev *pdev,
                                    const struct pci_device_id *ent)
 {
@@ -4120,7 +4307,6 @@ reinit_after_soft_reset:
                return -ENOMEM;
 
        h->pdev = pdev;
-       h->busy_initializing = 1;
        h->intr_mode = hpsa_simple_mode ? SIMPLE_MODE_INT : PERF_MODE_INT;
        INIT_LIST_HEAD(&h->cmpQ);
        INIT_LIST_HEAD(&h->reqQ);
@@ -4229,7 +4415,7 @@ reinit_after_soft_reset:
 
        hpsa_hba_inquiry(h);
        hpsa_register_scsi(h);  /* hook ourselves into SCSI subsystem */
-       h->busy_initializing = 0;
+       start_controller_lockup_detector(h);
        return 1;
 
 clean4:
@@ -4238,7 +4424,6 @@ clean4:
        free_irq(h->intr[h->intr_mode], h);
 clean2:
 clean1:
-       h->busy_initializing = 0;
        kfree(h);
        return rc;
 }
@@ -4293,10 +4478,11 @@ static void __devexit hpsa_remove_one(struct pci_dev *pdev)
        struct ctlr_info *h;
 
        if (pci_get_drvdata(pdev) == NULL) {
-               dev_err(&pdev->dev, "unable to remove device \n");
+               dev_err(&pdev->dev, "unable to remove device\n");
                return;
        }
        h = pci_get_drvdata(pdev);
+       stop_controller_lockup_detector(h);
        hpsa_unregister_scsi(h);        /* unhook from SCSI subsystem */
        hpsa_shutdown(pdev);
        iounmap(h->vaddr);
index 7f53cea..91edafb 100644 (file)
@@ -95,8 +95,6 @@ struct ctlr_info {
        unsigned long           *cmd_pool_bits;
        int                     nr_allocs;
        int                     nr_frees;
-       int                     busy_initializing;
-       int                     busy_scanning;
        int                     scan_finished;
        spinlock_t              scan_lock;
        wait_queue_head_t       scan_wait_queue;
@@ -104,8 +102,7 @@ struct ctlr_info {
        struct Scsi_Host *scsi_host;
        spinlock_t devlock; /* to protect hba[ctlr]->dev[];  */
        int ndevices; /* number of used elements in .dev[] array. */
-#define HPSA_MAX_SCSI_DEVS_PER_HBA 256
-       struct hpsa_scsi_dev_t *dev[HPSA_MAX_SCSI_DEVS_PER_HBA];
+       struct hpsa_scsi_dev_t *dev[HPSA_MAX_DEVICES];
        /*
         * Performant mode tables.
         */
@@ -124,6 +121,11 @@ struct ctlr_info {
        unsigned char reply_pool_wraparound;
        u32 *blockFetchTable;
        unsigned char *hba_inquiry_data;
+       u64 last_intr_timestamp;
+       u32 last_heartbeat;
+       u64 last_heartbeat_timestamp;
+       u32 lockup_detected;
+       struct list_head lockup_list;
 };
 #define HPSA_ABORT_MSG 0
 #define HPSA_DEVICE_RESET_MSG 1
index 55d741b..3fd4715 100644 (file)
@@ -123,8 +123,11 @@ union u64bit {
 
 /* FIXME this is a per controller value (barf!) */
 #define HPSA_MAX_TARGETS_PER_CTLR 16
-#define HPSA_MAX_LUN 256
+#define HPSA_MAX_LUN 1024
 #define HPSA_MAX_PHYS_LUN 1024
+#define MAX_MSA2XXX_ENCLOSURES 32
+#define HPSA_MAX_DEVICES (HPSA_MAX_PHYS_LUN + HPSA_MAX_LUN + \
+       MAX_MSA2XXX_ENCLOSURES + 1) /* + 1 is for the controller itself */
 
 /* SCSI-3 Commands */
 #pragma pack(1)
index 73e24b4..fd860d9 100644 (file)
@@ -9123,6 +9123,8 @@ static struct pci_device_id ipr_pci_table[] __devinitdata = {
        { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROC_FPGA_E2,
                PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B2, 0, 0, 0 },
        { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROC_FPGA_E2,
+               PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57C3, 0, 0, 0 },
+       { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROC_FPGA_E2,
                PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57C4, 0, 0, 0 },
        { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROC_ASIC_E2,
                PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B4, 0, 0, 0 },
index 6d257e0..ac84736 100644 (file)
@@ -82,6 +82,7 @@
 
 #define IPR_SUBS_DEV_ID_57B4    0x033B
 #define IPR_SUBS_DEV_ID_57B2    0x035F
+#define IPR_SUBS_DEV_ID_57C3    0x0353
 #define IPR_SUBS_DEV_ID_57C4    0x0354
 #define IPR_SUBS_DEV_ID_57C6    0x0357
 #define IPR_SUBS_DEV_ID_57CC    0x035C
index f07f30f..e7fe9c4 100644 (file)
@@ -1350,7 +1350,7 @@ static void isci_user_parameters_get(struct sci_user_parameters *u)
        u->stp_max_occupancy_timeout = stp_max_occ_to;
        u->ssp_max_occupancy_timeout = ssp_max_occ_to;
        u->no_outbound_task_timeout = no_outbound_task_to;
-       u->max_number_concurrent_device_spin_up = max_concurr_spinup;
+       u->max_concurr_spinup = max_concurr_spinup;
 }
 
 static void sci_controller_initial_state_enter(struct sci_base_state_machine *sm)
@@ -1661,7 +1661,7 @@ static void sci_controller_set_default_config_parameters(struct isci_host *ihost
        ihost->oem_parameters.controller.mode_type = SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE;
 
        /* Default to APC mode. */
-       ihost->oem_parameters.controller.max_concurrent_dev_spin_up = 1;
+       ihost->oem_parameters.controller.max_concurr_spin_up = 1;
 
        /* Default to no SSC operation. */
        ihost->oem_parameters.controller.do_enable_ssc = false;
@@ -1787,7 +1787,8 @@ int sci_oem_parameters_validate(struct sci_oem_params *oem)
        } else
                return -EINVAL;
 
-       if (oem->controller.max_concurrent_dev_spin_up > MAX_CONCURRENT_DEVICE_SPIN_UP_COUNT)
+       if (oem->controller.max_concurr_spin_up > MAX_CONCURRENT_DEVICE_SPIN_UP_COUNT ||
+           oem->controller.max_concurr_spin_up < 1)
                return -EINVAL;
 
        return 0;
@@ -1810,6 +1811,16 @@ static enum sci_status sci_oem_parameters_set(struct isci_host *ihost)
        return SCI_FAILURE_INVALID_STATE;
 }
 
+static u8 max_spin_up(struct isci_host *ihost)
+{
+       if (ihost->user_parameters.max_concurr_spinup)
+               return min_t(u8, ihost->user_parameters.max_concurr_spinup,
+                            MAX_CONCURRENT_DEVICE_SPIN_UP_COUNT);
+       else
+               return min_t(u8, ihost->oem_parameters.controller.max_concurr_spin_up,
+                            MAX_CONCURRENT_DEVICE_SPIN_UP_COUNT);
+}
+
 static void power_control_timeout(unsigned long data)
 {
        struct sci_timer *tmr = (struct sci_timer *)data;
@@ -1839,8 +1850,7 @@ static void power_control_timeout(unsigned long data)
                if (iphy == NULL)
                        continue;
 
-               if (ihost->power_control.phys_granted_power >=
-                   ihost->oem_parameters.controller.max_concurrent_dev_spin_up)
+               if (ihost->power_control.phys_granted_power >= max_spin_up(ihost))
                        break;
 
                ihost->power_control.requesters[i] = NULL;
@@ -1865,8 +1875,7 @@ void sci_controller_power_control_queue_insert(struct isci_host *ihost,
 {
        BUG_ON(iphy == NULL);
 
-       if (ihost->power_control.phys_granted_power <
-           ihost->oem_parameters.controller.max_concurrent_dev_spin_up) {
+       if (ihost->power_control.phys_granted_power < max_spin_up(ihost)) {
                ihost->power_control.phys_granted_power++;
                sci_phy_consume_power_handler(iphy);
 
index 43fe840..a97edab 100644 (file)
@@ -118,7 +118,7 @@ unsigned char phy_gen = 3;
 module_param(phy_gen, byte, 0);
 MODULE_PARM_DESC(phy_gen, "PHY generation (1: 1.5Gbps 2: 3.0Gbps 3: 6.0Gbps)");
 
-unsigned char max_concurr_spinup = 1;
+unsigned char max_concurr_spinup;
 module_param(max_concurr_spinup, byte, 0);
 MODULE_PARM_DESC(max_concurr_spinup, "Max concurrent device spinup");
 
index 8e59c88..ac7f277 100644 (file)
@@ -145,48 +145,15 @@ static void sci_port_bcn_enable(struct isci_port *iport)
        }
 }
 
-/* called under sci_lock to stabilize phy:port associations */
-void isci_port_bcn_enable(struct isci_host *ihost, struct isci_port *iport)
-{
-       int i;
-
-       clear_bit(IPORT_BCN_BLOCKED, &iport->flags);
-       wake_up(&ihost->eventq);
-
-       if (!test_and_clear_bit(IPORT_BCN_PENDING, &iport->flags))
-               return;
-
-       for (i = 0; i < ARRAY_SIZE(iport->phy_table); i++) {
-               struct isci_phy *iphy = iport->phy_table[i];
-
-               if (!iphy)
-                       continue;
-
-               ihost->sas_ha.notify_port_event(&iphy->sas_phy,
-                                               PORTE_BROADCAST_RCVD);
-               break;
-       }
-}
-
 static void isci_port_bc_change_received(struct isci_host *ihost,
                                         struct isci_port *iport,
                                         struct isci_phy *iphy)
 {
-       if (iport && test_bit(IPORT_BCN_BLOCKED, &iport->flags)) {
-               dev_dbg(&ihost->pdev->dev,
-                       "%s: disabled BCN; isci_phy = %p, sas_phy = %p\n",
-                       __func__, iphy, &iphy->sas_phy);
-               set_bit(IPORT_BCN_PENDING, &iport->flags);
-               atomic_inc(&iport->event);
-               wake_up(&ihost->eventq);
-       } else {
-               dev_dbg(&ihost->pdev->dev,
-                       "%s: isci_phy = %p, sas_phy = %p\n",
-                       __func__, iphy, &iphy->sas_phy);
+       dev_dbg(&ihost->pdev->dev,
+               "%s: isci_phy = %p, sas_phy = %p\n",
+               __func__, iphy, &iphy->sas_phy);
 
-               ihost->sas_ha.notify_port_event(&iphy->sas_phy,
-                                               PORTE_BROADCAST_RCVD);
-       }
+       ihost->sas_ha.notify_port_event(&iphy->sas_phy, PORTE_BROADCAST_RCVD);
        sci_port_bcn_enable(iport);
 }
 
@@ -278,9 +245,6 @@ static void isci_port_link_down(struct isci_host *isci_host,
                /* check to see if this is the last phy on this port. */
                if (isci_phy->sas_phy.port &&
                    isci_phy->sas_phy.port->num_phys == 1) {
-                       atomic_inc(&isci_port->event);
-                       isci_port_bcn_enable(isci_host, isci_port);
-
                        /* change the state for all devices on this port.  The
                         * next task sent to this device will be returned as
                         * SAS_TASK_UNDELIVERED, and the scsi mid layer will
@@ -350,6 +314,34 @@ static void isci_port_stop_complete(struct isci_host *ihost,
        dev_dbg(&ihost->pdev->dev, "Port stop complete\n");
 }
 
+
+static bool is_port_ready_state(enum sci_port_states state)
+{
+       switch (state) {
+       case SCI_PORT_READY:
+       case SCI_PORT_SUB_WAITING:
+       case SCI_PORT_SUB_OPERATIONAL:
+       case SCI_PORT_SUB_CONFIGURING:
+               return true;
+       default:
+               return false;
+       }
+}
+
+/* flag dummy rnc hanling when exiting a ready state */
+static void port_state_machine_change(struct isci_port *iport,
+                                     enum sci_port_states state)
+{
+       struct sci_base_state_machine *sm = &iport->sm;
+       enum sci_port_states old_state = sm->current_state_id;
+
+       if (is_port_ready_state(old_state) && !is_port_ready_state(state))
+               iport->ready_exit = true;
+
+       sci_change_state(sm, state);
+       iport->ready_exit = false;
+}
+
 /**
  * isci_port_hard_reset_complete() - This function is called by the sci core
  *    when the hard reset complete notification has been received.
@@ -368,6 +360,26 @@ static void isci_port_hard_reset_complete(struct isci_port *isci_port,
        /* Save the status of the hard reset from the port. */
        isci_port->hard_reset_status = completion_status;
 
+       if (completion_status != SCI_SUCCESS) {
+
+               /* The reset failed.  The port state is now SCI_PORT_FAILED. */
+               if (isci_port->active_phy_mask == 0) {
+
+                       /* Generate the link down now to the host, since it
+                        * was intercepted by the hard reset state machine when
+                        * it really happened.
+                        */
+                       isci_port_link_down(isci_port->isci_host,
+                                           &isci_port->isci_host->phys[
+                                                  isci_port->last_active_phy],
+                                           isci_port);
+               }
+               /* Advance the port state so that link state changes will be
+               * noticed.
+               */
+               port_state_machine_change(isci_port, SCI_PORT_SUB_WAITING);
+
+       }
        complete_all(&isci_port->hard_reset_complete);
 }
 
@@ -657,6 +669,8 @@ void sci_port_deactivate_phy(struct isci_port *iport, struct isci_phy *iphy,
        struct isci_host *ihost = iport->owning_controller;
 
        iport->active_phy_mask &= ~(1 << iphy->phy_index);
+       if (!iport->active_phy_mask)
+               iport->last_active_phy = iphy->phy_index;
 
        iphy->max_negotiated_speed = SAS_LINK_RATE_UNKNOWN;
 
@@ -683,33 +697,6 @@ static void sci_port_invalid_link_up(struct isci_port *iport, struct isci_phy *i
        }
 }
 
-static bool is_port_ready_state(enum sci_port_states state)
-{
-       switch (state) {
-       case SCI_PORT_READY:
-       case SCI_PORT_SUB_WAITING:
-       case SCI_PORT_SUB_OPERATIONAL:
-       case SCI_PORT_SUB_CONFIGURING:
-               return true;
-       default:
-               return false;
-       }
-}
-
-/* flag dummy rnc hanling when exiting a ready state */
-static void port_state_machine_change(struct isci_port *iport,
-                                     enum sci_port_states state)
-{
-       struct sci_base_state_machine *sm = &iport->sm;
-       enum sci_port_states old_state = sm->current_state_id;
-
-       if (is_port_ready_state(old_state) && !is_port_ready_state(state))
-               iport->ready_exit = true;
-
-       sci_change_state(sm, state);
-       iport->ready_exit = false;
-}
-
 /**
  * sci_port_general_link_up_handler - phy can be assigned to port?
  * @sci_port: sci_port object for which has a phy that has gone link up.
@@ -1622,7 +1609,8 @@ void sci_port_construct(struct isci_port *iport, u8 index,
        iport->logical_port_index  = SCIC_SDS_DUMMY_PORT;
        iport->physical_port_index = index;
        iport->active_phy_mask     = 0;
-       iport->ready_exit             = false;
+       iport->last_active_phy     = 0;
+       iport->ready_exit          = false;
 
        iport->owning_controller = ihost;
 
@@ -1648,7 +1636,6 @@ void isci_port_init(struct isci_port *iport, struct isci_host *ihost, int index)
        init_completion(&iport->start_complete);
        iport->isci_host = ihost;
        isci_port_change_state(iport, isci_freed);
-       atomic_set(&iport->event, 0);
 }
 
 /**
@@ -1676,7 +1663,7 @@ int isci_port_perform_hard_reset(struct isci_host *ihost, struct isci_port *ipor
 {
        unsigned long flags;
        enum sci_status status;
-       int idx, ret = TMF_RESP_FUNC_COMPLETE;
+       int ret = TMF_RESP_FUNC_COMPLETE;
 
        dev_dbg(&ihost->pdev->dev, "%s: iport = %p\n",
                __func__, iport);
@@ -1697,8 +1684,13 @@ int isci_port_perform_hard_reset(struct isci_host *ihost, struct isci_port *ipor
                        "%s: iport = %p; hard reset completion\n",
                        __func__, iport);
 
-               if (iport->hard_reset_status != SCI_SUCCESS)
+               if (iport->hard_reset_status != SCI_SUCCESS) {
                        ret = TMF_RESP_FUNC_FAILED;
+
+                       dev_err(&ihost->pdev->dev,
+                               "%s: iport = %p; hard reset failed (0x%x)\n",
+                               __func__, iport, iport->hard_reset_status);
+               }
        } else {
                ret = TMF_RESP_FUNC_FAILED;
 
@@ -1718,18 +1710,6 @@ int isci_port_perform_hard_reset(struct isci_host *ihost, struct isci_port *ipor
                        "%s: iport = %p; hard reset failed "
                        "(0x%x) - driving explicit link fail for all phys\n",
                        __func__, iport, iport->hard_reset_status);
-
-               /* Down all phys in the port. */
-               spin_lock_irqsave(&ihost->scic_lock, flags);
-               for (idx = 0; idx < SCI_MAX_PHYS; ++idx) {
-                       struct isci_phy *iphy = iport->phy_table[idx];
-
-                       if (!iphy)
-                               continue;
-                       sci_phy_stop(iphy);
-                       sci_phy_start(iphy);
-               }
-               spin_unlock_irqrestore(&ihost->scic_lock, flags);
        }
        return ret;
 }
index b50ecd4..cb5ffbc 100644 (file)
@@ -77,7 +77,6 @@ enum isci_status {
 
 /**
  * struct isci_port - isci direct attached sas port object
- * @event: counts bcns and port stop events (for bcn filtering)
  * @ready_exit: several states constitute 'ready'. When exiting ready we
  *              need to take extra port-teardown actions that are
  *              skipped when exiting to another 'ready' state.
@@ -92,10 +91,6 @@ enum isci_status {
  */
 struct isci_port {
        enum isci_status status;
-       #define IPORT_BCN_BLOCKED 0
-       #define IPORT_BCN_PENDING 1
-       unsigned long flags;
-       atomic_t event;
        struct isci_host *isci_host;
        struct asd_sas_port sas_port;
        struct list_head remote_dev_list;
@@ -109,6 +104,7 @@ struct isci_port {
        u8 logical_port_index;
        u8 physical_port_index;
        u8 active_phy_mask;
+       u8 last_active_phy;
        u16 reserved_rni;
        u16 reserved_tag;
        u32 started_request_count;
index dc007e6..2c75248 100644 (file)
@@ -112,7 +112,7 @@ struct sci_user_parameters {
         * This field specifies the maximum number of direct attached devices
         * that can have power supplied to them simultaneously.
         */
-       u8 max_number_concurrent_device_spin_up;
+       u8 max_concurr_spinup;
 
        /**
         * This field specifies the number of seconds to allow a phy to consume
@@ -219,7 +219,7 @@ struct sci_bios_oem_param_block_hdr {
 struct sci_oem_params {
        struct {
                uint8_t mode_type;
-               uint8_t max_concurrent_dev_spin_up;
+               uint8_t max_concurr_spin_up;
                uint8_t do_enable_ssc;
                uint8_t reserved;
        } controller;
index fbf9ce2..b207cd3 100644 (file)
@@ -1438,88 +1438,3 @@ int isci_remote_device_found(struct domain_device *domain_dev)
 
        return status == SCI_SUCCESS ? 0 : -ENODEV;
 }
-/**
- * isci_device_is_reset_pending() - This function will check if there is any
- *    pending reset condition on the device.
- * @request: This parameter is the isci_device object.
- *
- * true if there is a reset pending for the device.
- */
-bool isci_device_is_reset_pending(
-       struct isci_host *isci_host,
-       struct isci_remote_device *isci_device)
-{
-       struct isci_request *isci_request;
-       struct isci_request *tmp_req;
-       bool reset_is_pending = false;
-       unsigned long flags;
-
-       dev_dbg(&isci_host->pdev->dev,
-               "%s: isci_device = %p\n", __func__, isci_device);
-
-       spin_lock_irqsave(&isci_host->scic_lock, flags);
-
-       /* Check for reset on all pending requests. */
-       list_for_each_entry_safe(isci_request, tmp_req,
-                                &isci_device->reqs_in_process, dev_node) {
-               dev_dbg(&isci_host->pdev->dev,
-                       "%s: isci_device = %p request = %p\n",
-                       __func__, isci_device, isci_request);
-
-               if (isci_request->ttype == io_task) {
-                       struct sas_task *task = isci_request_access_task(
-                               isci_request);
-
-                       spin_lock(&task->task_state_lock);
-                       if (task->task_state_flags & SAS_TASK_NEED_DEV_RESET)
-                               reset_is_pending = true;
-                       spin_unlock(&task->task_state_lock);
-               }
-       }
-
-       spin_unlock_irqrestore(&isci_host->scic_lock, flags);
-
-       dev_dbg(&isci_host->pdev->dev,
-               "%s: isci_device = %p reset_is_pending = %d\n",
-               __func__, isci_device, reset_is_pending);
-
-       return reset_is_pending;
-}
-
-/**
- * isci_device_clear_reset_pending() - This function will clear if any pending
- *    reset condition flags on the device.
- * @request: This parameter is the isci_device object.
- *
- * true if there is a reset pending for the device.
- */
-void isci_device_clear_reset_pending(struct isci_host *ihost, struct isci_remote_device *idev)
-{
-       struct isci_request *isci_request;
-       struct isci_request *tmp_req;
-       unsigned long flags = 0;
-
-       dev_dbg(&ihost->pdev->dev, "%s: idev=%p, ihost=%p\n",
-                __func__, idev, ihost);
-
-       spin_lock_irqsave(&ihost->scic_lock, flags);
-
-       /* Clear reset pending on all pending requests. */
-       list_for_each_entry_safe(isci_request, tmp_req,
-                                &idev->reqs_in_process, dev_node) {
-               dev_dbg(&ihost->pdev->dev, "%s: idev = %p request = %p\n",
-                        __func__, idev, isci_request);
-
-               if (isci_request->ttype == io_task) {
-
-                       unsigned long flags2;
-                       struct sas_task *task = isci_request_access_task(
-                               isci_request);
-
-                       spin_lock_irqsave(&task->task_state_lock, flags2);
-                       task->task_state_flags &= ~SAS_TASK_NEED_DEV_RESET;
-                       spin_unlock_irqrestore(&task->task_state_lock, flags2);
-               }
-       }
-       spin_unlock_irqrestore(&ihost->scic_lock, flags);
-}
index e1747ea..483ee50 100644 (file)
@@ -132,10 +132,7 @@ void isci_remote_device_nuke_requests(struct isci_host *ihost,
                                      struct isci_remote_device *idev);
 void isci_remote_device_gone(struct domain_device *domain_dev);
 int isci_remote_device_found(struct domain_device *domain_dev);
-bool isci_device_is_reset_pending(struct isci_host *ihost,
-                                 struct isci_remote_device *idev);
-void isci_device_clear_reset_pending(struct isci_host *ihost,
-                                    struct isci_remote_device *idev);
+
 /**
  * sci_remote_device_stop() - This method will stop both transmission and
  *    reception of link activity for the supplied remote device.  This method
index 565a9f0..192cb48 100644 (file)
@@ -191,7 +191,7 @@ static void sci_task_request_build_ssp_task_iu(struct isci_request *ireq)
 
        task_iu->task_func = isci_tmf->tmf_code;
        task_iu->task_tag =
-               (ireq->ttype == tmf_task) ?
+               (test_bit(IREQ_TMF, &ireq->flags)) ?
                isci_tmf->io_tag :
                SCI_CONTROLLER_INVALID_IO_TAG;
 }
@@ -516,7 +516,7 @@ sci_io_request_construct_sata(struct isci_request *ireq,
        struct domain_device *dev = ireq->target_device->domain_dev;
 
        /* check for management protocols */
-       if (ireq->ttype == tmf_task) {
+       if (test_bit(IREQ_TMF, &ireq->flags)) {
                struct isci_tmf *tmf = isci_request_access_tmf(ireq);
 
                if (tmf->tmf_code == isci_tmf_sata_srst_high ||
@@ -632,7 +632,7 @@ enum sci_status sci_task_request_construct_sata(struct isci_request *ireq)
        enum sci_status status = SCI_SUCCESS;
 
        /* check for management protocols */
-       if (ireq->ttype == tmf_task) {
+       if (test_bit(IREQ_TMF, &ireq->flags)) {
                struct isci_tmf *tmf = isci_request_access_tmf(ireq);
 
                if (tmf->tmf_code == isci_tmf_sata_srst_high ||
@@ -2630,14 +2630,8 @@ static void isci_task_save_for_upper_layer_completion(
        switch (task_notification_selection) {
 
        case isci_perform_normal_io_completion:
-
                /* Normal notification (task_done) */
-               dev_dbg(&host->pdev->dev,
-                       "%s: Normal - task = %p, response=%d (%d), status=%d (%d)\n",
-                       __func__,
-                       task,
-                       task->task_status.resp, response,
-                       task->task_status.stat, status);
+
                /* Add to the completed list. */
                list_add(&request->completed_node,
                         &host->requests_to_complete);
@@ -2650,13 +2644,6 @@ static void isci_task_save_for_upper_layer_completion(
                /* No notification to libsas because this request is
                 * already in the abort path.
                 */
-               dev_dbg(&host->pdev->dev,
-                        "%s: Aborted - task = %p, response=%d (%d), status=%d (%d)\n",
-                        __func__,
-                        task,
-                        task->task_status.resp, response,
-                        task->task_status.stat, status);
-
                /* Wake up whatever process was waiting for this
                 * request to complete.
                 */
@@ -2673,30 +2660,22 @@ static void isci_task_save_for_upper_layer_completion(
 
        case isci_perform_error_io_completion:
                /* Use sas_task_abort */
-               dev_dbg(&host->pdev->dev,
-                        "%s: Error - task = %p, response=%d (%d), status=%d (%d)\n",
-                        __func__,
-                        task,
-                        task->task_status.resp, response,
-                        task->task_status.stat, status);
                /* Add to the aborted list. */
                list_add(&request->completed_node,
                         &host->requests_to_errorback);
                break;
 
        default:
-               dev_dbg(&host->pdev->dev,
-                        "%s: Unknown - task = %p, response=%d (%d), status=%d (%d)\n",
-                        __func__,
-                        task,
-                        task->task_status.resp, response,
-                        task->task_status.stat, status);
-
                /* Add to the error to libsas list. */
                list_add(&request->completed_node,
                         &host->requests_to_errorback);
                break;
        }
+       dev_dbg(&host->pdev->dev,
+               "%s: %d - task = %p, response=%d (%d), status=%d (%d)\n",
+               __func__, task_notification_selection, task,
+               (task) ? task->task_status.resp : 0, response,
+               (task) ? task->task_status.stat : 0, status);
 }
 
 static void isci_process_stp_response(struct sas_task *task, struct dev_to_host_fis *fis)
@@ -2728,9 +2707,9 @@ static void isci_request_io_request_complete(struct isci_host *ihost,
        struct sas_task *task = isci_request_access_task(request);
        struct ssp_response_iu *resp_iu;
        unsigned long task_flags;
-       struct isci_remote_device *idev = isci_lookup_device(task->dev);
-       enum service_response response       = SAS_TASK_UNDELIVERED;
-       enum exec_status status         = SAS_ABORTED_TASK;
+       struct isci_remote_device *idev = request->target_device;
+       enum service_response response = SAS_TASK_UNDELIVERED;
+       enum exec_status status = SAS_ABORTED_TASK;
        enum isci_request_status request_status;
        enum isci_completion_selection complete_to_host
                = isci_perform_normal_io_completion;
@@ -3061,7 +3040,6 @@ static void isci_request_io_request_complete(struct isci_host *ihost,
 
        /* complete the io request to the core. */
        sci_controller_complete_io(ihost, request->target_device, request);
-       isci_put_device(idev);
 
        /* set terminated handle so it cannot be completed or
         * terminated again, and to cause any calls into abort
@@ -3080,7 +3058,7 @@ static void sci_request_started_state_enter(struct sci_base_state_machine *sm)
        /* XXX as hch said always creating an internal sas_task for tmf
         * requests would simplify the driver
         */
-       task = ireq->ttype == io_task ? isci_request_access_task(ireq) : NULL;
+       task = (test_bit(IREQ_TMF, &ireq->flags)) ? NULL : isci_request_access_task(ireq);
 
        /* all unaccelerated request types (non ssp or ncq) handled with
         * substates
@@ -3564,7 +3542,7 @@ static struct isci_request *isci_io_request_from_tag(struct isci_host *ihost,
 
        ireq = isci_request_from_tag(ihost, tag);
        ireq->ttype_ptr.io_task_ptr = task;
-       ireq->ttype = io_task;
+       clear_bit(IREQ_TMF, &ireq->flags);
        task->lldd_task = ireq;
 
        return ireq;
@@ -3578,7 +3556,7 @@ struct isci_request *isci_tmf_request_from_tag(struct isci_host *ihost,
 
        ireq = isci_request_from_tag(ihost, tag);
        ireq->ttype_ptr.tmf_task_ptr = isci_tmf;
-       ireq->ttype = tmf_task;
+       set_bit(IREQ_TMF, &ireq->flags);
 
        return ireq;
 }
index f720b97..be38933 100644 (file)
@@ -77,11 +77,6 @@ enum isci_request_status {
        dead        = 0x07
 };
 
-enum task_type {
-       io_task  = 0,
-       tmf_task = 1
-};
-
 enum sci_request_protocol {
        SCIC_NO_PROTOCOL,
        SCIC_SMP_PROTOCOL,
@@ -116,7 +111,6 @@ struct isci_request {
        #define IREQ_ACTIVE 3
        unsigned long flags;
        /* XXX kill ttype and ttype_ptr, allocate full sas_task */
-       enum task_type ttype;
        union ttype_ptr_union {
                struct sas_task *io_task_ptr;   /* When ttype==io_task  */
                struct isci_tmf *tmf_task_ptr;  /* When ttype==tmf_task */
index e2d9418..66ad3dc 100644 (file)
@@ -212,16 +212,27 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags)
                                        task->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
                                        spin_unlock_irqrestore(&task->task_state_lock, flags);
 
-                                       /* Indicate QUEUE_FULL so that the scsi
-                                       * midlayer retries. if the request
-                                       * failed for remote device reasons,
-                                       * it gets returned as
-                                       * SAS_TASK_UNDELIVERED next time
-                                       * through.
-                                       */
-                                       isci_task_refuse(ihost, task,
-                                                        SAS_TASK_COMPLETE,
-                                                        SAS_QUEUE_FULL);
+                                       if (test_bit(IDEV_GONE, &idev->flags)) {
+
+                                               /* Indicate that the device
+                                                * is gone.
+                                                */
+                                               isci_task_refuse(ihost, task,
+                                                       SAS_TASK_UNDELIVERED,
+                                                       SAS_DEVICE_UNKNOWN);
+                                       } else {
+                                               /* Indicate QUEUE_FULL so that
+                                                * the scsi midlayer retries.
+                                                * If the request failed for
+                                                * remote device reasons, it
+                                                * gets returned as
+                                                * SAS_TASK_UNDELIVERED next
+                                                * time through.
+                                                */
+                                               isci_task_refuse(ihost, task,
+                                                       SAS_TASK_COMPLETE,
+                                                       SAS_QUEUE_FULL);
+                                       }
                                }
                        }
                }
@@ -243,7 +254,7 @@ static enum sci_status isci_sata_management_task_request_build(struct isci_reque
        struct isci_tmf *isci_tmf;
        enum sci_status status;
 
-       if (tmf_task != ireq->ttype)
+       if (!test_bit(IREQ_TMF, &ireq->flags))
                return SCI_FAILURE;
 
        isci_tmf = isci_request_access_tmf(ireq);
@@ -327,6 +338,60 @@ static struct isci_request *isci_task_request_build(struct isci_host *ihost,
        return ireq;
 }
 
+/**
+* isci_request_mark_zombie() - This function must be called with scic_lock held.
+*/
+static void isci_request_mark_zombie(struct isci_host *ihost, struct isci_request *ireq)
+{
+       struct completion *tmf_completion = NULL;
+       struct completion *req_completion;
+
+       /* Set the request state to "dead". */
+       ireq->status = dead;
+
+       req_completion = ireq->io_request_completion;
+       ireq->io_request_completion = NULL;
+
+       if (test_bit(IREQ_TMF, &ireq->flags)) {
+               /* Break links with the TMF request. */
+               struct isci_tmf *tmf = isci_request_access_tmf(ireq);
+
+               /* In the case where a task request is dying,
+                * the thread waiting on the complete will sit and
+                * timeout unless we wake it now.  Since the TMF
+                * has a default error status, complete it here
+                * to wake the waiting thread.
+                */
+               if (tmf) {
+                       tmf_completion = tmf->complete;
+                       tmf->complete = NULL;
+               }
+               ireq->ttype_ptr.tmf_task_ptr = NULL;
+               dev_dbg(&ihost->pdev->dev, "%s: tmf_code %d, managed tag %#x\n",
+                       __func__, tmf->tmf_code, tmf->io_tag);
+       } else {
+               /* Break links with the sas_task - the callback is done
+                * elsewhere.
+                */
+               struct sas_task *task = isci_request_access_task(ireq);
+
+               if (task)
+                       task->lldd_task = NULL;
+
+               ireq->ttype_ptr.io_task_ptr = NULL;
+       }
+
+       dev_warn(&ihost->pdev->dev, "task context unrecoverable (tag: %#x)\n",
+                ireq->io_tag);
+
+       /* Don't force waiting threads to timeout. */
+       if (req_completion)
+               complete(req_completion);
+
+       if (tmf_completion != NULL)
+               complete(tmf_completion);
+}
+
 static int isci_task_execute_tmf(struct isci_host *ihost,
                                 struct isci_remote_device *idev,
                                 struct isci_tmf *tmf, unsigned long timeout_ms)
@@ -364,6 +429,7 @@ static int isci_task_execute_tmf(struct isci_host *ihost,
 
        /* Assign the pointer to the TMF's completion kernel wait structure. */
        tmf->complete = &completion;
+       tmf->status = SCI_FAILURE_TIMEOUT;
 
        ireq = isci_task_request_build(ihost, idev, tag, tmf);
        if (!ireq)
@@ -399,18 +465,35 @@ static int isci_task_execute_tmf(struct isci_host *ihost,
                                               msecs_to_jiffies(timeout_ms));
 
        if (timeleft == 0) {
+               /* The TMF did not complete - this could be because
+                * of an unplug.  Terminate the TMF request now.
+                */
                spin_lock_irqsave(&ihost->scic_lock, flags);
 
                if (tmf->cb_state_func != NULL)
-                       tmf->cb_state_func(isci_tmf_timed_out, tmf, tmf->cb_data);
+                       tmf->cb_state_func(isci_tmf_timed_out, tmf,
+                                          tmf->cb_data);
 
-               sci_controller_terminate_request(ihost,
-                                                 idev,
-                                                 ireq);
+               sci_controller_terminate_request(ihost, idev, ireq);
 
                spin_unlock_irqrestore(&ihost->scic_lock, flags);
 
-               wait_for_completion(tmf->complete);
+               timeleft = wait_for_completion_timeout(
+                       &completion,
+                       msecs_to_jiffies(ISCI_TERMINATION_TIMEOUT_MSEC));
+
+               if (!timeleft) {
+                       /* Strange condition - the termination of the TMF
+                        * request timed-out.
+                        */
+                       spin_lock_irqsave(&ihost->scic_lock, flags);
+
+                       /* If the TMF status has not changed, kill it. */
+                       if (tmf->status == SCI_FAILURE_TIMEOUT)
+                               isci_request_mark_zombie(ihost, ireq);
+
+                       spin_unlock_irqrestore(&ihost->scic_lock, flags);
+               }
        }
 
        isci_print_tmf(tmf);
@@ -501,48 +584,17 @@ static enum isci_request_status isci_task_validate_request_to_abort(
        return old_state;
 }
 
-/**
-* isci_request_cleanup_completed_loiterer() - This function will take care of
-*    the final cleanup on any request which has been explicitly terminated.
-* @isci_host: This parameter specifies the ISCI host object
-* @isci_device: This is the device to which the request is pending.
-* @isci_request: This parameter specifies the terminated request object.
-* @task: This parameter is the libsas I/O request.
-*/
-static void isci_request_cleanup_completed_loiterer(
-       struct isci_host          *isci_host,
-       struct isci_remote_device *isci_device,
-       struct isci_request       *isci_request,
-       struct sas_task           *task)
+static int isci_request_is_dealloc_managed(enum isci_request_status stat)
 {
-       unsigned long flags;
-
-       dev_dbg(&isci_host->pdev->dev,
-               "%s: isci_device=%p, request=%p, task=%p\n",
-               __func__, isci_device, isci_request, task);
-
-       if (task != NULL) {
-
-               spin_lock_irqsave(&task->task_state_lock, flags);
-               task->lldd_task = NULL;
-
-               task->task_state_flags &= ~SAS_TASK_NEED_DEV_RESET;
-
-               isci_set_task_doneflags(task);
-
-               /* If this task is not in the abort path, call task_done. */
-               if (!(task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
-
-                       spin_unlock_irqrestore(&task->task_state_lock, flags);
-                       task->task_done(task);
-               } else
-                       spin_unlock_irqrestore(&task->task_state_lock, flags);
-       }
-
-       if (isci_request != NULL) {
-               spin_lock_irqsave(&isci_host->scic_lock, flags);
-               list_del_init(&isci_request->dev_node);
-               spin_unlock_irqrestore(&isci_host->scic_lock, flags);
+       switch (stat) {
+       case aborted:
+       case aborting:
+       case terminating:
+       case completed:
+       case dead:
+               return true;
+       default:
+               return false;
        }
 }
 
@@ -563,11 +615,9 @@ static void isci_terminate_request_core(struct isci_host *ihost,
        enum sci_status status      = SCI_SUCCESS;
        bool was_terminated         = false;
        bool needs_cleanup_handling = false;
-       enum isci_request_status request_status;
        unsigned long     flags;
        unsigned long     termination_completed = 1;
        struct completion *io_request_completion;
-       struct sas_task   *task;
 
        dev_dbg(&ihost->pdev->dev,
                "%s: device = %p; request = %p\n",
@@ -577,10 +627,6 @@ static void isci_terminate_request_core(struct isci_host *ihost,
 
        io_request_completion = isci_request->io_request_completion;
 
-       task = (isci_request->ttype == io_task)
-               ? isci_request_access_task(isci_request)
-               : NULL;
-
        /* Note that we are not going to control
         * the target to abort the request.
         */
@@ -619,42 +665,27 @@ static void isci_terminate_request_core(struct isci_host *ihost,
                                __func__, isci_request, io_request_completion);
 
                        /* Wait here for the request to complete. */
-                       #define TERMINATION_TIMEOUT_MSEC 500
                        termination_completed
                                = wait_for_completion_timeout(
                                   io_request_completion,
-                                  msecs_to_jiffies(TERMINATION_TIMEOUT_MSEC));
+                                  msecs_to_jiffies(ISCI_TERMINATION_TIMEOUT_MSEC));
 
                        if (!termination_completed) {
 
                                /* The request to terminate has timed out.  */
-                               spin_lock_irqsave(&ihost->scic_lock,
-                                                 flags);
+                               spin_lock_irqsave(&ihost->scic_lock, flags);
 
                                /* Check for state changes. */
-                               if (!test_bit(IREQ_TERMINATED, &isci_request->flags)) {
+                               if (!test_bit(IREQ_TERMINATED,
+                                             &isci_request->flags)) {
 
                                        /* The best we can do is to have the
                                         * request die a silent death if it
                                         * ever really completes.
-                                        *
-                                        * Set the request state to "dead",
-                                        * and clear the task pointer so that
-                                        * an actual completion event callback
-                                        * doesn't do anything.
                                         */
-                                       isci_request->status = dead;
-                                       isci_request->io_request_completion
-                                               = NULL;
-
-                                       if (isci_request->ttype == io_task) {
-
-                                               /* Break links with the
-                                               * sas_task.
-                                               */
-                                               isci_request->ttype_ptr.io_task_ptr
-                                                       = NULL;
-                                       }
+                                       isci_request_mark_zombie(ihost,
+                                                                isci_request);
+                                       needs_cleanup_handling = true;
                                } else
                                        termination_completed = 1;
 
@@ -691,29 +722,28 @@ static void isci_terminate_request_core(struct isci_host *ihost,
                         * needs to be detached and freed here.
                         */
                        spin_lock_irqsave(&isci_request->state_lock, flags);
-                       request_status = isci_request->status;
-
-                       if ((isci_request->ttype == io_task) /* TMFs are in their own thread */
-                           && ((request_status == aborted)
-                               || (request_status == aborting)
-                               || (request_status == terminating)
-                               || (request_status == completed)
-                               || (request_status == dead)
-                               )
-                           ) {
-
-                               /* The completion routine won't free a request in
-                                * the aborted/aborting/etc. states, so we do
-                                * it here.
-                                */
-                               needs_cleanup_handling = true;
-                       }
+
+                       needs_cleanup_handling
+                               = isci_request_is_dealloc_managed(
+                                       isci_request->status);
+
                        spin_unlock_irqrestore(&isci_request->state_lock, flags);
 
                }
-               if (needs_cleanup_handling)
-                       isci_request_cleanup_completed_loiterer(
-                               ihost, idev, isci_request, task);
+               if (needs_cleanup_handling) {
+
+                       dev_dbg(&ihost->pdev->dev,
+                               "%s: cleanup isci_device=%p, request=%p\n",
+                               __func__, idev, isci_request);
+
+                       if (isci_request != NULL) {
+                               spin_lock_irqsave(&ihost->scic_lock, flags);
+                               isci_free_tag(ihost, isci_request->io_tag);
+                               isci_request_change_state(isci_request, unallocated);
+                               list_del_init(&isci_request->dev_node);
+                               spin_unlock_irqrestore(&ihost->scic_lock, flags);
+                       }
+               }
        }
 }
 
@@ -772,7 +802,9 @@ void isci_terminate_pending_requests(struct isci_host *ihost,
                dev_dbg(&ihost->pdev->dev,
                         "%s: idev=%p request=%p; task=%p old_state=%d\n",
                         __func__, idev, ireq,
-                       ireq->ttype == io_task ? isci_request_access_task(ireq) : NULL,
+                       (!test_bit(IREQ_TMF, &ireq->flags)
+                               ? isci_request_access_task(ireq)
+                               : NULL),
                        old_state);
 
                /* If the old_state is started:
@@ -889,22 +921,14 @@ int isci_task_lu_reset(struct domain_device *domain_device, u8 *lun)
                "%s: domain_device=%p, isci_host=%p; isci_device=%p\n",
                 __func__, domain_device, isci_host, isci_device);
 
-       if (isci_device)
-               set_bit(IDEV_EH, &isci_device->flags);
+       if (!isci_device) {
+               /* If the device is gone, stop the escalations. */
+               dev_dbg(&isci_host->pdev->dev, "%s: No dev\n", __func__);
 
-       /* If there is a device reset pending on any request in the
-        * device's list, fail this LUN reset request in order to
-        * escalate to the device reset.
-        */
-       if (!isci_device ||
-           isci_device_is_reset_pending(isci_host, isci_device)) {
-               dev_dbg(&isci_host->pdev->dev,
-                        "%s: No dev (%p), or "
-                        "RESET PENDING: domain_device=%p\n",
-                        __func__, isci_device, domain_device);
-               ret = TMF_RESP_FUNC_FAILED;
+               ret = TMF_RESP_FUNC_COMPLETE;
                goto out;
        }
+       set_bit(IDEV_EH, &isci_device->flags);
 
        /* Send the task management part of the reset. */
        if (sas_protocol_ata(domain_device->tproto)) {
@@ -1013,7 +1037,7 @@ int isci_task_abort_task(struct sas_task *task)
        struct isci_tmf           tmf;
        int                       ret = TMF_RESP_FUNC_FAILED;
        unsigned long             flags;
-       bool                      any_dev_reset = false;
+       int                       perform_termination = 0;
 
        /* Get the isci_request reference from the task.  Note that
         * this check does not depend on the pending request list
@@ -1035,89 +1059,34 @@ int isci_task_abort_task(struct sas_task *task)
        spin_unlock_irqrestore(&isci_host->scic_lock, flags);
 
        dev_dbg(&isci_host->pdev->dev,
-               "%s: task = %p\n", __func__, task);
-
-       if (!isci_device || !old_request)
-               goto out;
-
-       set_bit(IDEV_EH, &isci_device->flags);
-
-       /* This version of the driver will fail abort requests for
-        * SATA/STP.  Failing the abort request this way will cause the
-        * SCSI error handler thread to escalate to LUN reset
-        */
-       if (sas_protocol_ata(task->task_proto)) {
-               dev_dbg(&isci_host->pdev->dev,
-                           " task %p is for a STP/SATA device;"
-                           " returning TMF_RESP_FUNC_FAILED\n"
-                           " to cause a LUN reset...\n", task);
-               goto out;
-       }
+               "%s: dev = %p, task = %p, old_request == %p\n",
+               __func__, isci_device, task, old_request);
 
-       dev_dbg(&isci_host->pdev->dev,
-               "%s: old_request == %p\n", __func__, old_request);
-
-       any_dev_reset = isci_device_is_reset_pending(isci_host, isci_device);
-
-       spin_lock_irqsave(&task->task_state_lock, flags);
-
-       any_dev_reset = any_dev_reset || (task->task_state_flags & SAS_TASK_NEED_DEV_RESET);
+       if (isci_device)
+               set_bit(IDEV_EH, &isci_device->flags);
 
-       /* If the extraction of the request reference from the task
-        * failed, then the request has been completed (or if there is a
-        * pending reset then this abort request function must be failed
-        * in order to escalate to the target reset).
+       /* Device reset conditions signalled in task_state_flags are the
+        * responsbility of libsas to observe at the start of the error
+        * handler thread.
         */
-       if ((old_request == NULL) || any_dev_reset) {
-
-               /* If the device reset task flag is set, fail the task
-                * management request.  Otherwise, the original request
-                * has completed.
-                */
-               if (any_dev_reset) {
-
-                       /* Turn off the task's DONE to make sure this
-                        * task is escalated to a target reset.
-                        */
-                       task->task_state_flags &= ~SAS_TASK_STATE_DONE;
-
-                       /* Make the reset happen as soon as possible. */
-                       task->task_state_flags |= SAS_TASK_NEED_DEV_RESET;
-
-                       spin_unlock_irqrestore(&task->task_state_lock, flags);
-
-                       /* Fail the task management request in order to
-                        * escalate to the target reset.
-                        */
-                       ret = TMF_RESP_FUNC_FAILED;
-
-                       dev_dbg(&isci_host->pdev->dev,
-                               "%s: Failing task abort in order to "
-                               "escalate to target reset because\n"
-                               "SAS_TASK_NEED_DEV_RESET is set for "
-                               "task %p on dev %p\n",
-                               __func__, task, isci_device);
-
-
-               } else {
-                       /* The request has already completed and there
-                        * is nothing to do here other than to set the task
-                        * done bit, and indicate that the task abort function
-                        * was sucessful.
-                        */
-                       isci_set_task_doneflags(task);
-
-                       spin_unlock_irqrestore(&task->task_state_lock, flags);
+       if (!isci_device || !old_request) {
+               /* The request has already completed and there
+               * is nothing to do here other than to set the task
+               * done bit, and indicate that the task abort function
+               * was sucessful.
+               */
+               spin_lock_irqsave(&task->task_state_lock, flags);
+               task->task_state_flags |= SAS_TASK_STATE_DONE;
+               task->task_state_flags &= ~(SAS_TASK_AT_INITIATOR |
+                                           SAS_TASK_STATE_PENDING);
+               spin_unlock_irqrestore(&task->task_state_lock, flags);
 
-                       ret = TMF_RESP_FUNC_COMPLETE;
+               ret = TMF_RESP_FUNC_COMPLETE;
 
-                       dev_dbg(&isci_host->pdev->dev,
-                               "%s: abort task not needed for %p\n",
-                               __func__, task);
-               }
+               dev_dbg(&isci_host->pdev->dev,
+                       "%s: abort task not needed for %p\n",
+                       __func__, task);
                goto out;
-       } else {
-               spin_unlock_irqrestore(&task->task_state_lock, flags);
        }
 
        spin_lock_irqsave(&isci_host->scic_lock, flags);
@@ -1146,24 +1115,44 @@ int isci_task_abort_task(struct sas_task *task)
                goto out;
        }
        if (task->task_proto == SAS_PROTOCOL_SMP ||
+           sas_protocol_ata(task->task_proto) ||
            test_bit(IREQ_COMPLETE_IN_TARGET, &old_request->flags)) {
 
                spin_unlock_irqrestore(&isci_host->scic_lock, flags);
 
                dev_dbg(&isci_host->pdev->dev,
-                       "%s: SMP request (%d)"
+                       "%s: %s request"
                        " or complete_in_target (%d), thus no TMF\n",
-                       __func__, (task->task_proto == SAS_PROTOCOL_SMP),
+                       __func__,
+                       ((task->task_proto == SAS_PROTOCOL_SMP)
+                               ? "SMP"
+                               : (sas_protocol_ata(task->task_proto)
+                                       ? "SATA/STP"
+                                       : "<other>")
+                        ),
                        test_bit(IREQ_COMPLETE_IN_TARGET, &old_request->flags));
 
-               /* Set the state on the task. */
-               isci_task_all_done(task);
-
-               ret = TMF_RESP_FUNC_COMPLETE;
+               if (test_bit(IREQ_COMPLETE_IN_TARGET, &old_request->flags)) {
+                       spin_lock_irqsave(&task->task_state_lock, flags);
+                       task->task_state_flags |= SAS_TASK_STATE_DONE;
+                       task->task_state_flags &= ~(SAS_TASK_AT_INITIATOR |
+                                                   SAS_TASK_STATE_PENDING);
+                       spin_unlock_irqrestore(&task->task_state_lock, flags);
+                       ret = TMF_RESP_FUNC_COMPLETE;
+               } else {
+                       spin_lock_irqsave(&task->task_state_lock, flags);
+                       task->task_state_flags &= ~(SAS_TASK_AT_INITIATOR |
+                                                   SAS_TASK_STATE_PENDING);
+                       spin_unlock_irqrestore(&task->task_state_lock, flags);
+               }
 
-               /* Stopping and SMP devices are not sent a TMF, and are not
-                * reset, but the outstanding I/O request is terminated below.
+               /* STP and SMP devices are not sent a TMF, but the
+                * outstanding I/O request is terminated below.  This is
+                * because SATA/STP and SMP discovery path timeouts directly
+                * call the abort task interface for cleanup.
                 */
+               perform_termination = 1;
+
        } else {
                /* Fill in the tmf stucture */
                isci_task_build_abort_task_tmf(&tmf, isci_tmf_ssp_task_abort,
@@ -1172,22 +1161,24 @@ int isci_task_abort_task(struct sas_task *task)
 
                spin_unlock_irqrestore(&isci_host->scic_lock, flags);
 
-               #define ISCI_ABORT_TASK_TIMEOUT_MS 500 /* half second timeout. */
+               #define ISCI_ABORT_TASK_TIMEOUT_MS 500 /* 1/2 second timeout */
                ret = isci_task_execute_tmf(isci_host, isci_device, &tmf,
                                            ISCI_ABORT_TASK_TIMEOUT_MS);
 
-               if (ret != TMF_RESP_FUNC_COMPLETE)
+               if (ret == TMF_RESP_FUNC_COMPLETE)
+                       perform_termination = 1;
+               else
                        dev_dbg(&isci_host->pdev->dev,
-                               "%s: isci_task_send_tmf failed\n",
-                               __func__);
+                               "%s: isci_task_send_tmf failed\n", __func__);
        }
-       if (ret == TMF_RESP_FUNC_COMPLETE) {
+       if (perform_termination) {
                set_bit(IREQ_COMPLETE_IN_TARGET, &old_request->flags);
 
                /* Clean up the request on our side, and wait for the aborted
                 * I/O to complete.
                 */
-               isci_terminate_request_core(isci_host, isci_device, old_request);
+               isci_terminate_request_core(isci_host, isci_device,
+                                           old_request);
        }
 
        /* Make sure we do not leave a reference to aborted_io_completion */
@@ -1288,7 +1279,8 @@ isci_task_request_complete(struct isci_host *ihost,
                           enum sci_task_status completion_status)
 {
        struct isci_tmf *tmf = isci_request_access_tmf(ireq);
-       struct completion *tmf_complete;
+       struct completion *tmf_complete = NULL;
+       struct completion *request_complete = ireq->io_request_completion;
 
        dev_dbg(&ihost->pdev->dev,
                "%s: request = %p, status=%d\n",
@@ -1296,255 +1288,53 @@ isci_task_request_complete(struct isci_host *ihost,
 
        isci_request_change_state(ireq, completed);
 
-       tmf->status = completion_status;
        set_bit(IREQ_COMPLETE_IN_TARGET, &ireq->flags);
 
-       if (tmf->proto == SAS_PROTOCOL_SSP) {
-               memcpy(&tmf->resp.resp_iu,
-                      &ireq->ssp.rsp,
-                      SSP_RESP_IU_MAX_SIZE);
-       } else if (tmf->proto == SAS_PROTOCOL_SATA) {
-               memcpy(&tmf->resp.d2h_fis,
-                      &ireq->stp.rsp,
-                      sizeof(struct dev_to_host_fis));
+       if (tmf) {
+               tmf->status = completion_status;
+
+               if (tmf->proto == SAS_PROTOCOL_SSP) {
+                       memcpy(&tmf->resp.resp_iu,
+                              &ireq->ssp.rsp,
+                              SSP_RESP_IU_MAX_SIZE);
+               } else if (tmf->proto == SAS_PROTOCOL_SATA) {
+                       memcpy(&tmf->resp.d2h_fis,
+                              &ireq->stp.rsp,
+                              sizeof(struct dev_to_host_fis));
+               }
+               /* PRINT_TMF( ((struct isci_tmf *)request->task)); */
+               tmf_complete = tmf->complete;
        }
-
-       /* PRINT_TMF( ((struct isci_tmf *)request->task)); */
-       tmf_complete = tmf->complete;
-
        sci_controller_complete_io(ihost, ireq->target_device, ireq);
        /* set the 'terminated' flag handle to make sure it cannot be terminated
         *  or completed again.
         */
        set_bit(IREQ_TERMINATED, &ireq->flags);
 
-       isci_request_change_state(ireq, unallocated);
-       list_del_init(&ireq->dev_node);
-
-       /* The task management part completes last. */
-       complete(tmf_complete);
-}
-
-static void isci_smp_task_timedout(unsigned long _task)
-{
-       struct sas_task *task = (void *) _task;
-       unsigned long flags;
-
-       spin_lock_irqsave(&task->task_state_lock, flags);
-       if (!(task->task_state_flags & SAS_TASK_STATE_DONE))
-               task->task_state_flags |= SAS_TASK_STATE_ABORTED;
-       spin_unlock_irqrestore(&task->task_state_lock, flags);
-
-       complete(&task->completion);
-}
-
-static void isci_smp_task_done(struct sas_task *task)
-{
-       if (!del_timer(&task->timer))
-               return;
-       complete(&task->completion);
-}
-
-static int isci_smp_execute_task(struct isci_host *ihost,
-                                struct domain_device *dev, void *req,
-                                int req_size, void *resp, int resp_size)
-{
-       int res, retry;
-       struct sas_task *task = NULL;
-
-       for (retry = 0; retry < 3; retry++) {
-               task = sas_alloc_task(GFP_KERNEL);
-               if (!task)
-                       return -ENOMEM;
-
-               task->dev = dev;
-               task->task_proto = dev->tproto;
-               sg_init_one(&task->smp_task.smp_req, req, req_size);
-               sg_init_one(&task->smp_task.smp_resp, resp, resp_size);
-
-               task->task_done = isci_smp_task_done;
-
-               task->timer.data = (unsigned long) task;
-               task->timer.function = isci_smp_task_timedout;
-               task->timer.expires = jiffies + 10*HZ;
-               add_timer(&task->timer);
-
-               res = isci_task_execute_task(task, 1, GFP_KERNEL);
-
-               if (res) {
-                       del_timer(&task->timer);
-                       dev_dbg(&ihost->pdev->dev,
-                               "%s: executing SMP task failed:%d\n",
-                               __func__, res);
-                       goto ex_err;
-               }
-
-               wait_for_completion(&task->completion);
-               res = -ECOMM;
-               if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
-                       dev_dbg(&ihost->pdev->dev,
-                               "%s: smp task timed out or aborted\n",
-                               __func__);
-                       isci_task_abort_task(task);
-                       if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) {
-                               dev_dbg(&ihost->pdev->dev,
-                                       "%s: SMP task aborted and not done\n",
-                                       __func__);
-                               goto ex_err;
-                       }
-               }
-               if (task->task_status.resp == SAS_TASK_COMPLETE &&
-                   task->task_status.stat == SAM_STAT_GOOD) {
-                       res = 0;
-                       break;
-               }
-               if (task->task_status.resp == SAS_TASK_COMPLETE &&
-                     task->task_status.stat == SAS_DATA_UNDERRUN) {
-                       /* no error, but return the number of bytes of
-                       * underrun */
-                       res = task->task_status.residual;
-                       break;
-               }
-               if (task->task_status.resp == SAS_TASK_COMPLETE &&
-                     task->task_status.stat == SAS_DATA_OVERRUN) {
-                       res = -EMSGSIZE;
-                       break;
-               } else {
-                       dev_dbg(&ihost->pdev->dev,
-                               "%s: task to dev %016llx response: 0x%x "
-                               "status 0x%x\n", __func__,
-                               SAS_ADDR(dev->sas_addr),
-                               task->task_status.resp,
-                               task->task_status.stat);
-                       sas_free_task(task);
-                       task = NULL;
-               }
-       }
-ex_err:
-       BUG_ON(retry == 3 && task != NULL);
-       sas_free_task(task);
-       return res;
-}
-
-#define DISCOVER_REQ_SIZE  16
-#define DISCOVER_RESP_SIZE 56
-
-int isci_smp_get_phy_attached_dev_type(struct isci_host *ihost,
-                                      struct domain_device *dev,
-                                      int phy_id, int *adt)
-{
-       struct smp_resp *disc_resp;
-       u8 *disc_req;
-       int res;
-
-       disc_resp = kzalloc(DISCOVER_RESP_SIZE, GFP_KERNEL);
-       if (!disc_resp)
-               return -ENOMEM;
-
-       disc_req = kzalloc(DISCOVER_REQ_SIZE, GFP_KERNEL);
-       if (disc_req) {
-               disc_req[0] = SMP_REQUEST;
-               disc_req[1] = SMP_DISCOVER;
-               disc_req[9] = phy_id;
-       } else {
-               kfree(disc_resp);
-               return -ENOMEM;
-       }
-       res = isci_smp_execute_task(ihost, dev, disc_req, DISCOVER_REQ_SIZE,
-                                   disc_resp, DISCOVER_RESP_SIZE);
-       if (!res) {
-               if (disc_resp->result != SMP_RESP_FUNC_ACC)
-                       res = disc_resp->result;
-               else
-                       *adt = disc_resp->disc.attached_dev_type;
+       /* As soon as something is in the terminate path, deallocation is
+        * managed there.  Note that the final non-managed state of a task
+        * request is "completed".
+        */
+       if ((ireq->status == completed) ||
+           !isci_request_is_dealloc_managed(ireq->status)) {
+               isci_request_change_state(ireq, unallocated);
+               isci_free_tag(ihost, ireq->io_tag);
+               list_del_init(&ireq->dev_node);
        }
-       kfree(disc_req);
-       kfree(disc_resp);
-
-       return res;
-}
-
-static void isci_wait_for_smp_phy_reset(struct isci_remote_device *idev, int phy_num)
-{
-       struct domain_device *dev = idev->domain_dev;
-       struct isci_port *iport = idev->isci_port;
-       struct isci_host *ihost = iport->isci_host;
-       int res, iteration = 0, attached_device_type;
-       #define STP_WAIT_MSECS 25000
-       unsigned long tmo = msecs_to_jiffies(STP_WAIT_MSECS);
-       unsigned long deadline = jiffies + tmo;
-       enum {
-               SMP_PHYWAIT_PHYDOWN,
-               SMP_PHYWAIT_PHYUP,
-               SMP_PHYWAIT_DONE
-       } phy_state = SMP_PHYWAIT_PHYDOWN;
-
-       /* While there is time, wait for the phy to go away and come back */
-       while (time_is_after_jiffies(deadline) && phy_state != SMP_PHYWAIT_DONE) {
-               int event = atomic_read(&iport->event);
-
-               ++iteration;
-
-               tmo = wait_event_timeout(ihost->eventq,
-                                        event != atomic_read(&iport->event) ||
-                                        !test_bit(IPORT_BCN_BLOCKED, &iport->flags),
-                                        tmo);
-               /* link down, stop polling */
-               if (!test_bit(IPORT_BCN_BLOCKED, &iport->flags))
-                       break;
 
-               dev_dbg(&ihost->pdev->dev,
-                       "%s: iport %p, iteration %d,"
-                       " phase %d: time_remaining %lu, bcns = %d\n",
-                       __func__, iport, iteration, phy_state,
-                       tmo, test_bit(IPORT_BCN_PENDING, &iport->flags));
-
-               res = isci_smp_get_phy_attached_dev_type(ihost, dev, phy_num,
-                                                        &attached_device_type);
-               tmo = deadline - jiffies;
-
-               if (res) {
-                       dev_dbg(&ihost->pdev->dev,
-                                "%s: iteration %d, phase %d:"
-                                " SMP error=%d, time_remaining=%lu\n",
-                                __func__, iteration, phy_state, res, tmo);
-                       break;
-               }
-               dev_dbg(&ihost->pdev->dev,
-                       "%s: iport %p, iteration %d,"
-                       " phase %d: time_remaining %lu, bcns = %d, "
-                       "attdevtype = %x\n",
-                       __func__, iport, iteration, phy_state,
-                       tmo, test_bit(IPORT_BCN_PENDING, &iport->flags),
-                       attached_device_type);
-
-               switch (phy_state) {
-               case SMP_PHYWAIT_PHYDOWN:
-                       /* Has the device gone away? */
-                       if (!attached_device_type)
-                               phy_state = SMP_PHYWAIT_PHYUP;
-
-                       break;
-
-               case SMP_PHYWAIT_PHYUP:
-                       /* Has the device come back? */
-                       if (attached_device_type)
-                               phy_state = SMP_PHYWAIT_DONE;
-                       break;
-
-               case SMP_PHYWAIT_DONE:
-                       break;
-               }
+       /* "request_complete" is set if the task was being terminated. */
+       if (request_complete)
+               complete(request_complete);
 
-       }
-       dev_dbg(&ihost->pdev->dev, "%s: done\n",  __func__);
+       /* The task management part completes last. */
+       if (tmf_complete)
+               complete(tmf_complete);
 }
 
 static int isci_reset_device(struct isci_host *ihost,
                             struct isci_remote_device *idev)
 {
        struct sas_phy *phy = sas_find_local_phy(idev->domain_dev);
-       struct isci_port *iport = idev->isci_port;
        enum sci_status status;
        unsigned long flags;
        int rc;
@@ -1564,13 +1354,6 @@ static int isci_reset_device(struct isci_host *ihost,
        }
        spin_unlock_irqrestore(&ihost->scic_lock, flags);
 
-       /* Make sure all pending requests are able to be fully terminated. */
-       isci_device_clear_reset_pending(ihost, idev);
-
-       /* If this is a device on an expander, disable BCN processing. */
-       if (!scsi_is_sas_phy_local(phy))
-               set_bit(IPORT_BCN_BLOCKED, &iport->flags);
-
        rc = sas_phy_reset(phy, true);
 
        /* Terminate in-progress I/O now. */
@@ -1581,21 +1364,6 @@ static int isci_reset_device(struct isci_host *ihost,
        status = sci_remote_device_reset_complete(idev);
        spin_unlock_irqrestore(&ihost->scic_lock, flags);
 
-       /* If this is a device on an expander, bring the phy back up. */
-       if (!scsi_is_sas_phy_local(phy)) {
-               /* A phy reset will cause the device to go away then reappear.
-                * Since libsas will take action on incoming BCNs (eg. remove
-                * a device going through an SMP phy-control driven reset),
-                * we need to wait until the phy comes back up before letting
-                * discovery proceed in libsas.
-                */
-               isci_wait_for_smp_phy_reset(idev, phy->number);
-
-               spin_lock_irqsave(&ihost->scic_lock, flags);
-               isci_port_bcn_enable(ihost, idev->isci_port);
-               spin_unlock_irqrestore(&ihost->scic_lock, flags);
-       }
-
        if (status != SCI_SUCCESS) {
                dev_dbg(&ihost->pdev->dev,
                         "%s: sci_remote_device_reset_complete(%p) "
index 15b18d1..bc78c0a 100644 (file)
@@ -58,6 +58,8 @@
 #include <scsi/sas_ata.h>
 #include "host.h"
 
+#define ISCI_TERMINATION_TIMEOUT_MSEC 500
+
 struct isci_request;
 
 /**
@@ -224,35 +226,6 @@ enum isci_completion_selection {
        isci_perform_error_io_completion        /* Use sas_task_abort */
 };
 
-static inline void isci_set_task_doneflags(
-       struct sas_task *task)
-{
-       /* Since no futher action will be taken on this task,
-        * make sure to mark it complete from the lldd perspective.
-        */
-       task->task_state_flags |= SAS_TASK_STATE_DONE;
-       task->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
-       task->task_state_flags &= ~SAS_TASK_STATE_PENDING;
-}
-/**
- * isci_task_all_done() - This function clears the task bits to indicate the
- *    LLDD is done with the task.
- *
- *
- */
-static inline void isci_task_all_done(
-       struct sas_task *task)
-{
-       unsigned long flags;
-
-       /* Since no futher action will be taken on this task,
-        * make sure to mark it complete from the lldd perspective.
-        */
-       spin_lock_irqsave(&task->task_state_lock, flags);
-       isci_set_task_doneflags(task);
-       spin_unlock_irqrestore(&task->task_state_lock, flags);
-}
-
 /**
  * isci_task_set_completion_status() - This function sets the completion status
  *    for the request.
@@ -334,7 +307,9 @@ isci_task_set_completion_status(
                /* Fall through to the normal case... */
        case isci_perform_normal_io_completion:
                /* Normal notification (task_done) */
-               isci_set_task_doneflags(task);
+               task->task_state_flags |= SAS_TASK_STATE_DONE;
+               task->task_state_flags &= ~(SAS_TASK_AT_INITIATOR |
+                                           SAS_TASK_STATE_PENDING);
                break;
        default:
                WARN_ONCE(1, "unknown task_notification_selection: %d\n",
index 7c055fd..1b22130 100644 (file)
@@ -469,6 +469,7 @@ static int fc_seq_send(struct fc_lport *lport, struct fc_seq *sp,
        struct fc_frame_header *fh = fc_frame_header_get(fp);
        int error;
        u32 f_ctl;
+       u8 fh_type = fh->fh_type;
 
        ep = fc_seq_exch(sp);
        WARN_ON((ep->esb_stat & ESB_ST_SEQ_INIT) != ESB_ST_SEQ_INIT);
@@ -493,7 +494,7 @@ static int fc_seq_send(struct fc_lport *lport, struct fc_seq *sp,
         */
        error = lport->tt.frame_send(lport, fp);
 
-       if (fh->fh_type == FC_TYPE_BLS)
+       if (fh_type == FC_TYPE_BLS)
                return error;
 
        /*
@@ -1792,6 +1793,9 @@ restart:
                        goto restart;
                }
        }
+       pool->next_index = 0;
+       pool->left = FC_XID_UNKNOWN;
+       pool->right = FC_XID_UNKNOWN;
        spin_unlock_bh(&pool->lock);
 }
 
@@ -2280,6 +2284,7 @@ struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lport,
                goto free_mempool;
        for_each_possible_cpu(cpu) {
                pool = per_cpu_ptr(mp->pool, cpu);
+               pool->next_index = 0;
                pool->left = FC_XID_UNKNOWN;
                pool->right = FC_XID_UNKNOWN;
                spin_lock_init(&pool->lock);
index 628f347..2cb12b9 100644 (file)
@@ -1030,16 +1030,8 @@ static void fc_lport_enter_reset(struct fc_lport *lport)
                           FCH_EVT_LIPRESET, 0);
        fc_vports_linkchange(lport);
        fc_lport_reset_locked(lport);
-       if (lport->link_up) {
-               /*
-                * Wait upto resource allocation time out before
-                * doing re-login since incomplete FIP exchanged
-                * from last session may collide with exchanges
-                * in new session.
-                */
-               msleep(lport->r_a_tov);
+       if (lport->link_up)
                fc_lport_enter_flogi(lport);
-       }
 }
 
 /**
@@ -1481,6 +1473,7 @@ void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
                         void *lp_arg)
 {
        struct fc_lport *lport = lp_arg;
+       struct fc_frame_header *fh;
        struct fc_els_flogi *flp;
        u32 did;
        u16 csp_flags;
@@ -1508,49 +1501,56 @@ void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
                goto err;
        }
 
+       fh = fc_frame_header_get(fp);
        did = fc_frame_did(fp);
-       if (fc_frame_payload_op(fp) == ELS_LS_ACC && did) {
-               flp = fc_frame_payload_get(fp, sizeof(*flp));
-               if (flp) {
-                       mfs = ntohs(flp->fl_csp.sp_bb_data) &
-                               FC_SP_BB_DATA_MASK;
-                       if (mfs >= FC_SP_MIN_MAX_PAYLOAD &&
-                           mfs < lport->mfs)
-                               lport->mfs = mfs;
-                       csp_flags = ntohs(flp->fl_csp.sp_features);
-                       r_a_tov = ntohl(flp->fl_csp.sp_r_a_tov);
-                       e_d_tov = ntohl(flp->fl_csp.sp_e_d_tov);
-                       if (csp_flags & FC_SP_FT_EDTR)
-                               e_d_tov /= 1000000;
-
-                       lport->npiv_enabled = !!(csp_flags & FC_SP_FT_NPIV_ACC);
-
-                       if ((csp_flags & FC_SP_FT_FPORT) == 0) {
-                               if (e_d_tov > lport->e_d_tov)
-                                       lport->e_d_tov = e_d_tov;
-                               lport->r_a_tov = 2 * e_d_tov;
-                               fc_lport_set_port_id(lport, did, fp);
-                               printk(KERN_INFO "host%d: libfc: "
-                                      "Port (%6.6x) entered "
-                                      "point-to-point mode\n",
-                                      lport->host->host_no, did);
-                               fc_lport_ptp_setup(lport, fc_frame_sid(fp),
-                                                  get_unaligned_be64(
-                                                          &flp->fl_wwpn),
-                                                  get_unaligned_be64(
-                                                          &flp->fl_wwnn));
-                       } else {
-                               lport->e_d_tov = e_d_tov;
-                               lport->r_a_tov = r_a_tov;
-                               fc_host_fabric_name(lport->host) =
-                                       get_unaligned_be64(&flp->fl_wwnn);
-                               fc_lport_set_port_id(lport, did, fp);
-                               fc_lport_enter_dns(lport);
-                       }
-               }
-       } else {
-               FC_LPORT_DBG(lport, "FLOGI RJT or bad response\n");
+       if (fh->fh_r_ctl != FC_RCTL_ELS_REP || did == 0 ||
+           fc_frame_payload_op(fp) != ELS_LS_ACC) {
+               FC_LPORT_DBG(lport, "FLOGI not accepted or bad response\n");
                fc_lport_error(lport, fp);
+               goto err;
+       }
+
+       flp = fc_frame_payload_get(fp, sizeof(*flp));
+       if (!flp) {
+               FC_LPORT_DBG(lport, "FLOGI bad response\n");
+               fc_lport_error(lport, fp);
+               goto err;
+       }
+
+       mfs = ntohs(flp->fl_csp.sp_bb_data) &
+               FC_SP_BB_DATA_MASK;
+       if (mfs >= FC_SP_MIN_MAX_PAYLOAD &&
+           mfs < lport->mfs)
+               lport->mfs = mfs;
+       csp_flags = ntohs(flp->fl_csp.sp_features);
+       r_a_tov = ntohl(flp->fl_csp.sp_r_a_tov);
+       e_d_tov = ntohl(flp->fl_csp.sp_e_d_tov);
+       if (csp_flags & FC_SP_FT_EDTR)
+               e_d_tov /= 1000000;
+
+       lport->npiv_enabled = !!(csp_flags & FC_SP_FT_NPIV_ACC);
+
+       if ((csp_flags & FC_SP_FT_FPORT) == 0) {
+               if (e_d_tov > lport->e_d_tov)
+                       lport->e_d_tov = e_d_tov;
+               lport->r_a_tov = 2 * e_d_tov;
+               fc_lport_set_port_id(lport, did, fp);
+               printk(KERN_INFO "host%d: libfc: "
+                      "Port (%6.6x) entered "
+                      "point-to-point mode\n",
+                      lport->host->host_no, did);
+               fc_lport_ptp_setup(lport, fc_frame_sid(fp),
+                                  get_unaligned_be64(
+                                          &flp->fl_wwpn),
+                                  get_unaligned_be64(
+                                          &flp->fl_wwnn));
+       } else {
+               lport->e_d_tov = e_d_tov;
+               lport->r_a_tov = r_a_tov;
+               fc_host_fabric_name(lport->host) =
+                       get_unaligned_be64(&flp->fl_wwnn);
+               fc_lport_set_port_id(lport, did, fp);
+               fc_lport_enter_dns(lport);
        }
 
 out:
index 3105d5e..8dc1b32 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2000-2010 LSI Corporation.
+ *  Copyright (c) 2000-2011 LSI Corporation.
  *
  *
  *           Name:  mpi2.h
@@ -8,7 +8,7 @@
  *                  scatter/gather formats.
  *  Creation Date:  June 21, 2006
  *
- *  mpi2.h Version:  02.00.18
+ *  mpi2.h Version:  02.00.20
  *
  *  Version History
  *  ---------------
@@ -66,6 +66,9 @@
  *  08-11-10  02.00.17  Bumped MPI2_HEADER_VERSION_UNIT.
  *  11-10-10  02.00.18  Bumped MPI2_HEADER_VERSION_UNIT.
  *                      Added MPI2_IEEE_SGE_FLAGS_SYSTEMPLBCPI_ADDR define.
+ *  02-23-11  02.00.19  Bumped MPI2_HEADER_VERSION_UNIT.
+ *                      Added MPI2_FUNCTION_SEND_HOST_MESSAGE.
+ *  03-09-11  02.00.20  Bumped MPI2_HEADER_VERSION_UNIT.
  *  --------------------------------------------------------------------------
  */
 
@@ -91,7 +94,7 @@
 #define MPI2_VERSION_02_00                  (0x0200)
 
 /* versioning for this MPI header set */
-#define MPI2_HEADER_VERSION_UNIT            (0x12)
+#define MPI2_HEADER_VERSION_UNIT            (0x14)
 #define MPI2_HEADER_VERSION_DEV             (0x00)
 #define MPI2_HEADER_VERSION_UNIT_MASK       (0xFF00)
 #define MPI2_HEADER_VERSION_UNIT_SHIFT      (8)
@@ -515,6 +518,8 @@ typedef union _MPI2_REPLY_DESCRIPTORS_UNION
 #define MPI2_FUNCTION_HOST_BASED_DISCOVERY_ACTION   (0x2F)
 /* Power Management Control */
 #define MPI2_FUNCTION_PWR_MGMT_CONTROL              (0x30)
+/* Send Host Message */
+#define MPI2_FUNCTION_SEND_HOST_MESSAGE             (0x31)
 /* beginning of product-specific range */
 #define MPI2_FUNCTION_MIN_PRODUCT_SPECIFIC          (0xF0)
 /* end of product-specific range */
index 61475a6..cfd95b4 100644 (file)
@@ -1,12 +1,12 @@
 /*
- *  Copyright (c) 2000-2010 LSI Corporation.
+ *  Copyright (c) 2000-2011 LSI Corporation.
  *
  *
  *           Name:  mpi2_cnfg.h
  *          Title:  MPI Configuration messages and pages
  *  Creation Date:  November 10, 2006
  *
- *    mpi2_cnfg.h Version:  02.00.17
+ *    mpi2_cnfg.h Version:  02.00.19
  *
  *  Version History
  *  ---------------
  *                      to MPI2_CONFIG_PAGE_IO_UNIT_7.
  *                      Added MPI2_CONFIG_EXTPAGETYPE_EXT_MANUFACTURING define
  *                      and MPI2_CONFIG_PAGE_EXT_MAN_PS structure.
+ *  02-23-11  02.00.18  Added ProxyVF_ID field to MPI2_CONFIG_REQUEST.
+ *                      Added IO Unit Page 8, IO Unit Page 9,
+ *                      and IO Unit Page 10.
+ *                      Added SASNotifyPrimitiveMasks field to
+ *                      MPI2_CONFIG_PAGE_IOC_7.
+ *  03-09-11  02.00.19  Fixed IO Unit Page 10 (to match the spec).
  *  --------------------------------------------------------------------------
  */
 
@@ -329,7 +335,9 @@ typedef struct _MPI2_CONFIG_REQUEST
     U8                      VP_ID;                      /* 0x08 */
     U8                      VF_ID;                      /* 0x09 */
     U16                     Reserved1;                  /* 0x0A */
-    U32                     Reserved2;                  /* 0x0C */
+       U8                      Reserved2;                  /* 0x0C */
+       U8                      ProxyVF_ID;                 /* 0x0D */
+       U16                     Reserved4;                  /* 0x0E */
     U32                     Reserved3;                  /* 0x10 */
     MPI2_CONFIG_PAGE_HEADER Header;                     /* 0x14 */
     U32                     PageAddress;                /* 0x18 */
@@ -915,6 +923,120 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_7 {
 #define MPI2_IOUNITPAGE7_BOARD_TEMP_FAHRENHEIT      (0x01)
 #define MPI2_IOUNITPAGE7_BOARD_TEMP_CELSIUS         (0x02)
 
+/* IO Unit Page 8 */
+
+#define MPI2_IOUNIT8_NUM_THRESHOLDS     (4)
+
+typedef struct _MPI2_IOUNIT8_SENSOR {
+       U16                     Flags;                /* 0x00 */
+       U16                     Reserved1;            /* 0x02 */
+       U16
+               Threshold[MPI2_IOUNIT8_NUM_THRESHOLDS]; /* 0x04 */
+       U32                     Reserved2;            /* 0x0C */
+       U32                     Reserved3;            /* 0x10 */
+       U32                     Reserved4;            /* 0x14 */
+} MPI2_IOUNIT8_SENSOR, MPI2_POINTER PTR_MPI2_IOUNIT8_SENSOR,
+Mpi2IOUnit8Sensor_t, MPI2_POINTER pMpi2IOUnit8Sensor_t;
+
+/* defines for IO Unit Page 8 Sensor Flags field */
+#define MPI2_IOUNIT8_SENSOR_FLAGS_T3_ENABLE         (0x0008)
+#define MPI2_IOUNIT8_SENSOR_FLAGS_T2_ENABLE         (0x0004)
+#define MPI2_IOUNIT8_SENSOR_FLAGS_T1_ENABLE         (0x0002)
+#define MPI2_IOUNIT8_SENSOR_FLAGS_T0_ENABLE         (0x0001)
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check the value returned for NumSensors at runtime.
+ */
+#ifndef MPI2_IOUNITPAGE8_SENSOR_ENTRIES
+#define MPI2_IOUNITPAGE8_SENSOR_ENTRIES     (1)
+#endif
+
+typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_8 {
+       MPI2_CONFIG_PAGE_HEADER Header;               /* 0x00 */
+       U32                     Reserved1;            /* 0x04 */
+       U32                     Reserved2;            /* 0x08 */
+       U8                      NumSensors;           /* 0x0C */
+       U8                      PollingInterval;      /* 0x0D */
+       U16                     Reserved3;            /* 0x0E */
+       MPI2_IOUNIT8_SENSOR
+                       Sensor[MPI2_IOUNITPAGE8_SENSOR_ENTRIES];/* 0x10 */
+} MPI2_CONFIG_PAGE_IO_UNIT_8, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_8,
+Mpi2IOUnitPage8_t, MPI2_POINTER pMpi2IOUnitPage8_t;
+
+#define MPI2_IOUNITPAGE8_PAGEVERSION                    (0x00)
+
+
+/* IO Unit Page 9 */
+
+typedef struct _MPI2_IOUNIT9_SENSOR {
+       U16                     CurrentTemperature;     /* 0x00 */
+       U16                     Reserved1;              /* 0x02 */
+       U8                      Flags;                  /* 0x04 */
+       U8                      Reserved2;              /* 0x05 */
+       U16                     Reserved3;              /* 0x06 */
+       U32                     Reserved4;              /* 0x08 */
+       U32                     Reserved5;              /* 0x0C */
+} MPI2_IOUNIT9_SENSOR, MPI2_POINTER PTR_MPI2_IOUNIT9_SENSOR,
+Mpi2IOUnit9Sensor_t, MPI2_POINTER pMpi2IOUnit9Sensor_t;
+
+/* defines for IO Unit Page 9 Sensor Flags field */
+#define MPI2_IOUNIT9_SENSOR_FLAGS_TEMP_VALID        (0x01)
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check the value returned for NumSensors at runtime.
+ */
+#ifndef MPI2_IOUNITPAGE9_SENSOR_ENTRIES
+#define MPI2_IOUNITPAGE9_SENSOR_ENTRIES     (1)
+#endif
+
+typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_9 {
+       MPI2_CONFIG_PAGE_HEADER Header;                /* 0x00 */
+       U32                     Reserved1;             /* 0x04 */
+       U32                     Reserved2;             /* 0x08 */
+       U8                      NumSensors;            /* 0x0C */
+       U8                      Reserved4;             /* 0x0D */
+       U16                     Reserved3;             /* 0x0E */
+       MPI2_IOUNIT9_SENSOR
+                       Sensor[MPI2_IOUNITPAGE9_SENSOR_ENTRIES];/* 0x10 */
+} MPI2_CONFIG_PAGE_IO_UNIT_9, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_9,
+Mpi2IOUnitPage9_t, MPI2_POINTER pMpi2IOUnitPage9_t;
+
+#define MPI2_IOUNITPAGE9_PAGEVERSION                    (0x00)
+
+
+/* IO Unit Page 10 */
+
+typedef struct _MPI2_IOUNIT10_FUNCTION {
+       U8                      CreditPercent;      /* 0x00 */
+       U8                      Reserved1;          /* 0x01 */
+       U16                     Reserved2;          /* 0x02 */
+} MPI2_IOUNIT10_FUNCTION, MPI2_POINTER PTR_MPI2_IOUNIT10_FUNCTION,
+Mpi2IOUnit10Function_t, MPI2_POINTER pMpi2IOUnit10Function_t;
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check the value returned for NumFunctions at runtime.
+ */
+#ifndef MPI2_IOUNITPAGE10_FUNCTION_ENTRIES
+#define MPI2_IOUNITPAGE10_FUNCTION_ENTRIES      (1)
+#endif
+
+typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_10 {
+       MPI2_CONFIG_PAGE_HEADER Header;                    /* 0x00 */
+       U8                      NumFunctions;             /* 0x04 */
+       U8                      Reserved1;              /* 0x05 */
+       U16                     Reserved2;              /* 0x06 */
+       U32                     Reserved3;              /* 0x08 */
+       U32                     Reserved4;              /* 0x0C */
+       MPI2_IOUNIT10_FUNCTION
+               Function[MPI2_IOUNITPAGE10_FUNCTION_ENTRIES];/* 0x10 */
+} MPI2_CONFIG_PAGE_IO_UNIT_10, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_10,
+Mpi2IOUnitPage10_t, MPI2_POINTER pMpi2IOUnitPage10_t;
+
+#define MPI2_IOUNITPAGE10_PAGEVERSION                   (0x01)
+
 
 
 /****************************************************************************
@@ -1022,12 +1144,12 @@ typedef struct _MPI2_CONFIG_PAGE_IOC_7
     U32                     Reserved1;                  /* 0x04 */
     U32                     EventMasks[MPI2_IOCPAGE7_EVENTMASK_WORDS];/* 0x08 */
     U16                     SASBroadcastPrimitiveMasks; /* 0x18 */
-    U16                     Reserved2;                  /* 0x1A */
+       U16                     SASNotifyPrimitiveMasks;    /* 0x1A */
     U32                     Reserved3;                  /* 0x1C */
 } MPI2_CONFIG_PAGE_IOC_7, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IOC_7,
   Mpi2IOCPage7_t, MPI2_POINTER pMpi2IOCPage7_t;
 
-#define MPI2_IOCPAGE7_PAGEVERSION                       (0x01)
+#define MPI2_IOCPAGE7_PAGEVERSION                       (0x02)
 
 
 /* IOC Page 8 */
@@ -2070,16 +2192,16 @@ typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_8 {
 #define MPI2_SASIOUNITPAGE8_PAGEVERSION     (0x00)
 
 /* defines for PowerManagementCapabilities field */
-#define MPI2_SASIOUNIT8_PM_HOST_PORT_WIDTH_MOD          (0x000001000)
-#define MPI2_SASIOUNIT8_PM_HOST_SAS_SLUMBER_MODE        (0x000000800)
-#define MPI2_SASIOUNIT8_PM_HOST_SAS_PARTIAL_MODE        (0x000000400)
-#define MPI2_SASIOUNIT8_PM_HOST_SATA_SLUMBER_MODE       (0x000000200)
-#define MPI2_SASIOUNIT8_PM_HOST_SATA_PARTIAL_MODE       (0x000000100)
-#define MPI2_SASIOUNIT8_PM_IOUNIT_PORT_WIDTH_MOD        (0x000000010)
-#define MPI2_SASIOUNIT8_PM_IOUNIT_SAS_SLUMBER_MODE      (0x000000008)
-#define MPI2_SASIOUNIT8_PM_IOUNIT_SAS_PARTIAL_MODE      (0x000000004)
-#define MPI2_SASIOUNIT8_PM_IOUNIT_SATA_SLUMBER_MODE     (0x000000002)
-#define MPI2_SASIOUNIT8_PM_IOUNIT_SATA_PARTIAL_MODE     (0x000000001)
+#define MPI2_SASIOUNIT8_PM_HOST_PORT_WIDTH_MOD          (0x00001000)
+#define MPI2_SASIOUNIT8_PM_HOST_SAS_SLUMBER_MODE        (0x00000800)
+#define MPI2_SASIOUNIT8_PM_HOST_SAS_PARTIAL_MODE        (0x00000400)
+#define MPI2_SASIOUNIT8_PM_HOST_SATA_SLUMBER_MODE       (0x00000200)
+#define MPI2_SASIOUNIT8_PM_HOST_SATA_PARTIAL_MODE       (0x00000100)
+#define MPI2_SASIOUNIT8_PM_IOUNIT_PORT_WIDTH_MOD        (0x00000010)
+#define MPI2_SASIOUNIT8_PM_IOUNIT_SAS_SLUMBER_MODE      (0x00000008)
+#define MPI2_SASIOUNIT8_PM_IOUNIT_SAS_PARTIAL_MODE      (0x00000004)
+#define MPI2_SASIOUNIT8_PM_IOUNIT_SATA_SLUMBER_MODE     (0x00000002)
+#define MPI2_SASIOUNIT8_PM_IOUNIT_SATA_PARTIAL_MODE     (0x00000001)
 
 
 
@@ -2266,6 +2388,7 @@ typedef struct _MPI2_CONFIG_PAGE_SAS_DEV_0
 /* see mpi2_sas.h for values for SAS Device Page 0 DeviceInfo values */
 
 /* values for SAS Device Page 0 Flags field */
+#define MPI2_SAS_DEVICE0_FLAGS_UNAUTHORIZED_DEVICE          (0x8000)
 #define MPI2_SAS_DEVICE0_FLAGS_SLUMBER_PM_CAPABLE           (0x1000)
 #define MPI2_SAS_DEVICE0_FLAGS_PARTIAL_PM_CAPABLE           (0x0800)
 #define MPI2_SAS_DEVICE0_FLAGS_SATA_ASYNCHRONOUS_NOTIFY     (0x0400)
index 1f0c190..93d9b69 100644 (file)
@@ -1,12 +1,12 @@
 /*
- *  Copyright (c) 2000-2010 LSI Corporation.
+ *  Copyright (c) 2000-2011 LSI Corporation.
  *
  *
  *           Name:  mpi2_ioc.h
  *          Title:  MPI IOC, Port, Event, FW Download, and FW Upload messages
  *  Creation Date:  October 11, 2006
  *
- *  mpi2_ioc.h Version:  02.00.16
+ *  mpi2_ioc.h Version:  02.00.17
  *
  *  Version History
  *  ---------------
  *  05-12-10  02.00.15  Marked Task Set Full Event as obsolete.
  *                      Added MPI2_EVENT_SAS_TOPO_LR_UNSUPPORTED_PHY define.
  *  11-10-10  02.00.16  Added MPI2_FW_DOWNLOAD_ITYPE_MIN_PRODUCT_SPECIFIC.
+ *  02-23-11  02.00.17  Added SAS NOTIFY Primitive event, and added
+ *                      SASNotifyPrimitiveMasks field to
+ *                      MPI2_EVENT_NOTIFICATION_REQUEST.
+ *                      Added Temperature Threshold Event.
+ *                      Added Host Message Event.
+ *                      Added Send Host Message request and reply.
  *  --------------------------------------------------------------------------
  */
 
@@ -421,7 +427,7 @@ typedef struct _MPI2_EVENT_NOTIFICATION_REQUEST
     U32                     Reserved6;                      /* 0x10 */
     U32                     EventMasks[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS];/* 0x14 */
     U16                     SASBroadcastPrimitiveMasks;     /* 0x24 */
-    U16                     Reserved7;                      /* 0x26 */
+        U16                     SASNotifyPrimitiveMasks;        /* 0x26 */
     U32                     Reserved8;                      /* 0x28 */
 } MPI2_EVENT_NOTIFICATION_REQUEST,
   MPI2_POINTER PTR_MPI2_EVENT_NOTIFICATION_REQUEST,
@@ -476,6 +482,9 @@ typedef struct _MPI2_EVENT_NOTIFICATION_REPLY
 #define MPI2_EVENT_GPIO_INTERRUPT                   (0x0023)
 #define MPI2_EVENT_HOST_BASED_DISCOVERY_PHY         (0x0024)
 #define MPI2_EVENT_SAS_QUIESCE                      (0x0025)
+#define MPI2_EVENT_SAS_NOTIFY_PRIMITIVE             (0x0026)
+#define MPI2_EVENT_TEMP_THRESHOLD                   (0x0027)
+#define MPI2_EVENT_HOST_MESSAGE                     (0x0028)
 
 
 /* Log Entry Added Event data */
@@ -507,6 +516,39 @@ typedef struct _MPI2_EVENT_DATA_GPIO_INTERRUPT {
   MPI2_POINTER PTR_MPI2_EVENT_DATA_GPIO_INTERRUPT,
   Mpi2EventDataGpioInterrupt_t, MPI2_POINTER pMpi2EventDataGpioInterrupt_t;
 
+/* Temperature Threshold Event data */
+
+typedef struct _MPI2_EVENT_DATA_TEMPERATURE {
+       U16         Status;                             /* 0x00 */
+       U8          SensorNum;                          /* 0x02 */
+       U8          Reserved1;                          /* 0x03 */
+       U16         CurrentTemperature;                 /* 0x04 */
+       U16         Reserved2;                          /* 0x06 */
+       U32         Reserved3;                          /* 0x08 */
+       U32         Reserved4;                          /* 0x0C */
+} MPI2_EVENT_DATA_TEMPERATURE,
+MPI2_POINTER PTR_MPI2_EVENT_DATA_TEMPERATURE,
+Mpi2EventDataTemperature_t, MPI2_POINTER pMpi2EventDataTemperature_t;
+
+/* Temperature Threshold Event data Status bits */
+#define MPI2_EVENT_TEMPERATURE3_EXCEEDED            (0x0008)
+#define MPI2_EVENT_TEMPERATURE2_EXCEEDED            (0x0004)
+#define MPI2_EVENT_TEMPERATURE1_EXCEEDED            (0x0002)
+#define MPI2_EVENT_TEMPERATURE0_EXCEEDED            (0x0001)
+
+
+/* Host Message Event data */
+
+typedef struct _MPI2_EVENT_DATA_HOST_MESSAGE {
+       U8          SourceVF_ID;                        /* 0x00 */
+       U8          Reserved1;                          /* 0x01 */
+       U16         Reserved2;                          /* 0x02 */
+       U32         Reserved3;                          /* 0x04 */
+       U32         HostData[1];                        /* 0x08 */
+} MPI2_EVENT_DATA_HOST_MESSAGE, MPI2_POINTER PTR_MPI2_EVENT_DATA_HOST_MESSAGE,
+Mpi2EventDataHostMessage_t, MPI2_POINTER pMpi2EventDataHostMessage_t;
+
+
 /* Hard Reset Received Event data */
 
 typedef struct _MPI2_EVENT_DATA_HARD_RESET_RECEIVED
@@ -749,6 +791,24 @@ typedef struct _MPI2_EVENT_DATA_SAS_BROADCAST_PRIMITIVE
 #define MPI2_EVENT_PRIMITIVE_CHANGE0_RESERVED               (0x07)
 #define MPI2_EVENT_PRIMITIVE_CHANGE1_RESERVED               (0x08)
 
+/* SAS Notify Primitive Event data */
+
+typedef struct _MPI2_EVENT_DATA_SAS_NOTIFY_PRIMITIVE {
+       U8                      PhyNum;                     /* 0x00 */
+       U8                      Port;                       /* 0x01 */
+       U8                      Reserved1;                  /* 0x02 */
+       U8                      Primitive;                  /* 0x03 */
+} MPI2_EVENT_DATA_SAS_NOTIFY_PRIMITIVE,
+MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_NOTIFY_PRIMITIVE,
+Mpi2EventDataSasNotifyPrimitive_t,
+MPI2_POINTER pMpi2EventDataSasNotifyPrimitive_t;
+
+/* defines for the Primitive field */
+#define MPI2_EVENT_NOTIFY_ENABLE_SPINUP                     (0x01)
+#define MPI2_EVENT_NOTIFY_POWER_LOSS_EXPECTED               (0x02)
+#define MPI2_EVENT_NOTIFY_RESERVED1                         (0x03)
+#define MPI2_EVENT_NOTIFY_RESERVED2                         (0x04)
+
 
 /* SAS Initiator Device Status Change Event data */
 
@@ -1001,6 +1061,53 @@ typedef struct _MPI2_EVENT_ACK_REPLY
 
 
 /****************************************************************************
+*  SendHostMessage message
+****************************************************************************/
+
+/* SendHostMessage Request message */
+typedef struct _MPI2_SEND_HOST_MESSAGE_REQUEST {
+       U16                     HostDataLength;                 /* 0x00 */
+       U8                      ChainOffset;                    /* 0x02 */
+       U8                      Function;                       /* 0x03 */
+       U16                     Reserved1;                      /* 0x04 */
+       U8                      Reserved2;                      /* 0x06 */
+       U8                      MsgFlags;                       /* 0x07 */
+       U8                      VP_ID;                          /* 0x08 */
+       U8                      VF_ID;                          /* 0x09 */
+       U16                     Reserved3;                      /* 0x0A */
+       U8                      Reserved4;                      /* 0x0C */
+       U8                      DestVF_ID;                      /* 0x0D */
+       U16                     Reserved5;                      /* 0x0E */
+       U32                     Reserved6;                      /* 0x10 */
+       U32                     Reserved7;                      /* 0x14 */
+       U32                     Reserved8;                      /* 0x18 */
+       U32                     Reserved9;                      /* 0x1C */
+       U32                     Reserved10;                     /* 0x20 */
+       U32                     HostData[1];                    /* 0x24 */
+} MPI2_SEND_HOST_MESSAGE_REQUEST,
+MPI2_POINTER PTR_MPI2_SEND_HOST_MESSAGE_REQUEST,
+Mpi2SendHostMessageRequest_t, MPI2_POINTER pMpi2SendHostMessageRequest_t;
+
+
+/* SendHostMessage Reply message */
+typedef struct _MPI2_SEND_HOST_MESSAGE_REPLY {
+       U16                     HostDataLength;                 /* 0x00 */
+       U8                      MsgLength;                      /* 0x02 */
+       U8                      Function;                       /* 0x03 */
+       U16                     Reserved1;                      /* 0x04 */
+       U8                      Reserved2;                      /* 0x06 */
+       U8                      MsgFlags;                       /* 0x07 */
+       U8                      VP_ID;                          /* 0x08 */
+       U8                      VF_ID;                          /* 0x09 */
+       U16                     Reserved3;                      /* 0x0A */
+       U16                     Reserved4;                      /* 0x0C */
+       U16                     IOCStatus;                      /* 0x0E */
+       U32                     IOCLogInfo;                     /* 0x10 */
+} MPI2_SEND_HOST_MESSAGE_REPLY, MPI2_POINTER PTR_MPI2_SEND_HOST_MESSAGE_REPLY,
+Mpi2SendHostMessageReply_t, MPI2_POINTER pMpi2SendHostMessageReply_t;
+
+
+/****************************************************************************
 *  FWDownload message
 ****************************************************************************/
 
index 81209ca..beda04a 100644 (file)
@@ -81,6 +81,15 @@ static int missing_delay[2] = {-1, -1};
 module_param_array(missing_delay, int, NULL, 0);
 MODULE_PARM_DESC(missing_delay, " device missing delay , io missing delay");
 
+static int mpt2sas_fwfault_debug;
+MODULE_PARM_DESC(mpt2sas_fwfault_debug, " enable detection of firmware fault "
+       "and halt firmware - (default=0)");
+
+static int disable_discovery = -1;
+module_param(disable_discovery, int, 0);
+MODULE_PARM_DESC(disable_discovery, " disable discovery ");
+
+
 /* diag_buffer_enable is bitwise
  * bit 0 set = TRACE
  * bit 1 set = SNAPSHOT
@@ -93,14 +102,6 @@ module_param(diag_buffer_enable, int, 0);
 MODULE_PARM_DESC(diag_buffer_enable, " post diag buffers "
     "(TRACE=1/SNAPSHOT=2/EXTENDED=4/default=0)");
 
-static int mpt2sas_fwfault_debug;
-MODULE_PARM_DESC(mpt2sas_fwfault_debug, " enable detection of firmware fault "
-    "and halt firmware - (default=0)");
-
-static int disable_discovery = -1;
-module_param(disable_discovery, int, 0);
-MODULE_PARM_DESC(disable_discovery, " disable discovery ");
-
 /**
  * _scsih_set_fwfault_debug - global setting of ioc->fwfault_debug.
  *
@@ -691,6 +692,7 @@ mpt2sas_base_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
                memcpy(ioc->base_cmds.reply, mpi_reply, mpi_reply->MsgLength*4);
        }
        ioc->base_cmds.status &= ~MPT2_CMD_PENDING;
+
        complete(&ioc->base_cmds.done);
        return 1;
 }
@@ -3470,6 +3472,58 @@ _base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
 }
 
 /**
+ * mpt2sas_port_enable_done - command completion routine for port enable
+ * @ioc: per adapter object
+ * @smid: system request message index
+ * @msix_index: MSIX table index supplied by the OS
+ * @reply: reply message frame(lower 32bit addr)
+ *
+ * Return 1 meaning mf should be freed from _base_interrupt
+ *        0 means the mf is freed from this function.
+ */
+u8
+mpt2sas_port_enable_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
+       u32 reply)
+{
+       MPI2DefaultReply_t *mpi_reply;
+       u16 ioc_status;
+
+       mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
+       if (mpi_reply && mpi_reply->Function == MPI2_FUNCTION_EVENT_ACK)
+               return 1;
+
+       if (ioc->port_enable_cmds.status == MPT2_CMD_NOT_USED)
+               return 1;
+
+       ioc->port_enable_cmds.status |= MPT2_CMD_COMPLETE;
+       if (mpi_reply) {
+               ioc->port_enable_cmds.status |= MPT2_CMD_REPLY_VALID;
+               memcpy(ioc->port_enable_cmds.reply, mpi_reply,
+                   mpi_reply->MsgLength*4);
+       }
+       ioc->port_enable_cmds.status &= ~MPT2_CMD_PENDING;
+
+       ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
+
+       if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
+               ioc->port_enable_failed = 1;
+
+       if (ioc->is_driver_loading) {
+               if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
+                       mpt2sas_port_enable_complete(ioc);
+                       return 1;
+               } else {
+                       ioc->start_scan_failed = ioc_status;
+                       ioc->start_scan = 0;
+                       return 1;
+               }
+       }
+       complete(&ioc->port_enable_cmds.done);
+       return 1;
+}
+
+
+/**
  * _base_send_port_enable - send port_enable(discovery stuff) to firmware
  * @ioc: per adapter object
  * @sleep_flag: CAN_SLEEP or NO_SLEEP
@@ -3480,67 +3534,151 @@ static int
 _base_send_port_enable(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
 {
        Mpi2PortEnableRequest_t *mpi_request;
-       u32 ioc_state;
+       Mpi2PortEnableReply_t *mpi_reply;
        unsigned long timeleft;
        int r = 0;
        u16 smid;
+       u16 ioc_status;
 
        printk(MPT2SAS_INFO_FMT "sending port enable !!\n", ioc->name);
 
-       if (ioc->base_cmds.status & MPT2_CMD_PENDING) {
+       if (ioc->port_enable_cmds.status & MPT2_CMD_PENDING) {
                printk(MPT2SAS_ERR_FMT "%s: internal command already in use\n",
                    ioc->name, __func__);
                return -EAGAIN;
        }
 
-       smid = mpt2sas_base_get_smid(ioc, ioc->base_cb_idx);
+       smid = mpt2sas_base_get_smid(ioc, ioc->port_enable_cb_idx);
        if (!smid) {
                printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
                    ioc->name, __func__);
                return -EAGAIN;
        }
 
-       ioc->base_cmds.status = MPT2_CMD_PENDING;
+       ioc->port_enable_cmds.status = MPT2_CMD_PENDING;
        mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
-       ioc->base_cmds.smid = smid;
+       ioc->port_enable_cmds.smid = smid;
        memset(mpi_request, 0, sizeof(Mpi2PortEnableRequest_t));
        mpi_request->Function = MPI2_FUNCTION_PORT_ENABLE;
-       mpi_request->VF_ID = 0; /* TODO */
-       mpi_request->VP_ID = 0;
 
+       init_completion(&ioc->port_enable_cmds.done);
        mpt2sas_base_put_smid_default(ioc, smid);
-       init_completion(&ioc->base_cmds.done);
-       timeleft = wait_for_completion_timeout(&ioc->base_cmds.done,
+       timeleft = wait_for_completion_timeout(&ioc->port_enable_cmds.done,
            300*HZ);
-       if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) {
+       if (!(ioc->port_enable_cmds.status & MPT2_CMD_COMPLETE)) {
                printk(MPT2SAS_ERR_FMT "%s: timeout\n",
                    ioc->name, __func__);
                _debug_dump_mf(mpi_request,
                    sizeof(Mpi2PortEnableRequest_t)/4);
-               if (ioc->base_cmds.status & MPT2_CMD_RESET)
+               if (ioc->port_enable_cmds.status & MPT2_CMD_RESET)
                        r = -EFAULT;
                else
                        r = -ETIME;
                goto out;
-       } else
-               dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: complete\n",
-                   ioc->name, __func__));
+       }
+       mpi_reply = ioc->port_enable_cmds.reply;
 
-       ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_OPERATIONAL,
-           60, sleep_flag);
-       if (ioc_state) {
-               printk(MPT2SAS_ERR_FMT "%s: failed going to operational state "
-                   " (ioc_state=0x%x)\n", ioc->name, __func__, ioc_state);
+       ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
+       if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+               printk(MPT2SAS_ERR_FMT "%s: failed with (ioc_status=0x%08x)\n",
+                   ioc->name, __func__, ioc_status);
                r = -EFAULT;
+               goto out;
        }
  out:
-       ioc->base_cmds.status = MPT2_CMD_NOT_USED;
-       printk(MPT2SAS_INFO_FMT "port enable: %s\n",
-           ioc->name, ((r == 0) ? "SUCCESS" : "FAILED"));
+       ioc->port_enable_cmds.status = MPT2_CMD_NOT_USED;
+       printk(MPT2SAS_INFO_FMT "port enable: %s\n", ioc->name, ((r == 0) ?
+           "SUCCESS" : "FAILED"));
        return r;
 }
 
 /**
+ * mpt2sas_port_enable - initiate firmware discovery (don't wait for reply)
+ * @ioc: per adapter object
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt2sas_port_enable(struct MPT2SAS_ADAPTER *ioc)
+{
+       Mpi2PortEnableRequest_t *mpi_request;
+       u16 smid;
+
+       printk(MPT2SAS_INFO_FMT "sending port enable !!\n", ioc->name);
+
+       if (ioc->port_enable_cmds.status & MPT2_CMD_PENDING) {
+               printk(MPT2SAS_ERR_FMT "%s: internal command already in use\n",
+                   ioc->name, __func__);
+               return -EAGAIN;
+       }
+
+       smid = mpt2sas_base_get_smid(ioc, ioc->port_enable_cb_idx);
+       if (!smid) {
+               printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
+                   ioc->name, __func__);
+               return -EAGAIN;
+       }
+
+       ioc->port_enable_cmds.status = MPT2_CMD_PENDING;
+       mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
+       ioc->port_enable_cmds.smid = smid;
+       memset(mpi_request, 0, sizeof(Mpi2PortEnableRequest_t));
+       mpi_request->Function = MPI2_FUNCTION_PORT_ENABLE;
+
+       mpt2sas_base_put_smid_default(ioc, smid);
+       return 0;
+}
+
+/**
+ * _base_determine_wait_on_discovery - desposition
+ * @ioc: per adapter object
+ *
+ * Decide whether to wait on discovery to complete. Used to either
+ * locate boot device, or report volumes ahead of physical devices.
+ *
+ * Returns 1 for wait, 0 for don't wait
+ */
+static int
+_base_determine_wait_on_discovery(struct MPT2SAS_ADAPTER *ioc)
+{
+       /* We wait for discovery to complete if IR firmware is loaded.
+        * The sas topology events arrive before PD events, so we need time to
+        * turn on the bit in ioc->pd_handles to indicate PD
+        * Also, it maybe required to report Volumes ahead of physical
+        * devices when MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING is set.
+        */
+       if (ioc->ir_firmware)
+               return 1;
+
+       /* if no Bios, then we don't need to wait */
+       if (!ioc->bios_pg3.BiosVersion)
+               return 0;
+
+       /* Bios is present, then we drop down here.
+        *
+        * If there any entries in the Bios Page 2, then we wait
+        * for discovery to complete.
+        */
+
+       /* Current Boot Device */
+       if ((ioc->bios_pg2.CurrentBootDeviceForm &
+           MPI2_BIOSPAGE2_FORM_MASK) ==
+           MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED &&
+       /* Request Boot Device */
+          (ioc->bios_pg2.ReqBootDeviceForm &
+           MPI2_BIOSPAGE2_FORM_MASK) ==
+           MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED &&
+       /* Alternate Request Boot Device */
+          (ioc->bios_pg2.ReqAltBootDeviceForm &
+           MPI2_BIOSPAGE2_FORM_MASK) ==
+           MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED)
+               return 0;
+
+       return 1;
+}
+
+
+/**
  * _base_unmask_events - turn on notification for this event
  * @ioc: per adapter object
  * @event: firmware event
@@ -3962,6 +4100,7 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
  skip_init_reply_post_host_index:
 
        _base_unmask_interrupts(ioc);
+
        r = _base_event_notification(ioc, sleep_flag);
        if (r)
                return r;
@@ -3969,7 +4108,18 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
        if (sleep_flag == CAN_SLEEP)
                _base_static_config_pages(ioc);
 
-       if (ioc->wait_for_port_enable_to_complete && ioc->is_warpdrive) {
+
+       if (ioc->is_driver_loading) {
+
+
+
+               ioc->wait_for_discovery_to_complete =
+                   _base_determine_wait_on_discovery(ioc);
+               return r; /* scan_start and scan_finished support */
+       }
+
+
+       if (ioc->wait_for_discovery_to_complete && ioc->is_warpdrive) {
                if (ioc->manu_pg10.OEMIdentifier  == 0x80) {
                        hide_flag = (u8) (ioc->manu_pg10.OEMSpecificFlags0 &
                            MFG_PAGE10_HIDE_SSDS_MASK);
@@ -3978,13 +4128,6 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
                }
        }
 
-       if (ioc->wait_for_port_enable_to_complete) {
-               if (diag_buffer_enable != 0)
-                       mpt2sas_enable_diag_buffer(ioc, diag_buffer_enable);
-               if (disable_discovery > 0)
-                       return r;
-       }
-
        r = _base_send_port_enable(ioc, sleep_flag);
        if (r)
                return r;
@@ -4121,6 +4264,10 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
        ioc->base_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
        ioc->base_cmds.status = MPT2_CMD_NOT_USED;
 
+       /* port_enable command bits */
+       ioc->port_enable_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
+       ioc->port_enable_cmds.status = MPT2_CMD_NOT_USED;
+
        /* transport internal command bits */
        ioc->transport_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
        ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
@@ -4162,8 +4309,6 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
                goto out_free_resources;
        }
 
-       init_completion(&ioc->shost_recovery_done);
-
        for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++)
                ioc->event_masks[i] = -1;
 
@@ -4186,7 +4331,6 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
                _base_update_missing_delay(ioc, missing_delay[0],
                    missing_delay[1]);
 
-       mpt2sas_base_start_watchdog(ioc);
        return 0;
 
  out_free_resources:
@@ -4204,6 +4348,7 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
        kfree(ioc->scsih_cmds.reply);
        kfree(ioc->config_cmds.reply);
        kfree(ioc->base_cmds.reply);
+       kfree(ioc->port_enable_cmds.reply);
        kfree(ioc->ctl_cmds.reply);
        kfree(ioc->ctl_cmds.sense);
        kfree(ioc->pfacts);
@@ -4243,6 +4388,7 @@ mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc)
        kfree(ioc->ctl_cmds.reply);
        kfree(ioc->ctl_cmds.sense);
        kfree(ioc->base_cmds.reply);
+       kfree(ioc->port_enable_cmds.reply);
        kfree(ioc->tm_cmds.reply);
        kfree(ioc->transport_cmds.reply);
        kfree(ioc->scsih_cmds.reply);
@@ -4284,6 +4430,20 @@ _base_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)
                        mpt2sas_base_free_smid(ioc, ioc->base_cmds.smid);
                        complete(&ioc->base_cmds.done);
                }
+               if (ioc->port_enable_cmds.status & MPT2_CMD_PENDING) {
+                       ioc->port_enable_failed = 1;
+                       ioc->port_enable_cmds.status |= MPT2_CMD_RESET;
+                       mpt2sas_base_free_smid(ioc, ioc->port_enable_cmds.smid);
+                       if (ioc->is_driver_loading) {
+                               ioc->start_scan_failed =
+                                   MPI2_IOCSTATUS_INTERNAL_ERROR;
+                               ioc->start_scan = 0;
+                               ioc->port_enable_cmds.status =
+                                               MPT2_CMD_NOT_USED;
+                       } else
+                               complete(&ioc->port_enable_cmds.done);
+
+               }
                if (ioc->config_cmds.status & MPT2_CMD_PENDING) {
                        ioc->config_cmds.status |= MPT2_CMD_RESET;
                        mpt2sas_base_free_smid(ioc, ioc->config_cmds.smid);
@@ -4349,7 +4509,6 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag,
 {
        int r;
        unsigned long flags;
-       u8 pe_complete = ioc->wait_for_port_enable_to_complete;
 
        dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name,
            __func__));
@@ -4396,7 +4555,8 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag,
        /* If this hard reset is called while port enable is active, then
         * there is no reason to call make_ioc_operational
         */
-       if (pe_complete) {
+       if (ioc->is_driver_loading && ioc->port_enable_failed) {
+               ioc->remove_host = 1;
                r = -EFAULT;
                goto out;
        }
@@ -4410,7 +4570,6 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag,
        spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
        ioc->ioc_reset_in_progress_status = r;
        ioc->shost_recovery = 0;
-       complete(&ioc->shost_recovery_done);
        spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
        mutex_unlock(&ioc->reset_in_progress_mutex);
 
index 59354db..3c3babc 100644 (file)
 #define MPT2SAS_DRIVER_NAME            "mpt2sas"
 #define MPT2SAS_AUTHOR "LSI Corporation <DL-MPTFusionLinux@lsi.com>"
 #define MPT2SAS_DESCRIPTION    "LSI MPT Fusion SAS 2.0 Device Driver"
-#define MPT2SAS_DRIVER_VERSION         "09.100.00.01"
-#define MPT2SAS_MAJOR_VERSION          09
+#define MPT2SAS_DRIVER_VERSION         "10.100.00.00"
+#define MPT2SAS_MAJOR_VERSION          10
 #define MPT2SAS_MINOR_VERSION          100
 #define MPT2SAS_BUILD_VERSION          00
-#define MPT2SAS_RELEASE_VERSION                01
+#define MPT2SAS_RELEASE_VERSION                00
 
 /*
  * Set MPT2SAS_SG_DEPTH value based on user input.
@@ -655,7 +655,12 @@ enum mutex_type {
  * @ignore_loginfos: ignore loginfos during task management
  * @remove_host: flag for when driver unloads, to avoid sending dev resets
  * @pci_error_recovery: flag to prevent ioc access until slot reset completes
- * @wait_for_port_enable_to_complete:
+ * @wait_for_discovery_to_complete: flag set at driver load time when
+ *                                               waiting on reporting devices
+ * @is_driver_loading: flag set at driver load time
+ * @port_enable_failed: flag set when port enable has failed
+ * @start_scan: flag set from scan_start callback, cleared from _mpt2sas_fw_work
+ * @start_scan_failed: means port enable failed, return's the ioc_status
  * @msix_enable: flag indicating msix is enabled
  * @msix_vector_count: number msix vectors
  * @cpu_msix_table: table for mapping cpus to msix index
@@ -790,15 +795,20 @@ struct MPT2SAS_ADAPTER {
        u8              shost_recovery;
 
        struct mutex    reset_in_progress_mutex;
-       struct completion       shost_recovery_done;
        spinlock_t      ioc_reset_in_progress_lock;
        u8              ioc_link_reset_in_progress;
-       int             ioc_reset_in_progress_status;
+       u8              ioc_reset_in_progress_status;
 
        u8              ignore_loginfos;
        u8              remove_host;
        u8              pci_error_recovery;
-       u8              wait_for_port_enable_to_complete;
+       u8              wait_for_discovery_to_complete;
+       struct completion       port_enable_done;
+       u8              is_driver_loading;
+       u8              port_enable_failed;
+
+       u8              start_scan;
+       u16             start_scan_failed;
 
        u8              msix_enable;
        u16             msix_vector_count;
@@ -814,11 +824,13 @@ struct MPT2SAS_ADAPTER {
        u8              scsih_cb_idx;
        u8              ctl_cb_idx;
        u8              base_cb_idx;
+       u8              port_enable_cb_idx;
        u8              config_cb_idx;
        u8              tm_tr_cb_idx;
        u8              tm_tr_volume_cb_idx;
        u8              tm_sas_control_cb_idx;
        struct _internal_cmd base_cmds;
+       struct _internal_cmd port_enable_cmds;
        struct _internal_cmd transport_cmds;
        struct _internal_cmd scsih_cmds;
        struct _internal_cmd tm_cmds;
@@ -1001,6 +1013,8 @@ void mpt2sas_base_release_callback_handler(u8 cb_idx);
 
 u8 mpt2sas_base_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
     u32 reply);
+u8 mpt2sas_port_enable_done(struct MPT2SAS_ADAPTER *ioc, u16 smid,
+       u8 msix_index,  u32 reply);
 void *mpt2sas_base_get_reply_virt_addr(struct MPT2SAS_ADAPTER *ioc, u32 phys_addr);
 
 u32 mpt2sas_base_get_iocstate(struct MPT2SAS_ADAPTER *ioc, int cooked);
@@ -1015,6 +1029,8 @@ void mpt2sas_base_validate_event_type(struct MPT2SAS_ADAPTER *ioc, u32 *event_ty
 
 void mpt2sas_halt_firmware(struct MPT2SAS_ADAPTER *ioc);
 
+int mpt2sas_port_enable(struct MPT2SAS_ADAPTER *ioc);
+
 /* scsih shared API */
 u8 mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index,
     u32 reply);
@@ -1032,6 +1048,8 @@ struct _sas_node *mpt2sas_scsih_expander_find_by_sas_address(struct MPT2SAS_ADAP
 struct _sas_device *mpt2sas_scsih_sas_device_find_by_sas_address(
     struct MPT2SAS_ADAPTER *ioc, u64 sas_address);
 
+void mpt2sas_port_enable_complete(struct MPT2SAS_ADAPTER *ioc);
+
 void mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase);
 
 /* config shared API */
index 2b11010..36ea0b2 100644 (file)
@@ -1356,6 +1356,9 @@ mpt2sas_config_get_volume_handle(struct MPT2SAS_ADAPTER *ioc, u16 pd_handle,
        Mpi2ConfigReply_t mpi_reply;
        int r, i, config_page_sz;
        u16 ioc_status;
+       int config_num;
+       u16 element_type;
+       u16 phys_disk_dev_handle;
 
        *volume_handle = 0;
        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
@@ -1371,35 +1374,53 @@ mpt2sas_config_get_volume_handle(struct MPT2SAS_ADAPTER *ioc, u16 pd_handle,
        if (r)
                goto out;
 
-       mpi_request.PageAddress =
-           cpu_to_le32(MPI2_RAID_PGAD_FORM_ACTIVE_CONFIG);
        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
        config_page_sz = (le16_to_cpu(mpi_reply.ExtPageLength) * 4);
        config_page = kmalloc(config_page_sz, GFP_KERNEL);
-       if (!config_page)
-               goto out;
-       r = _config_request(ioc, &mpi_request, &mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
-           config_page_sz);
-       if (r)
+       if (!config_page) {
+               r = -1;
                goto out;
-
-       r = -1;
-       ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
-       if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
-               goto out;
-       for (i = 0; i < config_page->NumElements; i++) {
-               if ((le16_to_cpu(config_page->ConfigElement[i].ElementFlags) &
-                   MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE) !=
-                   MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT)
-                       continue;
-               if (le16_to_cpu(config_page->ConfigElement[i].
-                   PhysDiskDevHandle) == pd_handle) {
-                       *volume_handle = le16_to_cpu(config_page->
-                           ConfigElement[i].VolDevHandle);
-                       r = 0;
+       }
+       config_num = 0xff;
+       while (1) {
+               mpi_request.PageAddress = cpu_to_le32(config_num +
+                   MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM);
+               r = _config_request(ioc, &mpi_request, &mpi_reply,
+                   MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
+                   config_page_sz);
+               if (r)
+                       goto out;
+               r = -1;
+               ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+                   MPI2_IOCSTATUS_MASK;
+               if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
                        goto out;
+               for (i = 0; i < config_page->NumElements; i++) {
+                       element_type = le16_to_cpu(config_page->
+                           ConfigElement[i].ElementFlags) &
+                           MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE;
+                       if (element_type ==
+                           MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT ||
+                           element_type ==
+                           MPI2_RAIDCONFIG0_EFLAGS_OCE_ELEMENT) {
+                               phys_disk_dev_handle =
+                                   le16_to_cpu(config_page->ConfigElement[i].
+                                   PhysDiskDevHandle);
+                               if (phys_disk_dev_handle == pd_handle) {
+                                       *volume_handle =
+                                           le16_to_cpu(config_page->
+                                           ConfigElement[i].VolDevHandle);
+                                       r = 0;
+                                       goto out;
+                               }
+                       } else if (element_type ==
+                           MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT) {
+                               *volume_handle = 0;
+                               r = 0;
+                               goto out;
+                       }
                }
+               config_num = config_page->ConfigNum;
        }
  out:
        kfree(config_page);
index 9adb013..aabcb91 100644 (file)
@@ -1207,6 +1207,9 @@ _ctl_do_reset(void __user *arg)
        if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
                return -ENODEV;
 
+       if (ioc->shost_recovery || ioc->pci_error_recovery ||
+               ioc->is_driver_loading)
+               return -EAGAIN;
        dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name,
            __func__));
 
@@ -2178,7 +2181,8 @@ _ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg)
                    !ioc)
                        return -ENODEV;
 
-               if (ioc->shost_recovery || ioc->pci_error_recovery)
+               if (ioc->shost_recovery || ioc->pci_error_recovery ||
+                               ioc->is_driver_loading)
                        return -EAGAIN;
 
                if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_command)) {
@@ -2297,7 +2301,8 @@ _ctl_compat_mpt_command(struct file *file, unsigned cmd, unsigned long arg)
        if (_ctl_verify_adapter(karg32.hdr.ioc_number, &ioc) == -1 || !ioc)
                return -ENODEV;
 
-       if (ioc->shost_recovery || ioc->pci_error_recovery)
+       if (ioc->shost_recovery || ioc->pci_error_recovery ||
+                       ioc->is_driver_loading)
                return -EAGAIN;
 
        memset(&karg, 0, sizeof(struct mpt2_ioctl_command));
index 1da1aa1..8889b1b 100644 (file)
@@ -71,6 +71,9 @@ static void _firmware_event_work(struct work_struct *work);
 
 static u8 _scsih_check_for_pending_tm(struct MPT2SAS_ADAPTER *ioc, u16 smid);
 
+static void _scsih_scan_start(struct Scsi_Host *shost);
+static int _scsih_scan_finished(struct Scsi_Host *shost, unsigned long time);
+
 /* global parameters */
 LIST_HEAD(mpt2sas_ioc_list);
 
@@ -79,6 +82,7 @@ static u8 scsi_io_cb_idx = -1;
 static u8 tm_cb_idx = -1;
 static u8 ctl_cb_idx = -1;
 static u8 base_cb_idx = -1;
+static u8 port_enable_cb_idx = -1;
 static u8 transport_cb_idx = -1;
 static u8 scsih_cb_idx = -1;
 static u8 config_cb_idx = -1;
@@ -103,6 +107,18 @@ static int max_lun = MPT2SAS_MAX_LUN;
 module_param(max_lun, int, 0);
 MODULE_PARM_DESC(max_lun, " max lun, default=16895 ");
 
+/* diag_buffer_enable is bitwise
+ * bit 0 set = TRACE
+ * bit 1 set = SNAPSHOT
+ * bit 2 set = EXTENDED
+ *
+ * Either bit can be set, or both
+ */
+static int diag_buffer_enable = -1;
+module_param(diag_buffer_enable, int, 0);
+MODULE_PARM_DESC(diag_buffer_enable, " post diag buffers "
+       "(TRACE=1/SNAPSHOT=2/EXTENDED=4/default=0)");
+
 /**
  * struct sense_info - common structure for obtaining sense keys
  * @skey: sense key
@@ -117,8 +133,8 @@ struct sense_info {
 
 
 #define MPT2SAS_TURN_ON_FAULT_LED (0xFFFC)
-#define MPT2SAS_RESCAN_AFTER_HOST_RESET (0xFFFF)
-
+#define MPT2SAS_PORT_ENABLE_COMPLETE (0xFFFD)
+#define MPT2SAS_REMOVE_UNRESPONDING_DEVICES (0xFFFF)
 /**
  * struct fw_event_work - firmware event struct
  * @list: link list framework
@@ -372,31 +388,34 @@ _scsih_get_sas_address(struct MPT2SAS_ADAPTER *ioc, u16 handle,
        Mpi2SasDevicePage0_t sas_device_pg0;
        Mpi2ConfigReply_t mpi_reply;
        u32 ioc_status;
+       *sas_address = 0;
 
        if (handle <= ioc->sas_hba.num_phys) {
                *sas_address = ioc->sas_hba.sas_address;
                return 0;
-       } else
-               *sas_address = 0;
+       }
 
        if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
            MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
+               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", ioc->name,
+               __FILE__, __LINE__, __func__);
                return -ENXIO;
        }
 
-       ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
-           MPI2_IOCSTATUS_MASK;
-       if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
-               printk(MPT2SAS_ERR_FMT "handle(0x%04x), ioc_status(0x%04x)"
-                   "\nfailure at %s:%d/%s()!\n", ioc->name, handle, ioc_status,
-                    __FILE__, __LINE__, __func__);
-               return -EIO;
+       ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
+       if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
+               *sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
+               return 0;
        }
 
-       *sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
-       return 0;
+       /* we hit this becuase the given parent handle doesn't exist */
+       if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
+               return -ENXIO;
+       /* else error case */
+       printk(MPT2SAS_ERR_FMT "handle(0x%04x), ioc_status(0x%04x), "
+           "failure at %s:%d/%s()!\n", ioc->name, handle, ioc_status,
+            __FILE__, __LINE__, __func__);
+       return -EIO;
 }
 
 /**
@@ -424,7 +443,11 @@ _scsih_determine_boot_device(struct MPT2SAS_ADAPTER *ioc,
        u16 slot;
 
         /* only process this function when driver loads */
-       if (!ioc->wait_for_port_enable_to_complete)
+       if (!ioc->is_driver_loading)
+               return;
+
+        /* no Bios, return immediately */
+       if (!ioc->bios_pg3.BiosVersion)
                return;
 
        if (!is_raid) {
@@ -587,8 +610,15 @@ _scsih_sas_device_add(struct MPT2SAS_ADAPTER *ioc,
        spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
 
        if (!mpt2sas_transport_port_add(ioc, sas_device->handle,
-            sas_device->sas_address_parent))
+            sas_device->sas_address_parent)) {
                _scsih_sas_device_remove(ioc, sas_device);
+               } else if (!sas_device->starget) {
+                       if (!ioc->is_driver_loading)
+                               mpt2sas_transport_port_remove(ioc,
+                               sas_device->sas_address,
+                           sas_device->sas_address_parent);
+                       _scsih_sas_device_remove(ioc, sas_device);
+               }
 }
 
 /**
@@ -1400,6 +1430,10 @@ _scsih_slave_destroy(struct scsi_device *sdev)
 {
        struct MPT2SAS_TARGET *sas_target_priv_data;
        struct scsi_target *starget;
+       struct Scsi_Host *shost;
+       struct MPT2SAS_ADAPTER *ioc;
+       struct _sas_device *sas_device;
+       unsigned long flags;
 
        if (!sdev->hostdata)
                return;
@@ -1407,6 +1441,19 @@ _scsih_slave_destroy(struct scsi_device *sdev)
        starget = scsi_target(sdev);
        sas_target_priv_data = starget->hostdata;
        sas_target_priv_data->num_luns--;
+
+       shost = dev_to_shost(&starget->dev);
+       ioc = shost_priv(shost);
+
+       if (!(sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) {
+               spin_lock_irqsave(&ioc->sas_device_lock, flags);
+               sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
+                  sas_target_priv_data->sas_address);
+               if (sas_device)
+                       sas_device->starget = NULL;
+               spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+       }
+
        kfree(sdev->hostdata);
        sdev->hostdata = NULL;
 }
@@ -1598,8 +1645,10 @@ _scsih_set_level(struct scsi_device *sdev, struct _raid_device *raid_device)
  * _scsih_get_volume_capabilities - volume capabilities
  * @ioc: per adapter object
  * @sas_device: the raid_device object
+ *
+ * Returns 0 for success, else 1
  */
-static void
+static int
 _scsih_get_volume_capabilities(struct MPT2SAS_ADAPTER *ioc,
     struct _raid_device *raid_device)
 {
@@ -1612,9 +1661,10 @@ _scsih_get_volume_capabilities(struct MPT2SAS_ADAPTER *ioc,
 
        if ((mpt2sas_config_get_number_pds(ioc, raid_device->handle,
            &num_pds)) || !num_pds) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               return;
+               dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
+                   "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__,
+                   __func__));
+               return 1;
        }
 
        raid_device->num_pds = num_pds;
@@ -1622,17 +1672,19 @@ _scsih_get_volume_capabilities(struct MPT2SAS_ADAPTER *ioc,
            sizeof(Mpi2RaidVol0PhysDisk_t));
        vol_pg0 = kzalloc(sz, GFP_KERNEL);
        if (!vol_pg0) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               return;
+               dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
+                   "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__,
+                   __func__));
+               return 1;
        }
 
        if ((mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply, vol_pg0,
             MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, raid_device->handle, sz))) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
+               dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
+                   "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__,
+                   __func__));
                kfree(vol_pg0);
-               return;
+               return 1;
        }
 
        raid_device->volume_type = vol_pg0->VolumeType;
@@ -1652,6 +1704,7 @@ _scsih_get_volume_capabilities(struct MPT2SAS_ADAPTER *ioc,
        }
 
        kfree(vol_pg0);
+       return 0;
 }
 /**
  * _scsih_disable_ddio - Disable direct I/O for all the volumes
@@ -1922,13 +1975,20 @@ _scsih_slave_configure(struct scsi_device *sdev)
                     sas_target_priv_data->handle);
                spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
                if (!raid_device) {
-                       printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                           ioc->name, __FILE__, __LINE__, __func__);
-                       return 0;
+                       dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
+                           "failure at %s:%d/%s()!\n", ioc->name, __FILE__,
+                           __LINE__, __func__));
+                       return 1;
                }
 
                _scsih_get_volume_capabilities(ioc, raid_device);
 
+               if (_scsih_get_volume_capabilities(ioc, raid_device)) {
+                       dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
+                           "failure at %s:%d/%s()!\n", ioc->name, __FILE__,
+                           __LINE__, __func__));
+                       return 1;
+               }
                /*
                 * WARPDRIVE: Initialize the required data for Direct IO
                 */
@@ -2002,11 +2062,22 @@ _scsih_slave_configure(struct scsi_device *sdev)
        if (sas_device) {
                if (sas_target_priv_data->flags &
                    MPT_TARGET_FLAGS_RAID_COMPONENT) {
-                       mpt2sas_config_get_volume_handle(ioc,
-                           sas_device->handle, &sas_device->volume_handle);
-                       mpt2sas_config_get_volume_wwid(ioc,
+                       if (mpt2sas_config_get_volume_handle(ioc,
+                           sas_device->handle, &sas_device->volume_handle)) {
+                               dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
+                                   "failure at %s:%d/%s()!\n", ioc->name,
+                                   __FILE__, __LINE__, __func__));
+                               return 1;
+                       }
+                       if (sas_device->volume_handle &&
+                           mpt2sas_config_get_volume_wwid(ioc,
                            sas_device->volume_handle,
-                           &sas_device->volume_wwid);
+                           &sas_device->volume_wwid)) {
+                               dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
+                                   "failure at %s:%d/%s()!\n", ioc->name,
+                                   __FILE__, __LINE__, __func__));
+                               return 1;
+                       }
                }
                if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET) {
                        qdepth = MPT2SAS_SAS_QUEUE_DEPTH;
@@ -2035,6 +2106,11 @@ _scsih_slave_configure(struct scsi_device *sdev)
 
                if (!ssp_target)
                        _scsih_display_sata_capabilities(ioc, sas_device, sdev);
+       } else {
+               dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
+                   "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__,
+                   __func__));
+               return 1;
        }
 
        _scsih_change_queue_depth(sdev, qdepth, SCSI_QDEPTH_DEFAULT);
@@ -2714,22 +2790,38 @@ _scsih_fw_event_free(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work
 
 
 /**
- * _scsih_queue_rescan - queue a topology rescan from user context
+ * _scsih_error_recovery_delete_devices - remove devices not responding
  * @ioc: per adapter object
  *
  * Return nothing.
  */
 static void
-_scsih_queue_rescan(struct MPT2SAS_ADAPTER *ioc)
+_scsih_error_recovery_delete_devices(struct MPT2SAS_ADAPTER *ioc)
 {
        struct fw_event_work *fw_event;
 
-       if (ioc->wait_for_port_enable_to_complete)
+       if (ioc->is_driver_loading)
                return;
+       fw_event->event = MPT2SAS_REMOVE_UNRESPONDING_DEVICES;
+       fw_event->ioc = ioc;
+       _scsih_fw_event_add(ioc, fw_event);
+}
+
+/**
+ * mpt2sas_port_enable_complete - port enable completed (fake event)
+ * @ioc: per adapter object
+ *
+ * Return nothing.
+ */
+void
+mpt2sas_port_enable_complete(struct MPT2SAS_ADAPTER *ioc)
+{
+       struct fw_event_work *fw_event;
+
        fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
        if (!fw_event)
                return;
-       fw_event->event = MPT2SAS_RESCAN_AFTER_HOST_RESET;
+       fw_event->event = MPT2SAS_PORT_ENABLE_COMPLETE;
        fw_event->ioc = ioc;
        _scsih_fw_event_add(ioc, fw_event);
 }
@@ -2977,14 +3069,27 @@ _scsih_tm_tr_send(struct MPT2SAS_ADAPTER *ioc, u16 handle)
        Mpi2SCSITaskManagementRequest_t *mpi_request;
        u16 smid;
        struct _sas_device *sas_device;
-       struct MPT2SAS_TARGET *sas_target_priv_data;
+       struct MPT2SAS_TARGET *sas_target_priv_data = NULL;
+       u64 sas_address = 0;
        unsigned long flags;
        struct _tr_list *delayed_tr;
+       u32 ioc_state;
 
-       if (ioc->shost_recovery || ioc->remove_host ||
-           ioc->pci_error_recovery) {
-               dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host reset in "
-                  "progress!\n", __func__, ioc->name));
+       if (ioc->remove_host) {
+               dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host has been "
+                   "removed: handle(0x%04x)\n", __func__, ioc->name, handle));
+               return;
+       } else if (ioc->pci_error_recovery) {
+               dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host in pci "
+                   "error recovery: handle(0x%04x)\n", __func__, ioc->name,
+                   handle));
+               return;
+       }
+       ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
+       if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
+               dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host is not "
+                  "operational: handle(0x%04x)\n", __func__, ioc->name,
+                  handle));
                return;
        }
 
@@ -2998,13 +3103,18 @@ _scsih_tm_tr_send(struct MPT2SAS_ADAPTER *ioc, u16 handle)
             sas_device->starget->hostdata) {
                sas_target_priv_data = sas_device->starget->hostdata;
                sas_target_priv_data->deleted = 1;
-               dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
-                   "setting delete flag: handle(0x%04x), "
-                   "sas_addr(0x%016llx)\n", ioc->name, handle,
-                   (unsigned long long) sas_device->sas_address));
+               sas_address = sas_device->sas_address;
        }
        spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
 
+       if (sas_target_priv_data) {
+               dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "setting delete flag: "
+               "handle(0x%04x), sas_addr(0x%016llx)\n", ioc->name, handle,
+                       (unsigned long long)sas_address));
+               _scsih_ublock_io_device(ioc, handle);
+               sas_target_priv_data->handle = MPT2SAS_INVALID_DEVICE_HANDLE;
+       }
+
        smid = mpt2sas_base_get_smid_hpr(ioc, ioc->tm_tr_cb_idx);
        if (!smid) {
                delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC);
@@ -3185,11 +3295,21 @@ _scsih_tm_tr_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
            mpt2sas_base_get_reply_virt_addr(ioc, reply);
        Mpi2SasIoUnitControlRequest_t *mpi_request;
        u16 smid_sas_ctrl;
+       u32 ioc_state;
 
-       if (ioc->shost_recovery || ioc->remove_host ||
-           ioc->pci_error_recovery) {
-               dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host reset in "
-                  "progress!\n", __func__, ioc->name));
+       if (ioc->remove_host) {
+               dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host has been "
+                  "removed\n", __func__, ioc->name));
+               return 1;
+       } else if (ioc->pci_error_recovery) {
+               dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host in pci "
+                   "error recovery\n", __func__, ioc->name));
+               return 1;
+       }
+       ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
+       if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
+               dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host is not "
+                   "operational\n", __func__, ioc->name));
                return 1;
        }
 
@@ -5099,7 +5219,7 @@ _scsih_add_device(struct MPT2SAS_ADAPTER *ioc, u16 handle, u8 phy_num, u8 is_pd)
        /* get device name */
        sas_device->device_name = le64_to_cpu(sas_device_pg0.DeviceName);
 
-       if (ioc->wait_for_port_enable_to_complete)
+       if (ioc->wait_for_discovery_to_complete)
                _scsih_sas_device_init_add(ioc, sas_device);
        else
                _scsih_sas_device_add(ioc, sas_device);
@@ -5135,6 +5255,9 @@ _scsih_remove_device(struct MPT2SAS_ADAPTER *ioc,
        if (sas_device_backup.starget && sas_device_backup.starget->hostdata) {
                sas_target_priv_data = sas_device_backup.starget->hostdata;
                sas_target_priv_data->deleted = 1;
+               _scsih_ublock_io_device(ioc, sas_device_backup.handle);
+               sas_target_priv_data->handle =
+                    MPT2SAS_INVALID_DEVICE_HANDLE;
        }
 
        _scsih_ublock_io_device(ioc, sas_device_backup.handle);
@@ -5288,7 +5411,7 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc,
                _scsih_sas_topology_change_event_debug(ioc, event_data);
 #endif
 
-       if (ioc->shost_recovery || ioc->remove_host || ioc->pci_error_recovery)
+       if (ioc->remove_host || ioc->pci_error_recovery)
                return;
 
        if (!ioc->sas_hba.num_phys)
@@ -5349,6 +5472,9 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc,
                switch (reason_code) {
                case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED:
 
+                       if (ioc->shost_recovery)
+                               break;
+
                        if (link_rate == prev_link_rate)
                                break;
 
@@ -5362,6 +5488,9 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc,
                        break;
                case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED:
 
+                       if (ioc->shost_recovery)
+                               break;
+
                        mpt2sas_transport_update_links(ioc, sas_address,
                            handle, phy_number, link_rate);
 
@@ -5622,7 +5751,7 @@ broadcast_aen_retry:
        termination_count = 0;
        query_count = 0;
        for (smid = 1; smid <= ioc->scsiio_depth; smid++) {
-               if (ioc->ioc_reset_in_progress_status)
+               if (ioc->shost_recovery)
                        goto out;
                scmd = _scsih_scsi_lookup_get(ioc, smid);
                if (!scmd)
@@ -5644,7 +5773,7 @@ broadcast_aen_retry:
                lun = sas_device_priv_data->lun;
                query_count++;
 
-               if (ioc->ioc_reset_in_progress_status)
+               if (ioc->shost_recovery)
                        goto out;
 
                spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
@@ -5686,7 +5815,7 @@ broadcast_aen_retry:
                        goto broadcast_aen_retry;
                }
 
-               if (ioc->ioc_reset_in_progress_status)
+               if (ioc->shost_recovery)
                        goto out_no_lock;
 
                r = mpt2sas_scsih_issue_tm(ioc, handle, sdev->channel, sdev->id,
@@ -5725,7 +5854,7 @@ broadcast_aen_retry:
            ioc->name, __func__, query_count, termination_count));
 
        ioc->broadcast_aen_busy = 0;
-       if (!ioc->ioc_reset_in_progress_status)
+       if (!ioc->shost_recovery)
                _scsih_ublock_io_all_device(ioc);
        mutex_unlock(&ioc->tm_cmds.mutex);
 }
@@ -5789,8 +5918,11 @@ _scsih_reprobe_lun(struct scsi_device *sdev, void *no_uld_attach)
 static void
 _scsih_reprobe_target(struct scsi_target *starget, int no_uld_attach)
 {
-       struct MPT2SAS_TARGET *sas_target_priv_data = starget->hostdata;
+       struct MPT2SAS_TARGET *sas_target_priv_data;
 
+       if (starget == NULL)
+               return;
+       sas_target_priv_data = starget->hostdata;
        if (no_uld_attach)
                sas_target_priv_data->flags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
        else
@@ -5845,7 +5977,7 @@ _scsih_sas_volume_add(struct MPT2SAS_ADAPTER *ioc,
        raid_device->handle = handle;
        raid_device->wwid = wwid;
        _scsih_raid_device_add(ioc, raid_device);
-       if (!ioc->wait_for_port_enable_to_complete) {
+       if (!ioc->wait_for_discovery_to_complete) {
                rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
                    raid_device->id, 0);
                if (rc)
@@ -6127,6 +6259,10 @@ _scsih_sas_ir_config_change_event(struct MPT2SAS_ADAPTER *ioc,
                _scsih_sas_ir_config_change_event_debug(ioc, event_data);
 
 #endif
+
+       if (ioc->shost_recovery)
+               return;
+
        foreign_config = (le32_to_cpu(event_data->Flags) &
            MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ? 1 : 0;
 
@@ -6185,6 +6321,9 @@ _scsih_sas_ir_volume_event(struct MPT2SAS_ADAPTER *ioc,
        int rc;
        Mpi2EventDataIrVolume_t *event_data = fw_event->event_data;
 
+       if (ioc->shost_recovery)
+               return;
+
        if (event_data->ReasonCode != MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED)
                return;
 
@@ -6267,6 +6406,9 @@ _scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc,
        Mpi2EventDataIrPhysicalDisk_t *event_data = fw_event->event_data;
        u64 sas_address;
 
+       if (ioc->shost_recovery)
+               return;
+
        if (event_data->ReasonCode != MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED)
                return;
 
@@ -6510,10 +6652,10 @@ _scsih_search_responding_sas_devices(struct MPT2SAS_ADAPTER *ioc)
        u32 device_info;
        u16 slot;
 
-       printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__);
+       printk(MPT2SAS_INFO_FMT "search for end-devices: start\n", ioc->name);
 
        if (list_empty(&ioc->sas_device_list))
-               return;
+               goto out;
 
        handle = 0xFFFF;
        while (!(mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply,
@@ -6532,6 +6674,9 @@ _scsih_search_responding_sas_devices(struct MPT2SAS_ADAPTER *ioc)
                _scsih_mark_responding_sas_device(ioc, sas_address, slot,
                    handle);
        }
+out:
+       printk(MPT2SAS_INFO_FMT "search for end-devices: complete\n",
+           ioc->name);
 }
 
 /**
@@ -6607,10 +6752,14 @@ _scsih_search_responding_raid_devices(struct MPT2SAS_ADAPTER *ioc)
        u16 handle;
        u8 phys_disk_num;
 
-       printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__);
+       if (!ioc->ir_firmware)
+               return;
+
+       printk(MPT2SAS_INFO_FMT "search for raid volumes: start\n",
+           ioc->name);
 
        if (list_empty(&ioc->raid_device_list))
-               return;
+               goto out;
 
        handle = 0xFFFF;
        while (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
@@ -6649,6 +6798,9 @@ _scsih_search_responding_raid_devices(struct MPT2SAS_ADAPTER *ioc)
                        set_bit(handle, ioc->pd_handles);
                }
        }
+out:
+       printk(MPT2SAS_INFO_FMT "search for responding raid volumes: "
+           "complete\n", ioc->name);
 }
 
 /**
@@ -6708,10 +6860,10 @@ _scsih_search_responding_expanders(struct MPT2SAS_ADAPTER *ioc)
        u64 sas_address;
        u16 handle;
 
-       printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__);
+       printk(MPT2SAS_INFO_FMT "search for expanders: start\n", ioc->name);
 
        if (list_empty(&ioc->sas_expander_list))
-               return;
+               goto out;
 
        handle = 0xFFFF;
        while (!(mpt2sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0,
@@ -6730,6 +6882,8 @@ _scsih_search_responding_expanders(struct MPT2SAS_ADAPTER *ioc)
                _scsih_mark_responding_expander(ioc, sas_address, handle);
        }
 
+ out:
+       printk(MPT2SAS_INFO_FMT "search for expanders: complete\n", ioc->name);
 }
 
 /**
@@ -6745,6 +6899,8 @@ _scsih_remove_unresponding_sas_devices(struct MPT2SAS_ADAPTER *ioc)
        struct _sas_node *sas_expander;
        struct _raid_device *raid_device, *raid_device_next;
 
+       printk(MPT2SAS_INFO_FMT "removing unresponding devices: start\n",
+           ioc->name);
 
        list_for_each_entry_safe(sas_device, sas_device_next,
            &ioc->sas_device_list, list) {
@@ -6764,6 +6920,9 @@ _scsih_remove_unresponding_sas_devices(struct MPT2SAS_ADAPTER *ioc)
                _scsih_remove_device(ioc, sas_device);
        }
 
+       if (!ioc->ir_firmware)
+               goto retry_expander_search;
+
        list_for_each_entry_safe(raid_device, raid_device_next,
            &ioc->raid_device_list, list) {
                if (raid_device->responding) {
@@ -6790,52 +6949,170 @@ _scsih_remove_unresponding_sas_devices(struct MPT2SAS_ADAPTER *ioc)
                mpt2sas_expander_remove(ioc, sas_expander->sas_address);
                goto retry_expander_search;
        }
+       printk(MPT2SAS_INFO_FMT "removing unresponding devices: complete\n",
+           ioc->name);
+       /* unblock devices */
+       _scsih_ublock_io_all_device(ioc);
+}
+
+static void
+_scsih_refresh_expander_links(struct MPT2SAS_ADAPTER *ioc,
+       struct _sas_node *sas_expander, u16 handle)
+{
+       Mpi2ExpanderPage1_t expander_pg1;
+       Mpi2ConfigReply_t mpi_reply;
+       int i;
+
+       for (i = 0 ; i < sas_expander->num_phys ; i++) {
+               if ((mpt2sas_config_get_expander_pg1(ioc, &mpi_reply,
+                   &expander_pg1, i, handle))) {
+                       printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+                           ioc->name, __FILE__, __LINE__, __func__);
+                       return;
+               }
+
+               mpt2sas_transport_update_links(ioc, sas_expander->sas_address,
+                   le16_to_cpu(expander_pg1.AttachedDevHandle), i,
+                   expander_pg1.NegotiatedLinkRate >> 4);
+       }
 }
 
 /**
- * _scsih_hide_unhide_sas_devices - add/remove device to/from OS
+ * _scsih_scan_for_devices_after_reset - scan for devices after host reset
  * @ioc: per adapter object
  *
  * Return nothing.
  */
 static void
-_scsih_hide_unhide_sas_devices(struct MPT2SAS_ADAPTER *ioc)
+_scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc)
 {
-       struct _sas_device *sas_device, *sas_device_next;
+       Mpi2ExpanderPage0_t expander_pg0;
+       Mpi2SasDevicePage0_t sas_device_pg0;
+       Mpi2RaidVolPage1_t volume_pg1;
+       Mpi2RaidVolPage0_t volume_pg0;
+       Mpi2RaidPhysDiskPage0_t pd_pg0;
+       Mpi2EventIrConfigElement_t element;
+       Mpi2ConfigReply_t mpi_reply;
+       u8 phys_disk_num;
+       u16 ioc_status;
+       u16 handle, parent_handle;
+       u64 sas_address;
+       struct _sas_device *sas_device;
+       struct _sas_node *expander_device;
+       static struct _raid_device *raid_device;
 
-       if (!ioc->is_warpdrive || ioc->mfg_pg10_hide_flag !=
-           MFG_PAGE10_HIDE_IF_VOL_PRESENT)
-               return;
+       printk(MPT2SAS_INFO_FMT "scan devices: start\n", ioc->name);
 
-       if (ioc->hide_drives) {
-               if (_scsih_get_num_volumes(ioc))
-                       return;
-               ioc->hide_drives = 0;
-               list_for_each_entry_safe(sas_device, sas_device_next,
-                   &ioc->sas_device_list, list) {
-                       if (!mpt2sas_transport_port_add(ioc, sas_device->handle,
-                               sas_device->sas_address_parent)) {
-                               _scsih_sas_device_remove(ioc, sas_device);
-                       } else if (!sas_device->starget) {
-                               mpt2sas_transport_port_remove(ioc,
-                                   sas_device->sas_address,
-                                   sas_device->sas_address_parent);
-                               _scsih_sas_device_remove(ioc, sas_device);
-                       }
+       _scsih_sas_host_refresh(ioc);
+
+       /* expanders */
+       handle = 0xFFFF;
+       while (!(mpt2sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0,
+           MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL, handle))) {
+               ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+                   MPI2_IOCSTATUS_MASK;
+               if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
+                       break;
+               handle = le16_to_cpu(expander_pg0.DevHandle);
+               expander_device = mpt2sas_scsih_expander_find_by_sas_address(
+                   ioc, le64_to_cpu(expander_pg0.SASAddress));
+               if (expander_device)
+                       _scsih_refresh_expander_links(ioc, expander_device,
+                           handle);
+               else
+                       _scsih_expander_add(ioc, handle);
+       }
+
+       if (!ioc->ir_firmware)
+               goto skip_to_sas;
+
+       /* phys disk */
+       phys_disk_num = 0xFF;
+       while (!(mpt2sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
+           &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM,
+           phys_disk_num))) {
+               ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+                   MPI2_IOCSTATUS_MASK;
+               if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
+                       break;
+               phys_disk_num = pd_pg0.PhysDiskNum;
+               handle = le16_to_cpu(pd_pg0.DevHandle);
+               sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
+               if (sas_device)
+                       continue;
+               if (mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply,
+                   &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
+                   handle) != 0)
+                       continue;
+               parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
+               if (!_scsih_get_sas_address(ioc, parent_handle,
+                   &sas_address)) {
+                       mpt2sas_transport_update_links(ioc, sas_address,
+                           handle, sas_device_pg0.PhyNum,
+                           MPI2_SAS_NEG_LINK_RATE_1_5);
+                       set_bit(handle, ioc->pd_handles);
+                       _scsih_add_device(ioc, handle, 0, 1);
                }
-       } else {
-               if (!_scsih_get_num_volumes(ioc))
-                       return;
-               ioc->hide_drives = 1;
-               list_for_each_entry_safe(sas_device, sas_device_next,
-                   &ioc->sas_device_list, list) {
-                       mpt2sas_transport_port_remove(ioc,
-                           sas_device->sas_address,
-                           sas_device->sas_address_parent);
+       }
+
+       /* volumes */
+       handle = 0xFFFF;
+       while (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
+           &volume_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
+               ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+                   MPI2_IOCSTATUS_MASK;
+               if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
+                       break;
+               handle = le16_to_cpu(volume_pg1.DevHandle);
+               raid_device = _scsih_raid_device_find_by_wwid(ioc,
+                   le64_to_cpu(volume_pg1.WWID));
+               if (raid_device)
+                       continue;
+               if (mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply,
+                   &volume_pg0, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
+                    sizeof(Mpi2RaidVolPage0_t)))
+                       continue;
+               if (volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_OPTIMAL ||
+                   volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_ONLINE ||
+                   volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_DEGRADED) {
+                       memset(&element, 0, sizeof(Mpi2EventIrConfigElement_t));
+                       element.ReasonCode = MPI2_EVENT_IR_CHANGE_RC_ADDED;
+                       element.VolDevHandle = volume_pg1.DevHandle;
+                       _scsih_sas_volume_add(ioc, &element);
                }
        }
+
+ skip_to_sas:
+
+       /* sas devices */
+       handle = 0xFFFF;
+       while (!(mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply,
+           &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE,
+           handle))) {
+               ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+                   MPI2_IOCSTATUS_MASK;
+               if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
+                       break;
+               handle = le16_to_cpu(sas_device_pg0.DevHandle);
+               if (!(_scsih_is_end_device(
+                   le32_to_cpu(sas_device_pg0.DeviceInfo))))
+                       continue;
+               sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
+                   le64_to_cpu(sas_device_pg0.SASAddress));
+               if (sas_device)
+                       continue;
+               parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
+               if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address)) {
+                       mpt2sas_transport_update_links(ioc, sas_address, handle,
+                           sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5);
+                       _scsih_add_device(ioc, handle, 0, 0);
+               }
+       }
+
+       printk(MPT2SAS_INFO_FMT "scan devices: complete\n", ioc->name);
 }
 
+
 /**
  * mpt2sas_scsih_reset_handler - reset callback handler (for scsih)
  * @ioc: per adapter object
@@ -6871,7 +7148,6 @@ mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)
                }
                _scsih_fw_event_cleanup_queue(ioc);
                _scsih_flush_running_cmds(ioc);
-               _scsih_queue_rescan(ioc);
                break;
        case MPT2_IOC_DONE_RESET:
                dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
@@ -6881,6 +7157,13 @@ mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)
                _scsih_search_responding_sas_devices(ioc);
                _scsih_search_responding_raid_devices(ioc);
                _scsih_search_responding_expanders(ioc);
+               if (!ioc->is_driver_loading) {
+                       _scsih_prep_device_scan(ioc);
+                       _scsih_search_responding_sas_devices(ioc);
+                       _scsih_search_responding_raid_devices(ioc);
+                       _scsih_search_responding_expanders(ioc);
+                       _scsih_error_recovery_delete_devices(ioc);
+               }
                break;
        }
 }
@@ -6898,7 +7181,6 @@ _firmware_event_work(struct work_struct *work)
 {
        struct fw_event_work *fw_event = container_of(work,
            struct fw_event_work, delayed_work.work);
-       unsigned long flags;
        struct MPT2SAS_ADAPTER *ioc = fw_event->ioc;
 
        /* the queue is being flushed so ignore this event */
@@ -6908,23 +7190,21 @@ _firmware_event_work(struct work_struct *work)
                return;
        }
 
-       if (fw_event->event == MPT2SAS_RESCAN_AFTER_HOST_RESET) {
-               _scsih_fw_event_free(ioc, fw_event);
-               spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
-               if (ioc->shost_recovery) {
-                       init_completion(&ioc->shost_recovery_done);
-                       spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock,
-                           flags);
-                       wait_for_completion(&ioc->shost_recovery_done);
-               } else
-                       spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock,
-                           flags);
+       switch (fw_event->event) {
+       case MPT2SAS_REMOVE_UNRESPONDING_DEVICES:
+               while (scsi_host_in_recovery(ioc->shost))
+                       ssleep(1);
                _scsih_remove_unresponding_sas_devices(ioc);
-               _scsih_hide_unhide_sas_devices(ioc);
-               return;
-       }
+               _scsih_scan_for_devices_after_reset(ioc);
+               break;
+       case MPT2SAS_PORT_ENABLE_COMPLETE:
+               ioc->start_scan = 0;
 
-       switch (fw_event->event) {
+
+
+               dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "port enable: complete "
+                   "from worker thread\n", ioc->name));
+               break;
        case MPT2SAS_TURN_ON_FAULT_LED:
                _scsih_turn_on_fault_led(ioc, fw_event->device_handle);
                break;
@@ -7121,6 +7401,8 @@ static struct scsi_host_template scsih_driver_template = {
        .slave_configure                = _scsih_slave_configure,
        .target_destroy                 = _scsih_target_destroy,
        .slave_destroy                  = _scsih_slave_destroy,
+       .scan_finished                  = _scsih_scan_finished,
+       .scan_start                     = _scsih_scan_start,
        .change_queue_depth             = _scsih_change_queue_depth,
        .change_queue_type              = _scsih_change_queue_type,
        .eh_abort_handler               = _scsih_abort,
@@ -7381,7 +7663,12 @@ _scsih_probe_boot_devices(struct MPT2SAS_ADAPTER *ioc)
        unsigned long flags;
        int rc;
 
+        /* no Bios, return immediately */
+       if (!ioc->bios_pg3.BiosVersion)
+               return;
+
        device = NULL;
+       is_raid = 0;
        if (ioc->req_boot_device.device) {
                device =  ioc->req_boot_device.device;
                is_raid = ioc->req_boot_device.is_raid;
@@ -7417,8 +7704,9 @@ _scsih_probe_boot_devices(struct MPT2SAS_ADAPTER *ioc)
                    sas_device->sas_address_parent)) {
                        _scsih_sas_device_remove(ioc, sas_device);
                } else if (!sas_device->starget) {
-                       mpt2sas_transport_port_remove(ioc, sas_address,
-                           sas_address_parent);
+                       if (!ioc->is_driver_loading)
+                               mpt2sas_transport_port_remove(ioc, sas_address,
+                                       sas_address_parent);
                        _scsih_sas_device_remove(ioc, sas_device);
                }
        }
@@ -7462,22 +7750,28 @@ _scsih_probe_sas(struct MPT2SAS_ADAPTER *ioc)
        /* SAS Device List */
        list_for_each_entry_safe(sas_device, next, &ioc->sas_device_init_list,
            list) {
-               spin_lock_irqsave(&ioc->sas_device_lock, flags);
-               list_move_tail(&sas_device->list, &ioc->sas_device_list);
-               spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
 
                if (ioc->hide_drives)
                        continue;
 
                if (!mpt2sas_transport_port_add(ioc, sas_device->handle,
                    sas_device->sas_address_parent)) {
-                       _scsih_sas_device_remove(ioc, sas_device);
+                       list_del(&sas_device->list);
+                       kfree(sas_device);
+                       continue;
                } else if (!sas_device->starget) {
-                       mpt2sas_transport_port_remove(ioc,
-                           sas_device->sas_address,
-                           sas_device->sas_address_parent);
-                       _scsih_sas_device_remove(ioc, sas_device);
+                       if (!ioc->is_driver_loading)
+                               mpt2sas_transport_port_remove(ioc,
+                                       sas_device->sas_address,
+                                       sas_device->sas_address_parent);
+                       list_del(&sas_device->list);
+                       kfree(sas_device);
+                       continue;
+
                }
+               spin_lock_irqsave(&ioc->sas_device_lock, flags);
+               list_move_tail(&sas_device->list, &ioc->sas_device_list);
+               spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
        }
 }
 
@@ -7490,9 +7784,7 @@ _scsih_probe_sas(struct MPT2SAS_ADAPTER *ioc)
 static void
 _scsih_probe_devices(struct MPT2SAS_ADAPTER *ioc)
 {
-       u16 volume_mapping_flags =
-           le16_to_cpu(ioc->ioc_pg8.IRVolumeMappingFlags) &
-           MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
+       u16 volume_mapping_flags;
 
        if (!(ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR))
                return;  /* return when IOC doesn't support initiator mode */
@@ -7500,18 +7792,93 @@ _scsih_probe_devices(struct MPT2SAS_ADAPTER *ioc)
        _scsih_probe_boot_devices(ioc);
 
        if (ioc->ir_firmware) {
-               if ((volume_mapping_flags &
-                    MPI2_IOCPAGE8_IRFLAGS_HIGH_VOLUME_MAPPING)) {
-                       _scsih_probe_sas(ioc);
+               volume_mapping_flags =
+                   le16_to_cpu(ioc->ioc_pg8.IRVolumeMappingFlags) &
+                   MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
+               if (volume_mapping_flags ==
+                   MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING) {
                        _scsih_probe_raid(ioc);
+                       _scsih_probe_sas(ioc);
                } else {
-                       _scsih_probe_raid(ioc);
                        _scsih_probe_sas(ioc);
+                       _scsih_probe_raid(ioc);
                }
        } else
                _scsih_probe_sas(ioc);
 }
 
+
+/**
+ * _scsih_scan_start - scsi lld callback for .scan_start
+ * @shost: SCSI host pointer
+ *
+ * The shost has the ability to discover targets on its own instead
+ * of scanning the entire bus.  In our implemention, we will kick off
+ * firmware discovery.
+ */
+static void
+_scsih_scan_start(struct Scsi_Host *shost)
+{
+       struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
+       int rc;
+
+       if (diag_buffer_enable != -1 && diag_buffer_enable != 0)
+               mpt2sas_enable_diag_buffer(ioc, diag_buffer_enable);
+
+       ioc->start_scan = 1;
+       rc = mpt2sas_port_enable(ioc);
+
+       if (rc != 0)
+               printk(MPT2SAS_INFO_FMT "port enable: FAILED\n", ioc->name);
+}
+
+/**
+ * _scsih_scan_finished - scsi lld callback for .scan_finished
+ * @shost: SCSI host pointer
+ * @time: elapsed time of the scan in jiffies
+ *
+ * This function will be called periodically until it returns 1 with the
+ * scsi_host and the elapsed time of the scan in jiffies. In our implemention,
+ * we wait for firmware discovery to complete, then return 1.
+ */
+static int
+_scsih_scan_finished(struct Scsi_Host *shost, unsigned long time)
+{
+       struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
+
+       if (time >= (300 * HZ)) {
+               ioc->base_cmds.status = MPT2_CMD_NOT_USED;
+               printk(MPT2SAS_INFO_FMT "port enable: FAILED with timeout "
+                   "(timeout=300s)\n", ioc->name);
+               ioc->is_driver_loading = 0;
+               return 1;
+       }
+
+       if (ioc->start_scan)
+               return 0;
+
+       if (ioc->start_scan_failed) {
+               printk(MPT2SAS_INFO_FMT "port enable: FAILED with "
+                   "(ioc_status=0x%08x)\n", ioc->name, ioc->start_scan_failed);
+               ioc->is_driver_loading = 0;
+               ioc->wait_for_discovery_to_complete = 0;
+               ioc->remove_host = 1;
+               return 1;
+       }
+
+       printk(MPT2SAS_INFO_FMT "port enable: SUCCESS\n", ioc->name);
+       ioc->base_cmds.status = MPT2_CMD_NOT_USED;
+
+       if (ioc->wait_for_discovery_to_complete) {
+               ioc->wait_for_discovery_to_complete = 0;
+               _scsih_probe_devices(ioc);
+       }
+       mpt2sas_base_start_watchdog(ioc);
+       ioc->is_driver_loading = 0;
+       return 1;
+}
+
+
 /**
  * _scsih_probe - attach and add scsi host
  * @pdev: PCI device struct
@@ -7548,6 +7915,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        ioc->tm_cb_idx = tm_cb_idx;
        ioc->ctl_cb_idx = ctl_cb_idx;
        ioc->base_cb_idx = base_cb_idx;
+       ioc->port_enable_cb_idx = port_enable_cb_idx;
        ioc->transport_cb_idx = transport_cb_idx;
        ioc->scsih_cb_idx = scsih_cb_idx;
        ioc->config_cb_idx = config_cb_idx;
@@ -7620,14 +7988,14 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                goto out_thread_fail;
        }
 
-       ioc->wait_for_port_enable_to_complete = 1;
+       ioc->is_driver_loading = 1;
        if ((mpt2sas_base_attach(ioc))) {
                printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
                    ioc->name, __FILE__, __LINE__, __func__);
                goto out_attach_fail;
        }
 
-       ioc->wait_for_port_enable_to_complete = 0;
+       scsi_scan_host(shost);
        if (ioc->is_warpdrive) {
                if (ioc->mfg_pg10_hide_flag ==  MFG_PAGE10_EXPOSE_ALL_DISKS)
                        ioc->hide_drives = 0;
@@ -7650,6 +8018,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
  out_thread_fail:
        list_del(&ioc->list);
        scsi_remove_host(shost);
+       scsi_host_put(shost);
  out_add_shost_fail:
        return -ENODEV;
 }
@@ -7896,6 +8265,8 @@ _scsih_init(void)
 
        /* base internal commands callback handler */
        base_cb_idx = mpt2sas_base_register_callback_handler(mpt2sas_base_done);
+       port_enable_cb_idx = mpt2sas_base_register_callback_handler(
+               mpt2sas_port_enable_done);
 
        /* transport internal commands callback handler */
        transport_cb_idx = mpt2sas_base_register_callback_handler(
@@ -7950,6 +8321,7 @@ _scsih_exit(void)
        mpt2sas_base_release_callback_handler(scsi_io_cb_idx);
        mpt2sas_base_release_callback_handler(tm_cb_idx);
        mpt2sas_base_release_callback_handler(base_cb_idx);
+       mpt2sas_base_release_callback_handler(port_enable_cb_idx);
        mpt2sas_base_release_callback_handler(transport_cb_idx);
        mpt2sas_base_release_callback_handler(scsih_cb_idx);
        mpt2sas_base_release_callback_handler(config_cb_idx);
index 621b5e0..6f58919 100644 (file)
@@ -732,6 +732,16 @@ static struct pci_device_id __devinitdata mvs_pci_table[] = {
                .class_mask     = 0,
                .driver_data    = chip_9485,
        },
+       { PCI_VDEVICE(OCZ, 0x1021), chip_9485}, /* OCZ RevoDrive3 */
+       { PCI_VDEVICE(OCZ, 0x1022), chip_9485}, /* OCZ RevoDrive3/zDriveR4 (exact model unknown) */
+       { PCI_VDEVICE(OCZ, 0x1040), chip_9485}, /* OCZ RevoDrive3/zDriveR4 (exact model unknown) */
+       { PCI_VDEVICE(OCZ, 0x1041), chip_9485}, /* OCZ RevoDrive3/zDriveR4 (exact model unknown) */
+       { PCI_VDEVICE(OCZ, 0x1042), chip_9485}, /* OCZ RevoDrive3/zDriveR4 (exact model unknown) */
+       { PCI_VDEVICE(OCZ, 0x1043), chip_9485}, /* OCZ RevoDrive3/zDriveR4 (exact model unknown) */
+       { PCI_VDEVICE(OCZ, 0x1044), chip_9485}, /* OCZ RevoDrive3/zDriveR4 (exact model unknown) */
+       { PCI_VDEVICE(OCZ, 0x1080), chip_9485}, /* OCZ RevoDrive3/zDriveR4 (exact model unknown) */
+       { PCI_VDEVICE(OCZ, 0x1083), chip_9485}, /* OCZ RevoDrive3/zDriveR4 (exact model unknown) */
+       { PCI_VDEVICE(OCZ, 0x1084), chip_9485}, /* OCZ RevoDrive3/zDriveR4 (exact model unknown) */
 
        { }     /* terminate list */
 };
index b86db84..5163edb 100644 (file)
@@ -4102,7 +4102,7 @@ static long pmcraid_chr_ioctl(
        struct pmcraid_ioctl_header *hdr = NULL;
        int retval = -ENOTTY;
 
-       hdr = kmalloc(GFP_KERNEL, sizeof(struct pmcraid_ioctl_header));
+       hdr = kmalloc(sizeof(struct pmcraid_ioctl_header), GFP_KERNEL);
 
        if (!hdr) {
                pmcraid_err("faile to allocate memory for ioctl header\n");
index 3474e86..2516adf 100644 (file)
@@ -2279,7 +2279,7 @@ qla25xx_msix_rsp_q(int irq, void *dev_id)
        ha = rsp->hw;
 
        /* Clear the interrupt, if enabled, for this response queue */
-       if (rsp->options & ~BIT_6) {
+       if (!ha->flags.disable_msix_handshake) {
                reg = &ha->iobase->isp24;
                spin_lock_irqsave(&ha->hardware_lock, flags);
                WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
index fc3f168..b4d43ae 100644 (file)
@@ -1698,6 +1698,15 @@ struct request_queue *scsi_alloc_queue(struct scsi_device *sdev)
 
 void scsi_free_queue(struct request_queue *q)
 {
+       unsigned long flags;
+
+       WARN_ON(q->queuedata);
+
+       /* cause scsi_request_fn() to kill all non-finished requests */
+       spin_lock_irqsave(q->queue_lock, flags);
+       q->request_fn(q);
+       spin_unlock_irqrestore(q->queue_lock, flags);
+
        blk_cleanup_queue(q);
 }
 
index 44e8ca3..72273a0 100644 (file)
@@ -322,6 +322,7 @@ out_device_destroy:
        scsi_device_set_state(sdev, SDEV_DEL);
        transport_destroy_device(&sdev->sdev_gendev);
        put_device(&sdev->sdev_dev);
+       scsi_free_queue(sdev->request_queue);
        put_device(&sdev->sdev_gendev);
 out:
        if (display_failure_msg)
index 1bcd65a..96029e6 100644 (file)
@@ -520,7 +520,7 @@ fail_host_msg:
 /**
  * iscsi_bsg_host_add - Create and add the bsg hooks to receive requests
  * @shost: shost for iscsi_host
- * @cls_host: iscsi_cls_host adding the structures to
+ * @ihost: iscsi_cls_host adding the structures to
  */
 static int
 iscsi_bsg_host_add(struct Scsi_Host *shost, struct iscsi_cls_host *ihost)
index a7942e5..fa3a591 100644 (file)
@@ -2590,18 +2590,16 @@ static int sd_probe(struct device *dev)
                spin_unlock(&sd_index_lock);
        } while (error == -EAGAIN);
 
-       if (error)
+       if (error) {
+               sdev_printk(KERN_WARNING, sdp, "sd_probe: memory exhausted.\n");
                goto out_put;
-
-       if (index >= SD_MAX_DISKS) {
-               error = -ENODEV;
-               sdev_printk(KERN_WARNING, sdp, "SCSI disk (sd) name space exhausted.\n");
-               goto out_free_index;
        }
 
        error = sd_format_disk_name("sd", index, gd->disk_name, DISK_NAME_LEN);
-       if (error)
+       if (error) {
+               sdev_printk(KERN_WARNING, sdp, "SCSI disk (sd) name length exceeded.\n");
                goto out_free_index;
+       }
 
        sdkp->device = sdp;
        sdkp->driver = &sd_template;
index 6ad798b..4163f29 100644 (file)
@@ -9,12 +9,6 @@
 #define SD_MAJORS      16
 
 /*
- * This is limited by the naming scheme enforced in sd_probe,
- * add another character to it if you really need more disks.
- */
-#define SD_MAX_DISKS   (((26 * 26) + 26 + 1) * 26)
-
-/*
  * Time out in seconds for disks and Magneto-opticals (which are slower).
  */
 #define SD_TIMEOUT             (30 * HZ)
index 1871b8a..9b28f39 100644 (file)
@@ -462,14 +462,16 @@ static void st_scsi_execute_end(struct request *req, int uptodate)
 {
        struct st_request *SRpnt = req->end_io_data;
        struct scsi_tape *STp = SRpnt->stp;
+       struct bio *tmp;
 
        STp->buffer->cmdstat.midlevel_result = SRpnt->result = req->errors;
        STp->buffer->cmdstat.residual = req->resid_len;
 
+       tmp = SRpnt->bio;
        if (SRpnt->waiting)
                complete(SRpnt->waiting);
 
-       blk_rq_unmap_user(SRpnt->bio);
+       blk_rq_unmap_user(tmp);
        __blk_put_request(req->q, req);
 }
 
index 595dacc..019a716 100644 (file)
 #define RXBUSY    (1<<2)
 #define TXBUSY    (1<<3)
 
+struct s3c64xx_spi_dma_data {
+       unsigned                ch;
+       enum dma_data_direction direction;
+       enum dma_ch     dmach;
+};
+
 /**
  * struct s3c64xx_spi_driver_data - Runtime info holder for SPI driver.
  * @clk: Pointer to the spi clock.
@@ -164,13 +170,14 @@ struct s3c64xx_spi_driver_data {
        struct work_struct              work;
        struct list_head                queue;
        spinlock_t                      lock;
-       enum dma_ch                     rx_dmach;
-       enum dma_ch                     tx_dmach;
        unsigned long                   sfr_start;
        struct completion               xfer_completion;
        unsigned                        state;
        unsigned                        cur_mode, cur_bpw;
        unsigned                        cur_speed;
+       struct s3c64xx_spi_dma_data     rx_dma;
+       struct s3c64xx_spi_dma_data     tx_dma;
+       struct samsung_dma_ops          *ops;
 };
 
 static struct s3c2410_dma_client s3c64xx_spi_dma_client = {
@@ -226,6 +233,78 @@ static void flush_fifo(struct s3c64xx_spi_driver_data *sdd)
        writel(val, regs + S3C64XX_SPI_CH_CFG);
 }
 
+static void s3c64xx_spi_dmacb(void *data)
+{
+       struct s3c64xx_spi_driver_data *sdd;
+       struct s3c64xx_spi_dma_data *dma = data;
+       unsigned long flags;
+
+       if (dma->direction == DMA_FROM_DEVICE)
+               sdd = container_of(data,
+                       struct s3c64xx_spi_driver_data, rx_dma);
+       else
+               sdd = container_of(data,
+                       struct s3c64xx_spi_driver_data, tx_dma);
+
+       spin_lock_irqsave(&sdd->lock, flags);
+
+       if (dma->direction == DMA_FROM_DEVICE) {
+               sdd->state &= ~RXBUSY;
+               if (!(sdd->state & TXBUSY))
+                       complete(&sdd->xfer_completion);
+       } else {
+               sdd->state &= ~TXBUSY;
+               if (!(sdd->state & RXBUSY))
+                       complete(&sdd->xfer_completion);
+       }
+
+       spin_unlock_irqrestore(&sdd->lock, flags);
+}
+
+static void prepare_dma(struct s3c64xx_spi_dma_data *dma,
+                                       unsigned len, dma_addr_t buf)
+{
+       struct s3c64xx_spi_driver_data *sdd;
+       struct samsung_dma_prep_info info;
+
+       if (dma->direction == DMA_FROM_DEVICE)
+               sdd = container_of((void *)dma,
+                       struct s3c64xx_spi_driver_data, rx_dma);
+       else
+               sdd = container_of((void *)dma,
+                       struct s3c64xx_spi_driver_data, tx_dma);
+
+       info.cap = DMA_SLAVE;
+       info.len = len;
+       info.fp = s3c64xx_spi_dmacb;
+       info.fp_param = dma;
+       info.direction = dma->direction;
+       info.buf = buf;
+
+       sdd->ops->prepare(dma->ch, &info);
+       sdd->ops->trigger(dma->ch);
+}
+
+static int acquire_dma(struct s3c64xx_spi_driver_data *sdd)
+{
+       struct samsung_dma_info info;
+
+       sdd->ops = samsung_dma_get_ops();
+
+       info.cap = DMA_SLAVE;
+       info.client = &s3c64xx_spi_dma_client;
+       info.width = sdd->cur_bpw / 8;
+
+       info.direction = sdd->rx_dma.direction;
+       info.fifo = sdd->sfr_start + S3C64XX_SPI_RX_DATA;
+       sdd->rx_dma.ch = sdd->ops->request(sdd->rx_dma.dmach, &info);
+       info.direction =  sdd->tx_dma.direction;
+       info.fifo = sdd->sfr_start + S3C64XX_SPI_TX_DATA;
+       sdd->tx_dma.ch = sdd->ops->request(sdd->tx_dma.dmach, &info);
+
+       return 1;
+}
+
 static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
                                struct spi_device *spi,
                                struct spi_transfer *xfer, int dma_mode)
@@ -258,10 +337,7 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
                chcfg |= S3C64XX_SPI_CH_TXCH_ON;
                if (dma_mode) {
                        modecfg |= S3C64XX_SPI_MODE_TXDMA_ON;
-                       s3c2410_dma_config(sdd->tx_dmach, sdd->cur_bpw / 8);
-                       s3c2410_dma_enqueue(sdd->tx_dmach, (void *)sdd,
-                                               xfer->tx_dma, xfer->len);
-                       s3c2410_dma_ctrl(sdd->tx_dmach, S3C2410_DMAOP_START);
+                       prepare_dma(&sdd->tx_dma, xfer->len, xfer->tx_dma);
                } else {
                        switch (sdd->cur_bpw) {
                        case 32:
@@ -293,10 +369,7 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
                        writel(((xfer->len * 8 / sdd->cur_bpw) & 0xffff)
                                        | S3C64XX_SPI_PACKET_CNT_EN,
                                        regs + S3C64XX_SPI_PACKET_CNT);
-                       s3c2410_dma_config(sdd->rx_dmach, sdd->cur_bpw / 8);
-                       s3c2410_dma_enqueue(sdd->rx_dmach, (void *)sdd,
-                                               xfer->rx_dma, xfer->len);
-                       s3c2410_dma_ctrl(sdd->rx_dmach, S3C2410_DMAOP_START);
+                       prepare_dma(&sdd->rx_dma, xfer->len, xfer->rx_dma);
                }
        }
 
@@ -482,46 +555,6 @@ static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
        }
 }
 
-static void s3c64xx_spi_dma_rxcb(struct s3c2410_dma_chan *chan, void *buf_id,
-                                int size, enum s3c2410_dma_buffresult res)
-{
-       struct s3c64xx_spi_driver_data *sdd = buf_id;
-       unsigned long flags;
-
-       spin_lock_irqsave(&sdd->lock, flags);
-
-       if (res == S3C2410_RES_OK)
-               sdd->state &= ~RXBUSY;
-       else
-               dev_err(&sdd->pdev->dev, "DmaAbrtRx-%d\n", size);
-
-       /* If the other done */
-       if (!(sdd->state & TXBUSY))
-               complete(&sdd->xfer_completion);
-
-       spin_unlock_irqrestore(&sdd->lock, flags);
-}
-
-static void s3c64xx_spi_dma_txcb(struct s3c2410_dma_chan *chan, void *buf_id,
-                                int size, enum s3c2410_dma_buffresult res)
-{
-       struct s3c64xx_spi_driver_data *sdd = buf_id;
-       unsigned long flags;
-
-       spin_lock_irqsave(&sdd->lock, flags);
-
-       if (res == S3C2410_RES_OK)
-               sdd->state &= ~TXBUSY;
-       else
-               dev_err(&sdd->pdev->dev, "DmaAbrtTx-%d \n", size);
-
-       /* If the other done */
-       if (!(sdd->state & RXBUSY))
-               complete(&sdd->xfer_completion);
-
-       spin_unlock_irqrestore(&sdd->lock, flags);
-}
-
 #define XFER_DMAADDR_INVALID DMA_BIT_MASK(32)
 
 static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd,
@@ -696,12 +729,10 @@ static void handle_msg(struct s3c64xx_spi_driver_data *sdd,
                        if (use_dma) {
                                if (xfer->tx_buf != NULL
                                                && (sdd->state & TXBUSY))
-                                       s3c2410_dma_ctrl(sdd->tx_dmach,
-                                                       S3C2410_DMAOP_FLUSH);
+                                       sdd->ops->stop(sdd->tx_dma.ch);
                                if (xfer->rx_buf != NULL
                                                && (sdd->state & RXBUSY))
-                                       s3c2410_dma_ctrl(sdd->rx_dmach,
-                                                       S3C2410_DMAOP_FLUSH);
+                                       sdd->ops->stop(sdd->rx_dma.ch);
                        }
 
                        goto out;
@@ -739,30 +770,6 @@ out:
                msg->complete(msg->context);
 }
 
-static int acquire_dma(struct s3c64xx_spi_driver_data *sdd)
-{
-       if (s3c2410_dma_request(sdd->rx_dmach,
-                                       &s3c64xx_spi_dma_client, NULL) < 0) {
-               dev_err(&sdd->pdev->dev, "cannot get RxDMA\n");
-               return 0;
-       }
-       s3c2410_dma_set_buffdone_fn(sdd->rx_dmach, s3c64xx_spi_dma_rxcb);
-       s3c2410_dma_devconfig(sdd->rx_dmach, S3C2410_DMASRC_HW,
-                                       sdd->sfr_start + S3C64XX_SPI_RX_DATA);
-
-       if (s3c2410_dma_request(sdd->tx_dmach,
-                                       &s3c64xx_spi_dma_client, NULL) < 0) {
-               dev_err(&sdd->pdev->dev, "cannot get TxDMA\n");
-               s3c2410_dma_free(sdd->rx_dmach, &s3c64xx_spi_dma_client);
-               return 0;
-       }
-       s3c2410_dma_set_buffdone_fn(sdd->tx_dmach, s3c64xx_spi_dma_txcb);
-       s3c2410_dma_devconfig(sdd->tx_dmach, S3C2410_DMASRC_MEM,
-                                       sdd->sfr_start + S3C64XX_SPI_TX_DATA);
-
-       return 1;
-}
-
 static void s3c64xx_spi_work(struct work_struct *work)
 {
        struct s3c64xx_spi_driver_data *sdd = container_of(work,
@@ -799,8 +806,8 @@ static void s3c64xx_spi_work(struct work_struct *work)
        spin_unlock_irqrestore(&sdd->lock, flags);
 
        /* Free DMA channels */
-       s3c2410_dma_free(sdd->tx_dmach, &s3c64xx_spi_dma_client);
-       s3c2410_dma_free(sdd->rx_dmach, &s3c64xx_spi_dma_client);
+       sdd->ops->release(sdd->rx_dma.ch, &s3c64xx_spi_dma_client);
+       sdd->ops->release(sdd->tx_dma.ch, &s3c64xx_spi_dma_client);
 }
 
 static int s3c64xx_spi_transfer(struct spi_device *spi,
@@ -1017,8 +1024,10 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
        sdd->cntrlr_info = sci;
        sdd->pdev = pdev;
        sdd->sfr_start = mem_res->start;
-       sdd->tx_dmach = dmatx_res->start;
-       sdd->rx_dmach = dmarx_res->start;
+       sdd->tx_dma.dmach = dmatx_res->start;
+       sdd->tx_dma.direction = DMA_TO_DEVICE;
+       sdd->rx_dma.dmach = dmarx_res->start;
+       sdd->rx_dma.direction = DMA_FROM_DEVICE;
 
        sdd->cur_bpw = 8;
 
@@ -1106,7 +1115,7 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
                                        pdev->id, master->num_chipselect);
        dev_dbg(&pdev->dev, "\tIOmem=[0x%x-0x%x]\tDMA=[Rx-%d, Tx-%d]\n",
                                        mem_res->end, mem_res->start,
-                                       sdd->rx_dmach, sdd->tx_dmach);
+                                       sdd->rx_dma.dmach, sdd->tx_dma.dmach);
 
        return 0;
 
index d132c27..25cdff3 100644 (file)
@@ -30,12 +30,6 @@ source "drivers/staging/et131x/Kconfig"
 
 source "drivers/staging/slicoss/Kconfig"
 
-source "drivers/staging/go7007/Kconfig"
-
-source "drivers/staging/cx25821/Kconfig"
-
-source "drivers/staging/cxd2099/Kconfig"
-
 source "drivers/staging/usbip/Kconfig"
 
 source "drivers/staging/winbond/Kconfig"
@@ -104,20 +98,12 @@ source "drivers/staging/wlags49_h25/Kconfig"
 
 source "drivers/staging/sm7xx/Kconfig"
 
-source "drivers/staging/dt3155v4l/Kconfig"
-
 source "drivers/staging/crystalhd/Kconfig"
 
 source "drivers/staging/cxt1e1/Kconfig"
 
 source "drivers/staging/xgifb/Kconfig"
 
-source "drivers/staging/lirc/Kconfig"
-
-source "drivers/staging/easycap/Kconfig"
-
-source "drivers/staging/solo6x10/Kconfig"
-
 source "drivers/staging/tidspbridge/Kconfig"
 
 source "drivers/staging/quickstart/Kconfig"
@@ -144,4 +130,6 @@ source "drivers/staging/mei/Kconfig"
 
 source "drivers/staging/nvec/Kconfig"
 
+source "drivers/staging/media/Kconfig"
+
 endif # STAGING
index 936b7c2..a25f3f2 100644 (file)
@@ -4,12 +4,9 @@
 obj-$(CONFIG_STAGING)          += staging.o
 
 obj-y                          += serial/
+obj-y                          += media/
 obj-$(CONFIG_ET131X)           += et131x/
 obj-$(CONFIG_SLICOSS)          += slicoss/
-obj-$(CONFIG_VIDEO_GO7007)     += go7007/
-obj-$(CONFIG_VIDEO_CX25821)    += cx25821/
-obj-$(CONFIG_DVB_CXD2099)      += cxd2099/
-obj-$(CONFIG_LIRC_STAGING)     += lirc/
 obj-$(CONFIG_USBIP_CORE)       += usbip/
 obj-$(CONFIG_W35UND)           += winbond/
 obj-$(CONFIG_PRISM2_USB)       += wlan-ng/
@@ -44,12 +41,9 @@ obj-$(CONFIG_ZCACHE)         += zcache/
 obj-$(CONFIG_WLAGS49_H2)       += wlags49_h2/
 obj-$(CONFIG_WLAGS49_H25)      += wlags49_h25/
 obj-$(CONFIG_FB_SM7XX)         += sm7xx/
-obj-$(CONFIG_VIDEO_DT3155)     += dt3155v4l/
 obj-$(CONFIG_CRYSTALHD)                += crystalhd/
 obj-$(CONFIG_CXT1E1)           += cxt1e1/
 obj-$(CONFIG_FB_XGI)           += xgifb/
-obj-$(CONFIG_EASYCAP)          += easycap/
-obj-$(CONFIG_SOLO6X10)         += solo6x10/
 obj-$(CONFIG_TIDSPBRIDGE)      += tidspbridge/
 obj-$(CONFIG_ACPI_QUICKSTART)  += quickstart/
 obj-$(CONFIG_SBE_2T3E3)                += sbe-2t3e3/
diff --git a/drivers/staging/cx25821/README b/drivers/staging/cx25821/README
deleted file mode 100644 (file)
index a9ba50b..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-Todo:
-       - checkpatch.pl cleanups
-       - sparse cleanups
-
-Please send patches to linux-media@vger.kernel.org
-
diff --git a/drivers/staging/media/Kconfig b/drivers/staging/media/Kconfig
new file mode 100644 (file)
index 0000000..7e5caa3
--- /dev/null
@@ -0,0 +1,37 @@
+menuconfig STAGING_MEDIA
+        bool "Media staging drivers"
+        default n
+        ---help---
+          This option allows you to select a number of media drivers that
+         don't have the "normal" Linux kernel quality level.
+         Most of them don't follow properly the V4L, DVB and/or RC API's,
+         so, they won't likely work fine with the existing applications.
+         That also means that, one fixed, their API's will change to match
+         the existing ones.
+
+          If you wish to work on these drivers, to help improve them, or
+          to report problems you have with them, please use the
+         linux-media@vger.kernel.org mailing list.
+
+          If in doubt, say N here.
+
+
+if STAGING_MEDIA
+
+# Please keep them in alphabetic order
+source "drivers/staging/media/as102/Kconfig"
+
+source "drivers/staging/media/cxd2099/Kconfig"
+
+source "drivers/staging/media/dt3155v4l/Kconfig"
+
+source "drivers/staging/media/easycap/Kconfig"
+
+source "drivers/staging/media/go7007/Kconfig"
+
+source "drivers/staging/media/solo6x10/Kconfig"
+
+# Keep LIRC at the end, as it has sub-menus
+source "drivers/staging/media/lirc/Kconfig"
+
+endif
diff --git a/drivers/staging/media/Makefile b/drivers/staging/media/Makefile
new file mode 100644 (file)
index 0000000..c69124c
--- /dev/null
@@ -0,0 +1,7 @@
+obj-$(CONFIG_DVB_AS102)                += as102/
+obj-$(CONFIG_DVB_CXD2099)      += cxd2099/
+obj-$(CONFIG_EASYCAP)          += easycap/
+obj-$(CONFIG_LIRC_STAGING)     += lirc/
+obj-$(CONFIG_SOLO6X10)         += solo6x10/
+obj-$(CONFIG_VIDEO_DT3155)     += dt3155v4l/
+obj-$(CONFIG_VIDEO_GO7007)     += go7007/
diff --git a/drivers/staging/media/as102/Kconfig b/drivers/staging/media/as102/Kconfig
new file mode 100644 (file)
index 0000000..5865029
--- /dev/null
@@ -0,0 +1,7 @@
+config DVB_AS102
+       tristate "Abilis AS102 DVB receiver"
+       depends on DVB_CORE && USB && I2C && INPUT
+       help
+         Choose Y or M here if you have a device containing an AS102
+
+         To compile this driver as a module, choose M here
diff --git a/drivers/staging/media/as102/Makefile b/drivers/staging/media/as102/Makefile
new file mode 100644 (file)
index 0000000..e7dbb6f
--- /dev/null
@@ -0,0 +1,6 @@
+dvb-as102-objs := as102_drv.o as102_fw.o as10x_cmd.o as10x_cmd_stream.o \
+               as102_fe.o as102_usb_drv.o as10x_cmd_cfg.o
+
+obj-$(CONFIG_DVB_AS102) += dvb-as102.o
+
+EXTRA_CFLAGS += -DCONFIG_AS102_USB -Idrivers/media/dvb/dvb-core
diff --git a/drivers/staging/media/as102/as102_drv.c b/drivers/staging/media/as102/as102_drv.c
new file mode 100644 (file)
index 0000000..d335c7d
--- /dev/null
@@ -0,0 +1,351 @@
+/*
+ * Abilis Systems Single DVB-T Receiver
+ * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com>
+ * Copyright (C) 2010 Devin Heitmueller <dheitmueller@kernellabs.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  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/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/kref.h>
+#include <asm/uaccess.h>
+#include <linux/usb.h>
+
+/* header file for Usb device driver*/
+#include "as102_drv.h"
+#include "as102_fw.h"
+#include "dvbdev.h"
+
+int debug;
+module_param_named(debug, debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off debugging (default: off)");
+
+int dual_tuner;
+module_param_named(dual_tuner, dual_tuner, int, 0644);
+MODULE_PARM_DESC(dual_tuner, "Activate Dual-Tuner config (default: off)");
+
+static int fw_upload = 1;
+module_param_named(fw_upload, fw_upload, int, 0644);
+MODULE_PARM_DESC(fw_upload, "Turn on/off default FW upload (default: on)");
+
+static int pid_filtering;
+module_param_named(pid_filtering, pid_filtering, int, 0644);
+MODULE_PARM_DESC(pid_filtering, "Activate HW PID filtering (default: off)");
+
+static int ts_auto_disable;
+module_param_named(ts_auto_disable, ts_auto_disable, int, 0644);
+MODULE_PARM_DESC(ts_auto_disable, "Stream Auto Enable on FW (default: off)");
+
+int elna_enable = 1;
+module_param_named(elna_enable, elna_enable, int, 0644);
+MODULE_PARM_DESC(elna_enable, "Activate eLNA (default: on)");
+
+#ifdef DVB_DEFINE_MOD_OPT_ADAPTER_NR
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+#endif
+
+static void as102_stop_stream(struct as102_dev_t *dev)
+{
+       struct as102_bus_adapter_t *bus_adap;
+
+       if (dev != NULL)
+               bus_adap = &dev->bus_adap;
+       else
+               return;
+
+       if (bus_adap->ops->stop_stream != NULL)
+               bus_adap->ops->stop_stream(dev);
+
+       if (ts_auto_disable) {
+               if (mutex_lock_interruptible(&dev->bus_adap.lock))
+                       return;
+
+               if (as10x_cmd_stop_streaming(bus_adap) < 0)
+                       dprintk(debug, "as10x_cmd_stop_streaming failed\n");
+
+               mutex_unlock(&dev->bus_adap.lock);
+       }
+}
+
+static int as102_start_stream(struct as102_dev_t *dev)
+{
+       struct as102_bus_adapter_t *bus_adap;
+       int ret = -EFAULT;
+
+       if (dev != NULL)
+               bus_adap = &dev->bus_adap;
+       else
+               return ret;
+
+       if (bus_adap->ops->start_stream != NULL)
+               ret = bus_adap->ops->start_stream(dev);
+
+       if (ts_auto_disable) {
+               if (mutex_lock_interruptible(&dev->bus_adap.lock))
+                       return -EFAULT;
+
+               ret = as10x_cmd_start_streaming(bus_adap);
+
+               mutex_unlock(&dev->bus_adap.lock);
+       }
+
+       return ret;
+}
+
+static int as10x_pid_filter(struct as102_dev_t *dev,
+                           int index, u16 pid, int onoff) {
+
+       struct as102_bus_adapter_t *bus_adap = &dev->bus_adap;
+       int ret = -EFAULT;
+
+       ENTER();
+
+       if (mutex_lock_interruptible(&dev->bus_adap.lock)) {
+               dprintk(debug, "mutex_lock_interruptible(lock) failed !\n");
+               return -EBUSY;
+       }
+
+       switch (onoff) {
+       case 0:
+           ret = as10x_cmd_del_PID_filter(bus_adap, (uint16_t) pid);
+           dprintk(debug, "DEL_PID_FILTER([%02d] 0x%04x) ret = %d\n",
+                   index, pid, ret);
+           break;
+       case 1:
+       {
+           struct as10x_ts_filter filter;
+
+           filter.type = TS_PID_TYPE_TS;
+           filter.idx = 0xFF;
+           filter.pid = pid;
+
+           ret = as10x_cmd_add_PID_filter(bus_adap, &filter);
+           dprintk(debug, "ADD_PID_FILTER([%02d -> %02d], 0x%04x) ret = %d\n",
+                   index, filter.idx, filter.pid, ret);
+           break;
+       }
+       }
+
+       mutex_unlock(&dev->bus_adap.lock);
+
+       LEAVE();
+       return ret;
+}
+
+static int as102_dvb_dmx_start_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+       int ret = 0;
+       struct dvb_demux *demux = dvbdmxfeed->demux;
+       struct as102_dev_t *as102_dev = demux->priv;
+
+       ENTER();
+
+       if (mutex_lock_interruptible(&as102_dev->sem))
+               return -ERESTARTSYS;
+
+       if (pid_filtering) {
+               as10x_pid_filter(as102_dev,
+                               dvbdmxfeed->index, dvbdmxfeed->pid, 1);
+       }
+
+       if (as102_dev->streaming++ == 0)
+               ret = as102_start_stream(as102_dev);
+
+       mutex_unlock(&as102_dev->sem);
+       LEAVE();
+       return ret;
+}
+
+static int as102_dvb_dmx_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+       struct dvb_demux *demux = dvbdmxfeed->demux;
+       struct as102_dev_t *as102_dev = demux->priv;
+
+       ENTER();
+
+       if (mutex_lock_interruptible(&as102_dev->sem))
+               return -ERESTARTSYS;
+
+       if (--as102_dev->streaming == 0)
+               as102_stop_stream(as102_dev);
+
+       if (pid_filtering) {
+               as10x_pid_filter(as102_dev,
+                               dvbdmxfeed->index, dvbdmxfeed->pid, 0);
+       }
+
+       mutex_unlock(&as102_dev->sem);
+       LEAVE();
+       return 0;
+}
+
+int as102_dvb_register(struct as102_dev_t *as102_dev)
+{
+       int ret = 0;
+       ENTER();
+
+       ret = dvb_register_adapter(&as102_dev->dvb_adap,
+                                  as102_dev->name,
+                                  THIS_MODULE,
+#if defined(CONFIG_AS102_USB)
+                                  &as102_dev->bus_adap.usb_dev->dev
+#elif defined(CONFIG_AS102_SPI)
+                                  &as102_dev->bus_adap.spi_dev->dev
+#else
+#error >>> dvb_register_adapter <<<
+#endif
+#ifdef DVB_DEFINE_MOD_OPT_ADAPTER_NR
+                                  , adapter_nr
+#endif
+                                  );
+       if (ret < 0) {
+               err("%s: dvb_register_adapter() failed (errno = %d)",
+                   __func__, ret);
+               goto failed;
+       }
+
+       as102_dev->dvb_dmx.priv = as102_dev;
+       as102_dev->dvb_dmx.filternum = pid_filtering ? 16 : 256;
+       as102_dev->dvb_dmx.feednum = 256;
+       as102_dev->dvb_dmx.start_feed = as102_dvb_dmx_start_feed;
+       as102_dev->dvb_dmx.stop_feed = as102_dvb_dmx_stop_feed;
+
+       as102_dev->dvb_dmx.dmx.capabilities = DMX_TS_FILTERING |
+                                             DMX_SECTION_FILTERING;
+
+       as102_dev->dvb_dmxdev.filternum = as102_dev->dvb_dmx.filternum;
+       as102_dev->dvb_dmxdev.demux = &as102_dev->dvb_dmx.dmx;
+       as102_dev->dvb_dmxdev.capabilities = 0;
+
+       ret = dvb_dmx_init(&as102_dev->dvb_dmx);
+       if (ret < 0) {
+               err("%s: dvb_dmx_init() failed (errno = %d)", __func__, ret);
+               goto failed;
+       }
+
+       ret = dvb_dmxdev_init(&as102_dev->dvb_dmxdev, &as102_dev->dvb_adap);
+       if (ret < 0) {
+               err("%s: dvb_dmxdev_init() failed (errno = %d)", __func__,
+                   ret);
+               goto failed;
+       }
+
+       ret = as102_dvb_register_fe(as102_dev, &as102_dev->dvb_fe);
+       if (ret < 0) {
+               err("%s: as102_dvb_register_frontend() failed (errno = %d)",
+                   __func__, ret);
+               goto failed;
+       }
+
+       /* init bus mutex for token locking */
+       mutex_init(&as102_dev->bus_adap.lock);
+
+       /* init start / stop stream mutex */
+       mutex_init(&as102_dev->sem);
+
+#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE)
+       /*
+        * try to load as102 firmware. If firmware upload failed, we'll be
+        * able to upload it later.
+        */
+       if (fw_upload)
+               try_then_request_module(as102_fw_upload(&as102_dev->bus_adap),
+                               "firmware_class");
+#endif
+
+failed:
+       LEAVE();
+       /* FIXME: free dvb_XXX */
+       return ret;
+}
+
+void as102_dvb_unregister(struct as102_dev_t *as102_dev)
+{
+       ENTER();
+
+       /* unregister as102 frontend */
+       as102_dvb_unregister_fe(&as102_dev->dvb_fe);
+
+       /* unregister demux device */
+       dvb_dmxdev_release(&as102_dev->dvb_dmxdev);
+       dvb_dmx_release(&as102_dev->dvb_dmx);
+
+       /* unregister dvb adapter */
+       dvb_unregister_adapter(&as102_dev->dvb_adap);
+
+       LEAVE();
+}
+
+static int __init as102_driver_init(void)
+{
+       int ret = 0;
+
+       ENTER();
+
+       /* register this driver with the low level subsystem */
+#if defined(CONFIG_AS102_USB)
+       ret = usb_register(&as102_usb_driver);
+       if (ret)
+               err("usb_register failed (ret = %d)", ret);
+#endif
+#if defined(CONFIG_AS102_SPI)
+       ret = spi_register_driver(&as102_spi_driver);
+       if (ret)
+               printk(KERN_ERR "spi_register failed (ret = %d)", ret);
+#endif
+
+       LEAVE();
+       return ret;
+}
+
+/*
+ * Mandatory function : Adds a special section to the module indicating
+ * where initialisation function is defined
+ */
+module_init(as102_driver_init);
+
+/**
+ * as102_driver_exit - as102 driver exit point
+ *
+ * This function is called when device has to be removed.
+ */
+static void __exit as102_driver_exit(void)
+{
+       ENTER();
+       /* deregister this driver with the low level bus subsystem */
+#if defined(CONFIG_AS102_USB)
+       usb_deregister(&as102_usb_driver);
+#endif
+#if defined(CONFIG_AS102_SPI)
+       spi_unregister_driver(&as102_spi_driver);
+#endif
+       LEAVE();
+}
+
+/*
+ * required function for unload: Adds a special section to the module
+ * indicating where unload function is defined
+ */
+module_exit(as102_driver_exit);
+/* modinfo details */
+MODULE_DESCRIPTION(DRIVER_FULL_NAME);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Pierrick Hascoet <pierrick.hascoet@abilis.com>");
+
+/* EOF - vim: set textwidth=80 ts=8 sw=8 sts=8 noet: */
diff --git a/drivers/staging/media/as102/as102_drv.h b/drivers/staging/media/as102/as102_drv.h
new file mode 100644 (file)
index 0000000..bcda635
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * Abilis Systems Single DVB-T Receiver
+ * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  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.
+ */
+
+#if defined(CONFIG_AS102_USB)
+#include <linux/usb.h>
+extern struct usb_driver as102_usb_driver;
+#endif
+
+#if defined(CONFIG_AS102_SPI)
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/cdev.h>
+
+extern struct spi_driver as102_spi_driver;
+#endif
+
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dmxdev.h"
+
+#define DRIVER_FULL_NAME "Abilis Systems as10x usb driver"
+#define DRIVER_NAME "as10x_usb"
+
+extern int debug;
+
+#define dprintk(debug, args...) \
+       do { if (debug) {       \
+               printk(KERN_DEBUG "%s: ",__FUNCTION__); \
+               printk(args);   \
+       } } while (0)
+
+#ifdef TRACE
+#define ENTER()                 printk(">> enter %s\n", __FUNCTION__)
+#define LEAVE()                 printk("<< leave %s\n", __FUNCTION__)
+#else
+#define ENTER()
+#define LEAVE()
+#endif
+
+#define AS102_DEVICE_MAJOR     192
+
+#define AS102_USB_BUF_SIZE     512
+#define MAX_STREAM_URB         32
+
+#include "as10x_cmd.h"
+
+#if defined(CONFIG_AS102_USB)
+#include "as102_usb_drv.h"
+#endif
+
+#if defined(CONFIG_AS102_SPI)
+#include "as10x_spi_drv.h"
+#endif
+
+
+struct as102_bus_adapter_t {
+#if defined(CONFIG_AS102_USB)
+       struct usb_device *usb_dev;
+#elif defined(CONFIG_AS102_SPI)
+       struct spi_device *spi_dev;
+       struct cdev cdev; /* spidev raw device */
+
+       struct timer_list timer;
+       struct completion xfer_done;
+#endif
+       /* bus token lock */
+       struct mutex lock;
+       /* low level interface for bus adapter */
+       union as10x_bus_token_t {
+#if defined(CONFIG_AS102_USB)
+               /* usb token */
+               struct as10x_usb_token_cmd_t usb;
+#endif
+#if defined(CONFIG_AS102_SPI)
+               /* spi token */
+               struct as10x_spi_token_cmd_t spi;
+#endif
+       } token;
+
+       /* token cmd xfer id */
+       uint16_t cmd_xid;
+
+       /* as10x command and response for dvb interface*/
+       struct as10x_cmd_t *cmd, *rsp;
+
+       /* bus adapter private ops callback */
+       struct as102_priv_ops_t *ops;
+};
+
+struct as102_dev_t {
+       const char *name;
+       struct as102_bus_adapter_t bus_adap;
+       struct list_head device_entry;
+       struct kref kref;
+       unsigned long minor;
+
+       struct dvb_adapter dvb_adap;
+       struct dvb_frontend dvb_fe;
+       struct dvb_demux dvb_dmx;
+       struct dmxdev dvb_dmxdev;
+
+       /* demodulator stats */
+       struct as10x_demod_stats demod_stats;
+       /* signal strength */
+       uint16_t signal_strength;
+       /* bit error rate */
+       uint32_t ber;
+
+       /* timer handle to trig ts stream download */
+       struct timer_list timer_handle;
+
+       struct mutex sem;
+       dma_addr_t dma_addr;
+       void *stream;
+       int streaming;
+       struct urb *stream_urb[MAX_STREAM_URB];
+};
+
+int as102_dvb_register(struct as102_dev_t *dev);
+void as102_dvb_unregister(struct as102_dev_t *dev);
+
+int as102_dvb_register_fe(struct as102_dev_t *dev, struct dvb_frontend *fe);
+int as102_dvb_unregister_fe(struct dvb_frontend *dev);
+
+/* EOF - vim: set textwidth=80 ts=8 sw=8 sts=8 noet: */
diff --git a/drivers/staging/media/as102/as102_fe.c b/drivers/staging/media/as102/as102_fe.c
new file mode 100644 (file)
index 0000000..3550f90
--- /dev/null
@@ -0,0 +1,603 @@
+/*
+ * Abilis Systems Single DVB-T Receiver
+ * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com>
+ * Copyright (C) 2010 Devin Heitmueller <dheitmueller@kernellabs.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  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/version.h>
+
+#include "as102_drv.h"
+#include "as10x_types.h"
+#include "as10x_cmd.h"
+
+extern int elna_enable;
+
+static void as10x_fe_copy_tps_parameters(struct dvb_frontend_parameters *dst,
+                                        struct as10x_tps *src);
+
+static void as102_fe_copy_tune_parameters(struct as10x_tune_args *dst,
+                                         struct dvb_frontend_parameters *src);
+
+static int as102_fe_set_frontend(struct dvb_frontend *fe,
+                                struct dvb_frontend_parameters *params)
+{
+       int ret = 0;
+       struct as102_dev_t *dev;
+       struct as10x_tune_args tune_args = { 0 };
+
+       ENTER();
+
+       dev = (struct as102_dev_t *) fe->tuner_priv;
+       if (dev == NULL)
+               return -ENODEV;
+
+       if (mutex_lock_interruptible(&dev->bus_adap.lock))
+               return -EBUSY;
+
+       as102_fe_copy_tune_parameters(&tune_args, params);
+
+       /* send abilis command: SET_TUNE */
+       ret =  as10x_cmd_set_tune(&dev->bus_adap, &tune_args);
+       if (ret != 0)
+               dprintk(debug, "as10x_cmd_set_tune failed. (err = %d)\n", ret);
+
+       mutex_unlock(&dev->bus_adap.lock);
+
+       LEAVE();
+       return (ret < 0) ? -EINVAL : 0;
+}
+
+static int as102_fe_get_frontend(struct dvb_frontend *fe,
+                                struct dvb_frontend_parameters *p) {
+       int ret = 0;
+       struct as102_dev_t *dev;
+       struct as10x_tps tps = { 0 };
+
+       ENTER();
+
+       dev = (struct as102_dev_t *) fe->tuner_priv;
+       if (dev == NULL)
+               return -EINVAL;
+
+       if (mutex_lock_interruptible(&dev->bus_adap.lock))
+               return -EBUSY;
+
+       /* send abilis command: GET_TPS */
+       ret = as10x_cmd_get_tps(&dev->bus_adap, &tps);
+
+       if (ret == 0)
+               as10x_fe_copy_tps_parameters(p, &tps);
+
+       mutex_unlock(&dev->bus_adap.lock);
+
+       LEAVE();
+       return (ret < 0) ? -EINVAL : 0;
+}
+
+static int as102_fe_get_tune_settings(struct dvb_frontend *fe,
+                       struct dvb_frontend_tune_settings *settings) {
+       ENTER();
+
+#if 0
+       dprintk(debug, "step_size    = %d\n", settings->step_size);
+       dprintk(debug, "max_drift    = %d\n", settings->max_drift);
+       dprintk(debug, "min_delay_ms = %d -> %d\n", settings->min_delay_ms,
+               1000);
+#endif
+
+       settings->min_delay_ms = 1000;
+
+       LEAVE();
+       return 0;
+}
+
+
+static int as102_fe_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+       int ret = 0;
+       struct as102_dev_t *dev;
+       struct as10x_tune_status tstate = { 0 };
+
+       ENTER();
+
+       dev = (struct as102_dev_t *) fe->tuner_priv;
+       if (dev == NULL)
+               return -ENODEV;
+
+       if (mutex_lock_interruptible(&dev->bus_adap.lock))
+               return -EBUSY;
+
+       /* send abilis command: GET_TUNE_STATUS */
+       ret = as10x_cmd_get_tune_status(&dev->bus_adap, &tstate);
+       if (ret < 0) {
+               dprintk(debug, "as10x_cmd_get_tune_status failed (err = %d)\n",
+                       ret);
+               goto out;
+       }
+
+       dev->signal_strength  = tstate.signal_strength;
+       dev->ber  = tstate.BER;
+
+       switch (tstate.tune_state) {
+       case TUNE_STATUS_SIGNAL_DVB_OK:
+               *status = FE_HAS_SIGNAL | FE_HAS_CARRIER;
+               break;
+       case TUNE_STATUS_STREAM_DETECTED:
+               *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_SYNC;
+               break;
+       case TUNE_STATUS_STREAM_TUNED:
+               *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_SYNC |
+                       FE_HAS_LOCK;
+               break;
+       default:
+               *status = TUNE_STATUS_NOT_TUNED;
+       }
+
+       dprintk(debug, "tuner status: 0x%02x, strength %d, per: %d, ber: %d\n",
+                       tstate.tune_state, tstate.signal_strength,
+                       tstate.PER, tstate.BER);
+
+       if (*status & FE_HAS_LOCK) {
+               if (as10x_cmd_get_demod_stats(&dev->bus_adap,
+                       (struct as10x_demod_stats *) &dev->demod_stats) < 0) {
+                       memset(&dev->demod_stats, 0, sizeof(dev->demod_stats));
+                       dprintk(debug, "as10x_cmd_get_demod_stats failed "
+                               "(probably not tuned)\n");
+               } else {
+                       dprintk(debug,
+                               "demod status: fc: 0x%08x, bad fc: 0x%08x, "
+                               "bytes corrected: 0x%08x , MER: 0x%04x\n",
+                               dev->demod_stats.frame_count,
+                               dev->demod_stats.bad_frame_count,
+                               dev->demod_stats.bytes_fixed_by_rs,
+                               dev->demod_stats.mer);
+               }
+       } else {
+               memset(&dev->demod_stats, 0, sizeof(dev->demod_stats));
+       }
+
+out:
+       mutex_unlock(&dev->bus_adap.lock);
+       LEAVE();
+       return ret;
+}
+
+/*
+ * Note:
+ * - in AS102 SNR=MER
+ *   - the SNR will be returned in linear terms, i.e. not in dB
+ *   - the accuracy equals Â±2dB for a SNR range from 4dB to 30dB
+ *   - the accuracy is >2dB for SNR values outside this range
+ */
+static int as102_fe_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+       struct as102_dev_t *dev;
+
+       ENTER();
+
+       dev = (struct as102_dev_t *) fe->tuner_priv;
+       if (dev == NULL)
+               return -ENODEV;
+
+       *snr = dev->demod_stats.mer;
+
+       LEAVE();
+       return 0;
+}
+
+static int as102_fe_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+       struct as102_dev_t *dev;
+
+       ENTER();
+
+       dev = (struct as102_dev_t *) fe->tuner_priv;
+       if (dev == NULL)
+               return -ENODEV;
+
+       *ber = dev->ber;
+
+       LEAVE();
+       return 0;
+}
+
+static int as102_fe_read_signal_strength(struct dvb_frontend *fe,
+                                        u16 *strength)
+{
+       struct as102_dev_t *dev;
+
+       ENTER();
+
+       dev = (struct as102_dev_t *) fe->tuner_priv;
+       if (dev == NULL)
+               return -ENODEV;
+
+       *strength = (((0xffff * 400) * dev->signal_strength + 41000) * 2);
+
+       LEAVE();
+       return 0;
+}
+
+static int as102_fe_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+       struct as102_dev_t *dev;
+
+       ENTER();
+
+       dev = (struct as102_dev_t *) fe->tuner_priv;
+       if (dev == NULL)
+               return -ENODEV;
+
+       if (dev->demod_stats.has_started)
+               *ucblocks = dev->demod_stats.bad_frame_count;
+       else
+               *ucblocks = 0;
+
+       LEAVE();
+       return 0;
+}
+
+static int as102_fe_ts_bus_ctrl(struct dvb_frontend *fe, int acquire)
+{
+       struct as102_dev_t *dev;
+       int ret;
+
+       ENTER();
+
+       dev = (struct as102_dev_t *) fe->tuner_priv;
+       if (dev == NULL)
+               return -ENODEV;
+
+       if (mutex_lock_interruptible(&dev->bus_adap.lock))
+               return -EBUSY;
+
+       if (acquire) {
+               if (elna_enable)
+                       as10x_cmd_set_context(&dev->bus_adap, 1010, 0xC0);
+
+               ret = as10x_cmd_turn_on(&dev->bus_adap);
+       } else {
+               ret = as10x_cmd_turn_off(&dev->bus_adap);
+       }
+
+       mutex_unlock(&dev->bus_adap.lock);
+
+       LEAVE();
+       return ret;
+}
+
+static struct dvb_frontend_ops as102_fe_ops = {
+       .info = {
+               .name                   = "Unknown AS102 device",
+               .type                   = FE_OFDM,
+               .frequency_min          = 174000000,
+               .frequency_max          = 862000000,
+               .frequency_stepsize     = 166667,
+               .caps = FE_CAN_INVERSION_AUTO
+                       | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4
+                       | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO
+                       | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QPSK
+                       | FE_CAN_QAM_AUTO
+                       | FE_CAN_TRANSMISSION_MODE_AUTO
+                       | FE_CAN_GUARD_INTERVAL_AUTO
+                       | FE_CAN_HIERARCHY_AUTO
+                       | FE_CAN_RECOVER
+                       | FE_CAN_MUTE_TS
+       },
+
+       .set_frontend           = as102_fe_set_frontend,
+       .get_frontend           = as102_fe_get_frontend,
+       .get_tune_settings      = as102_fe_get_tune_settings,
+
+       .read_status            = as102_fe_read_status,
+       .read_snr               = as102_fe_read_snr,
+       .read_ber               = as102_fe_read_ber,
+       .read_signal_strength   = as102_fe_read_signal_strength,
+       .read_ucblocks          = as102_fe_read_ucblocks,
+       .ts_bus_ctrl            = as102_fe_ts_bus_ctrl,
+};
+
+int as102_dvb_unregister_fe(struct dvb_frontend *fe)
+{
+       /* unregister frontend */
+       dvb_unregister_frontend(fe);
+
+       /* detach frontend */
+       dvb_frontend_detach(fe);
+
+       return 0;
+}
+
+int as102_dvb_register_fe(struct as102_dev_t *as102_dev,
+                         struct dvb_frontend *dvb_fe)
+{
+       int errno;
+       struct dvb_adapter *dvb_adap;
+
+       if (as102_dev == NULL)
+               return -EINVAL;
+
+       /* extract dvb_adapter */
+       dvb_adap = &as102_dev->dvb_adap;
+
+       /* init frontend callback ops */
+       memcpy(&dvb_fe->ops, &as102_fe_ops, sizeof(struct dvb_frontend_ops));
+       strncpy(dvb_fe->ops.info.name, as102_dev->name,
+               sizeof(dvb_fe->ops.info.name));
+
+       /* register dbvb frontend */
+       errno = dvb_register_frontend(dvb_adap, dvb_fe);
+       if (errno == 0)
+               dvb_fe->tuner_priv = as102_dev;
+
+       return errno;
+}
+
+static void as10x_fe_copy_tps_parameters(struct dvb_frontend_parameters *dst,
+                                        struct as10x_tps *as10x_tps)
+{
+
+       struct dvb_ofdm_parameters *fe_tps = &dst->u.ofdm;
+
+       /* extract consteallation */
+       switch (as10x_tps->constellation) {
+       case CONST_QPSK:
+               fe_tps->constellation = QPSK;
+               break;
+       case CONST_QAM16:
+               fe_tps->constellation = QAM_16;
+               break;
+       case CONST_QAM64:
+               fe_tps->constellation = QAM_64;
+               break;
+       }
+
+       /* extract hierarchy */
+       switch (as10x_tps->hierarchy) {
+       case HIER_NONE:
+               fe_tps->hierarchy_information = HIERARCHY_NONE;
+               break;
+       case HIER_ALPHA_1:
+               fe_tps->hierarchy_information = HIERARCHY_1;
+               break;
+       case HIER_ALPHA_2:
+               fe_tps->hierarchy_information = HIERARCHY_2;
+               break;
+       case HIER_ALPHA_4:
+               fe_tps->hierarchy_information = HIERARCHY_4;
+               break;
+       }
+
+       /* extract code rate HP */
+       switch (as10x_tps->code_rate_HP) {
+       case CODE_RATE_1_2:
+               fe_tps->code_rate_HP = FEC_1_2;
+               break;
+       case CODE_RATE_2_3:
+               fe_tps->code_rate_HP = FEC_2_3;
+               break;
+       case CODE_RATE_3_4:
+               fe_tps->code_rate_HP = FEC_3_4;
+               break;
+       case CODE_RATE_5_6:
+               fe_tps->code_rate_HP = FEC_5_6;
+               break;
+       case CODE_RATE_7_8:
+               fe_tps->code_rate_HP = FEC_7_8;
+               break;
+       }
+
+       /* extract code rate LP */
+       switch (as10x_tps->code_rate_LP) {
+       case CODE_RATE_1_2:
+               fe_tps->code_rate_LP = FEC_1_2;
+               break;
+       case CODE_RATE_2_3:
+               fe_tps->code_rate_LP = FEC_2_3;
+               break;
+       case CODE_RATE_3_4:
+               fe_tps->code_rate_LP = FEC_3_4;
+               break;
+       case CODE_RATE_5_6:
+               fe_tps->code_rate_LP = FEC_5_6;
+               break;
+       case CODE_RATE_7_8:
+               fe_tps->code_rate_LP = FEC_7_8;
+               break;
+       }
+
+       /* extract guard interval */
+       switch (as10x_tps->guard_interval) {
+       case GUARD_INT_1_32:
+               fe_tps->guard_interval = GUARD_INTERVAL_1_32;
+               break;
+       case GUARD_INT_1_16:
+               fe_tps->guard_interval = GUARD_INTERVAL_1_16;
+               break;
+       case GUARD_INT_1_8:
+               fe_tps->guard_interval = GUARD_INTERVAL_1_8;
+               break;
+       case GUARD_INT_1_4:
+               fe_tps->guard_interval = GUARD_INTERVAL_1_4;
+               break;
+       }
+
+       /* extract transmission mode */
+       switch (as10x_tps->transmission_mode) {
+       case TRANS_MODE_2K:
+               fe_tps->transmission_mode = TRANSMISSION_MODE_2K;
+               break;
+       case TRANS_MODE_8K:
+               fe_tps->transmission_mode = TRANSMISSION_MODE_8K;
+               break;
+       }
+}
+
+static uint8_t as102_fe_get_code_rate(fe_code_rate_t arg)
+{
+       uint8_t c;
+
+       switch (arg) {
+       case FEC_1_2:
+               c = CODE_RATE_1_2;
+               break;
+       case FEC_2_3:
+               c = CODE_RATE_2_3;
+               break;
+       case FEC_3_4:
+               c = CODE_RATE_3_4;
+               break;
+       case FEC_5_6:
+               c = CODE_RATE_5_6;
+               break;
+       case FEC_7_8:
+               c = CODE_RATE_7_8;
+               break;
+       default:
+               c = CODE_RATE_UNKNOWN;
+               break;
+       }
+
+       return c;
+}
+
+static void as102_fe_copy_tune_parameters(struct as10x_tune_args *tune_args,
+                         struct dvb_frontend_parameters *params)
+{
+
+       /* set frequency */
+       tune_args->freq = params->frequency / 1000;
+
+       /* fix interleaving_mode */
+       tune_args->interleaving_mode = INTLV_NATIVE;
+
+       switch (params->u.ofdm.bandwidth) {
+       case BANDWIDTH_8_MHZ:
+               tune_args->bandwidth = BW_8_MHZ;
+               break;
+       case BANDWIDTH_7_MHZ:
+               tune_args->bandwidth = BW_7_MHZ;
+               break;
+       case BANDWIDTH_6_MHZ:
+               tune_args->bandwidth = BW_6_MHZ;
+               break;
+       default:
+               tune_args->bandwidth = BW_8_MHZ;
+       }
+
+       switch (params->u.ofdm.guard_interval) {
+       case GUARD_INTERVAL_1_32:
+               tune_args->guard_interval = GUARD_INT_1_32;
+               break;
+       case GUARD_INTERVAL_1_16:
+               tune_args->guard_interval = GUARD_INT_1_16;
+               break;
+       case GUARD_INTERVAL_1_8:
+               tune_args->guard_interval = GUARD_INT_1_8;
+               break;
+       case GUARD_INTERVAL_1_4:
+               tune_args->guard_interval = GUARD_INT_1_4;
+               break;
+       case GUARD_INTERVAL_AUTO:
+       default:
+               tune_args->guard_interval = GUARD_UNKNOWN;
+               break;
+       }
+
+       switch (params->u.ofdm.constellation) {
+       case QPSK:
+               tune_args->constellation = CONST_QPSK;
+               break;
+       case QAM_16:
+               tune_args->constellation = CONST_QAM16;
+               break;
+       case QAM_64:
+               tune_args->constellation = CONST_QAM64;
+               break;
+       default:
+               tune_args->constellation = CONST_UNKNOWN;
+               break;
+       }
+
+       switch (params->u.ofdm.transmission_mode) {
+       case TRANSMISSION_MODE_2K:
+               tune_args->transmission_mode = TRANS_MODE_2K;
+               break;
+       case TRANSMISSION_MODE_8K:
+               tune_args->transmission_mode = TRANS_MODE_8K;
+               break;
+       default:
+               tune_args->transmission_mode = TRANS_MODE_UNKNOWN;
+       }
+
+       switch (params->u.ofdm.hierarchy_information) {
+       case HIERARCHY_NONE:
+               tune_args->hierarchy = HIER_NONE;
+               break;
+       case HIERARCHY_1:
+               tune_args->hierarchy = HIER_ALPHA_1;
+               break;
+       case HIERARCHY_2:
+               tune_args->hierarchy = HIER_ALPHA_2;
+               break;
+       case HIERARCHY_4:
+               tune_args->hierarchy = HIER_ALPHA_4;
+               break;
+       case HIERARCHY_AUTO:
+               tune_args->hierarchy = HIER_UNKNOWN;
+               break;
+       }
+
+       dprintk(debug, "tuner parameters: freq: %d  bw: 0x%02x  gi: 0x%02x\n",
+                       params->frequency,
+                       tune_args->bandwidth,
+                       tune_args->guard_interval);
+
+       /*
+        * Detect a hierarchy selection
+        * if HP/LP are both set to FEC_NONE, HP will be selected.
+        */
+       if ((tune_args->hierarchy != HIER_NONE) &&
+                      ((params->u.ofdm.code_rate_LP == FEC_NONE) ||
+                       (params->u.ofdm.code_rate_HP == FEC_NONE))) {
+
+               if (params->u.ofdm.code_rate_LP == FEC_NONE) {
+                       tune_args->hier_select = HIER_HIGH_PRIORITY;
+                       tune_args->code_rate =
+                          as102_fe_get_code_rate(params->u.ofdm.code_rate_HP);
+               }
+
+               if (params->u.ofdm.code_rate_HP == FEC_NONE) {
+                       tune_args->hier_select = HIER_LOW_PRIORITY;
+                       tune_args->code_rate =
+                          as102_fe_get_code_rate(params->u.ofdm.code_rate_LP);
+               }
+
+               dprintk(debug, "\thierarchy: 0x%02x  "
+                               "selected: %s  code_rate_%s: 0x%02x\n",
+                       tune_args->hierarchy,
+                       tune_args->hier_select == HIER_HIGH_PRIORITY ?
+                       "HP" : "LP",
+                       tune_args->hier_select == HIER_HIGH_PRIORITY ?
+                       "HP" : "LP",
+                       tune_args->code_rate);
+       } else {
+               tune_args->code_rate =
+                       as102_fe_get_code_rate(params->u.ofdm.code_rate_HP);
+       }
+}
+
+/* EOF - vim: set textwidth=80 ts=8 sw=8 sts=8 noet: */
diff --git a/drivers/staging/media/as102/as102_fw.c b/drivers/staging/media/as102/as102_fw.c
new file mode 100644 (file)
index 0000000..c019df9
--- /dev/null
@@ -0,0 +1,251 @@
+/*
+ * Abilis Systems Single DVB-T Receiver
+ * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com>
+ * Copyright (C) 2010 Devin Heitmueller <dheitmueller@kernellabs.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  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/errno.h>
+#include <linux/ctype.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+
+#include "as102_drv.h"
+#include "as102_fw.h"
+
+#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE)
+char as102_st_fw1[] = "as102_data1_st.hex";
+char as102_st_fw2[] = "as102_data2_st.hex";
+char as102_dt_fw1[] = "as102_data1_dt.hex";
+char as102_dt_fw2[] = "as102_data2_dt.hex";
+
+static unsigned char atohx(unsigned char *dst, char *src)
+{
+       unsigned char value = 0;
+
+       char msb = tolower(*src) - '0';
+       char lsb = tolower(*(src + 1)) - '0';
+
+       if (msb > 9)
+               msb -= 7;
+       if (lsb > 9)
+               lsb -= 7;
+
+       *dst = value = ((msb & 0xF) << 4) | (lsb & 0xF);
+       return value;
+}
+
+/*
+ * Parse INTEL HEX firmware file to extract address and data.
+ */
+static int parse_hex_line(unsigned char *fw_data, unsigned char *addr,
+                         unsigned char *data, int *dataLength,
+                         unsigned char *addr_has_changed) {
+
+       int count = 0;
+       unsigned char *src, dst;
+
+       if (*fw_data++ != ':') {
+               printk(KERN_ERR "invalid firmware file\n");
+               return -EFAULT;
+       }
+
+       /* locate end of line */
+       for (src = fw_data; *src != '\n'; src += 2) {
+               atohx(&dst, src);
+               /* parse line to split addr / data */
+               switch (count) {
+               case 0:
+                       *dataLength = dst;
+                       break;
+               case 1:
+                       addr[2] = dst;
+                       break;
+               case 2:
+                       addr[3] = dst;
+                       break;
+               case 3:
+                       /* check if data is an address */
+                       if (dst == 0x04)
+                               *addr_has_changed = 1;
+                       else
+                               *addr_has_changed = 0;
+                       break;
+               case  4:
+               case  5:
+                       if (*addr_has_changed)
+                               addr[(count - 4)] = dst;
+                       else
+                               data[(count - 4)] = dst;
+                       break;
+               default:
+                       data[(count - 4)] = dst;
+                       break;
+               }
+               count++;
+       }
+
+       /* return read value + ':' + '\n' */
+       return (count * 2) + 2;
+}
+
+static int as102_firmware_upload(struct as102_bus_adapter_t *bus_adap,
+                                unsigned char *cmd,
+                                const struct firmware *firmware) {
+
+       struct as10x_fw_pkt_t fw_pkt;
+       int total_read_bytes = 0, errno = 0;
+       unsigned char addr_has_changed = 0;
+
+       ENTER();
+
+       for (total_read_bytes = 0; total_read_bytes < firmware->size; ) {
+               int read_bytes = 0, data_len = 0;
+
+               /* parse intel hex line */
+               read_bytes = parse_hex_line(
+                               (u8 *) (firmware->data + total_read_bytes),
+                               fw_pkt.raw.address,
+                               fw_pkt.raw.data,
+                               &data_len,
+                               &addr_has_changed);
+
+               if (read_bytes <= 0)
+                       goto error;
+
+               /* detect the end of file */
+               total_read_bytes += read_bytes;
+               if (total_read_bytes == firmware->size) {
+                       fw_pkt.u.request[0] = 0x00;
+                       fw_pkt.u.request[1] = 0x03;
+
+                       /* send EOF command */
+                       errno = bus_adap->ops->upload_fw_pkt(bus_adap,
+                                                            (uint8_t *)
+                                                            &fw_pkt, 2, 0);
+                       if (errno < 0)
+                               goto error;
+               } else {
+                       if (!addr_has_changed) {
+                               /* prepare command to send */
+                               fw_pkt.u.request[0] = 0x00;
+                               fw_pkt.u.request[1] = 0x01;
+
+                               data_len += sizeof(fw_pkt.u.request);
+                               data_len += sizeof(fw_pkt.raw.address);
+
+                               /* send cmd to device */
+                               errno = bus_adap->ops->upload_fw_pkt(bus_adap,
+                                                                    (uint8_t *)
+                                                                    &fw_pkt,
+                                                                    data_len,
+                                                                    0);
+                               if (errno < 0)
+                                       goto error;
+                       }
+               }
+       }
+error:
+       LEAVE();
+       return (errno == 0) ? total_read_bytes : errno;
+}
+
+int as102_fw_upload(struct as102_bus_adapter_t *bus_adap)
+{
+       int errno = -EFAULT;
+       const struct firmware *firmware;
+       unsigned char *cmd_buf = NULL;
+       char *fw1, *fw2;
+
+#if defined(CONFIG_AS102_USB)
+       struct usb_device *dev = bus_adap->usb_dev;
+#endif
+#if defined(CONFIG_AS102_SPI)
+       struct spi_device *dev = bus_adap->spi_dev;
+#endif
+       ENTER();
+
+       /* select fw file to upload */
+       if (dual_tuner) {
+               fw1 = as102_dt_fw1;
+               fw2 = as102_dt_fw2;
+       } else {
+               fw1 = as102_st_fw1;
+               fw2 = as102_st_fw2;
+       }
+
+#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE)
+       /* allocate buffer to store firmware upload command and data */
+       cmd_buf = kzalloc(MAX_FW_PKT_SIZE, GFP_KERNEL);
+       if (cmd_buf == NULL) {
+               errno = -ENOMEM;
+               goto error;
+       }
+
+       /* request kernel to locate firmware file: part1 */
+       errno = request_firmware(&firmware, fw1, &dev->dev);
+       if (errno < 0) {
+               printk(KERN_ERR "%s: unable to locate firmware file: %s\n",
+                                DRIVER_NAME, fw1);
+               goto error;
+       }
+
+       /* initiate firmware upload */
+       errno = as102_firmware_upload(bus_adap, cmd_buf, firmware);
+       if (errno < 0) {
+               printk(KERN_ERR "%s: error during firmware upload part1\n",
+                                DRIVER_NAME);
+               goto error;
+       }
+
+       printk(KERN_INFO "%s: fimrware: %s loaded with success\n",
+                        DRIVER_NAME, fw1);
+       release_firmware(firmware);
+
+       /* wait for boot to complete */
+       mdelay(100);
+
+       /* request kernel to locate firmware file: part2 */
+       errno = request_firmware(&firmware, fw2, &dev->dev);
+       if (errno < 0) {
+               printk(KERN_ERR "%s: unable to locate firmware file: %s\n",
+                                DRIVER_NAME, fw2);
+               goto error;
+       }
+
+       /* initiate firmware upload */
+       errno = as102_firmware_upload(bus_adap, cmd_buf, firmware);
+       if (errno < 0) {
+               printk(KERN_ERR "%s: error during firmware upload part2\n",
+                                DRIVER_NAME);
+               goto error;
+       }
+
+       printk(KERN_INFO "%s: fimrware: %s loaded with success\n",
+                       DRIVER_NAME, fw2);
+error:
+       /* free data buffer */
+       kfree(cmd_buf);
+       /* release firmware if needed */
+       if (firmware != NULL)
+               release_firmware(firmware);
+#endif
+       LEAVE();
+       return errno;
+}
+#endif
+
+/* EOF - vim: set textwidth=80 ts=8 sw=8 sts=8 noet: */
diff --git a/drivers/staging/media/as102/as102_fw.h b/drivers/staging/media/as102/as102_fw.h
new file mode 100644 (file)
index 0000000..27e5347
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Abilis Systems Single DVB-T Receiver
+ * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#define MAX_FW_PKT_SIZE        64
+
+extern int dual_tuner;
+
+#pragma pack(1)
+struct as10x_raw_fw_pkt {
+       unsigned char address[4];
+       unsigned char data[MAX_FW_PKT_SIZE - 6];
+};
+
+struct as10x_fw_pkt_t {
+       union {
+               unsigned char request[2];
+               unsigned char length[2];
+       } u;
+       struct as10x_raw_fw_pkt raw;
+};
+#pragma pack()
+
+#ifdef __KERNEL__
+int as102_fw_upload(struct as102_bus_adapter_t *bus_adap);
+#endif
+
+/* EOF - vim: set textwidth=80 ts=8 sw=8 sts=8 noet: */
diff --git a/drivers/staging/media/as102/as102_usb_drv.c b/drivers/staging/media/as102/as102_usb_drv.c
new file mode 100644 (file)
index 0000000..264be2d
--- /dev/null
@@ -0,0 +1,478 @@
+/*
+ * Abilis Systems Single DVB-T Receiver
+ * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com>
+ * Copyright (C) 2010 Devin Heitmueller <dheitmueller@kernellabs.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  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/errno.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/usb.h>
+
+#include "as102_drv.h"
+#include "as102_usb_drv.h"
+#include "as102_fw.h"
+
+static void as102_usb_disconnect(struct usb_interface *interface);
+static int as102_usb_probe(struct usb_interface *interface,
+                          const struct usb_device_id *id);
+
+static int as102_usb_start_stream(struct as102_dev_t *dev);
+static void as102_usb_stop_stream(struct as102_dev_t *dev);
+
+static int as102_open(struct inode *inode, struct file *file);
+static int as102_release(struct inode *inode, struct file *file);
+
+static struct usb_device_id as102_usb_id_table[] = {
+       { USB_DEVICE(AS102_USB_DEVICE_VENDOR_ID, AS102_USB_DEVICE_PID_0001) },
+       { USB_DEVICE(PCTV_74E_USB_VID, PCTV_74E_USB_PID) },
+       { USB_DEVICE(ELGATO_EYETV_DTT_USB_VID, ELGATO_EYETV_DTT_USB_PID) },
+       { USB_DEVICE(NBOX_DVBT_DONGLE_USB_VID, NBOX_DVBT_DONGLE_USB_PID) },
+       { } /* Terminating entry */
+};
+
+/* Note that this table must always have the same number of entries as the
+   as102_usb_id_table struct */
+static const char *as102_device_names[] = {
+       AS102_REFERENCE_DESIGN,
+       AS102_PCTV_74E,
+       AS102_ELGATO_EYETV_DTT_NAME,
+       AS102_NBOX_DVBT_DONGLE_NAME,
+       NULL /* Terminating entry */
+};
+
+struct usb_driver as102_usb_driver = {
+       .name       =  DRIVER_FULL_NAME,
+       .probe      =  as102_usb_probe,
+       .disconnect =  as102_usb_disconnect,
+       .id_table   =  as102_usb_id_table
+};
+
+static const struct file_operations as102_dev_fops = {
+       .owner   = THIS_MODULE,
+       .open    = as102_open,
+       .release = as102_release,
+};
+
+static struct usb_class_driver as102_usb_class_driver = {
+       .name           = "aton2-%d",
+       .fops           = &as102_dev_fops,
+       .minor_base     = AS102_DEVICE_MAJOR,
+};
+
+static int as102_usb_xfer_cmd(struct as102_bus_adapter_t *bus_adap,
+                             unsigned char *send_buf, int send_buf_len,
+                             unsigned char *recv_buf, int recv_buf_len)
+{
+       int ret = 0;
+       ENTER();
+
+       if (send_buf != NULL) {
+               ret = usb_control_msg(bus_adap->usb_dev,
+                                     usb_sndctrlpipe(bus_adap->usb_dev, 0),
+                                     AS102_USB_DEVICE_TX_CTRL_CMD,
+                                     USB_DIR_OUT | USB_TYPE_VENDOR |
+                                     USB_RECIP_DEVICE,
+                                     bus_adap->cmd_xid, /* value */
+                                     0, /* index */
+                                     send_buf, send_buf_len,
+                                     USB_CTRL_SET_TIMEOUT /* 200 */);
+               if (ret < 0) {
+                       dprintk(debug, "usb_control_msg(send) failed, err %i\n",
+                                       ret);
+                       return ret;
+               }
+
+               if (ret != send_buf_len) {
+                       dprintk(debug, "only wrote %d of %d bytes\n",
+                                       ret, send_buf_len);
+                       return -1;
+               }
+       }
+
+       if (recv_buf != NULL) {
+#ifdef TRACE
+               dprintk(debug, "want to read: %d bytes\n", recv_buf_len);
+#endif
+               ret = usb_control_msg(bus_adap->usb_dev,
+                                     usb_rcvctrlpipe(bus_adap->usb_dev, 0),
+                                     AS102_USB_DEVICE_RX_CTRL_CMD,
+                                     USB_DIR_IN | USB_TYPE_VENDOR |
+                                     USB_RECIP_DEVICE,
+                                     bus_adap->cmd_xid, /* value */
+                                     0, /* index */
+                                     recv_buf, recv_buf_len,
+                                     USB_CTRL_GET_TIMEOUT /* 200 */);
+               if (ret < 0) {
+                       dprintk(debug, "usb_control_msg(recv) failed, err %i\n",
+                                       ret);
+                       return ret;
+               }
+#ifdef TRACE
+               dprintk(debug, "read %d bytes\n", recv_buf_len);
+#endif
+       }
+
+       LEAVE();
+       return ret;
+}
+
+static int as102_send_ep1(struct as102_bus_adapter_t *bus_adap,
+                         unsigned char *send_buf,
+                         int send_buf_len,
+                         int swap32)
+{
+       int ret = 0, actual_len;
+
+       ret = usb_bulk_msg(bus_adap->usb_dev,
+                          usb_sndbulkpipe(bus_adap->usb_dev, 1),
+                          send_buf, send_buf_len, &actual_len, 200);
+       if (ret) {
+               dprintk(debug, "usb_bulk_msg(send) failed, err %i\n", ret);
+               return ret;
+       }
+
+       if (actual_len != send_buf_len) {
+               dprintk(debug, "only wrote %d of %d bytes\n",
+                               actual_len, send_buf_len);
+               return -1;
+       }
+       return ret ? ret : actual_len;
+}
+
+static int as102_read_ep2(struct as102_bus_adapter_t *bus_adap,
+                  unsigned char *recv_buf, int recv_buf_len)
+{
+       int ret = 0, actual_len;
+
+       if (recv_buf == NULL)
+               return -EINVAL;
+
+       ret = usb_bulk_msg(bus_adap->usb_dev,
+                          usb_rcvbulkpipe(bus_adap->usb_dev, 2),
+                          recv_buf, recv_buf_len, &actual_len, 200);
+       if (ret) {
+               dprintk(debug, "usb_bulk_msg(recv) failed, err %i\n", ret);
+               return ret;
+       }
+
+       if (actual_len != recv_buf_len) {
+               dprintk(debug, "only read %d of %d bytes\n",
+                               actual_len, recv_buf_len);
+               return -1;
+       }
+       return ret ? ret : actual_len;
+}
+
+struct as102_priv_ops_t as102_priv_ops = {
+       .upload_fw_pkt  = as102_send_ep1,
+       .xfer_cmd       = as102_usb_xfer_cmd,
+       .as102_read_ep2 = as102_read_ep2,
+       .start_stream   = as102_usb_start_stream,
+       .stop_stream    = as102_usb_stop_stream,
+};
+
+static int as102_submit_urb_stream(struct as102_dev_t *dev, struct urb *urb)
+{
+       int err;
+
+       usb_fill_bulk_urb(urb,
+                         dev->bus_adap.usb_dev,
+                         usb_rcvbulkpipe(dev->bus_adap.usb_dev, 0x2),
+                         urb->transfer_buffer,
+                         AS102_USB_BUF_SIZE,
+                         as102_urb_stream_irq,
+                         dev);
+
+       err = usb_submit_urb(urb, GFP_ATOMIC);
+       if (err)
+               dprintk(debug, "%s: usb_submit_urb failed\n", __func__);
+
+       return err;
+}
+
+void as102_urb_stream_irq(struct urb *urb)
+{
+       struct as102_dev_t *as102_dev = urb->context;
+
+       if (urb->actual_length > 0) {
+               dvb_dmx_swfilter(&as102_dev->dvb_dmx,
+                                urb->transfer_buffer,
+                                urb->actual_length);
+       } else {
+               if (urb->actual_length == 0)
+                       memset(urb->transfer_buffer, 0, AS102_USB_BUF_SIZE);
+       }
+
+       /* is not stopped, re-submit urb */
+       if (as102_dev->streaming)
+               as102_submit_urb_stream(as102_dev, urb);
+}
+
+static void as102_free_usb_stream_buffer(struct as102_dev_t *dev)
+{
+       int i;
+
+       ENTER();
+
+       for (i = 0; i < MAX_STREAM_URB; i++)
+               usb_free_urb(dev->stream_urb[i]);
+
+       usb_free_coherent(dev->bus_adap.usb_dev,
+                       MAX_STREAM_URB * AS102_USB_BUF_SIZE,
+                       dev->stream,
+                       dev->dma_addr);
+       LEAVE();
+}
+
+static int as102_alloc_usb_stream_buffer(struct as102_dev_t *dev)
+{
+       int i, ret = 0;
+
+       ENTER();
+
+       dev->stream = usb_alloc_coherent(dev->bus_adap.usb_dev,
+                                      MAX_STREAM_URB * AS102_USB_BUF_SIZE,
+                                      GFP_KERNEL,
+                                      &dev->dma_addr);
+       if (!dev->stream) {
+               dprintk(debug, "%s: usb_buffer_alloc failed\n", __func__);
+               return -ENOMEM;
+       }
+
+       memset(dev->stream, 0, MAX_STREAM_URB * AS102_USB_BUF_SIZE);
+
+       /* init urb buffers */
+       for (i = 0; i < MAX_STREAM_URB; i++) {
+               struct urb *urb;
+
+               urb = usb_alloc_urb(0, GFP_ATOMIC);
+               if (urb == NULL) {
+                       dprintk(debug, "%s: usb_alloc_urb failed\n", __func__);
+                       as102_free_usb_stream_buffer(dev);
+                       return -ENOMEM;
+               }
+
+               urb->transfer_buffer = dev->stream + (i * AS102_USB_BUF_SIZE);
+               urb->transfer_buffer_length = AS102_USB_BUF_SIZE;
+
+               dev->stream_urb[i] = urb;
+       }
+       LEAVE();
+       return ret;
+}
+
+static void as102_usb_stop_stream(struct as102_dev_t *dev)
+{
+       int i;
+
+       for (i = 0; i < MAX_STREAM_URB; i++)
+               usb_kill_urb(dev->stream_urb[i]);
+}
+
+static int as102_usb_start_stream(struct as102_dev_t *dev)
+{
+       int i, ret = 0;
+
+       for (i = 0; i < MAX_STREAM_URB; i++) {
+               ret = as102_submit_urb_stream(dev, dev->stream_urb[i]);
+               if (ret) {
+                       as102_usb_stop_stream(dev);
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
+static void as102_usb_release(struct kref *kref)
+{
+       struct as102_dev_t *as102_dev;
+
+       ENTER();
+
+       as102_dev = container_of(kref, struct as102_dev_t, kref);
+       if (as102_dev != NULL) {
+               usb_put_dev(as102_dev->bus_adap.usb_dev);
+               kfree(as102_dev);
+       }
+
+       LEAVE();
+}
+
+static void as102_usb_disconnect(struct usb_interface *intf)
+{
+       struct as102_dev_t *as102_dev;
+
+       ENTER();
+
+       /* extract as102_dev_t from usb_device private data */
+       as102_dev = usb_get_intfdata(intf);
+
+       /* unregister dvb layer */
+       as102_dvb_unregister(as102_dev);
+
+       /* free usb buffers */
+       as102_free_usb_stream_buffer(as102_dev);
+
+       usb_set_intfdata(intf, NULL);
+
+       /* usb unregister device */
+       usb_deregister_dev(intf, &as102_usb_class_driver);
+
+       /* decrement usage counter */
+       kref_put(&as102_dev->kref, as102_usb_release);
+
+       printk(KERN_INFO "%s: device has been disconnected\n", DRIVER_NAME);
+
+       LEAVE();
+}
+
+static int as102_usb_probe(struct usb_interface *intf,
+                          const struct usb_device_id *id)
+{
+       int ret;
+       struct as102_dev_t *as102_dev;
+       int i;
+
+       ENTER();
+
+       as102_dev = kzalloc(sizeof(struct as102_dev_t), GFP_KERNEL);
+       if (as102_dev == NULL) {
+               err("%s: kzalloc failed", __func__);
+               return -ENOMEM;
+       }
+
+       /* This should never actually happen */
+       if ((sizeof(as102_usb_id_table) / sizeof(struct usb_device_id)) !=
+           (sizeof(as102_device_names) / sizeof(const char *))) {
+               printk(KERN_ERR "Device names table invalid size");
+               return -EINVAL;
+       }
+
+       /* Assign the user-friendly device name */
+       for (i = 0; i < (sizeof(as102_usb_id_table) /
+                        sizeof(struct usb_device_id)); i++) {
+               if (id == &as102_usb_id_table[i])
+                       as102_dev->name = as102_device_names[i];
+       }
+
+       if (as102_dev->name == NULL)
+               as102_dev->name = "Unknown AS102 device";
+
+       /* set private callback functions */
+       as102_dev->bus_adap.ops = &as102_priv_ops;
+
+       /* init cmd token for usb bus */
+       as102_dev->bus_adap.cmd = &as102_dev->bus_adap.token.usb.c;
+       as102_dev->bus_adap.rsp = &as102_dev->bus_adap.token.usb.r;
+
+       /* init kernel device reference */
+       kref_init(&as102_dev->kref);
+
+       /* store as102 device to usb_device private data */
+       usb_set_intfdata(intf, (void *) as102_dev);
+
+       /* store in as102 device the usb_device pointer */
+       as102_dev->bus_adap.usb_dev = usb_get_dev(interface_to_usbdev(intf));
+
+       /* we can register the device now, as it is ready */
+       ret = usb_register_dev(intf, &as102_usb_class_driver);
+       if (ret < 0) {
+               /* something prevented us from registering this driver */
+               err("%s: usb_register_dev() failed (errno = %d)",
+                   __func__, ret);
+               goto failed;
+       }
+
+       printk(KERN_INFO "%s: device has been detected\n", DRIVER_NAME);
+
+       /* request buffer allocation for streaming */
+       ret = as102_alloc_usb_stream_buffer(as102_dev);
+       if (ret != 0)
+               goto failed;
+
+       /* register dvb layer */
+       ret = as102_dvb_register(as102_dev);
+
+       LEAVE();
+       return ret;
+
+failed:
+       usb_set_intfdata(intf, NULL);
+       kfree(as102_dev);
+       return ret;
+}
+
+static int as102_open(struct inode *inode, struct file *file)
+{
+       int ret = 0, minor = 0;
+       struct usb_interface *intf = NULL;
+       struct as102_dev_t *dev = NULL;
+
+       ENTER();
+
+       /* read minor from inode */
+       minor = iminor(inode);
+
+       /* fetch device from usb interface */
+       intf = usb_find_interface(&as102_usb_driver, minor);
+       if (intf == NULL) {
+               printk(KERN_ERR "%s: can't find device for minor %d\n",
+                               __func__, minor);
+               ret = -ENODEV;
+               goto exit;
+       }
+
+       /* get our device */
+       dev = usb_get_intfdata(intf);
+       if (dev == NULL) {
+               ret = -EFAULT;
+               goto exit;
+       }
+
+       /* save our device object in the file's private structure */
+       file->private_data = dev;
+
+       /* increment our usage count for the device */
+       kref_get(&dev->kref);
+
+exit:
+       LEAVE();
+       return ret;
+}
+
+static int as102_release(struct inode *inode, struct file *file)
+{
+       int ret = 0;
+       struct as102_dev_t *dev = NULL;
+
+       ENTER();
+
+       dev = file->private_data;
+       if (dev != NULL) {
+               /* decrement the count on our device */
+               kref_put(&dev->kref, as102_usb_release);
+       }
+
+       LEAVE();
+       return ret;
+}
+
+MODULE_DEVICE_TABLE(usb, as102_usb_id_table);
+
+/* EOF - vim: set textwidth=80 ts=8 sw=8 sts=8 noet: */
diff --git a/drivers/staging/media/as102/as102_usb_drv.h b/drivers/staging/media/as102/as102_usb_drv.h
new file mode 100644 (file)
index 0000000..fb1fc41
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Abilis Systems Single DVB-T Receiver
+ * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com>
+ * Copyright (C) 2010 Devin Heitmueller <dheitmueller@kernellabs.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  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/version.h>
+
+#ifndef _AS102_USB_DRV_H_
+#define _AS102_USB_DRV_H_
+
+#define AS102_USB_DEVICE_TX_CTRL_CMD   0xF1
+#define AS102_USB_DEVICE_RX_CTRL_CMD   0xF2
+
+/* define these values to match the supported devices */
+
+/* Abilis system: "TITAN" */
+#define AS102_REFERENCE_DESIGN         "Abilis Systems DVB-Titan"
+#define AS102_USB_DEVICE_VENDOR_ID     0x1BA6
+#define AS102_USB_DEVICE_PID_0001      0x0001
+
+/* PCTV Systems: PCTV picoStick (74e) */
+#define AS102_PCTV_74E                 "PCTV Systems picoStick (74e)"
+#define PCTV_74E_USB_VID               0x2013
+#define PCTV_74E_USB_PID               0x0246
+
+/* Elgato: EyeTV DTT Deluxe */
+#define AS102_ELGATO_EYETV_DTT_NAME    "Elgato EyeTV DTT Deluxe"
+#define ELGATO_EYETV_DTT_USB_VID       0x0fd9
+#define ELGATO_EYETV_DTT_USB_PID       0x002c
+
+/* nBox: nBox DVB-T Dongle */
+#define AS102_NBOX_DVBT_DONGLE_NAME    "nBox DVB-T Dongle"
+#define NBOX_DVBT_DONGLE_USB_VID       0x0b89
+#define NBOX_DVBT_DONGLE_USB_PID       0x0007
+
+void as102_urb_stream_irq(struct urb *urb);
+
+struct as10x_usb_token_cmd_t {
+       /* token cmd */
+       struct as10x_cmd_t c;
+       /* token response */
+       struct as10x_cmd_t r;
+};
+#endif
+/* EOF - vim: set textwidth=80 ts=8 sw=8 sts=8 noet: */
diff --git a/drivers/staging/media/as102/as10x_cmd.c b/drivers/staging/media/as102/as10x_cmd.c
new file mode 100644 (file)
index 0000000..0dcba80
--- /dev/null
@@ -0,0 +1,452 @@
+/*
+ * Abilis Systems Single DVB-T Receiver
+ * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com>
+ * Copyright (C) 2010 Devin Heitmueller <dheitmueller@kernellabs.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  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 "as102_drv.h"
+#include "as10x_types.h"
+#include "as10x_cmd.h"
+
+/**
+ * as10x_cmd_turn_on - send turn on command to AS10x
+ * @phandle:   pointer to AS10x handle
+ *
+ * Return 0 when no error, < 0 in case of error.
+ */
+int as10x_cmd_turn_on(as10x_handle_t *phandle)
+{
+       int error;
+       struct as10x_cmd_t *pcmd, *prsp;
+
+       ENTER();
+
+       pcmd = phandle->cmd;
+       prsp = phandle->rsp;
+
+       /* prepare command */
+       as10x_cmd_build(pcmd, (++phandle->cmd_xid),
+                       sizeof(pcmd->body.turn_on.req));
+
+       /* fill command */
+       pcmd->body.turn_on.req.proc_id = cpu_to_le16(CONTROL_PROC_TURNON);
+
+       /* send command */
+       if (phandle->ops->xfer_cmd) {
+               error = phandle->ops->xfer_cmd(phandle, (uint8_t *) pcmd,
+                                              sizeof(pcmd->body.turn_on.req) +
+                                              HEADER_SIZE,
+                                              (uint8_t *) prsp,
+                                              sizeof(prsp->body.turn_on.rsp) +
+                                              HEADER_SIZE);
+       } else {
+               error = AS10X_CMD_ERROR;
+       }
+
+       if (error < 0)
+               goto out;
+
+       /* parse response */
+       error = as10x_rsp_parse(prsp, CONTROL_PROC_TURNON_RSP);
+
+out:
+       LEAVE();
+       return error;
+}
+
+/**
+ * as10x_cmd_turn_off - send turn off command to AS10x
+ * @phandle:   pointer to AS10x handle
+ *
+ * Return 0 on success or negative value in case of error.
+ */
+int as10x_cmd_turn_off(as10x_handle_t *phandle)
+{
+       int error;
+       struct as10x_cmd_t *pcmd, *prsp;
+
+       ENTER();
+
+       pcmd = phandle->cmd;
+       prsp = phandle->rsp;
+
+       /* prepare command */
+       as10x_cmd_build(pcmd, (++phandle->cmd_xid),
+                       sizeof(pcmd->body.turn_off.req));
+
+       /* fill command */
+       pcmd->body.turn_off.req.proc_id = cpu_to_le16(CONTROL_PROC_TURNOFF);
+
+       /* send command */
+       if (phandle->ops->xfer_cmd) {
+               error = phandle->ops->xfer_cmd(
+                       phandle, (uint8_t *) pcmd,
+                       sizeof(pcmd->body.turn_off.req) + HEADER_SIZE,
+                       (uint8_t *) prsp,
+                       sizeof(prsp->body.turn_off.rsp) + HEADER_SIZE);
+       } else {
+               error = AS10X_CMD_ERROR;
+       }
+
+       if (error < 0)
+               goto out;
+
+       /* parse response */
+       error = as10x_rsp_parse(prsp, CONTROL_PROC_TURNOFF_RSP);
+
+out:
+       LEAVE();
+       return error;
+}
+
+/**
+ * as10x_cmd_set_tune - send set tune command to AS10x
+ * @phandle: pointer to AS10x handle
+ * @ptune:   tune parameters
+ *
+ * Return 0 on success or negative value in case of error.
+ */
+int as10x_cmd_set_tune(as10x_handle_t *phandle, struct as10x_tune_args *ptune)
+{
+       int error;
+       struct as10x_cmd_t *preq, *prsp;
+
+       ENTER();
+
+       preq = phandle->cmd;
+       prsp = phandle->rsp;
+
+       /* prepare command */
+       as10x_cmd_build(preq, (++phandle->cmd_xid),
+                       sizeof(preq->body.set_tune.req));
+
+       /* fill command */
+       preq->body.set_tune.req.proc_id = cpu_to_le16(CONTROL_PROC_SETTUNE);
+       preq->body.set_tune.req.args.freq = cpu_to_le32(ptune->freq);
+       preq->body.set_tune.req.args.bandwidth = ptune->bandwidth;
+       preq->body.set_tune.req.args.hier_select = ptune->hier_select;
+       preq->body.set_tune.req.args.constellation = ptune->constellation;
+       preq->body.set_tune.req.args.hierarchy = ptune->hierarchy;
+       preq->body.set_tune.req.args.interleaving_mode  =
+               ptune->interleaving_mode;
+       preq->body.set_tune.req.args.code_rate  = ptune->code_rate;
+       preq->body.set_tune.req.args.guard_interval = ptune->guard_interval;
+       preq->body.set_tune.req.args.transmission_mode  =
+               ptune->transmission_mode;
+
+       /* send command */
+       if (phandle->ops->xfer_cmd) {
+               error = phandle->ops->xfer_cmd(phandle,
+                                              (uint8_t *) preq,
+                                              sizeof(preq->body.set_tune.req)
+                                              + HEADER_SIZE,
+                                              (uint8_t *) prsp,
+                                              sizeof(prsp->body.set_tune.rsp)
+                                              + HEADER_SIZE);
+       } else {
+               error = AS10X_CMD_ERROR;
+       }
+
+       if (error < 0)
+               goto out;
+
+       /* parse response */
+       error = as10x_rsp_parse(prsp, CONTROL_PROC_SETTUNE_RSP);
+
+out:
+       LEAVE();
+       return error;
+}
+
+/**
+ * as10x_cmd_get_tune_status - send get tune status command to AS10x
+ * @phandle: pointer to AS10x handle
+ * @pstatus: pointer to updated status structure of the current tune
+ *
+ * Return 0 on success or negative value in case of error.
+ */
+int as10x_cmd_get_tune_status(as10x_handle_t *phandle,
+                             struct as10x_tune_status *pstatus)
+{
+       int error;
+       struct as10x_cmd_t  *preq, *prsp;
+
+       ENTER();
+
+       preq = phandle->cmd;
+       prsp = phandle->rsp;
+
+       /* prepare command */
+       as10x_cmd_build(preq, (++phandle->cmd_xid),
+                       sizeof(preq->body.get_tune_status.req));
+
+       /* fill command */
+       preq->body.get_tune_status.req.proc_id =
+               cpu_to_le16(CONTROL_PROC_GETTUNESTAT);
+
+       /* send command */
+       if (phandle->ops->xfer_cmd) {
+               error = phandle->ops->xfer_cmd(
+                       phandle,
+                       (uint8_t *) preq,
+                       sizeof(preq->body.get_tune_status.req) + HEADER_SIZE,
+                       (uint8_t *) prsp,
+                       sizeof(prsp->body.get_tune_status.rsp) + HEADER_SIZE);
+       } else {
+               error = AS10X_CMD_ERROR;
+       }
+
+       if (error < 0)
+               goto out;
+
+       /* parse response */
+       error = as10x_rsp_parse(prsp, CONTROL_PROC_GETTUNESTAT_RSP);
+       if (error < 0)
+               goto out;
+
+       /* Response OK -> get response data */
+       pstatus->tune_state = prsp->body.get_tune_status.rsp.sts.tune_state;
+       pstatus->signal_strength  =
+               le16_to_cpu(prsp->body.get_tune_status.rsp.sts.signal_strength);
+       pstatus->PER = le16_to_cpu(prsp->body.get_tune_status.rsp.sts.PER);
+       pstatus->BER = le16_to_cpu(prsp->body.get_tune_status.rsp.sts.BER);
+
+out:
+       LEAVE();
+       return error;
+}
+
+/**
+ * send get TPS command to AS10x
+ * @phandle:   pointer to AS10x handle
+ * @ptps:      pointer to TPS parameters structure
+ *
+ * Return 0 on success or negative value in case of error.
+ */
+int as10x_cmd_get_tps(as10x_handle_t *phandle, struct as10x_tps *ptps)
+{
+       int error;
+       struct as10x_cmd_t *pcmd, *prsp;
+
+       ENTER();
+
+       pcmd = phandle->cmd;
+       prsp = phandle->rsp;
+
+       /* prepare command */
+       as10x_cmd_build(pcmd, (++phandle->cmd_xid),
+                       sizeof(pcmd->body.get_tps.req));
+
+       /* fill command */
+       pcmd->body.get_tune_status.req.proc_id =
+               cpu_to_le16(CONTROL_PROC_GETTPS);
+
+       /* send command */
+       if (phandle->ops->xfer_cmd) {
+               error = phandle->ops->xfer_cmd(phandle,
+                                              (uint8_t *) pcmd,
+                                              sizeof(pcmd->body.get_tps.req) +
+                                              HEADER_SIZE,
+                                              (uint8_t *) prsp,
+                                              sizeof(prsp->body.get_tps.rsp) +
+                                              HEADER_SIZE);
+       } else {
+               error = AS10X_CMD_ERROR;
+       }
+
+       if (error < 0)
+               goto out;
+
+       /* parse response */
+       error = as10x_rsp_parse(prsp, CONTROL_PROC_GETTPS_RSP);
+       if (error < 0)
+               goto out;
+
+       /* Response OK -> get response data */
+       ptps->constellation = prsp->body.get_tps.rsp.tps.constellation;
+       ptps->hierarchy = prsp->body.get_tps.rsp.tps.hierarchy;
+       ptps->interleaving_mode = prsp->body.get_tps.rsp.tps.interleaving_mode;
+       ptps->code_rate_HP = prsp->body.get_tps.rsp.tps.code_rate_HP;
+       ptps->code_rate_LP = prsp->body.get_tps.rsp.tps.code_rate_LP;
+       ptps->guard_interval = prsp->body.get_tps.rsp.tps.guard_interval;
+       ptps->transmission_mode  = prsp->body.get_tps.rsp.tps.transmission_mode;
+       ptps->DVBH_mask_HP = prsp->body.get_tps.rsp.tps.DVBH_mask_HP;
+       ptps->DVBH_mask_LP = prsp->body.get_tps.rsp.tps.DVBH_mask_LP;
+       ptps->cell_ID = le16_to_cpu(prsp->body.get_tps.rsp.tps.cell_ID);
+
+out:
+       LEAVE();
+       return error;
+}
+
+/**
+ * as10x_cmd_get_demod_stats - send get demod stats command to AS10x
+ * @phandle:       pointer to AS10x handle
+ * @pdemod_stats:  pointer to demod stats parameters structure
+ *
+ * Return 0 on success or negative value in case of error.
+ */
+int as10x_cmd_get_demod_stats(as10x_handle_t  *phandle,
+                             struct as10x_demod_stats *pdemod_stats)
+{
+       int error;
+       struct as10x_cmd_t *pcmd, *prsp;
+
+       ENTER();
+
+       pcmd = phandle->cmd;
+       prsp = phandle->rsp;
+
+       /* prepare command */
+       as10x_cmd_build(pcmd, (++phandle->cmd_xid),
+                       sizeof(pcmd->body.get_demod_stats.req));
+
+       /* fill command */
+       pcmd->body.get_demod_stats.req.proc_id =
+               cpu_to_le16(CONTROL_PROC_GET_DEMOD_STATS);
+
+       /* send command */
+       if (phandle->ops->xfer_cmd) {
+               error = phandle->ops->xfer_cmd(phandle,
+                               (uint8_t *) pcmd,
+                               sizeof(pcmd->body.get_demod_stats.req)
+                               + HEADER_SIZE,
+                               (uint8_t *) prsp,
+                               sizeof(prsp->body.get_demod_stats.rsp)
+                               + HEADER_SIZE);
+       } else {
+               error = AS10X_CMD_ERROR;
+       }
+
+       if (error < 0)
+               goto out;
+
+       /* parse response */
+       error = as10x_rsp_parse(prsp, CONTROL_PROC_GET_DEMOD_STATS_RSP);
+       if (error < 0)
+               goto out;
+
+       /* Response OK -> get response data */
+       pdemod_stats->frame_count =
+               le32_to_cpu(prsp->body.get_demod_stats.rsp.stats.frame_count);
+       pdemod_stats->bad_frame_count =
+               le32_to_cpu(prsp->body.get_demod_stats.rsp.stats.bad_frame_count);
+       pdemod_stats->bytes_fixed_by_rs =
+               le32_to_cpu(prsp->body.get_demod_stats.rsp.stats.bytes_fixed_by_rs);
+       pdemod_stats->mer =
+               le16_to_cpu(prsp->body.get_demod_stats.rsp.stats.mer);
+       pdemod_stats->has_started =
+               prsp->body.get_demod_stats.rsp.stats.has_started;
+
+out:
+       LEAVE();
+       return error;
+}
+
+/**
+ * as10x_cmd_get_impulse_resp - send get impulse response command to AS10x
+ * @phandle:  pointer to AS10x handle
+ * @is_ready: pointer to value indicating when impulse
+ *           response data is ready
+ *
+ * Return 0 on success or negative value in case of error.
+ */
+int as10x_cmd_get_impulse_resp(as10x_handle_t     *phandle,
+                              uint8_t *is_ready)
+{
+       int error;
+       struct as10x_cmd_t *pcmd, *prsp;
+
+       ENTER();
+
+       pcmd = phandle->cmd;
+       prsp = phandle->rsp;
+
+       /* prepare command */
+       as10x_cmd_build(pcmd, (++phandle->cmd_xid),
+                       sizeof(pcmd->body.get_impulse_rsp.req));
+
+       /* fill command */
+       pcmd->body.get_impulse_rsp.req.proc_id =
+               cpu_to_le16(CONTROL_PROC_GET_IMPULSE_RESP);
+
+       /* send command */
+       if (phandle->ops->xfer_cmd) {
+               error = phandle->ops->xfer_cmd(phandle,
+                                       (uint8_t *) pcmd,
+                                       sizeof(pcmd->body.get_impulse_rsp.req)
+                                       + HEADER_SIZE,
+                                       (uint8_t *) prsp,
+                                       sizeof(prsp->body.get_impulse_rsp.rsp)
+                                       + HEADER_SIZE);
+       } else {
+               error = AS10X_CMD_ERROR;
+       }
+
+       if (error < 0)
+               goto out;
+
+       /* parse response */
+       error = as10x_rsp_parse(prsp, CONTROL_PROC_GET_IMPULSE_RESP_RSP);
+       if (error < 0)
+               goto out;
+
+       /* Response OK -> get response data */
+       *is_ready = prsp->body.get_impulse_rsp.rsp.is_ready;
+
+out:
+       LEAVE();
+       return error;
+}
+
+/**
+ * as10x_cmd_build - build AS10x command header
+ * @pcmd:     pointer to AS10x command buffer
+ * @xid:      sequence id of the command
+ * @cmd_len:  length of the command
+ */
+void as10x_cmd_build(struct as10x_cmd_t *pcmd,
+                    uint16_t xid, uint16_t cmd_len)
+{
+       pcmd->header.req_id = cpu_to_le16(xid);
+       pcmd->header.prog = cpu_to_le16(SERVICE_PROG_ID);
+       pcmd->header.version = cpu_to_le16(SERVICE_PROG_VERSION);
+       pcmd->header.data_len = cpu_to_le16(cmd_len);
+}
+
+/**
+ * as10x_rsp_parse - Parse command response
+ * @prsp:       pointer to AS10x command buffer
+ * @proc_id:    id of the command
+ *
+ * Return 0 on success or negative value in case of error.
+ */
+int as10x_rsp_parse(struct as10x_cmd_t *prsp, uint16_t proc_id)
+{
+       int error;
+
+       /* extract command error code */
+       error = prsp->body.common.rsp.error;
+
+       if ((error == 0) &&
+           (le16_to_cpu(prsp->body.common.rsp.proc_id) == proc_id)) {
+               return 0;
+       }
+
+       return AS10X_CMD_ERROR;
+}
diff --git a/drivers/staging/media/as102/as10x_cmd.h b/drivers/staging/media/as102/as10x_cmd.h
new file mode 100644 (file)
index 0000000..01a7163
--- /dev/null
@@ -0,0 +1,540 @@
+/*
+ * Abilis Systems Single DVB-T Receiver
+ * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  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.
+ */
+#ifndef _AS10X_CMD_H_
+#define _AS10X_CMD_H_
+
+#ifdef __KERNEL__
+#include <linux/kernel.h>
+#endif
+
+#include "as10x_types.h"
+
+/*********************************/
+/*       MACRO DEFINITIONS       */
+/*********************************/
+#define AS10X_CMD_ERROR -1
+
+#define SERVICE_PROG_ID        0x0002
+#define SERVICE_PROG_VERSION   0x0001
+
+#define HIER_NONE              0x00
+#define HIER_LOW_PRIORITY      0x01
+
+#define HEADER_SIZE (sizeof(struct as10x_cmd_header_t))
+
+/* context request types */
+#define GET_CONTEXT_DATA        1
+#define SET_CONTEXT_DATA        2
+
+/* ODSP suspend modes */
+#define CFG_MODE_ODSP_RESUME  0
+#define CFG_MODE_ODSP_SUSPEND 1
+
+/* Dump memory size */
+#define DUMP_BLOCK_SIZE_MAX   0x20
+
+/*********************************/
+/*     TYPE DEFINITION           */
+/*********************************/
+typedef enum {
+   CONTROL_PROC_TURNON               = 0x0001,
+   CONTROL_PROC_TURNON_RSP           = 0x0100,
+   CONTROL_PROC_SET_REGISTER         = 0x0002,
+   CONTROL_PROC_SET_REGISTER_RSP     = 0x0200,
+   CONTROL_PROC_GET_REGISTER         = 0x0003,
+   CONTROL_PROC_GET_REGISTER_RSP     = 0x0300,
+   CONTROL_PROC_SETTUNE              = 0x000A,
+   CONTROL_PROC_SETTUNE_RSP          = 0x0A00,
+   CONTROL_PROC_GETTUNESTAT          = 0x000B,
+   CONTROL_PROC_GETTUNESTAT_RSP      = 0x0B00,
+   CONTROL_PROC_GETTPS               = 0x000D,
+   CONTROL_PROC_GETTPS_RSP           = 0x0D00,
+   CONTROL_PROC_SETFILTER            = 0x000E,
+   CONTROL_PROC_SETFILTER_RSP        = 0x0E00,
+   CONTROL_PROC_REMOVEFILTER         = 0x000F,
+   CONTROL_PROC_REMOVEFILTER_RSP     = 0x0F00,
+   CONTROL_PROC_GET_IMPULSE_RESP     = 0x0012,
+   CONTROL_PROC_GET_IMPULSE_RESP_RSP = 0x1200,
+   CONTROL_PROC_START_STREAMING      = 0x0013,
+   CONTROL_PROC_START_STREAMING_RSP  = 0x1300,
+   CONTROL_PROC_STOP_STREAMING       = 0x0014,
+   CONTROL_PROC_STOP_STREAMING_RSP   = 0x1400,
+   CONTROL_PROC_GET_DEMOD_STATS      = 0x0015,
+   CONTROL_PROC_GET_DEMOD_STATS_RSP  = 0x1500,
+   CONTROL_PROC_ELNA_CHANGE_MODE     = 0x0016,
+   CONTROL_PROC_ELNA_CHANGE_MODE_RSP = 0x1600,
+   CONTROL_PROC_ODSP_CHANGE_MODE     = 0x0017,
+   CONTROL_PROC_ODSP_CHANGE_MODE_RSP = 0x1700,
+   CONTROL_PROC_AGC_CHANGE_MODE      = 0x0018,
+   CONTROL_PROC_AGC_CHANGE_MODE_RSP  = 0x1800,
+
+   CONTROL_PROC_CONTEXT              = 0x00FC,
+   CONTROL_PROC_CONTEXT_RSP          = 0xFC00,
+   CONTROL_PROC_DUMP_MEMORY          = 0x00FD,
+   CONTROL_PROC_DUMP_MEMORY_RSP      = 0xFD00,
+   CONTROL_PROC_DUMPLOG_MEMORY       = 0x00FE,
+   CONTROL_PROC_DUMPLOG_MEMORY_RSP   = 0xFE00,
+   CONTROL_PROC_TURNOFF              = 0x00FF,
+   CONTROL_PROC_TURNOFF_RSP          = 0xFF00
+} control_proc;
+
+
+#pragma pack(1)
+typedef union {
+   /* request */
+   struct {
+      /* request identifier */
+      uint16_t proc_id;
+   } req;
+   /* response */
+   struct {
+      /* response identifier */
+      uint16_t proc_id;
+      /* error */
+      uint8_t error;
+   } rsp;
+} TURN_ON;
+
+typedef union {
+   /* request */
+   struct {
+      /* request identifier */
+      uint16_t proc_id;
+   } req;
+   /* response */
+   struct {
+      /* response identifier */
+      uint16_t proc_id;
+      /* error */
+      uint8_t err;
+   } rsp;
+} TURN_OFF;
+
+typedef union {
+   /* request */
+   struct {
+      /* request identifier */
+      uint16_t proc_id;
+      /* tune params */
+      struct as10x_tune_args args;
+   } req;
+   /* response */
+   struct {
+      /* response identifier */
+      uint16_t proc_id;
+      /* response error */
+      uint8_t error;
+   } rsp;
+} SET_TUNE;
+
+typedef union {
+   /* request */
+   struct {
+      /* request identifier */
+      uint16_t proc_id;
+   } req;
+   /* response */
+   struct {
+      /* response identifier */
+      uint16_t proc_id;
+      /* response error */
+      uint8_t error;
+      /* tune status */
+      struct as10x_tune_status sts;
+   } rsp;
+} GET_TUNE_STATUS;
+
+typedef union {
+   /* request */
+   struct {
+      /* request identifier */
+      uint16_t proc_id;
+   } req;
+   /* response */
+   struct {
+      /* response identifier */
+      uint16_t proc_id;
+      /* response error */
+      uint8_t error;
+      /* tps details */
+      struct as10x_tps tps;
+   } rsp;
+} GET_TPS;
+
+typedef union {
+   /* request */
+   struct {
+      /* request identifier */
+      uint16_t  proc_id;
+   } req;
+   /* response */
+   struct {
+      /* response identifier */
+      uint16_t proc_id;
+      /* response error */
+      uint8_t error;
+   } rsp;
+} COMMON;
+
+typedef union {
+   /* request */
+   struct {
+      /* request identifier */
+      uint16_t  proc_id;
+      /* PID to filter */
+      uint16_t  pid;
+      /* stream type (MPE, PSI/SI or PES )*/
+      uint8_t stream_type;
+      /* PID index in filter table */
+      uint8_t idx;
+   } req;
+   /* response */
+   struct {
+      /* response identifier */
+      uint16_t proc_id;
+      /* response error */
+      uint8_t error;
+      /* Filter id */
+      uint8_t filter_id;
+   } rsp;
+} ADD_PID_FILTER;
+
+typedef union {
+   /* request */
+   struct {
+      /* request identifier */
+      uint16_t  proc_id;
+      /* PID to remove */
+      uint16_t  pid;
+   } req;
+   /* response */
+   struct {
+      /* response identifier */
+      uint16_t proc_id;
+      /* response error */
+      uint8_t error;
+   } rsp;
+} DEL_PID_FILTER;
+
+typedef union {
+   /* request */
+   struct {
+      /* request identifier */
+      uint16_t proc_id;
+   } req;
+   /* response */
+   struct {
+      /* response identifier */
+      uint16_t proc_id;
+      /* error */
+      uint8_t error;
+   } rsp;
+} START_STREAMING;
+
+typedef union {
+   /* request */
+   struct {
+      /* request identifier */
+      uint16_t proc_id;
+   } req;
+   /* response */
+   struct {
+      /* response identifier */
+      uint16_t proc_id;
+      /* error */
+      uint8_t error;
+   } rsp;
+} STOP_STREAMING;
+
+typedef union {
+   /* request */
+   struct {
+      /* request identifier */
+      uint16_t proc_id;
+   } req;
+   /* response */
+   struct {
+      /* response identifier */
+      uint16_t proc_id;
+      /* error */
+      uint8_t error;
+      /* demod stats */
+      struct as10x_demod_stats stats;
+   } rsp;
+} GET_DEMOD_STATS;
+
+typedef union {
+   /* request */
+   struct {
+      /* request identifier */
+      uint16_t proc_id;
+   } req;
+   /* response */
+   struct {
+      /* response identifier */
+      uint16_t proc_id;
+      /* error */
+      uint8_t error;
+      /* impulse response ready */
+      uint8_t is_ready;
+   } rsp;
+} GET_IMPULSE_RESP;
+
+typedef union {
+   /* request */
+   struct {
+      /* request identifier */
+      uint16_t proc_id;
+      /* value to write (for set context)*/
+      struct as10x_register_value reg_val;
+      /* context tag */
+      uint16_t tag;
+      /* context request type */
+      uint16_t type;
+   } req;
+   /* response */
+   struct {
+      /* response identifier */
+      uint16_t proc_id;
+      /* value read (for get context) */
+      struct as10x_register_value reg_val;
+      /* context request type */
+      uint16_t type;
+      /* error */
+      uint8_t error;
+   } rsp;
+} FW_CONTEXT;
+
+typedef union {
+   /* request */
+   struct {
+      /* response identifier */
+      uint16_t proc_id;
+      /* register description */
+      struct as10x_register_addr reg_addr;
+      /* register content */
+      struct as10x_register_value reg_val;
+   } req;
+   /* response */
+   struct {
+      /* response identifier */
+      uint16_t proc_id;
+      /* error */
+      uint8_t error;
+   } rsp;
+} SET_REGISTER;
+
+typedef union {
+   /* request */
+   struct {
+      /* response identifier */
+      uint16_t proc_id;
+      /* register description */
+      struct as10x_register_addr reg_addr;
+   } req;
+   /* response */
+   struct {
+      /* response identifier */
+      uint16_t proc_id;
+      /* error */
+      uint8_t error;
+      /* register content */
+      struct as10x_register_value reg_val;
+   } rsp;
+} GET_REGISTER;
+
+typedef union {
+   /* request */
+   struct {
+      /* request identifier */
+      uint16_t proc_id;
+      /* mode */
+      uint8_t mode;
+   } req;
+   /* response */
+   struct {
+      /* response identifier */
+      uint16_t proc_id;
+      /* error */
+      uint8_t error;
+   } rsp;
+} CFG_CHANGE_MODE;
+
+struct as10x_cmd_header_t {
+   uint16_t req_id;
+   uint16_t prog;
+   uint16_t version;
+   uint16_t data_len;
+};
+
+#define DUMP_BLOCK_SIZE 16
+typedef union {
+   /* request */
+   struct {
+      /* request identifier */
+      uint16_t proc_id;
+      /* dump memory type request */
+      uint8_t dump_req;
+      /* register description */
+      struct as10x_register_addr reg_addr;
+      /* nb blocks to read */
+      uint16_t num_blocks;
+   } req;
+   /* response */
+   struct {
+      /* response identifier */
+      uint16_t proc_id;
+      /* error */
+      uint8_t error;
+      /* dump response */
+      uint8_t dump_rsp;
+      /* data */
+      union {
+        uint8_t  data8[DUMP_BLOCK_SIZE];
+        uint16_t data16[DUMP_BLOCK_SIZE / sizeof(uint16_t)];
+        uint32_t data32[DUMP_BLOCK_SIZE / sizeof(uint32_t)];
+      } u;
+   } rsp;
+} DUMP_MEMORY;
+
+typedef union {
+   struct {
+      /* request identifier */
+      uint16_t proc_id;
+      /* dump memory type request */
+      uint8_t dump_req;
+   } req;
+   struct {
+      /* request identifier */
+      uint16_t proc_id;
+      /* error */
+      uint8_t error;
+      /* dump response */
+      uint8_t dump_rsp;
+      /* dump data */
+      uint8_t data[DUMP_BLOCK_SIZE];
+   } rsp;
+} DUMPLOG_MEMORY;
+
+typedef union {
+   /* request */
+   struct {
+      uint16_t proc_id;
+      uint8_t data[64 - sizeof(struct as10x_cmd_header_t) -2 /* proc_id */];
+   } req;
+   /* response */
+   struct {
+      uint16_t proc_id;
+      uint8_t error;
+      uint8_t data[64 - sizeof(struct as10x_cmd_header_t) /* header */
+                     - 2 /* proc_id */ - 1 /* rc */];
+   } rsp;
+} RAW_DATA;
+
+struct as10x_cmd_t {
+   /* header */
+   struct as10x_cmd_header_t header;
+   /* body */
+   union {
+      TURN_ON           turn_on;
+      TURN_OFF          turn_off;
+      SET_TUNE          set_tune;
+      GET_TUNE_STATUS   get_tune_status;
+      GET_TPS           get_tps;
+      COMMON            common;
+      ADD_PID_FILTER    add_pid_filter;
+      DEL_PID_FILTER    del_pid_filter;
+      START_STREAMING   start_streaming;
+      STOP_STREAMING    stop_streaming;
+      GET_DEMOD_STATS   get_demod_stats;
+      GET_IMPULSE_RESP  get_impulse_rsp;
+      FW_CONTEXT        context;
+      SET_REGISTER      set_register;
+      GET_REGISTER      get_register;
+      CFG_CHANGE_MODE   cfg_change_mode;
+      DUMP_MEMORY       dump_memory;
+      DUMPLOG_MEMORY    dumplog_memory;
+      RAW_DATA          raw_data;
+   } body;
+};
+
+struct as10x_token_cmd_t {
+   /* token cmd */
+   struct as10x_cmd_t c;
+   /* token response */
+   struct as10x_cmd_t r;
+};
+#pragma pack()
+
+
+/**************************/
+/* FUNCTION DECLARATION   */
+/**************************/
+
+void as10x_cmd_build(struct as10x_cmd_t *pcmd, uint16_t proc_id,
+                     uint16_t cmd_len);
+int as10x_rsp_parse(struct as10x_cmd_t *r, uint16_t proc_id);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* as10x cmd */
+int as10x_cmd_turn_on(as10x_handle_t *phandle);
+int as10x_cmd_turn_off(as10x_handle_t *phandle);
+
+int as10x_cmd_set_tune(as10x_handle_t *phandle,
+                      struct as10x_tune_args *ptune);
+
+int as10x_cmd_get_tune_status(as10x_handle_t *phandle,
+                             struct as10x_tune_status *pstatus);
+
+int as10x_cmd_get_tps(as10x_handle_t *phandle,
+                     struct as10x_tps *ptps);
+
+int as10x_cmd_get_demod_stats(as10x_handle_t  *phandle,
+                             struct as10x_demod_stats *pdemod_stats);
+
+int as10x_cmd_get_impulse_resp(as10x_handle_t *phandle,
+                              uint8_t *is_ready);
+
+/* as10x cmd stream */
+int as10x_cmd_add_PID_filter(as10x_handle_t *phandle,
+                            struct as10x_ts_filter *filter);
+int as10x_cmd_del_PID_filter(as10x_handle_t *phandle,
+                            uint16_t pid_value);
+
+int as10x_cmd_start_streaming(as10x_handle_t *phandle);
+int as10x_cmd_stop_streaming(as10x_handle_t *phandle);
+
+/* as10x cmd cfg */
+int as10x_cmd_set_context(as10x_handle_t *phandle,
+                         uint16_t tag,
+                         uint32_t value);
+int as10x_cmd_get_context(as10x_handle_t *phandle,
+                         uint16_t tag,
+                         uint32_t *pvalue);
+
+int as10x_cmd_eLNA_change_mode(as10x_handle_t *phandle, uint8_t mode);
+int as10x_context_rsp_parse(struct as10x_cmd_t *prsp, uint16_t proc_id);
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* EOF - vim: set textwidth=80 ts=3 sw=3 sts=3 et: */
diff --git a/drivers/staging/media/as102/as10x_cmd_cfg.c b/drivers/staging/media/as102/as10x_cmd_cfg.c
new file mode 100644 (file)
index 0000000..ec6f69f
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * Abilis Systems Single DVB-T Receiver
+ * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  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 "as102_drv.h"
+#include "as10x_types.h"
+#include "as10x_cmd.h"
+
+/***************************/
+/* FUNCTION DEFINITION     */
+/***************************/
+
+/**
+ * as10x_cmd_get_context - Send get context command to AS10x
+ * @phandle:   pointer to AS10x handle
+ * @tag:       context tag
+ * @pvalue:    pointer where to store context value read
+ *
+ * Return 0 on success or negative value in case of error.
+ */
+int as10x_cmd_get_context(as10x_handle_t *phandle, uint16_t tag,
+                         uint32_t *pvalue)
+{
+       int  error;
+       struct as10x_cmd_t *pcmd, *prsp;
+
+       ENTER();
+
+       pcmd = phandle->cmd;
+       prsp = phandle->rsp;
+
+       /* prepare command */
+       as10x_cmd_build(pcmd, (++phandle->cmd_xid),
+                       sizeof(pcmd->body.context.req));
+
+       /* fill command */
+       pcmd->body.context.req.proc_id = cpu_to_le16(CONTROL_PROC_CONTEXT);
+       pcmd->body.context.req.tag = cpu_to_le16(tag);
+       pcmd->body.context.req.type = cpu_to_le16(GET_CONTEXT_DATA);
+
+       /* send command */
+       if (phandle->ops->xfer_cmd) {
+               error  = phandle->ops->xfer_cmd(phandle,
+                                               (uint8_t *) pcmd,
+                                               sizeof(pcmd->body.context.req)
+                                               + HEADER_SIZE,
+                                               (uint8_t *) prsp,
+                                               sizeof(prsp->body.context.rsp)
+                                               + HEADER_SIZE);
+       } else {
+               error = AS10X_CMD_ERROR;
+       }
+
+       if (error < 0)
+               goto out;
+
+       /* parse response: context command do not follow the common response */
+       /* structure -> specific handling response parse required            */
+       error = as10x_context_rsp_parse(prsp, CONTROL_PROC_CONTEXT_RSP);
+
+       if (error == 0) {
+               /* Response OK -> get response data */
+               *pvalue = le32_to_cpu(prsp->body.context.rsp.reg_val.u.value32);
+               /* value returned is always a 32-bit value */
+       }
+
+out:
+       LEAVE();
+       return error;
+}
+
+/**
+ * as10x_cmd_set_context - send set context command to AS10x
+ * @phandle:   pointer to AS10x handle
+ * @tag:       context tag
+ * @value:     value to set in context
+ *
+ * Return 0 on success or negative value in case of error.
+ */
+int as10x_cmd_set_context(as10x_handle_t *phandle, uint16_t tag,
+                         uint32_t value)
+{
+       int error;
+       struct as10x_cmd_t *pcmd, *prsp;
+
+       ENTER();
+
+       pcmd = phandle->cmd;
+       prsp = phandle->rsp;
+
+       /* prepare command */
+       as10x_cmd_build(pcmd, (++phandle->cmd_xid),
+                       sizeof(pcmd->body.context.req));
+
+       /* fill command */
+       pcmd->body.context.req.proc_id = cpu_to_le16(CONTROL_PROC_CONTEXT);
+       /* pcmd->body.context.req.reg_val.mode initialization is not required */
+       pcmd->body.context.req.reg_val.u.value32 = cpu_to_le32(value);
+       pcmd->body.context.req.tag = cpu_to_le16(tag);
+       pcmd->body.context.req.type = cpu_to_le16(SET_CONTEXT_DATA);
+
+       /* send command */
+       if (phandle->ops->xfer_cmd) {
+               error  = phandle->ops->xfer_cmd(phandle,
+                                               (uint8_t *) pcmd,
+                                               sizeof(pcmd->body.context.req)
+                                               + HEADER_SIZE,
+                                               (uint8_t *) prsp,
+                                               sizeof(prsp->body.context.rsp)
+                                               + HEADER_SIZE);
+       } else {
+               error = AS10X_CMD_ERROR;
+       }
+
+       if (error < 0)
+               goto out;
+
+       /* parse response: context command do not follow the common response */
+       /* structure -> specific handling response parse required            */
+       error = as10x_context_rsp_parse(prsp, CONTROL_PROC_CONTEXT_RSP);
+
+out:
+       LEAVE();
+       return error;
+}
+
+/**
+ * as10x_cmd_eLNA_change_mode - send eLNA change mode command to AS10x
+ * @phandle:   pointer to AS10x handle
+ * @mode:      mode selected:
+ *             - ON    : 0x0 => eLNA always ON
+ *             - OFF   : 0x1 => eLNA always OFF
+ *             - AUTO  : 0x2 => eLNA follow hysteresis parameters
+ *                              to be ON or OFF
+ *
+ * Return 0 on success or negative value in case of error.
+ */
+int as10x_cmd_eLNA_change_mode(as10x_handle_t *phandle, uint8_t mode)
+{
+       int error;
+       struct as10x_cmd_t *pcmd, *prsp;
+
+       ENTER();
+
+       pcmd = phandle->cmd;
+       prsp = phandle->rsp;
+
+       /* prepare command */
+       as10x_cmd_build(pcmd, (++phandle->cmd_xid),
+                       sizeof(pcmd->body.cfg_change_mode.req));
+
+       /* fill command */
+       pcmd->body.cfg_change_mode.req.proc_id =
+               cpu_to_le16(CONTROL_PROC_ELNA_CHANGE_MODE);
+       pcmd->body.cfg_change_mode.req.mode = mode;
+
+       /* send command */
+       if (phandle->ops->xfer_cmd) {
+               error  = phandle->ops->xfer_cmd(phandle, (uint8_t *) pcmd,
+                               sizeof(pcmd->body.cfg_change_mode.req)
+                               + HEADER_SIZE, (uint8_t *) prsp,
+                               sizeof(prsp->body.cfg_change_mode.rsp)
+                               + HEADER_SIZE);
+       } else {
+               error = AS10X_CMD_ERROR;
+       }
+
+       if (error < 0)
+               goto out;
+
+       /* parse response */
+       error = as10x_rsp_parse(prsp, CONTROL_PROC_ELNA_CHANGE_MODE_RSP);
+
+out:
+       LEAVE();
+       return error;
+}
+
+/**
+ * as10x_context_rsp_parse - Parse context command response
+ * @prsp:       pointer to AS10x command response buffer
+ * @proc_id:    id of the command
+ *
+ * Since the contex command reponse does not follow the common
+ * response, a specific parse function is required.
+ * Return 0 on success or negative value in case of error.
+ */
+int as10x_context_rsp_parse(struct as10x_cmd_t *prsp, uint16_t proc_id)
+{
+       int err;
+
+       err = prsp->body.context.rsp.error;
+
+       if ((err == 0) &&
+           (le16_to_cpu(prsp->body.context.rsp.proc_id) == proc_id)) {
+               return 0;
+       }
+       return AS10X_CMD_ERROR;
+}
diff --git a/drivers/staging/media/as102/as10x_cmd_stream.c b/drivers/staging/media/as102/as10x_cmd_stream.c
new file mode 100644 (file)
index 0000000..045c706
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+ * Abilis Systems Single DVB-T Receiver
+ * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  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 "as102_drv.h"
+#include "as10x_cmd.h"
+
+/**
+ * as10x_cmd_add_PID_filter - send add filter command to AS10x
+ * @phandle:   pointer to AS10x handle
+ * @filter:    TSFilter filter for DVB-T
+ *
+ * Return 0 on success or negative value in case of error.
+ */
+int as10x_cmd_add_PID_filter(as10x_handle_t *phandle,
+                            struct as10x_ts_filter *filter)
+{
+       int error;
+       struct as10x_cmd_t *pcmd, *prsp;
+
+       ENTER();
+
+       pcmd = phandle->cmd;
+       prsp = phandle->rsp;
+
+       /* prepare command */
+       as10x_cmd_build(pcmd, (++phandle->cmd_xid),
+                       sizeof(pcmd->body.add_pid_filter.req));
+
+       /* fill command */
+       pcmd->body.add_pid_filter.req.proc_id =
+               cpu_to_le16(CONTROL_PROC_SETFILTER);
+       pcmd->body.add_pid_filter.req.pid = cpu_to_le16(filter->pid);
+       pcmd->body.add_pid_filter.req.stream_type = filter->type;
+
+       if (filter->idx < 16)
+               pcmd->body.add_pid_filter.req.idx = filter->idx;
+       else
+               pcmd->body.add_pid_filter.req.idx = 0xFF;
+
+       /* send command */
+       if (phandle->ops->xfer_cmd) {
+               error = phandle->ops->xfer_cmd(phandle, (uint8_t *) pcmd,
+                               sizeof(pcmd->body.add_pid_filter.req)
+                               + HEADER_SIZE, (uint8_t *) prsp,
+                               sizeof(prsp->body.add_pid_filter.rsp)
+                               + HEADER_SIZE);
+       } else {
+               error = AS10X_CMD_ERROR;
+       }
+
+       if (error < 0)
+               goto out;
+
+       /* parse response */
+       error = as10x_rsp_parse(prsp, CONTROL_PROC_SETFILTER_RSP);
+
+       if (error == 0) {
+               /* Response OK -> get response data */
+               filter->idx = prsp->body.add_pid_filter.rsp.filter_id;
+       }
+
+out:
+       LEAVE();
+       return error;
+}
+
+/**
+ * as10x_cmd_del_PID_filter - Send delete filter command to AS10x
+ * @phandle:      pointer to AS10x handle
+ * @pid_value:    PID to delete
+ *
+ * Return 0 on success or negative value in case of error.
+ */
+int as10x_cmd_del_PID_filter(as10x_handle_t *phandle,
+                            uint16_t pid_value)
+{
+       int error;
+       struct as10x_cmd_t *pcmd, *prsp;
+
+       ENTER();
+
+       pcmd = phandle->cmd;
+       prsp = phandle->rsp;
+
+       /* prepare command */
+       as10x_cmd_build(pcmd, (++phandle->cmd_xid),
+                       sizeof(pcmd->body.del_pid_filter.req));
+
+       /* fill command */
+       pcmd->body.del_pid_filter.req.proc_id =
+               cpu_to_le16(CONTROL_PROC_REMOVEFILTER);
+       pcmd->body.del_pid_filter.req.pid = cpu_to_le16(pid_value);
+
+       /* send command */
+       if (phandle->ops->xfer_cmd) {
+               error = phandle->ops->xfer_cmd(phandle, (uint8_t *) pcmd,
+                               sizeof(pcmd->body.del_pid_filter.req)
+                               + HEADER_SIZE, (uint8_t *) prsp,
+                               sizeof(prsp->body.del_pid_filter.rsp)
+                               + HEADER_SIZE);
+       } else {
+               error = AS10X_CMD_ERROR;
+       }
+
+       if (error < 0)
+               goto out;
+
+       /* parse response */
+       error = as10x_rsp_parse(prsp, CONTROL_PROC_REMOVEFILTER_RSP);
+
+out:
+       LEAVE();
+       return error;
+}
+
+/**
+ * as10x_cmd_start_streaming - Send start streaming command to AS10x
+ * @phandle:   pointer to AS10x handle
+ *
+ * Return 0 on success or negative value in case of error.
+ */
+int as10x_cmd_start_streaming(as10x_handle_t *phandle)
+{
+       int error;
+       struct as10x_cmd_t *pcmd, *prsp;
+
+       ENTER();
+
+       pcmd = phandle->cmd;
+       prsp = phandle->rsp;
+
+       /* prepare command */
+       as10x_cmd_build(pcmd, (++phandle->cmd_xid),
+                       sizeof(pcmd->body.start_streaming.req));
+
+       /* fill command */
+       pcmd->body.start_streaming.req.proc_id =
+               cpu_to_le16(CONTROL_PROC_START_STREAMING);
+
+       /* send command */
+       if (phandle->ops->xfer_cmd) {
+               error = phandle->ops->xfer_cmd(phandle, (uint8_t *) pcmd,
+                               sizeof(pcmd->body.start_streaming.req)
+                               + HEADER_SIZE, (uint8_t *) prsp,
+                               sizeof(prsp->body.start_streaming.rsp)
+                               + HEADER_SIZE);
+       } else {
+               error = AS10X_CMD_ERROR;
+       }
+
+       if (error < 0)
+               goto out;
+
+       /* parse response */
+       error = as10x_rsp_parse(prsp, CONTROL_PROC_START_STREAMING_RSP);
+
+out:
+       LEAVE();
+       return error;
+}
+
+/**
+ * as10x_cmd_stop_streaming - Send stop streaming command to AS10x
+ * @phandle:   pointer to AS10x handle
+ *
+ * Return 0 on success or negative value in case of error.
+ */
+int as10x_cmd_stop_streaming(as10x_handle_t *phandle)
+{
+       int8_t error;
+       struct as10x_cmd_t *pcmd, *prsp;
+
+       ENTER();
+
+       pcmd = phandle->cmd;
+       prsp = phandle->rsp;
+
+       /* prepare command */
+       as10x_cmd_build(pcmd, (++phandle->cmd_xid),
+                       sizeof(pcmd->body.stop_streaming.req));
+
+       /* fill command */
+       pcmd->body.stop_streaming.req.proc_id =
+               cpu_to_le16(CONTROL_PROC_STOP_STREAMING);
+
+       /* send command */
+       if (phandle->ops->xfer_cmd) {
+               error = phandle->ops->xfer_cmd(phandle, (uint8_t *) pcmd,
+                               sizeof(pcmd->body.stop_streaming.req)
+                               + HEADER_SIZE, (uint8_t *) prsp,
+                               sizeof(prsp->body.stop_streaming.rsp)
+                               + HEADER_SIZE);
+       } else {
+               error = AS10X_CMD_ERROR;
+       }
+
+       if (error < 0)
+               goto out;
+
+       /* parse response */
+       error = as10x_rsp_parse(prsp, CONTROL_PROC_STOP_STREAMING_RSP);
+
+out:
+       LEAVE();
+       return error;
+}
diff --git a/drivers/staging/media/as102/as10x_handle.h b/drivers/staging/media/as102/as10x_handle.h
new file mode 100644 (file)
index 0000000..4f01a76
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Abilis Systems Single DVB-T Receiver
+ * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  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.
+ */
+#ifdef __KERNEL__
+struct as102_bus_adapter_t;
+struct as102_dev_t;
+
+#define as10x_handle_t struct as102_bus_adapter_t
+#include "as10x_cmd.h"
+
+/* values for "mode" field */
+#define REGMODE8         8
+#define REGMODE16        16
+#define REGMODE32        32
+
+struct as102_priv_ops_t {
+       int (*upload_fw_pkt) (struct as102_bus_adapter_t *bus_adap,
+                             unsigned char *buf, int buflen, int swap32);
+
+       int (*send_cmd) (struct as102_bus_adapter_t *bus_adap,
+                        unsigned char *buf, int buflen);
+
+       int (*xfer_cmd) (struct as102_bus_adapter_t *bus_adap,
+                        unsigned char *send_buf, int send_buf_len,
+                        unsigned char *recv_buf, int recv_buf_len);
+/*
+       int (*pid_filter) (struct as102_bus_adapter_t *bus_adap,
+                          int index, u16 pid, int onoff);
+*/
+       int (*start_stream) (struct as102_dev_t *dev);
+       void (*stop_stream) (struct as102_dev_t *dev);
+
+       int (*reset_target) (struct as102_bus_adapter_t *bus_adap);
+
+       int (*read_write)(struct as102_bus_adapter_t *bus_adap, uint8_t mode,
+                         uint32_t rd_addr, uint16_t rd_len,
+                         uint32_t wr_addr, uint16_t wr_len);
+
+       int (*as102_read_ep2) (struct as102_bus_adapter_t *bus_adap,
+                              unsigned char *recv_buf,
+                              int recv_buf_len);
+};
+#endif
diff --git a/drivers/staging/media/as102/as10x_types.h b/drivers/staging/media/as102/as10x_types.h
new file mode 100644 (file)
index 0000000..3dedb3c
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+ * Abilis Systems Single DVB-T Receiver
+ * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  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.
+ */
+#ifndef _AS10X_TYPES_H_
+#define _AS10X_TYPES_H_
+
+#include "as10x_handle.h"
+
+/*********************************/
+/*       MACRO DEFINITIONS       */
+/*********************************/
+
+/* bandwidth constant values */
+#define BW_5_MHZ           0x00
+#define BW_6_MHZ           0x01
+#define BW_7_MHZ           0x02
+#define BW_8_MHZ           0x03
+
+/* hierarchy priority selection values */
+#define HIER_NO_PRIORITY   0x00
+#define HIER_LOW_PRIORITY  0x01
+#define HIER_HIGH_PRIORITY 0x02
+
+/* constellation available values */
+#define CONST_QPSK         0x00
+#define CONST_QAM16        0x01
+#define CONST_QAM64        0x02
+#define CONST_UNKNOWN      0xFF
+
+/* hierarchy available values */
+#define HIER_NONE         0x00
+#define HIER_ALPHA_1      0x01
+#define HIER_ALPHA_2      0x02
+#define HIER_ALPHA_4      0x03
+#define HIER_UNKNOWN      0xFF
+
+/* interleaving available values */
+#define INTLV_NATIVE      0x00
+#define INTLV_IN_DEPTH    0x01
+#define INTLV_UNKNOWN     0xFF
+
+/* code rate available values */
+#define CODE_RATE_1_2     0x00
+#define CODE_RATE_2_3     0x01
+#define CODE_RATE_3_4     0x02
+#define CODE_RATE_5_6     0x03
+#define CODE_RATE_7_8     0x04
+#define CODE_RATE_UNKNOWN 0xFF
+
+/* guard interval available values */
+#define GUARD_INT_1_32    0x00
+#define GUARD_INT_1_16    0x01
+#define GUARD_INT_1_8     0x02
+#define GUARD_INT_1_4     0x03
+#define GUARD_UNKNOWN     0xFF
+
+/* transmission mode available values */
+#define TRANS_MODE_2K      0x00
+#define TRANS_MODE_8K      0x01
+#define TRANS_MODE_4K      0x02
+#define TRANS_MODE_UNKNOWN 0xFF
+
+/* DVBH signalling available values */
+#define TIMESLICING_PRESENT   0x01
+#define MPE_FEC_PRESENT       0x02
+
+/* tune state available */
+#define TUNE_STATUS_NOT_TUNED       0x00
+#define TUNE_STATUS_IDLE            0x01
+#define TUNE_STATUS_LOCKING         0x02
+#define TUNE_STATUS_SIGNAL_DVB_OK   0x03
+#define TUNE_STATUS_STREAM_DETECTED 0x04
+#define TUNE_STATUS_STREAM_TUNED    0x05
+#define TUNE_STATUS_ERROR           0xFF
+
+/* available TS FID filter types */
+#define TS_PID_TYPE_TS       0
+#define TS_PID_TYPE_PSI_SI   1
+#define TS_PID_TYPE_MPE      2
+
+/* number of echos available */
+#define MAX_ECHOS   15
+
+/* Context types */
+#define CONTEXT_LNA                   1010
+#define CONTEXT_ELNA_HYSTERESIS       4003
+#define CONTEXT_ELNA_GAIN             4004
+#define CONTEXT_MER_THRESHOLD         5005
+#define CONTEXT_MER_OFFSET            5006
+#define CONTEXT_IR_STATE              7000
+#define CONTEXT_TSOUT_MSB_FIRST       7004
+#define CONTEXT_TSOUT_FALLING_EDGE    7005
+
+/* Configuration modes */
+#define CFG_MODE_ON     0
+#define CFG_MODE_OFF    1
+#define CFG_MODE_AUTO   2
+
+#pragma pack(1)
+struct as10x_tps {
+   uint8_t constellation;
+   uint8_t hierarchy;
+   uint8_t interleaving_mode;
+   uint8_t code_rate_HP;
+   uint8_t code_rate_LP;
+   uint8_t guard_interval;
+   uint8_t transmission_mode;
+   uint8_t DVBH_mask_HP;
+   uint8_t DVBH_mask_LP;
+   uint16_t cell_ID;
+};
+
+struct as10x_tune_args {
+   /* frequency */
+   uint32_t freq;
+   /* bandwidth */
+   uint8_t bandwidth;
+   /* hierarchy selection */
+   uint8_t hier_select;
+   /* constellation */
+   uint8_t constellation;
+   /* hierarchy */
+   uint8_t hierarchy;
+   /* interleaving mode */
+   uint8_t interleaving_mode;
+   /* code rate */
+   uint8_t code_rate;
+   /* guard interval */
+   uint8_t guard_interval;
+   /* transmission mode */
+   uint8_t transmission_mode;
+};
+
+struct as10x_tune_status {
+   /* tune status */
+   uint8_t tune_state;
+   /* signal strength */
+   int16_t signal_strength;
+   /* packet error rate 10^-4 */
+   uint16_t PER;
+   /* bit error rate 10^-4 */
+   uint16_t BER;
+};
+
+struct as10x_demod_stats {
+   /* frame counter */
+   uint32_t frame_count;
+   /* Bad frame counter */
+   uint32_t bad_frame_count;
+   /* Number of wrong bytes fixed by Reed-Solomon */
+   uint32_t bytes_fixed_by_rs;
+   /* Averaged MER */
+   uint16_t mer;
+   /* statistics calculation state indicator (started or not) */
+   uint8_t has_started;
+};
+
+struct as10x_ts_filter {
+   uint16_t pid;  /** valid PID value 0x00 : 0x2000 */
+   uint8_t  type; /** Red TS_PID_TYPE_<N> values */
+   uint8_t  idx;  /** index in filtering table */
+};
+
+struct as10x_register_value {
+   uint8_t       mode;
+   union {
+      uint8_t    value8;    /* 8 bit value */
+      uint16_t   value16;   /* 16 bit value */
+      uint32_t   value32;   /* 32 bit value */
+   }u;
+};
+
+#pragma pack()
+
+struct as10x_register_addr {
+   /* register addr */
+   uint32_t addr;
+   /* register mode access */
+   uint8_t mode;
+};
+
+
+#endif
index b9926ee..09de99f 100644 (file)
@@ -556,7 +556,7 @@ static inline int valid_io_request(struct zram *zram, struct bio *bio)
 /*
  * Handler function for all zram I/O requests.
  */
-static int zram_make_request(struct request_queue *queue, struct bio *bio)
+static void zram_make_request(struct request_queue *queue, struct bio *bio)
 {
        struct zram *zram = queue->queuedata;
 
@@ -575,13 +575,12 @@ static int zram_make_request(struct request_queue *queue, struct bio *bio)
        __zram_make_request(zram, bio, bio_data_dir(bio));
        up_read(&zram->init_lock);
 
-       return 0;
+       return;
 
 error_unlock:
        up_read(&zram->init_lock);
 error:
        bio_io_error(bio);
-       return 0;
 }
 
 void __zram_reset_device(struct zram *zram)
index e371753..4222035 100644 (file)
@@ -34,6 +34,15 @@ config HVC_ISERIES
        help
          iSeries machines support a hypervisor virtual console.
 
+config HVC_OPAL
+       bool "OPAL Console support"
+       depends on PPC_POWERNV
+       select HVC_DRIVER
+       select HVC_IRQ
+       default y
+       help
+         PowerNV machines running under OPAL need that driver to get a console
+
 config HVC_RTAS
        bool "IBM RTAS Console support"
        depends on PPC_RTAS
index e292053..89abf40 100644 (file)
@@ -1,4 +1,5 @@
 obj-$(CONFIG_HVC_CONSOLE)      += hvc_vio.o hvsi_lib.o
+obj-$(CONFIG_HVC_OPAL)         += hvc_opal.o hvsi_lib.o
 obj-$(CONFIG_HVC_OLD_HVSI)     += hvsi.o
 obj-$(CONFIG_HVC_ISERIES)      += hvc_iseries.o
 obj-$(CONFIG_HVC_RTAS)         += hvc_rtas.o
diff --git a/drivers/tty/hvc/hvc_opal.c b/drivers/tty/hvc/hvc_opal.c
new file mode 100644 (file)
index 0000000..7b38512
--- /dev/null
@@ -0,0 +1,424 @@
+/*
+ * opal driver interface to hvc_console.c
+ *
+ * Copyright 2011 Benjamin Herrenschmidt <benh@kernel.crashing.org>, IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#undef DEBUG
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/console.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+
+#include <asm/hvconsole.h>
+#include <asm/prom.h>
+#include <asm/firmware.h>
+#include <asm/hvsi.h>
+#include <asm/udbg.h>
+#include <asm/opal.h>
+
+#include "hvc_console.h"
+
+static const char hvc_opal_name[] = "hvc_opal";
+
+static struct of_device_id hvc_opal_match[] __devinitdata = {
+       { .name = "serial", .compatible = "ibm,opal-console-raw" },
+       { .name = "serial", .compatible = "ibm,opal-console-hvsi" },
+       { },
+};
+
+typedef enum hv_protocol {
+       HV_PROTOCOL_RAW,
+       HV_PROTOCOL_HVSI
+} hv_protocol_t;
+
+struct hvc_opal_priv {
+       hv_protocol_t           proto;  /* Raw data or HVSI packets */
+       struct hvsi_priv        hvsi;   /* HVSI specific data */
+};
+static struct hvc_opal_priv *hvc_opal_privs[MAX_NR_HVC_CONSOLES];
+
+/* For early boot console */
+static struct hvc_opal_priv hvc_opal_boot_priv;
+static u32 hvc_opal_boot_termno;
+
+static const struct hv_ops hvc_opal_raw_ops = {
+       .get_chars = opal_get_chars,
+       .put_chars = opal_put_chars,
+       .notifier_add = notifier_add_irq,
+       .notifier_del = notifier_del_irq,
+       .notifier_hangup = notifier_hangup_irq,
+};
+
+static int hvc_opal_hvsi_get_chars(uint32_t vtermno, char *buf, int count)
+{
+       struct hvc_opal_priv *pv = hvc_opal_privs[vtermno];
+
+       if (WARN_ON(!pv))
+               return -ENODEV;
+
+       return hvsilib_get_chars(&pv->hvsi, buf, count);
+}
+
+static int hvc_opal_hvsi_put_chars(uint32_t vtermno, const char *buf, int count)
+{
+       struct hvc_opal_priv *pv = hvc_opal_privs[vtermno];
+
+       if (WARN_ON(!pv))
+               return -ENODEV;
+
+       return hvsilib_put_chars(&pv->hvsi, buf, count);
+}
+
+static int hvc_opal_hvsi_open(struct hvc_struct *hp, int data)
+{
+       struct hvc_opal_priv *pv = hvc_opal_privs[hp->vtermno];
+       int rc;
+
+       pr_devel("HVSI@%x: do open !\n", hp->vtermno);
+
+       rc = notifier_add_irq(hp, data);
+       if (rc)
+               return rc;
+
+       return hvsilib_open(&pv->hvsi, hp);
+}
+
+static void hvc_opal_hvsi_close(struct hvc_struct *hp, int data)
+{
+       struct hvc_opal_priv *pv = hvc_opal_privs[hp->vtermno];
+
+       pr_devel("HVSI@%x: do close !\n", hp->vtermno);
+
+       hvsilib_close(&pv->hvsi, hp);
+
+       notifier_del_irq(hp, data);
+}
+
+void hvc_opal_hvsi_hangup(struct hvc_struct *hp, int data)
+{
+       struct hvc_opal_priv *pv = hvc_opal_privs[hp->vtermno];
+
+       pr_devel("HVSI@%x: do hangup !\n", hp->vtermno);
+
+       hvsilib_close(&pv->hvsi, hp);
+
+       notifier_hangup_irq(hp, data);
+}
+
+static int hvc_opal_hvsi_tiocmget(struct hvc_struct *hp)
+{
+       struct hvc_opal_priv *pv = hvc_opal_privs[hp->vtermno];
+
+       if (!pv)
+               return -EINVAL;
+       return pv->hvsi.mctrl;
+}
+
+static int hvc_opal_hvsi_tiocmset(struct hvc_struct *hp, unsigned int set,
+                               unsigned int clear)
+{
+       struct hvc_opal_priv *pv = hvc_opal_privs[hp->vtermno];
+
+       pr_devel("HVSI@%x: Set modem control, set=%x,clr=%x\n",
+                hp->vtermno, set, clear);
+
+       if (set & TIOCM_DTR)
+               hvsilib_write_mctrl(&pv->hvsi, 1);
+       else if (clear & TIOCM_DTR)
+               hvsilib_write_mctrl(&pv->hvsi, 0);
+
+       return 0;
+}
+
+static const struct hv_ops hvc_opal_hvsi_ops = {
+       .get_chars = hvc_opal_hvsi_get_chars,
+       .put_chars = hvc_opal_hvsi_put_chars,
+       .notifier_add = hvc_opal_hvsi_open,
+       .notifier_del = hvc_opal_hvsi_close,
+       .notifier_hangup = hvc_opal_hvsi_hangup,
+       .tiocmget = hvc_opal_hvsi_tiocmget,
+       .tiocmset = hvc_opal_hvsi_tiocmset,
+};
+
+static int __devinit hvc_opal_probe(struct platform_device *dev)
+{
+       const struct hv_ops *ops;
+       struct hvc_struct *hp;
+       struct hvc_opal_priv *pv;
+       hv_protocol_t proto;
+       unsigned int termno, boot = 0;
+       const __be32 *reg;
+
+       if (of_device_is_compatible(dev->dev.of_node, "ibm,opal-console-raw")) {
+               proto = HV_PROTOCOL_RAW;
+               ops = &hvc_opal_raw_ops;
+       } else if (of_device_is_compatible(dev->dev.of_node,
+                                          "ibm,opal-console-hvsi")) {
+               proto = HV_PROTOCOL_HVSI;
+               ops = &hvc_opal_hvsi_ops;
+       } else {
+               pr_err("hvc_opal: Unkown protocol for %s\n",
+                      dev->dev.of_node->full_name);
+               return -ENXIO;
+       }
+
+       reg = of_get_property(dev->dev.of_node, "reg", NULL);
+       termno = reg ? be32_to_cpup(reg) : 0;
+
+       /* Is it our boot one ? */
+       if (hvc_opal_privs[termno] == &hvc_opal_boot_priv) {
+               pv = hvc_opal_privs[termno];
+               boot = 1;
+       } else if (hvc_opal_privs[termno] == NULL) {
+               pv = kzalloc(sizeof(struct hvc_opal_priv), GFP_KERNEL);
+               if (!pv)
+                       return -ENOMEM;
+               pv->proto = proto;
+               hvc_opal_privs[termno] = pv;
+               if (proto == HV_PROTOCOL_HVSI)
+                       hvsilib_init(&pv->hvsi, opal_get_chars, opal_put_chars,
+                                    termno, 0);
+
+               /* Instanciate now to establish a mapping index==vtermno */
+               hvc_instantiate(termno, termno, ops);
+       } else {
+               pr_err("hvc_opal: Device %s has duplicate terminal number #%d\n",
+                      dev->dev.of_node->full_name, termno);
+               return -ENXIO;
+       }
+
+       pr_info("hvc%d: %s protocol on %s%s\n", termno,
+               proto == HV_PROTOCOL_RAW ? "raw" : "hvsi",
+               dev->dev.of_node->full_name,
+               boot ? " (boot console)" : "");
+
+       /* We don't do IRQ yet */
+       hp = hvc_alloc(termno, 0, ops, MAX_VIO_PUT_CHARS);
+       if (IS_ERR(hp))
+               return PTR_ERR(hp);
+       dev_set_drvdata(&dev->dev, hp);
+
+       return 0;
+}
+
+static int __devexit hvc_opal_remove(struct platform_device *dev)
+{
+       struct hvc_struct *hp = dev_get_drvdata(&dev->dev);
+       int rc, termno;
+
+       termno = hp->vtermno;
+       rc = hvc_remove(hp);
+       if (rc == 0) {
+               if (hvc_opal_privs[termno] != &hvc_opal_boot_priv)
+                       kfree(hvc_opal_privs[termno]);
+               hvc_opal_privs[termno] = NULL;
+       }
+       return rc;
+}
+
+static struct platform_driver hvc_opal_driver = {
+       .probe          = hvc_opal_probe,
+       .remove         = __devexit_p(hvc_opal_remove),
+       .driver         = {
+               .name   = hvc_opal_name,
+               .owner  = THIS_MODULE,
+               .of_match_table = hvc_opal_match,
+       }
+};
+
+static int __init hvc_opal_init(void)
+{
+       if (!firmware_has_feature(FW_FEATURE_OPAL))
+               return -ENODEV;
+
+       /* Register as a vio device to receive callbacks */
+       return platform_driver_register(&hvc_opal_driver);
+}
+module_init(hvc_opal_init);
+
+static void __exit hvc_opal_exit(void)
+{
+       platform_driver_unregister(&hvc_opal_driver);
+}
+module_exit(hvc_opal_exit);
+
+static void udbg_opal_putc(char c)
+{
+       unsigned int termno = hvc_opal_boot_termno;
+       int count = -1;
+
+       if (c == '\n')
+               udbg_opal_putc('\r');
+
+       do {
+               switch(hvc_opal_boot_priv.proto) {
+               case HV_PROTOCOL_RAW:
+                       count = opal_put_chars(termno, &c, 1);
+                       break;
+               case HV_PROTOCOL_HVSI:
+                       count = hvc_opal_hvsi_put_chars(termno, &c, 1);
+                       break;
+               }
+       } while(count == 0 || count == -EAGAIN);
+}
+
+static int udbg_opal_getc_poll(void)
+{
+       unsigned int termno = hvc_opal_boot_termno;
+       int rc = 0;
+       char c;
+
+       switch(hvc_opal_boot_priv.proto) {
+       case HV_PROTOCOL_RAW:
+               rc = opal_get_chars(termno, &c, 1);
+               break;
+       case HV_PROTOCOL_HVSI:
+               rc = hvc_opal_hvsi_get_chars(termno, &c, 1);
+               break;
+       }
+       if (!rc)
+               return -1;
+       return c;
+}
+
+static int udbg_opal_getc(void)
+{
+       int ch;
+       for (;;) {
+               ch = udbg_opal_getc_poll();
+               if (ch == -1) {
+                       /* This shouldn't be needed...but... */
+                       volatile unsigned long delay;
+                       for (delay=0; delay < 2000000; delay++)
+                               ;
+               } else {
+                       return ch;
+               }
+       }
+}
+
+static void udbg_init_opal_common(void)
+{
+       udbg_putc = udbg_opal_putc;
+       udbg_getc = udbg_opal_getc;
+       udbg_getc_poll = udbg_opal_getc_poll;
+       tb_ticks_per_usec = 0x200; /* Make udelay not suck */
+}
+
+void __init hvc_opal_init_early(void)
+{
+       struct device_node *stdout_node = NULL;
+       const u32 *termno;
+       const char *name = NULL;
+       const struct hv_ops *ops;
+       u32 index;
+
+       /* find the boot console from /chosen/stdout */
+       if (of_chosen)
+               name = of_get_property(of_chosen, "linux,stdout-path", NULL);
+       if (name) {
+               stdout_node = of_find_node_by_path(name);
+               if (!stdout_node) {
+                       pr_err("hvc_opal: Failed to locate default console!\n");
+                       return;
+               }
+       } else {
+               struct device_node *opal, *np;
+
+               /* Current OPAL takeover doesn't provide the stdout
+                * path, so we hard wire it
+                */
+               opal = of_find_node_by_path("/ibm,opal/consoles");
+               if (opal)
+                       pr_devel("hvc_opal: Found consoles in new location\n");
+               if (!opal) {
+                       opal = of_find_node_by_path("/ibm,opal");
+                       if (opal)
+                               pr_devel("hvc_opal: "
+                                        "Found consoles in old location\n");
+               }
+               if (!opal)
+                       return;
+               for_each_child_of_node(opal, np) {
+                       if (!strcmp(np->name, "serial")) {
+                               stdout_node = np;
+                               break;
+                       }
+               }
+               of_node_put(opal);
+       }
+       if (!stdout_node)
+               return;
+       termno = of_get_property(stdout_node, "reg", NULL);
+       index = termno ? *termno : 0;
+       if (index >= MAX_NR_HVC_CONSOLES)
+               return;
+       hvc_opal_privs[index] = &hvc_opal_boot_priv;
+
+       /* Check the protocol */
+       if (of_device_is_compatible(stdout_node, "ibm,opal-console-raw")) {
+               hvc_opal_boot_priv.proto = HV_PROTOCOL_RAW;
+               ops = &hvc_opal_raw_ops;
+               pr_devel("hvc_opal: Found RAW console\n");
+       }
+       else if (of_device_is_compatible(stdout_node,"ibm,opal-console-hvsi")) {
+               hvc_opal_boot_priv.proto = HV_PROTOCOL_HVSI;
+               ops = &hvc_opal_hvsi_ops;
+               hvsilib_init(&hvc_opal_boot_priv.hvsi, opal_get_chars,
+                            opal_put_chars, index, 1);
+               /* HVSI, perform the handshake now */
+               hvsilib_establish(&hvc_opal_boot_priv.hvsi);
+               pr_devel("hvc_opal: Found HVSI console\n");
+       } else
+               goto out;
+       hvc_opal_boot_termno = index;
+       udbg_init_opal_common();
+       add_preferred_console("hvc", index, NULL);
+       hvc_instantiate(index, index, ops);
+out:
+       of_node_put(stdout_node);
+}
+
+#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL_RAW
+void __init udbg_init_debug_opal(void)
+{
+       u32 index = CONFIG_PPC_EARLY_DEBUG_OPAL_VTERMNO;
+       hvc_opal_privs[index] = &hvc_opal_boot_priv;
+       hvc_opal_boot_priv.proto = HV_PROTOCOL_RAW;
+       hvc_opal_boot_termno = index;
+       udbg_init_opal_common();
+}
+#endif /* CONFIG_PPC_EARLY_DEBUG_OPAL_RAW */
+
+#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL_HVSI
+void __init udbg_init_debug_opal_hvsi(void)
+{
+       u32 index = CONFIG_PPC_EARLY_DEBUG_OPAL_VTERMNO;
+       hvc_opal_privs[index] = &hvc_opal_boot_priv;
+       hvc_opal_boot_termno = index;
+       udbg_init_opal_common();
+       hvsilib_init(&hvc_opal_boot_priv.hvsi, opal_get_chars, opal_put_chars,
+                    index, 1);
+       hvsilib_establish(&hvc_opal_boot_priv.hvsi);
+}
+#endif /* CONFIG_PPC_EARLY_DEBUG_OPAL_HVSI */
index 55882b5..b9040be 100644 (file)
@@ -1532,7 +1532,7 @@ static int __devinit hvcs_initialize(void)
                goto register_fail;
        }
 
-       hvcs_pi_buff = kmalloc(PAGE_SIZE, GFP_KERNEL);
+       hvcs_pi_buff = (unsigned long *) __get_free_page(GFP_KERNEL);
        if (!hvcs_pi_buff) {
                rc = -ENOMEM;
                goto buff_alloc_fail;
@@ -1548,7 +1548,7 @@ static int __devinit hvcs_initialize(void)
        return 0;
 
 kthread_fail:
-       kfree(hvcs_pi_buff);
+       free_page((unsigned long)hvcs_pi_buff);
 buff_alloc_fail:
        tty_unregister_driver(hvcs_tty_driver);
 register_fail:
@@ -1597,7 +1597,7 @@ static void __exit hvcs_module_exit(void)
        kthread_stop(hvcs_task);
 
        spin_lock(&hvcs_pi_lock);
-       kfree(hvcs_pi_buff);
+       free_page((unsigned long)hvcs_pi_buff);
        hvcs_pi_buff = NULL;
        spin_unlock(&hvcs_pi_lock);
 
index bd9b098..6f4dd83 100644 (file)
@@ -183,7 +183,7 @@ int hvsilib_get_chars(struct hvsi_priv *pv, char *buf, int count)
        unsigned int tries, read = 0;
 
        if (WARN_ON(!pv))
-               return 0;
+               return -ENXIO;
 
        /* If we aren't open, don't do anything in order to avoid races
         * with connection establishment. The hvc core will call this
@@ -234,7 +234,7 @@ int hvsilib_put_chars(struct hvsi_priv *pv, const char *buf, int count)
        int rc, adjcount = min(count, HVSI_MAX_OUTGOING_DATA);
 
        if (WARN_ON(!pv))
-               return 0;
+               return -ENODEV;
 
        dp.hdr.type = VS_DATA_PACKET_HEADER;
        dp.hdr.len = adjcount + sizeof(struct hvsi_header);
index a87a56c..eeadf1b 100644 (file)
@@ -450,24 +450,6 @@ static void au_serial_out(struct uart_port *p, int offset, int value)
        __raw_writel(value, p->membase + offset);
 }
 
-static unsigned int tsi_serial_in(struct uart_port *p, int offset)
-{
-       unsigned int tmp;
-       offset = map_8250_in_reg(p, offset) << p->regshift;
-       if (offset == UART_IIR) {
-               tmp = readl(p->membase + (UART_IIR & ~3));
-               return (tmp >> 16) & 0xff; /* UART_IIR % 4 == 2 */
-       } else
-               return readb(p->membase + offset);
-}
-
-static void tsi_serial_out(struct uart_port *p, int offset, int value)
-{
-       offset = map_8250_out_reg(p, offset) << p->regshift;
-       if (!((offset == UART_IER) && (value & UART_IER_UUE)))
-               writeb(value, p->membase + offset);
-}
-
 static unsigned int io_serial_in(struct uart_port *p, int offset)
 {
        offset = map_8250_in_reg(p, offset) << p->regshift;
@@ -508,11 +490,6 @@ static void set_io_from_upio(struct uart_port *p)
                p->serial_out = au_serial_out;
                break;
 
-       case UPIO_TSI:
-               p->serial_in = tsi_serial_in;
-               p->serial_out = tsi_serial_out;
-               break;
-
        default:
                p->serial_in = io_serial_in;
                p->serial_out = io_serial_out;
index 9871c57..1945c70 100644 (file)
@@ -1446,12 +1446,8 @@ static bool filter(struct dma_chan *chan, void *slave)
        dev_dbg(chan->device->dev, "%s: slave ID %d\n", __func__,
                param->slave_id);
 
-       if (param->dma_dev == chan->device->dev) {
-               chan->private = param;
-               return true;
-       } else {
-               return false;
-       }
+       chan->private = param;
+       return true;
 }
 
 static void rx_timer_fn(unsigned long arg)
@@ -1477,10 +1473,10 @@ static void sci_request_dma(struct uart_port *port)
        dma_cap_mask_t mask;
        int nent;
 
-       dev_dbg(port->dev, "%s: port %d DMA %p\n", __func__,
-               port->line, s->cfg->dma_dev);
+       dev_dbg(port->dev, "%s: port %d\n", __func__,
+               port->line);
 
-       if (!s->cfg->dma_dev)
+       if (s->cfg->dma_slave_tx <= 0 || s->cfg->dma_slave_rx <= 0)
                return;
 
        dma_cap_zero(mask);
@@ -1490,7 +1486,6 @@ static void sci_request_dma(struct uart_port *port)
 
        /* Slave ID, e.g., SHDMA_SLAVE_SCIF0_TX */
        param->slave_id = s->cfg->dma_slave_tx;
-       param->dma_dev = s->cfg->dma_dev;
 
        s->cookie_tx = -EINVAL;
        chan = dma_request_channel(mask, filter, param);
@@ -1519,7 +1514,6 @@ static void sci_request_dma(struct uart_port *port)
 
        /* Slave ID, e.g., SHDMA_SLAVE_SCIF0_RX */
        param->slave_id = s->cfg->dma_slave_rx;
-       param->dma_dev = s->cfg->dma_dev;
 
        chan = dma_request_channel(mask, filter, param);
        dev_dbg(port->dev, "%s: RX: got channel %p\n", __func__, chan);
@@ -1564,9 +1558,6 @@ static void sci_free_dma(struct uart_port *port)
 {
        struct sci_port *s = to_sci_port(port);
 
-       if (!s->cfg->dma_dev)
-               return;
-
        if (s->chan_tx)
                sci_tx_dma_release(s, false);
        if (s->chan_rx)
@@ -1981,9 +1972,9 @@ static int __devinit sci_init_single(struct platform_device *dev,
        port->serial_in         = sci_serial_in;
        port->serial_out        = sci_serial_out;
 
-       if (p->dma_dev)
-               dev_dbg(port->dev, "DMA device %p, tx %d, rx %d\n",
-                       p->dma_dev, p->dma_slave_tx, p->dma_slave_rx);
+       if (p->dma_slave_tx > 0 && p->dma_slave_rx > 0)
+               dev_dbg(port->dev, "DMA tx %d, rx %d\n",
+                       p->dma_slave_tx, p->dma_slave_rx);
 
        return 0;
 }
index 3b029a0..c2c0ae5 100644 (file)
@@ -1667,6 +1667,11 @@ int usb_runtime_suspend(struct device *dev)
                return -EAGAIN;
 
        status = usb_suspend_both(udev, PMSG_AUTO_SUSPEND);
+
+       /* Allow a retry if autosuspend failed temporarily */
+       if (status == -EAGAIN || status == -EBUSY)
+               usb_mark_last_busy(udev);
+
        /* The PM core reacts badly unless the return code is 0,
         * -EAGAIN, or -EBUSY, so always return -EBUSY on an error.
         */
index 3d91621..4939e0c 100644 (file)
@@ -706,6 +706,7 @@ static const struct file_operations fsl_hv_fops = {
        .poll = fsl_hv_poll,
        .read = fsl_hv_read,
        .unlocked_ioctl = fsl_hv_ioctl,
+       .compat_ioctl = fsl_hv_ioctl,
 };
 
 static struct miscdevice fsl_hv_misc_dev = {
index 64c6752..6285867 100644 (file)
@@ -66,6 +66,7 @@ config SOFT_WATCHDOG
 config WM831X_WATCHDOG
        tristate "WM831x watchdog"
        depends on MFD_WM831X
+       select WATCHDOG_CORE
        help
          Support for the watchdog in the WM831x AudioPlus PMICs.  When
          the watchdog triggers the system will be reset.
@@ -170,6 +171,7 @@ config HAVE_S3C2410_WATCHDOG
 config S3C2410_WATCHDOG
        tristate "S3C2410 Watchdog"
        depends on ARCH_S3C2410 || HAVE_S3C2410_WATCHDOG
+       select WATCHDOG_CORE
        help
          Watchdog timer block in the Samsung SoCs. This will reboot
          the system when the timer expires with the watchdog enabled.
index 9291506..03f449a 100644 (file)
@@ -429,7 +429,7 @@ static int __init coh901327_probe(struct platform_device *pdev)
        writew(U300_WDOG_SR_RESET_STATUS_RESET, virtbase + U300_WDOG_SR);
 
        irq = platform_get_irq(pdev, 0);
-       if (request_irq(irq, coh901327_interrupt, IRQF_DISABLED,
+       if (request_irq(irq, coh901327_interrupt, 0,
                        DRV_NAME " Bark", pdev)) {
                ret = -EIO;
                goto out_no_irq;
index f1d1da6..41018d4 100644 (file)
@@ -427,7 +427,7 @@ static int __init eurwdt_init(void)
 {
        int ret;
 
-       ret = request_irq(irq, eurwdt_interrupt, IRQF_DISABLED, "eurwdt", NULL);
+       ret = request_irq(irq, eurwdt_interrupt, 0, "eurwdt", NULL);
        if (ret) {
                printk(KERN_ERR "eurwdt: IRQ %d is not free.\n", irq);
                goto out;
index 751a591..ba6ad66 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     intel TCO Watchdog Driver
  *
- *     (c) Copyright 2006-2010 Wim Van Sebroeck <wim@iguana.be>.
+ *     (c) Copyright 2006-2011 Wim Van Sebroeck <wim@iguana.be>.
  *
  *     This program is free software; you can redistribute it and/or
  *     modify it under the terms of the GNU General Public License
@@ -44,7 +44,7 @@
 
 /* Module and version information */
 #define DRV_NAME       "iTCO_wdt"
-#define DRV_VERSION    "1.06"
+#define DRV_VERSION    "1.07"
 #define PFX            DRV_NAME ": "
 
 /* Includes */
@@ -384,6 +384,11 @@ MODULE_PARM_DESC(nowayout,
        "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
+static int turn_SMI_watchdog_clear_off = 0;
+module_param(turn_SMI_watchdog_clear_off, int, 0);
+MODULE_PARM_DESC(turn_SMI_watchdog_clear_off,
+       "Turn off SMI clearing watchdog (default=0)");
+
 /*
  * Some TCO specific functions
  */
@@ -808,10 +813,12 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
                ret = -EIO;
                goto out_unmap;
        }
-       /* Bit 13: TCO_EN -> 0 = Disables TCO logic generating an SMI# */
-       val32 = inl(SMI_EN);
-       val32 &= 0xffffdfff;    /* Turn off SMI clearing watchdog */
-       outl(val32, SMI_EN);
+       if (turn_SMI_watchdog_clear_off) {
+               /* Bit 13: TCO_EN -> 0 = Disables TCO logic generating an SMI# */
+               val32 = inl(SMI_EN);
+               val32 &= 0xffffdfff;    /* Turn off SMI clearing watchdog */
+               outl(val32, SMI_EN);
+       }
 
        /* The TCO I/O registers reside in a 32-byte range pointed to
           by the TCOBASE value */
index 4dc3102..82ccd36 100644 (file)
@@ -367,8 +367,7 @@ static int __devinit mpcore_wdt_probe(struct platform_device *dev)
                goto err_misc;
        }
 
-       ret = request_irq(wdt->irq, mpcore_wdt_fire, IRQF_DISABLED,
-                                                       "mpcore_wdt", wdt);
+       ret = request_irq(wdt->irq, mpcore_wdt_fire, 0, "mpcore_wdt", wdt);
        if (ret) {
                dev_printk(KERN_ERR, wdt->dev,
                        "cannot register IRQ%d for watchdog\n", wdt->irq);
index 945ee83..7c0d863 100644 (file)
@@ -402,7 +402,7 @@ static void octeon_wdt_setup_interrupt(int cpu)
        irq = OCTEON_IRQ_WDOG0 + core;
 
        if (request_irq(irq, octeon_wdt_poke_irq,
-                       IRQF_DISABLED, "octeon_wdt", octeon_wdt_poke_irq))
+                       IRQF_NO_THREAD, "octeon_wdt", octeon_wdt_poke_irq))
                panic("octeon_wdt: Couldn't obtain irq %d", irq);
 
        cpumask_set_cpu(cpu, &irq_enabled_cpus);
index 30da88f..5de7e4f 100644 (file)
@@ -27,9 +27,8 @@
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/timer.h>
-#include <linux/miscdevice.h>
+#include <linux/miscdevice.h> /* for MODULE_ALIAS_MISCDEV */
 #include <linux/watchdog.h>
-#include <linux/fs.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
@@ -38,6 +37,7 @@
 #include <linux/io.h>
 #include <linux/cpufreq.h>
 #include <linux/slab.h>
+#include <linux/err.h>
 
 #include <mach/map.h>
 
@@ -74,14 +74,12 @@ MODULE_PARM_DESC(soft_noboot, "Watchdog action, set to 1 to ignore reboots, "
                        "0 to reboot (default 0)");
 MODULE_PARM_DESC(debug, "Watchdog debug, set to >1 for debug (default 0)");
 
-static unsigned long open_lock;
 static struct device    *wdt_dev;      /* platform device attached to */
 static struct resource *wdt_mem;
 static struct resource *wdt_irq;
 static struct clk      *wdt_clock;
 static void __iomem    *wdt_base;
 static unsigned int     wdt_count;
-static char             expect_close;
 static DEFINE_SPINLOCK(wdt_lock);
 
 /* watchdog control routines */
@@ -93,11 +91,13 @@ static DEFINE_SPINLOCK(wdt_lock);
 
 /* functions */
 
-static void s3c2410wdt_keepalive(void)
+static int s3c2410wdt_keepalive(struct watchdog_device *wdd)
 {
        spin_lock(&wdt_lock);
        writel(wdt_count, wdt_base + S3C2410_WTCNT);
        spin_unlock(&wdt_lock);
+
+       return 0;
 }
 
 static void __s3c2410wdt_stop(void)
@@ -109,14 +109,16 @@ static void __s3c2410wdt_stop(void)
        writel(wtcon, wdt_base + S3C2410_WTCON);
 }
 
-static void s3c2410wdt_stop(void)
+static int s3c2410wdt_stop(struct watchdog_device *wdd)
 {
        spin_lock(&wdt_lock);
        __s3c2410wdt_stop();
        spin_unlock(&wdt_lock);
+
+       return 0;
 }
 
-static void s3c2410wdt_start(void)
+static int s3c2410wdt_start(struct watchdog_device *wdd)
 {
        unsigned long wtcon;
 
@@ -142,6 +144,8 @@ static void s3c2410wdt_start(void)
        writel(wdt_count, wdt_base + S3C2410_WTCNT);
        writel(wtcon, wdt_base + S3C2410_WTCON);
        spin_unlock(&wdt_lock);
+
+       return 0;
 }
 
 static inline int s3c2410wdt_is_running(void)
@@ -149,7 +153,7 @@ static inline int s3c2410wdt_is_running(void)
        return readl(wdt_base + S3C2410_WTCON) & S3C2410_WTCON_ENABLE;
 }
 
-static int s3c2410wdt_set_heartbeat(int timeout)
+static int s3c2410wdt_set_heartbeat(struct watchdog_device *wdd, unsigned timeout)
 {
        unsigned long freq = clk_get_rate(wdt_clock);
        unsigned int count;
@@ -182,8 +186,6 @@ static int s3c2410wdt_set_heartbeat(int timeout)
                }
        }
 
-       tmr_margin = timeout;
-
        DBG("%s: timeout=%d, divisor=%d, count=%d (%08x)\n",
            __func__, timeout, divisor, count, count/divisor);
 
@@ -201,70 +203,6 @@ static int s3c2410wdt_set_heartbeat(int timeout)
        return 0;
 }
 
-/*
- *     /dev/watchdog handling
- */
-
-static int s3c2410wdt_open(struct inode *inode, struct file *file)
-{
-       if (test_and_set_bit(0, &open_lock))
-               return -EBUSY;
-
-       if (nowayout)
-               __module_get(THIS_MODULE);
-
-       expect_close = 0;
-
-       /* start the timer */
-       s3c2410wdt_start();
-       return nonseekable_open(inode, file);
-}
-
-static int s3c2410wdt_release(struct inode *inode, struct file *file)
-{
-       /*
-        *      Shut off the timer.
-        *      Lock it in if it's a module and we set nowayout
-        */
-
-       if (expect_close == 42)
-               s3c2410wdt_stop();
-       else {
-               dev_err(wdt_dev, "Unexpected close, not stopping watchdog\n");
-               s3c2410wdt_keepalive();
-       }
-       expect_close = 0;
-       clear_bit(0, &open_lock);
-       return 0;
-}
-
-static ssize_t s3c2410wdt_write(struct file *file, const char __user *data,
-                               size_t len, loff_t *ppos)
-{
-       /*
-        *      Refresh the timer.
-        */
-       if (len) {
-               if (!nowayout) {
-                       size_t i;
-
-                       /* In case it was set long ago */
-                       expect_close = 0;
-
-                       for (i = 0; i != len; i++) {
-                               char c;
-
-                               if (get_user(c, data + i))
-                                       return -EFAULT;
-                               if (c == 'V')
-                                       expect_close = 42;
-                       }
-               }
-               s3c2410wdt_keepalive();
-       }
-       return len;
-}
-
 #define OPTIONS (WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE)
 
 static const struct watchdog_info s3c2410_wdt_ident = {
@@ -273,53 +211,17 @@ static const struct watchdog_info s3c2410_wdt_ident = {
        .identity         =     "S3C2410 Watchdog",
 };
 
-
-static long s3c2410wdt_ioctl(struct file *file,        unsigned int cmd,
-                                                       unsigned long arg)
-{
-       void __user *argp = (void __user *)arg;
-       int __user *p = argp;
-       int new_margin;
-
-       switch (cmd) {
-       case WDIOC_GETSUPPORT:
-               return copy_to_user(argp, &s3c2410_wdt_ident,
-                       sizeof(s3c2410_wdt_ident)) ? -EFAULT : 0;
-       case WDIOC_GETSTATUS:
-       case WDIOC_GETBOOTSTATUS:
-               return put_user(0, p);
-       case WDIOC_KEEPALIVE:
-               s3c2410wdt_keepalive();
-               return 0;
-       case WDIOC_SETTIMEOUT:
-               if (get_user(new_margin, p))
-                       return -EFAULT;
-               if (s3c2410wdt_set_heartbeat(new_margin))
-                       return -EINVAL;
-               s3c2410wdt_keepalive();
-               return put_user(tmr_margin, p);
-       case WDIOC_GETTIMEOUT:
-               return put_user(tmr_margin, p);
-       default:
-               return -ENOTTY;
-       }
-}
-
-/* kernel interface */
-
-static const struct file_operations s3c2410wdt_fops = {
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .write          = s3c2410wdt_write,
-       .unlocked_ioctl = s3c2410wdt_ioctl,
-       .open           = s3c2410wdt_open,
-       .release        = s3c2410wdt_release,
+static struct watchdog_ops s3c2410wdt_ops = {
+       .owner = THIS_MODULE,
+       .start = s3c2410wdt_start,
+       .stop = s3c2410wdt_stop,
+       .ping = s3c2410wdt_keepalive,
+       .set_timeout = s3c2410wdt_set_heartbeat,
 };
 
-static struct miscdevice s3c2410wdt_miscdev = {
-       .minor          = WATCHDOG_MINOR,
-       .name           = "watchdog",
-       .fops           = &s3c2410wdt_fops,
+static struct watchdog_device s3c2410_wdd = {
+       .info = &s3c2410_wdt_ident,
+       .ops = &s3c2410wdt_ops,
 };
 
 /* interrupt handler code */
@@ -328,7 +230,7 @@ static irqreturn_t s3c2410wdt_irq(int irqno, void *param)
 {
        dev_info(wdt_dev, "watchdog timer expired (irq)\n");
 
-       s3c2410wdt_keepalive();
+       s3c2410wdt_keepalive(&s3c2410_wdd);
        return IRQ_HANDLED;
 }
 
@@ -349,14 +251,14 @@ static int s3c2410wdt_cpufreq_transition(struct notifier_block *nb,
                 * the watchdog is running.
                 */
 
-               s3c2410wdt_keepalive();
+               s3c2410wdt_keepalive(&s3c2410_wdd);
        } else if (val == CPUFREQ_POSTCHANGE) {
-               s3c2410wdt_stop();
+               s3c2410wdt_stop(&s3c2410_wdd);
 
-               ret = s3c2410wdt_set_heartbeat(tmr_margin);
+               ret = s3c2410wdt_set_heartbeat(&s3c2410_wdd, s3c2410_wdd.timeout);
 
                if (ret >= 0)
-                       s3c2410wdt_start();
+                       s3c2410wdt_start(&s3c2410_wdd);
                else
                        goto err;
        }
@@ -365,7 +267,8 @@ done:
        return 0;
 
  err:
-       dev_err(wdt_dev, "cannot set new value for timeout %d\n", tmr_margin);
+       dev_err(wdt_dev, "cannot set new value for timeout %d\n",
+                               s3c2410_wdd.timeout);
        return ret;
 }
 
@@ -396,10 +299,6 @@ static inline void s3c2410wdt_cpufreq_deregister(void)
 }
 #endif
 
-
-
-/* device interface */
-
 static int __devinit s3c2410wdt_probe(struct platform_device *pdev)
 {
        struct device *dev;
@@ -466,8 +365,8 @@ static int __devinit s3c2410wdt_probe(struct platform_device *pdev)
        /* see if we can actually set the requested timer margin, and if
         * not, try the default value */
 
-       if (s3c2410wdt_set_heartbeat(tmr_margin)) {
-               started = s3c2410wdt_set_heartbeat(
+       if (s3c2410wdt_set_heartbeat(&s3c2410_wdd, tmr_margin)) {
+               started = s3c2410wdt_set_heartbeat(&s3c2410_wdd,
                                        CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME);
 
                if (started == 0)
@@ -479,22 +378,21 @@ static int __devinit s3c2410wdt_probe(struct platform_device *pdev)
                                                        "cannot start\n");
        }
 
-       ret = misc_register(&s3c2410wdt_miscdev);
+       ret = watchdog_register_device(&s3c2410_wdd);
        if (ret) {
-               dev_err(dev, "cannot register miscdev on minor=%d (%d)\n",
-                       WATCHDOG_MINOR, ret);
+               dev_err(dev, "cannot register watchdog (%d)\n", ret);
                goto err_cpufreq;
        }
 
        if (tmr_atboot && started == 0) {
                dev_info(dev, "starting watchdog timer\n");
-               s3c2410wdt_start();
+               s3c2410wdt_start(&s3c2410_wdd);
        } else if (!tmr_atboot) {
                /* if we're not enabling the watchdog, then ensure it is
                 * disabled if it has been left running from the bootloader
                 * or other source */
 
-               s3c2410wdt_stop();
+               s3c2410wdt_stop(&s3c2410_wdd);
        }
 
        /* print out a statement of readiness */
@@ -530,7 +428,7 @@ static int __devinit s3c2410wdt_probe(struct platform_device *pdev)
 
 static int __devexit s3c2410wdt_remove(struct platform_device *dev)
 {
-       misc_deregister(&s3c2410wdt_miscdev);
+       watchdog_unregister_device(&s3c2410_wdd);
 
        s3c2410wdt_cpufreq_deregister();
 
@@ -550,7 +448,7 @@ static int __devexit s3c2410wdt_remove(struct platform_device *dev)
 
 static void s3c2410wdt_shutdown(struct platform_device *dev)
 {
-       s3c2410wdt_stop();
+       s3c2410wdt_stop(&s3c2410_wdd);
 }
 
 #ifdef CONFIG_PM
@@ -565,7 +463,7 @@ static int s3c2410wdt_suspend(struct platform_device *dev, pm_message_t state)
        wtdat_save = readl(wdt_base + S3C2410_WTDAT);
 
        /* Note that WTCNT doesn't need to be saved. */
-       s3c2410wdt_stop();
+       s3c2410wdt_stop(&s3c2410_wdd);
 
        return 0;
 }
index f31493e..b01a30e 100644 (file)
@@ -300,7 +300,7 @@ static int __init sbwdog_init(void)
         * get the resources
         */
 
-       ret = request_irq(1, sbwdog_interrupt, IRQF_DISABLED | IRQF_SHARED,
+       ret = request_irq(1, sbwdog_interrupt, IRQF_SHARED,
                ident.identity, (void *)user_dog);
        if (ret) {
                printk(KERN_ERR "%s: failed to request irq 1 - %d\n",
@@ -350,7 +350,7 @@ void platform_wd_setup(void)
 {
        int ret;
 
-       ret = request_irq(1, sbwdog_interrupt, IRQF_DISABLED | IRQF_SHARED,
+       ret = request_irq(1, sbwdog_interrupt, IRQF_SHARED,
                "Kernel Watchdog", IOADDR(A_SCD_WDOG_CFG_0));
        if (ret) {
                printk(KERN_CRIT
index 52b63f2..b284040 100644 (file)
@@ -398,7 +398,7 @@ static int __init sc520_wdt_init(void)
                                                        WATCHDOG_TIMEOUT);
        }
 
-       wdtmrctl = ioremap((unsigned long)(MMCR_BASE + OFFS_WDTMRCTL), 2);
+       wdtmrctl = ioremap(MMCR_BASE + OFFS_WDTMRCTL, 2);
        if (!wdtmrctl) {
                printk(KERN_ERR PFX "Unable to remap memory\n");
                rc = -ENOMEM;
index e5c91d4..dd5d675 100644 (file)
@@ -142,7 +142,7 @@ static void w83627hf_init(void)
        w83627hf_unselect_wd_register();
 }
 
-static void wdt_ctrl(int timeout)
+static void wdt_set_time(int timeout)
 {
        spin_lock(&io_lock);
 
@@ -158,13 +158,13 @@ static void wdt_ctrl(int timeout)
 
 static int wdt_ping(void)
 {
-       wdt_ctrl(timeout);
+       wdt_set_time(timeout);
        return 0;
 }
 
 static int wdt_disable(void)
 {
-       wdt_ctrl(0);
+       wdt_set_time(0);
        return 0;
 }
 
@@ -176,6 +176,24 @@ static int wdt_set_heartbeat(int t)
        return 0;
 }
 
+static int wdt_get_time(void)
+{
+       int timeleft;
+
+       spin_lock(&io_lock);
+
+       w83627hf_select_wd_register();
+
+       outb_p(0xF6, WDT_EFER);    /* Select CRF6 */
+       timeleft = inb_p(WDT_EFDR); /* Read Timeout counter to CRF6 */
+
+       w83627hf_unselect_wd_register();
+
+       spin_unlock(&io_lock);
+
+       return timeleft;
+}
+
 static ssize_t wdt_write(struct file *file, const char __user *buf,
                                                size_t count, loff_t *ppos)
 {
@@ -202,7 +220,7 @@ static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
        void __user *argp = (void __user *)arg;
        int __user *p = argp;
-       int new_timeout;
+       int timeval;
        static const struct watchdog_info ident = {
                .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
                                                        WDIOF_MAGICCLOSE,
@@ -238,14 +256,17 @@ static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                wdt_ping();
                break;
        case WDIOC_SETTIMEOUT:
-               if (get_user(new_timeout, p))
+               if (get_user(timeval, p))
                        return -EFAULT;
-               if (wdt_set_heartbeat(new_timeout))
+               if (wdt_set_heartbeat(timeval))
                        return -EINVAL;
                wdt_ping();
                /* Fall */
        case WDIOC_GETTIMEOUT:
                return put_user(timeout, p);
+       case WDIOC_GETTIMELEFT:
+               timeval = wdt_get_time();
+               return put_user(timeval, p);
        default:
                return -ENOTTY;
        }
index bb03e15..d2ef002 100644 (file)
@@ -612,7 +612,7 @@ static int __init wdt_init(void)
                goto out;
        }
 
-       ret = request_irq(irq, wdt_interrupt, IRQF_DISABLED, "wdt501p", NULL);
+       ret = request_irq(irq, wdt_interrupt, 0, "wdt501p", NULL);
        if (ret) {
                printk(KERN_ERR "wdt: IRQ %d is not free.\n", irq);
                goto outreg;
index 172dad6..e0fc3ba 100644 (file)
@@ -643,7 +643,7 @@ static int __devinit wdtpci_init_one(struct pci_dev *dev,
        irq = dev->irq;
        io = pci_resource_start(dev, 2);
 
-       if (request_irq(irq, wdtpci_interrupt, IRQF_DISABLED | IRQF_SHARED,
+       if (request_irq(irq, wdtpci_interrupt, IRQF_SHARED,
                         "wdt_pci", &wdtpci_miscdev)) {
                printk(KERN_ERR PFX "IRQ %d is not free\n", irq);
                goto out_reg;
index 871caea..7be3855 100644 (file)
@@ -12,8 +12,7 @@
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/miscdevice.h>
+#include <linux/slab.h>
 #include <linux/platform_device.h>
 #include <linux/watchdog.h>
 #include <linux/uaccess.h>
@@ -29,19 +28,19 @@ MODULE_PARM_DESC(nowayout,
                 "Watchdog cannot be stopped once started (default="
                 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
-static unsigned long wm831x_wdt_users;
-static struct miscdevice wm831x_wdt_miscdev;
-static int wm831x_wdt_expect_close;
-static DEFINE_MUTEX(wdt_mutex);
-static struct wm831x *wm831x;
-static unsigned int update_gpio;
-static unsigned int update_state;
+struct wm831x_wdt_drvdata {
+       struct watchdog_device wdt;
+       struct wm831x *wm831x;
+       struct mutex lock;
+       int update_gpio;
+       int update_state;
+};
 
 /* We can't use the sub-second values here but they're included
  * for completeness.  */
 static struct {
-       int time;  /* Seconds */
-       u16 val;   /* WDOG_TO value */
+       unsigned int time;  /* Seconds */
+       u16 val;            /* WDOG_TO value */
 } wm831x_wdt_cfgs[] = {
        {  1, 2 },
        {  2, 3 },
@@ -52,32 +51,13 @@ static struct {
        { 33, 7 },  /* Actually 32.768s so include both, others round down */
 };
 
-static int wm831x_wdt_set_timeout(struct wm831x *wm831x, u16 value)
-{
-       int ret;
-
-       mutex_lock(&wdt_mutex);
-
-       ret = wm831x_reg_unlock(wm831x);
-       if (ret == 0) {
-               ret = wm831x_set_bits(wm831x, WM831X_WATCHDOG,
-                                     WM831X_WDOG_TO_MASK, value);
-               wm831x_reg_lock(wm831x);
-       } else {
-               dev_err(wm831x->dev, "Failed to unlock security key: %d\n",
-                       ret);
-       }
-
-       mutex_unlock(&wdt_mutex);
-
-       return ret;
-}
-
-static int wm831x_wdt_start(struct wm831x *wm831x)
+static int wm831x_wdt_start(struct watchdog_device *wdt_dev)
 {
+       struct wm831x_wdt_drvdata *driver_data = watchdog_get_drvdata(wdt_dev);
+       struct wm831x *wm831x = driver_data->wm831x;
        int ret;
 
-       mutex_lock(&wdt_mutex);
+       mutex_lock(&driver_data->lock);
 
        ret = wm831x_reg_unlock(wm831x);
        if (ret == 0) {
@@ -89,16 +69,18 @@ static int wm831x_wdt_start(struct wm831x *wm831x)
                        ret);
        }
 
-       mutex_unlock(&wdt_mutex);
+       mutex_unlock(&driver_data->lock);
 
        return ret;
 }
 
-static int wm831x_wdt_stop(struct wm831x *wm831x)
+static int wm831x_wdt_stop(struct watchdog_device *wdt_dev)
 {
+       struct wm831x_wdt_drvdata *driver_data = watchdog_get_drvdata(wdt_dev);
+       struct wm831x *wm831x = driver_data->wm831x;
        int ret;
 
-       mutex_lock(&wdt_mutex);
+       mutex_lock(&driver_data->lock);
 
        ret = wm831x_reg_unlock(wm831x);
        if (ret == 0) {
@@ -110,26 +92,28 @@ static int wm831x_wdt_stop(struct wm831x *wm831x)
                        ret);
        }
 
-       mutex_unlock(&wdt_mutex);
+       mutex_unlock(&driver_data->lock);
 
        return ret;
 }
 
-static int wm831x_wdt_kick(struct wm831x *wm831x)
+static int wm831x_wdt_ping(struct watchdog_device *wdt_dev)
 {
+       struct wm831x_wdt_drvdata *driver_data = watchdog_get_drvdata(wdt_dev);
+       struct wm831x *wm831x = driver_data->wm831x;
        int ret;
        u16 reg;
 
-       mutex_lock(&wdt_mutex);
+       mutex_lock(&driver_data->lock);
 
-       if (update_gpio) {
-               gpio_set_value_cansleep(update_gpio, update_state);
-               update_state = !update_state;
+       if (driver_data->update_gpio) {
+               gpio_set_value_cansleep(driver_data->update_gpio,
+                                       driver_data->update_state);
+               driver_data->update_state = !driver_data->update_state;
                ret = 0;
                goto out;
        }
 
-
        reg = wm831x_reg_read(wm831x, WM831X_WATCHDOG);
 
        if (!(reg & WM831X_WDOG_RST_SRC)) {
@@ -150,182 +134,59 @@ static int wm831x_wdt_kick(struct wm831x *wm831x)
        }
 
 out:
-       mutex_unlock(&wdt_mutex);
+       mutex_unlock(&driver_data->lock);
 
        return ret;
 }
 
-static int wm831x_wdt_open(struct inode *inode, struct file *file)
+static int wm831x_wdt_set_timeout(struct watchdog_device *wdt_dev,
+                                 unsigned int timeout)
 {
-       int ret;
-
-       if (!wm831x)
-               return -ENODEV;
-
-       if (test_and_set_bit(0, &wm831x_wdt_users))
-               return -EBUSY;
+       struct wm831x_wdt_drvdata *driver_data = watchdog_get_drvdata(wdt_dev);
+       struct wm831x *wm831x = driver_data->wm831x;
+       int ret, i;
 
-       ret = wm831x_wdt_start(wm831x);
-       if (ret != 0)
-               return ret;
-
-       return nonseekable_open(inode, file);
-}
+       for (i = 0; i < ARRAY_SIZE(wm831x_wdt_cfgs); i++)
+               if (wm831x_wdt_cfgs[i].time == timeout)
+                       break;
+       if (i == ARRAY_SIZE(wm831x_wdt_cfgs))
+               ret = -EINVAL;
 
-static int wm831x_wdt_release(struct inode *inode, struct file *file)
-{
-       if (wm831x_wdt_expect_close)
-               wm831x_wdt_stop(wm831x);
-       else {
-               dev_warn(wm831x->dev, "Watchdog device closed uncleanly\n");
-               wm831x_wdt_kick(wm831x);
+       ret = wm831x_reg_unlock(wm831x);
+       if (ret == 0) {
+               ret = wm831x_set_bits(wm831x, WM831X_WATCHDOG,
+                                     WM831X_WDOG_TO_MASK,
+                                     wm831x_wdt_cfgs[i].val);
+               wm831x_reg_lock(wm831x);
+       } else {
+               dev_err(wm831x->dev, "Failed to unlock security key: %d\n",
+                       ret);
        }
 
-       clear_bit(0, &wm831x_wdt_users);
-
-       return 0;
-}
-
-static ssize_t wm831x_wdt_write(struct file *file,
-                               const char __user *data, size_t count,
-                               loff_t *ppos)
-{
-       size_t i;
-
-       if (count) {
-               wm831x_wdt_kick(wm831x);
-
-               if (!nowayout) {
-                       /* In case it was set long ago */
-                       wm831x_wdt_expect_close = 0;
-
-                       /* scan to see whether or not we got the magic
-                          character */
-                       for (i = 0; i != count; i++) {
-                               char c;
-                               if (get_user(c, data + i))
-                                       return -EFAULT;
-                               if (c == 'V')
-                                       wm831x_wdt_expect_close = 42;
-                       }
-               }
-       }
-       return count;
+       return ret;
 }
 
-static const struct watchdog_info ident = {
+static const struct watchdog_info wm831x_wdt_info = {
        .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
        .identity = "WM831x Watchdog",
 };
 
-static long wm831x_wdt_ioctl(struct file *file, unsigned int cmd,
-                            unsigned long arg)
-{
-       int ret = -ENOTTY, time, i;
-       void __user *argp = (void __user *)arg;
-       int __user *p = argp;
-       u16 reg;
-
-       switch (cmd) {
-       case WDIOC_GETSUPPORT:
-               ret = copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
-               break;
-
-       case WDIOC_GETSTATUS:
-       case WDIOC_GETBOOTSTATUS:
-               ret = put_user(0, p);
-               break;
-
-       case WDIOC_SETOPTIONS:
-       {
-               int options;
-
-               if (get_user(options, p))
-                       return -EFAULT;
-
-               ret = -EINVAL;
-
-               /* Setting both simultaneously means at least one must fail */
-               if (options == WDIOS_DISABLECARD)
-                       ret = wm831x_wdt_start(wm831x);
-
-               if (options == WDIOS_ENABLECARD)
-                       ret = wm831x_wdt_stop(wm831x);
-               break;
-       }
-
-       case WDIOC_KEEPALIVE:
-               ret = wm831x_wdt_kick(wm831x);
-               break;
-
-       case WDIOC_SETTIMEOUT:
-               ret = get_user(time, p);
-               if (ret)
-                       break;
-
-               if (time == 0) {
-                       if (nowayout)
-                               ret = -EINVAL;
-                       else
-                               wm831x_wdt_stop(wm831x);
-                       break;
-               }
-
-               for (i = 0; i < ARRAY_SIZE(wm831x_wdt_cfgs); i++)
-                       if (wm831x_wdt_cfgs[i].time == time)
-                               break;
-               if (i == ARRAY_SIZE(wm831x_wdt_cfgs))
-                       ret = -EINVAL;
-               else
-                       ret = wm831x_wdt_set_timeout(wm831x,
-                                                    wm831x_wdt_cfgs[i].val);
-               break;
-
-       case WDIOC_GETTIMEOUT:
-               reg = wm831x_reg_read(wm831x, WM831X_WATCHDOG);
-               reg &= WM831X_WDOG_TO_MASK;
-               for (i = 0; i < ARRAY_SIZE(wm831x_wdt_cfgs); i++)
-                       if (wm831x_wdt_cfgs[i].val == reg)
-                               break;
-               if (i == ARRAY_SIZE(wm831x_wdt_cfgs)) {
-                       dev_warn(wm831x->dev,
-                                "Unknown watchdog configuration: %x\n", reg);
-                       ret = -EINVAL;
-               } else
-                       ret = put_user(wm831x_wdt_cfgs[i].time, p);
-
-       }
-
-       return ret;
-}
-
-static const struct file_operations wm831x_wdt_fops = {
+static const struct watchdog_ops wm831x_wdt_ops = {
        .owner = THIS_MODULE,
-       .llseek = no_llseek,
-       .write = wm831x_wdt_write,
-       .unlocked_ioctl = wm831x_wdt_ioctl,
-       .open = wm831x_wdt_open,
-       .release = wm831x_wdt_release,
-};
-
-static struct miscdevice wm831x_wdt_miscdev = {
-       .minor = WATCHDOG_MINOR,
-       .name = "watchdog",
-       .fops = &wm831x_wdt_fops,
+       .start = wm831x_wdt_start,
+       .stop = wm831x_wdt_stop,
+       .ping = wm831x_wdt_ping,
+       .set_timeout = wm831x_wdt_set_timeout,
 };
 
 static int __devinit wm831x_wdt_probe(struct platform_device *pdev)
 {
+       struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
        struct wm831x_pdata *chip_pdata;
        struct wm831x_watchdog_pdata *pdata;
-       int reg, ret;
-
-       if (wm831x) {
-               dev_err(&pdev->dev, "wm831x watchdog already registered\n");
-               return -EBUSY;
-       }
-
-       wm831x = dev_get_drvdata(pdev->dev.parent);
+       struct wm831x_wdt_drvdata *driver_data;
+       struct watchdog_device *wm831x_wdt;
+       int reg, ret, i;
 
        ret = wm831x_reg_read(wm831x, WM831X_WATCHDOG);
        if (ret < 0) {
@@ -338,6 +199,36 @@ static int __devinit wm831x_wdt_probe(struct platform_device *pdev)
        if (reg & WM831X_WDOG_DEBUG)
                dev_warn(wm831x->dev, "Watchdog is paused\n");
 
+       driver_data = kzalloc(sizeof(*driver_data), GFP_KERNEL);
+       if (!driver_data) {
+               dev_err(wm831x->dev, "Unable to alloacate watchdog device\n");
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       mutex_init(&driver_data->lock);
+       driver_data->wm831x = wm831x;
+
+       wm831x_wdt = &driver_data->wdt;
+
+       wm831x_wdt->info = &wm831x_wdt_info;
+       wm831x_wdt->ops = &wm831x_wdt_ops;
+       watchdog_set_drvdata(wm831x_wdt, driver_data);
+
+       if (nowayout)
+               wm831x_wdt->status |= WDOG_NO_WAY_OUT;
+
+       reg = wm831x_reg_read(wm831x, WM831X_WATCHDOG);
+       reg &= WM831X_WDOG_TO_MASK;
+       for (i = 0; i < ARRAY_SIZE(wm831x_wdt_cfgs); i++)
+               if (wm831x_wdt_cfgs[i].val == reg)
+                       break;
+       if (i == ARRAY_SIZE(wm831x_wdt_cfgs))
+               dev_warn(wm831x->dev,
+                        "Unknown watchdog timeout: %x\n", reg);
+       else
+               wm831x_wdt->timeout = wm831x_wdt_cfgs[i].time;
+
        /* Apply any configuration */
        if (pdev->dev.parent->platform_data) {
                chip_pdata = pdev->dev.parent->platform_data;
@@ -361,7 +252,7 @@ static int __devinit wm831x_wdt_probe(struct platform_device *pdev)
                                dev_err(wm831x->dev,
                                        "Failed to request update GPIO: %d\n",
                                        ret);
-                               goto err;
+                               goto err_alloc;
                        }
 
                        ret = gpio_direction_output(pdata->update_gpio, 0);
@@ -372,7 +263,7 @@ static int __devinit wm831x_wdt_probe(struct platform_device *pdev)
                                goto err_gpio;
                        }
 
-                       update_gpio = pdata->update_gpio;
+                       driver_data->update_gpio = pdata->update_gpio;
 
                        /* Make sure the watchdog takes hardware updates */
                        reg |= WM831X_WDOG_RST_SRC;
@@ -389,33 +280,34 @@ static int __devinit wm831x_wdt_probe(struct platform_device *pdev)
                }
        }
 
-       wm831x_wdt_miscdev.parent = &pdev->dev;
-
-       ret = misc_register(&wm831x_wdt_miscdev);
+       ret = watchdog_register_device(&driver_data->wdt);
        if (ret != 0) {
-               dev_err(wm831x->dev, "Failed to register miscdev: %d\n", ret);
+               dev_err(wm831x->dev, "watchdog_register_device() failed: %d\n",
+                       ret);
                goto err_gpio;
        }
 
+       dev_set_drvdata(&pdev->dev, driver_data);
+
        return 0;
 
 err_gpio:
-       if (update_gpio) {
-               gpio_free(update_gpio);
-               update_gpio = 0;
-       }
+       if (driver_data->update_gpio)
+               gpio_free(driver_data->update_gpio);
+err_alloc:
+       kfree(driver_data);
 err:
        return ret;
 }
 
 static int __devexit wm831x_wdt_remove(struct platform_device *pdev)
 {
-       if (update_gpio) {
-               gpio_free(update_gpio);
-               update_gpio = 0;
-       }
+       struct wm831x_wdt_drvdata *driver_data = dev_get_drvdata(&pdev->dev);
+
+       watchdog_unregister_device(&driver_data->wdt);
 
-       misc_deregister(&wm831x_wdt_miscdev);
+       if (driver_data->update_gpio)
+               gpio_free(driver_data->update_gpio);
 
        return 0;
 }
index 9bfade8..41c93c7 100644 (file)
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -255,7 +255,6 @@ void bio_init(struct bio *bio)
 {
        memset(bio, 0, sizeof(*bio));
        bio->bi_flags = 1 << BIO_UPTODATE;
-       bio->bi_comp_cpu = -1;
        atomic_set(&bio->bi_cnt, 1);
 }
 EXPORT_SYMBOL(bio_init);
index 95f786e..b07f1da 100644 (file)
@@ -971,7 +971,7 @@ static void flush_disk(struct block_device *bdev, bool kill_dirty)
 
        if (!bdev->bd_disk)
                return;
-       if (disk_partitionable(bdev->bd_disk))
+       if (disk_part_scan_enabled(bdev->bd_disk))
                bdev->bd_invalidated = 1;
 }
 
@@ -1085,6 +1085,7 @@ static int __blkdev_put(struct block_device *bdev, fmode_t mode, int for_part);
 static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
 {
        struct gendisk *disk;
+       struct module *owner;
        int ret;
        int partno;
        int perm = 0;
@@ -1110,6 +1111,7 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
        disk = get_gendisk(bdev->bd_dev, &partno);
        if (!disk)
                goto out;
+       owner = disk->fops->owner;
 
        disk_block_events(disk);
        mutex_lock_nested(&bdev->bd_mutex, for_part);
@@ -1137,8 +1139,8 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
                                        bdev->bd_disk = NULL;
                                        mutex_unlock(&bdev->bd_mutex);
                                        disk_unblock_events(disk);
-                                       module_put(disk->fops->owner);
                                        put_disk(disk);
+                                       module_put(owner);
                                        goto restart;
                                }
                        }
@@ -1194,8 +1196,8 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
                                goto out_unlock_bdev;
                }
                /* only one opener holds refs to the module and disk */
-               module_put(disk->fops->owner);
                put_disk(disk);
+               module_put(owner);
        }
        bdev->bd_openers++;
        if (for_part)
@@ -1215,8 +1217,8 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
  out_unlock_bdev:
        mutex_unlock(&bdev->bd_mutex);
        disk_unblock_events(disk);
-       module_put(disk->fops->owner);
        put_disk(disk);
+       module_put(owner);
  out:
        bdput(bdev);
 
@@ -1442,14 +1444,15 @@ static int __blkdev_put(struct block_device *bdev, fmode_t mode, int for_part)
        if (!bdev->bd_openers) {
                struct module *owner = disk->fops->owner;
 
-               put_disk(disk);
-               module_put(owner);
                disk_put_part(bdev->bd_part);
                bdev->bd_part = NULL;
                bdev->bd_disk = NULL;
                if (bdev != bdev->bd_contains)
                        victim = bdev->bd_contains;
                bdev->bd_contains = NULL;
+
+               put_disk(disk);
+               module_put(owner);
        }
        mutex_unlock(&bdev->bd_mutex);
        bdput(bdev);
index fa9a286..da42f32 100644 (file)
@@ -5,7 +5,7 @@
 # selected by any of the users.
 config ORE
        tristate
-       depends on EXOFS_FS
+       depends on EXOFS_FS || PNFS_OBJLAYOUT
        select ASYNC_XOR
        default SCSI_OSD_ULD
 
index 918ad64..726e59a 100644 (file)
@@ -488,17 +488,18 @@ static __be32 decode_recallany_args(struct svc_rqst *rqstp,
                                      struct xdr_stream *xdr,
                                      struct cb_recallanyargs *args)
 {
-       __be32 *p;
+       uint32_t bitmap[2];
+       __be32 *p, status;
 
        args->craa_addr = svc_addr(rqstp);
        p = read_buf(xdr, 4);
        if (unlikely(p == NULL))
                return htonl(NFS4ERR_BADXDR);
        args->craa_objs_to_keep = ntohl(*p++);
-       p = read_buf(xdr, 4);
-       if (unlikely(p == NULL))
-               return htonl(NFS4ERR_BADXDR);
-       args->craa_type_mask = ntohl(*p);
+       status = decode_bitmap(xdr, bitmap);
+       if (unlikely(status))
+               return status;
+       args->craa_type_mask = bitmap[0];
 
        return 0;
 }
@@ -986,4 +987,5 @@ struct svc_version nfs4_callback_version4 = {
        .vs_proc = nfs4_callback_procedures1,
        .vs_xdrsize = NFS4_CALLBACK_XDRSIZE,
        .vs_dispatch = NULL,
+       .vs_hidden = 1,
 };
index 91c01f0..0a1f831 100644 (file)
@@ -137,11 +137,9 @@ nfs_file_open(struct inode *inode, struct file *filp)
 static int
 nfs_file_release(struct inode *inode, struct file *filp)
 {
-       struct dentry *dentry = filp->f_path.dentry;
-
        dprintk("NFS: release(%s/%s)\n",
-                       dentry->d_parent->d_name.name,
-                       dentry->d_name.name);
+                       filp->f_path.dentry->d_parent->d_name.name,
+                       filp->f_path.dentry->d_name.name);
 
        nfs_inc_stats(inode, NFSIOS_VFSRELEASE);
        return nfs_release(inode, filp);
@@ -228,14 +226,13 @@ nfs_file_read(struct kiocb *iocb, const struct iovec *iov,
        struct dentry * dentry = iocb->ki_filp->f_path.dentry;
        struct inode * inode = dentry->d_inode;
        ssize_t result;
-       size_t count = iov_length(iov, nr_segs);
 
        if (iocb->ki_filp->f_flags & O_DIRECT)
                return nfs_file_direct_read(iocb, iov, nr_segs, pos);
 
        dprintk("NFS: read(%s/%s, %lu@%lu)\n",
                dentry->d_parent->d_name.name, dentry->d_name.name,
-               (unsigned long) count, (unsigned long) pos);
+               (unsigned long) iov_length(iov, nr_segs), (unsigned long) pos);
 
        result = nfs_revalidate_mapping(inode, iocb->ki_filp->f_mapping);
        if (!result) {
index 0911941..12185aa 100644 (file)
@@ -449,9 +449,8 @@ filelayout_check_layout(struct pnfs_layout_hdr *lo,
 
        fl->dsaddr = dsaddr;
 
-       if (fl->first_stripe_index < 0 ||
-           fl->first_stripe_index >= dsaddr->stripe_count) {
-               dprintk("%s Bad first_stripe_index %d\n",
+       if (fl->first_stripe_index >= dsaddr->stripe_count) {
+               dprintk("%s Bad first_stripe_index %u\n",
                                __func__, fl->first_stripe_index);
                goto out_put;
        }
@@ -552,7 +551,7 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo,
 
        /* Note that a zero value for num_fh is legal for STRIPE_SPARSE.
         * Futher checking is done in filelayout_check_layout */
-       if (fl->num_fh < 0 || fl->num_fh >
+       if (fl->num_fh >
            max(NFS4_PNFS_MAX_STRIPE_CNT, NFS4_PNFS_MAX_MULTI_CNT))
                goto out_err;
 
index d2ae413..b60fddf 100644 (file)
@@ -5950,6 +5950,7 @@ static void nfs4_layoutcommit_release(void *calldata)
 {
        struct nfs4_layoutcommit_data *data = calldata;
        struct pnfs_layout_segment *lseg, *tmp;
+       unsigned long *bitlock = &NFS_I(data->args.inode)->flags;
 
        pnfs_cleanup_layoutcommit(data);
        /* Matched by references in pnfs_set_layoutcommit */
@@ -5959,6 +5960,11 @@ static void nfs4_layoutcommit_release(void *calldata)
                                       &lseg->pls_flags))
                        put_lseg(lseg);
        }
+
+       clear_bit_unlock(NFS_INO_LAYOUTCOMMITTING, bitlock);
+       smp_mb__after_clear_bit();
+       wake_up_bit(bitlock, NFS_INO_LAYOUTCOMMITTING);
+
        put_rpccred(data->cred);
        kfree(data);
 }
index 1dce12f..e6161b2 100644 (file)
@@ -6602,8 +6602,6 @@ static int nfs4_xdr_dec_secinfo(struct rpc_rqst *rqstp,
        if (status)
                goto out;
        status = decode_secinfo(xdr, res);
-       if (status)
-               goto out;
 out:
        return status;
 }
index d0cda12..c807ab9 100644 (file)
  */
 
 #include <linux/module.h>
-#include <scsi/osd_initiator.h>
+#include <scsi/osd_ore.h>
 
 #include "objlayout.h"
 
 #define NFSDBG_FACILITY         NFSDBG_PNFS_LD
 
-#define _LLU(x) ((unsigned long long)x)
-
-enum { BIO_MAX_PAGES_KMALLOC =
-               (PAGE_SIZE - sizeof(struct bio)) / sizeof(struct bio_vec),
-};
-
 struct objio_dev_ent {
        struct nfs4_deviceid_node id_node;
-       struct osd_dev *od;
+       struct ore_dev od;
 };
 
 static void
@@ -60,8 +54,8 @@ objio_free_deviceid_node(struct nfs4_deviceid_node *d)
 {
        struct objio_dev_ent *de = container_of(d, struct objio_dev_ent, id_node);
 
-       dprintk("%s: free od=%p\n", __func__, de->od);
-       osduld_put_device(de->od);
+       dprintk("%s: free od=%p\n", __func__, de->od.od);
+       osduld_put_device(de->od.od);
        kfree(de);
 }
 
@@ -98,12 +92,12 @@ _dev_list_add(const struct nfs_server *nfss,
                                nfss->pnfs_curr_ld,
                                nfss->nfs_client,
                                d_id);
-       de->od = od;
+       de->od.od = od;
 
        d = nfs4_insert_deviceid_node(&de->id_node);
        n = container_of(d, struct objio_dev_ent, id_node);
        if (n != de) {
-               dprintk("%s: Race with other n->od=%p\n", __func__, n->od);
+               dprintk("%s: Race with other n->od=%p\n", __func__, n->od.od);
                objio_free_deviceid_node(&de->id_node);
                de = n;
        }
@@ -111,28 +105,11 @@ _dev_list_add(const struct nfs_server *nfss,
        return de;
 }
 
-struct caps_buffers {
-       u8 caps_key[OSD_CRYPTO_KEYID_SIZE];
-       u8 creds[OSD_CAP_LEN];
-};
-
 struct objio_segment {
        struct pnfs_layout_segment lseg;
 
-       struct pnfs_osd_object_cred *comps;
-
-       unsigned mirrors_p1;
-       unsigned stripe_unit;
-       unsigned group_width;   /* Data stripe_units without integrity comps */
-       u64 group_depth;
-       unsigned group_count;
-
-       unsigned max_io_size;
-
-       unsigned comps_index;
-       unsigned num_comps;
-       /* variable length */
-       struct objio_dev_ent *ods[];
+       struct ore_layout layout;
+       struct ore_components oc;
 };
 
 static inline struct objio_segment *
@@ -141,59 +118,44 @@ OBJIO_LSEG(struct pnfs_layout_segment *lseg)
        return container_of(lseg, struct objio_segment, lseg);
 }
 
-struct objio_state;
-typedef ssize_t (*objio_done_fn)(struct objio_state *ios);
-
 struct objio_state {
        /* Generic layer */
-       struct objlayout_io_state ol_state;
-
-       struct objio_segment *layout;
-
-       struct kref kref;
-       objio_done_fn done;
-       void *private;
-
-       unsigned long length;
-       unsigned numdevs; /* Actually used devs in this IO */
-       /* A per-device variable array of size numdevs */
-       struct _objio_per_comp {
-               struct bio *bio;
-               struct osd_request *or;
-               unsigned long length;
-               u64 offset;
-               unsigned dev;
-       } per_dev[];
+       struct objlayout_io_res oir;
+
+       bool sync;
+       /*FIXME: Support for extra_bytes at ore_get_rw_state() */
+       struct ore_io_state *ios;
 };
 
 /* Send and wait for a get_device_info of devices in the layout,
    then look them up with the osd_initiator library */
-static struct objio_dev_ent *_device_lookup(struct pnfs_layout_hdr *pnfslay,
-                               struct objio_segment *objio_seg, unsigned comp,
-                               gfp_t gfp_flags)
+static int objio_devices_lookup(struct pnfs_layout_hdr *pnfslay,
+       struct objio_segment *objio_seg, unsigned c, struct nfs4_deviceid *d_id,
+       gfp_t gfp_flags)
 {
        struct pnfs_osd_deviceaddr *deviceaddr;
-       struct nfs4_deviceid *d_id;
        struct objio_dev_ent *ode;
        struct osd_dev *od;
        struct osd_dev_info odi;
        int err;
 
-       d_id = &objio_seg->comps[comp].oc_object_id.oid_device_id;
-
        ode = _dev_list_find(NFS_SERVER(pnfslay->plh_inode), d_id);
-       if (ode)
-               return ode;
+       if (ode) {
+               objio_seg->oc.ods[c] = &ode->od; /* must use container_of */
+               return 0;
+       }
 
        err = objlayout_get_deviceinfo(pnfslay, d_id, &deviceaddr, gfp_flags);
        if (unlikely(err)) {
                dprintk("%s: objlayout_get_deviceinfo dev(%llx:%llx) =>%d\n",
                        __func__, _DEVID_LO(d_id), _DEVID_HI(d_id), err);
-               return ERR_PTR(err);
+               return err;
        }
 
        odi.systemid_len = deviceaddr->oda_systemid.len;
        if (odi.systemid_len > sizeof(odi.systemid)) {
+               dprintk("%s: odi.systemid_len > sizeof(systemid=%zd)\n",
+                       __func__, sizeof(odi.systemid));
                err = -EINVAL;
                goto out;
        } else if (odi.systemid_len)
@@ -218,96 +180,53 @@ static struct objio_dev_ent *_device_lookup(struct pnfs_layout_hdr *pnfslay,
 
        ode = _dev_list_add(NFS_SERVER(pnfslay->plh_inode), d_id, od,
                            gfp_flags);
-
+       objio_seg->oc.ods[c] = &ode->od; /* must use container_of */
+       dprintk("Adding new dev_id(%llx:%llx)\n",
+               _DEVID_LO(d_id), _DEVID_HI(d_id));
 out:
-       dprintk("%s: return=%d\n", __func__, err);
        objlayout_put_deviceinfo(deviceaddr);
-       return err ? ERR_PTR(err) : ode;
+       return err;
 }
 
-static int objio_devices_lookup(struct pnfs_layout_hdr *pnfslay,
-       struct objio_segment *objio_seg,
-       gfp_t gfp_flags)
+static void copy_single_comp(struct ore_components *oc, unsigned c,
+                            struct pnfs_osd_object_cred *src_comp)
 {
-       unsigned i;
-       int err;
+       struct ore_comp *ocomp = &oc->comps[c];
 
-       /* lookup all devices */
-       for (i = 0; i < objio_seg->num_comps; i++) {
-               struct objio_dev_ent *ode;
+       WARN_ON(src_comp->oc_cap_key.cred_len > 0); /* libosd is NO_SEC only */
+       WARN_ON(src_comp->oc_cap.cred_len > sizeof(ocomp->cred));
 
-               ode = _device_lookup(pnfslay, objio_seg, i, gfp_flags);
-               if (unlikely(IS_ERR(ode))) {
-                       err = PTR_ERR(ode);
-                       goto out;
-               }
-               objio_seg->ods[i] = ode;
-       }
-       err = 0;
+       ocomp->obj.partition = src_comp->oc_object_id.oid_partition_id;
+       ocomp->obj.id = src_comp->oc_object_id.oid_object_id;
 
-out:
-       dprintk("%s: return=%d\n", __func__, err);
-       return err;
+       memcpy(ocomp->cred, src_comp->oc_cap.cred, sizeof(ocomp->cred));
 }
 
-static int _verify_data_map(struct pnfs_osd_layout *layout)
+int __alloc_objio_seg(unsigned numdevs, gfp_t gfp_flags,
+                      struct objio_segment **pseg)
 {
-       struct pnfs_osd_data_map *data_map = &layout->olo_map;
-       u64 stripe_length;
-       u32 group_width;
-
-/* FIXME: Only raid0 for now. if not go through MDS */
-       if (data_map->odm_raid_algorithm != PNFS_OSD_RAID_0) {
-               printk(KERN_ERR "Only RAID_0 for now\n");
-               return -ENOTSUPP;
-       }
-       if (0 != (data_map->odm_num_comps % (data_map->odm_mirror_cnt + 1))) {
-               printk(KERN_ERR "Data Map wrong, num_comps=%u mirrors=%u\n",
-                         data_map->odm_num_comps, data_map->odm_mirror_cnt);
-               return -EINVAL;
-       }
+       struct __alloc_objio_segment {
+               struct objio_segment olseg;
+               struct ore_dev *ods[numdevs];
+               struct ore_comp comps[numdevs];
+       } *aolseg;
 
-       if (data_map->odm_group_width)
-               group_width = data_map->odm_group_width;
-       else
-               group_width = data_map->odm_num_comps /
-                                               (data_map->odm_mirror_cnt + 1);
-
-       stripe_length = (u64)data_map->odm_stripe_unit * group_width;
-       if (stripe_length >= (1ULL << 32)) {
-               printk(KERN_ERR "Total Stripe length(0x%llx)"
-                         " >= 32bit is not supported\n", _LLU(stripe_length));
-               return -ENOTSUPP;
+       aolseg = kzalloc(sizeof(*aolseg), gfp_flags);
+       if (unlikely(!aolseg)) {
+               dprintk("%s: Faild allocation numdevs=%d size=%zd\n", __func__,
+                       numdevs, sizeof(*aolseg));
+               return -ENOMEM;
        }
 
-       if (0 != (data_map->odm_stripe_unit & ~PAGE_MASK)) {
-               printk(KERN_ERR "Stripe Unit(0x%llx)"
-                         " must be Multples of PAGE_SIZE(0x%lx)\n",
-                         _LLU(data_map->odm_stripe_unit), PAGE_SIZE);
-               return -ENOTSUPP;
-       }
+       aolseg->olseg.oc.numdevs = numdevs;
+       aolseg->olseg.oc.single_comp = EC_MULTPLE_COMPS;
+       aolseg->olseg.oc.comps = aolseg->comps;
+       aolseg->olseg.oc.ods = aolseg->ods;
 
+       *pseg = &aolseg->olseg;
        return 0;
 }
 
-static void copy_single_comp(struct pnfs_osd_object_cred *cur_comp,
-                            struct pnfs_osd_object_cred *src_comp,
-                            struct caps_buffers *caps_p)
-{
-       WARN_ON(src_comp->oc_cap_key.cred_len > sizeof(caps_p->caps_key));
-       WARN_ON(src_comp->oc_cap.cred_len > sizeof(caps_p->creds));
-
-       *cur_comp = *src_comp;
-
-       memcpy(caps_p->caps_key, src_comp->oc_cap_key.cred,
-              sizeof(caps_p->caps_key));
-       cur_comp->oc_cap_key.cred = caps_p->caps_key;
-
-       memcpy(caps_p->creds, src_comp->oc_cap.cred,
-              sizeof(caps_p->creds));
-       cur_comp->oc_cap.cred = caps_p->creds;
-}
-
 int objio_alloc_lseg(struct pnfs_layout_segment **outp,
        struct pnfs_layout_hdr *pnfslay,
        struct pnfs_layout_range *range,
@@ -317,59 +236,43 @@ int objio_alloc_lseg(struct pnfs_layout_segment **outp,
        struct objio_segment *objio_seg;
        struct pnfs_osd_xdr_decode_layout_iter iter;
        struct pnfs_osd_layout layout;
-       struct pnfs_osd_object_cred *cur_comp, src_comp;
-       struct caps_buffers *caps_p;
+       struct pnfs_osd_object_cred src_comp;
+       unsigned cur_comp;
        int err;
 
        err = pnfs_osd_xdr_decode_layout_map(&layout, &iter, xdr);
        if (unlikely(err))
                return err;
 
-       err = _verify_data_map(&layout);
+       err = __alloc_objio_seg(layout.olo_num_comps, gfp_flags, &objio_seg);
        if (unlikely(err))
                return err;
 
-       objio_seg = kzalloc(sizeof(*objio_seg) +
-                           sizeof(objio_seg->ods[0]) * layout.olo_num_comps +
-                           sizeof(*objio_seg->comps) * layout.olo_num_comps +
-                           sizeof(struct caps_buffers) * layout.olo_num_comps,
-                           gfp_flags);
-       if (!objio_seg)
-               return -ENOMEM;
+       objio_seg->layout.stripe_unit = layout.olo_map.odm_stripe_unit;
+       objio_seg->layout.group_width = layout.olo_map.odm_group_width;
+       objio_seg->layout.group_depth = layout.olo_map.odm_group_depth;
+       objio_seg->layout.mirrors_p1 = layout.olo_map.odm_mirror_cnt + 1;
+       objio_seg->layout.raid_algorithm = layout.olo_map.odm_raid_algorithm;
 
-       objio_seg->comps = (void *)(objio_seg->ods + layout.olo_num_comps);
-       cur_comp = objio_seg->comps;
-       caps_p = (void *)(cur_comp + layout.olo_num_comps);
-       while (pnfs_osd_xdr_decode_layout_comp(&src_comp, &iter, xdr, &err))
-               copy_single_comp(cur_comp++, &src_comp, caps_p++);
+       err = ore_verify_layout(layout.olo_map.odm_num_comps,
+                                         &objio_seg->layout);
        if (unlikely(err))
                goto err;
 
-       objio_seg->num_comps = layout.olo_num_comps;
-       objio_seg->comps_index = layout.olo_comps_index;
-       err = objio_devices_lookup(pnfslay, objio_seg, gfp_flags);
-       if (err)
-               goto err;
-
-       objio_seg->mirrors_p1 = layout.olo_map.odm_mirror_cnt + 1;
-       objio_seg->stripe_unit = layout.olo_map.odm_stripe_unit;
-       if (layout.olo_map.odm_group_width) {
-               objio_seg->group_width = layout.olo_map.odm_group_width;
-               objio_seg->group_depth = layout.olo_map.odm_group_depth;
-               objio_seg->group_count = layout.olo_map.odm_num_comps /
-                                               objio_seg->mirrors_p1 /
-                                               objio_seg->group_width;
-       } else {
-               objio_seg->group_width = layout.olo_map.odm_num_comps /
-                                               objio_seg->mirrors_p1;
-               objio_seg->group_depth = -1;
-               objio_seg->group_count = 1;
+       objio_seg->oc.first_dev = layout.olo_comps_index;
+       cur_comp = 0;
+       while (pnfs_osd_xdr_decode_layout_comp(&src_comp, &iter, xdr, &err)) {
+               copy_single_comp(&objio_seg->oc, cur_comp, &src_comp);
+               err = objio_devices_lookup(pnfslay, objio_seg, cur_comp,
+                                          &src_comp.oc_object_id.oid_device_id,
+                                          gfp_flags);
+               if (err)
+                       goto err;
+               ++cur_comp;
        }
-
-       /* Cache this calculation it will hit for every page */
-       objio_seg->max_io_size = (BIO_MAX_PAGES_KMALLOC * PAGE_SIZE -
-                                 objio_seg->stripe_unit) *
-                                objio_seg->group_width;
+       /* pnfs_osd_xdr_decode_layout_comp returns false on error */
+       if (unlikely(err))
+               goto err;
 
        *outp = &objio_seg->lseg;
        return 0;
@@ -386,43 +289,63 @@ void objio_free_lseg(struct pnfs_layout_segment *lseg)
        int i;
        struct objio_segment *objio_seg = OBJIO_LSEG(lseg);
 
-       for (i = 0; i < objio_seg->num_comps; i++) {
-               if (!objio_seg->ods[i])
+       for (i = 0; i < objio_seg->oc.numdevs; i++) {
+               struct ore_dev *od = objio_seg->oc.ods[i];
+               struct objio_dev_ent *ode;
+
+               if (!od)
                        break;
-               nfs4_put_deviceid_node(&objio_seg->ods[i]->id_node);
+               ode = container_of(od, typeof(*ode), od);
+               nfs4_put_deviceid_node(&ode->id_node);
        }
        kfree(objio_seg);
 }
 
-int objio_alloc_io_state(struct pnfs_layout_segment *lseg,
-                        struct objlayout_io_state **outp,
-                        gfp_t gfp_flags)
+static int
+objio_alloc_io_state(struct pnfs_layout_hdr *pnfs_layout_type, bool is_reading,
+       struct pnfs_layout_segment *lseg, struct page **pages, unsigned pgbase,
+       loff_t offset, size_t count, void *rpcdata, gfp_t gfp_flags,
+       struct objio_state **outp)
 {
        struct objio_segment *objio_seg = OBJIO_LSEG(lseg);
-       struct objio_state *ios;
-       const unsigned first_size = sizeof(*ios) +
-                               objio_seg->num_comps * sizeof(ios->per_dev[0]);
-       const unsigned sec_size = objio_seg->num_comps *
-                                               sizeof(ios->ol_state.ioerrs[0]);
-
-       ios = kzalloc(first_size + sec_size, gfp_flags);
-       if (unlikely(!ios))
+       struct ore_io_state *ios;
+       int ret;
+       struct __alloc_objio_state {
+               struct objio_state objios;
+               struct pnfs_osd_ioerr ioerrs[objio_seg->oc.numdevs];
+       } *aos;
+
+       aos = kzalloc(sizeof(*aos), gfp_flags);
+       if (unlikely(!aos))
                return -ENOMEM;
 
-       ios->layout = objio_seg;
-       ios->ol_state.ioerrs = ((void *)ios) + first_size;
-       ios->ol_state.num_comps = objio_seg->num_comps;
+       objlayout_init_ioerrs(&aos->objios.oir, objio_seg->oc.numdevs,
+                       aos->ioerrs, rpcdata, pnfs_layout_type);
 
-       *outp = &ios->ol_state;
+       ret = ore_get_rw_state(&objio_seg->layout, &objio_seg->oc, is_reading,
+                              offset, count, &ios);
+       if (unlikely(ret)) {
+               kfree(aos);
+               return ret;
+       }
+
+       ios->pages = pages;
+       ios->pgbase = pgbase;
+       ios->private = aos;
+       BUG_ON(ios->nr_pages > (pgbase + count + PAGE_SIZE - 1) >> PAGE_SHIFT);
+
+       aos->objios.sync = 0;
+       aos->objios.ios = ios;
+       *outp = &aos->objios;
        return 0;
 }
 
-void objio_free_io_state(struct objlayout_io_state *ol_state)
+void objio_free_result(struct objlayout_io_res *oir)
 {
-       struct objio_state *ios = container_of(ol_state, struct objio_state,
-                                              ol_state);
+       struct objio_state *objios = container_of(oir, struct objio_state, oir);
 
-       kfree(ios);
+       ore_put_io_state(objios->ios);
+       kfree(objios);
 }
 
 enum pnfs_osd_errno osd_pri_2_pnfs_err(enum osd_err_priority oep)
@@ -455,539 +378,152 @@ enum pnfs_osd_errno osd_pri_2_pnfs_err(enum osd_err_priority oep)
        }
 }
 
-static void _clear_bio(struct bio *bio)
+static void __on_dev_error(struct ore_io_state *ios,
+       struct ore_dev *od, unsigned dev_index, enum osd_err_priority oep,
+       u64 dev_offset, u64  dev_len)
 {
-       struct bio_vec *bv;
-       unsigned i;
-
-       __bio_for_each_segment(bv, bio, i, 0) {
-               unsigned this_count = bv->bv_len;
-
-               if (likely(PAGE_SIZE == this_count))
-                       clear_highpage(bv->bv_page);
-               else
-                       zero_user(bv->bv_page, bv->bv_offset, this_count);
-       }
-}
-
-static int _io_check(struct objio_state *ios, bool is_write)
-{
-       enum osd_err_priority oep = OSD_ERR_PRI_NO_ERROR;
-       int lin_ret = 0;
-       int i;
-
-       for (i = 0; i <  ios->numdevs; i++) {
-               struct osd_sense_info osi;
-               struct osd_request *or = ios->per_dev[i].or;
-               int ret;
-
-               if (!or)
-                       continue;
+       struct objio_state *objios = ios->private;
+       struct pnfs_osd_objid pooid;
+       struct objio_dev_ent *ode = container_of(od, typeof(*ode), od);
+       /* FIXME: what to do with more-then-one-group layouts. We need to
+        * translate from ore_io_state index to oc->comps index
+        */
+       unsigned comp = dev_index;
 
-               ret = osd_req_decode_sense(or, &osi);
-               if (likely(!ret))
-                       continue;
+       pooid.oid_device_id = ode->id_node.deviceid;
+       pooid.oid_partition_id = ios->oc->comps[comp].obj.partition;
+       pooid.oid_object_id = ios->oc->comps[comp].obj.id;
 
-               if (OSD_ERR_PRI_CLEAR_PAGES == osi.osd_err_pri) {
-                       /* start read offset passed endof file */
-                       BUG_ON(is_write);
-                       _clear_bio(ios->per_dev[i].bio);
-                       dprintk("%s: start read offset passed end of file "
-                               "offset=0x%llx, length=0x%lx\n", __func__,
-                               _LLU(ios->per_dev[i].offset),
-                               ios->per_dev[i].length);
-
-                       continue; /* we recovered */
-               }
-               objlayout_io_set_result(&ios->ol_state, i,
-                                       &ios->layout->comps[i].oc_object_id,
-                                       osd_pri_2_pnfs_err(osi.osd_err_pri),
-                                       ios->per_dev[i].offset,
-                                       ios->per_dev[i].length,
-                                       is_write);
-
-               if (osi.osd_err_pri >= oep) {
-                       oep = osi.osd_err_pri;
-                       lin_ret = ret;
-               }
-       }
-
-       return lin_ret;
-}
-
-/*
- * Common IO state helpers.
- */
-static void _io_free(struct objio_state *ios)
-{
-       unsigned i;
-
-       for (i = 0; i < ios->numdevs; i++) {
-               struct _objio_per_comp *per_dev = &ios->per_dev[i];
-
-               if (per_dev->or) {
-                       osd_end_request(per_dev->or);
-                       per_dev->or = NULL;
-               }
-
-               if (per_dev->bio) {
-                       bio_put(per_dev->bio);
-                       per_dev->bio = NULL;
-               }
-       }
-}
-
-struct osd_dev *_io_od(struct objio_state *ios, unsigned dev)
-{
-       unsigned min_dev = ios->layout->comps_index;
-       unsigned max_dev = min_dev + ios->layout->num_comps;
-
-       BUG_ON(dev < min_dev || max_dev <= dev);
-       return ios->layout->ods[dev - min_dev]->od;
-}
-
-struct _striping_info {
-       u64 obj_offset;
-       u64 group_length;
-       unsigned dev;
-       unsigned unit_off;
-};
-
-static void _calc_stripe_info(struct objio_state *ios, u64 file_offset,
-                             struct _striping_info *si)
-{
-       u32     stripe_unit = ios->layout->stripe_unit;
-       u32     group_width = ios->layout->group_width;
-       u64     group_depth = ios->layout->group_depth;
-       u32     U = stripe_unit * group_width;
-
-       u64     T = U * group_depth;
-       u64     S = T * ios->layout->group_count;
-       u64     M = div64_u64(file_offset, S);
-
-       /*
-       G = (L - (M * S)) / T
-       H = (L - (M * S)) % T
-       */
-       u64     LmodU = file_offset - M * S;
-       u32     G = div64_u64(LmodU, T);
-       u64     H = LmodU - G * T;
-
-       u32     N = div_u64(H, U);
-
-       div_u64_rem(file_offset, stripe_unit, &si->unit_off);
-       si->obj_offset = si->unit_off + (N * stripe_unit) +
-                                 (M * group_depth * stripe_unit);
-
-       /* "H - (N * U)" is just "H % U" so it's bound to u32 */
-       si->dev = (u32)(H - (N * U)) / stripe_unit + G * group_width;
-       si->dev *= ios->layout->mirrors_p1;
-
-       si->group_length = T - H;
-}
-
-static int _add_stripe_unit(struct objio_state *ios,  unsigned *cur_pg,
-               unsigned pgbase, struct _objio_per_comp *per_dev, int len,
-               gfp_t gfp_flags)
-{
-       unsigned pg = *cur_pg;
-       int cur_len = len;
-       struct request_queue *q =
-                       osd_request_queue(_io_od(ios, per_dev->dev));
-
-       if (per_dev->bio == NULL) {
-               unsigned pages_in_stripe = ios->layout->group_width *
-                                     (ios->layout->stripe_unit / PAGE_SIZE);
-               unsigned bio_size = (ios->ol_state.nr_pages + pages_in_stripe) /
-                                   ios->layout->group_width;
-
-               if (BIO_MAX_PAGES_KMALLOC < bio_size)
-                       bio_size = BIO_MAX_PAGES_KMALLOC;
-
-               per_dev->bio = bio_kmalloc(gfp_flags, bio_size);
-               if (unlikely(!per_dev->bio)) {
-                       dprintk("Faild to allocate BIO size=%u\n", bio_size);
-                       return -ENOMEM;
-               }
-       }
-
-       while (cur_len > 0) {
-               unsigned pglen = min_t(unsigned, PAGE_SIZE - pgbase, cur_len);
-               unsigned added_len;
-
-               BUG_ON(ios->ol_state.nr_pages <= pg);
-               cur_len -= pglen;
-
-               added_len = bio_add_pc_page(q, per_dev->bio,
-                                       ios->ol_state.pages[pg], pglen, pgbase);
-               if (unlikely(pglen != added_len))
-                       return -ENOMEM;
-               pgbase = 0;
-               ++pg;
-       }
-       BUG_ON(cur_len);
-
-       per_dev->length += len;
-       *cur_pg = pg;
-       return 0;
-}
-
-static int _prepare_one_group(struct objio_state *ios, u64 length,
-                             struct _striping_info *si, unsigned *last_pg,
-                             gfp_t gfp_flags)
-{
-       unsigned stripe_unit = ios->layout->stripe_unit;
-       unsigned mirrors_p1 = ios->layout->mirrors_p1;
-       unsigned devs_in_group = ios->layout->group_width * mirrors_p1;
-       unsigned dev = si->dev;
-       unsigned first_dev = dev - (dev % devs_in_group);
-       unsigned max_comp = ios->numdevs ? ios->numdevs - mirrors_p1 : 0;
-       unsigned cur_pg = *last_pg;
-       int ret = 0;
-
-       while (length) {
-               struct _objio_per_comp *per_dev = &ios->per_dev[dev - first_dev];
-               unsigned cur_len, page_off = 0;
-
-               if (!per_dev->length) {
-                       per_dev->dev = dev;
-                       if (dev < si->dev) {
-                               per_dev->offset = si->obj_offset + stripe_unit -
-                                                                  si->unit_off;
-                               cur_len = stripe_unit;
-                       } else if (dev == si->dev) {
-                               per_dev->offset = si->obj_offset;
-                               cur_len = stripe_unit - si->unit_off;
-                               page_off = si->unit_off & ~PAGE_MASK;
-                               BUG_ON(page_off &&
-                                     (page_off != ios->ol_state.pgbase));
-                       } else { /* dev > si->dev */
-                               per_dev->offset = si->obj_offset - si->unit_off;
-                               cur_len = stripe_unit;
-                       }
-
-                       if (max_comp < dev - first_dev)
-                               max_comp = dev - first_dev;
-               } else {
-                       cur_len = stripe_unit;
-               }
-               if (cur_len >= length)
-                       cur_len = length;
-
-               ret = _add_stripe_unit(ios, &cur_pg, page_off , per_dev,
-                                      cur_len, gfp_flags);
-               if (unlikely(ret))
-                       goto out;
-
-               dev += mirrors_p1;
-               dev = (dev % devs_in_group) + first_dev;
-
-               length -= cur_len;
-               ios->length += cur_len;
-       }
-out:
-       ios->numdevs = max_comp + mirrors_p1;
-       *last_pg = cur_pg;
-       return ret;
-}
-
-static int _io_rw_pagelist(struct objio_state *ios, gfp_t gfp_flags)
-{
-       u64 length = ios->ol_state.count;
-       u64 offset = ios->ol_state.offset;
-       struct _striping_info si;
-       unsigned last_pg = 0;
-       int ret = 0;
-
-       while (length) {
-               _calc_stripe_info(ios, offset, &si);
-
-               if (length < si.group_length)
-                       si.group_length = length;
-
-               ret = _prepare_one_group(ios, si.group_length, &si, &last_pg, gfp_flags);
-               if (unlikely(ret))
-                       goto out;
-
-               offset += si.group_length;
-               length -= si.group_length;
-       }
-
-out:
-       if (!ios->length)
-               return ret;
-
-       return 0;
-}
-
-static ssize_t _sync_done(struct objio_state *ios)
-{
-       struct completion *waiting = ios->private;
-
-       complete(waiting);
-       return 0;
-}
-
-static void _last_io(struct kref *kref)
-{
-       struct objio_state *ios = container_of(kref, struct objio_state, kref);
-
-       ios->done(ios);
-}
-
-static void _done_io(struct osd_request *or, void *p)
-{
-       struct objio_state *ios = p;
-
-       kref_put(&ios->kref, _last_io);
-}
-
-static ssize_t _io_exec(struct objio_state *ios)
-{
-       DECLARE_COMPLETION_ONSTACK(wait);
-       ssize_t status = 0; /* sync status */
-       unsigned i;
-       objio_done_fn saved_done_fn = ios->done;
-       bool sync = ios->ol_state.sync;
-
-       if (sync) {
-               ios->done = _sync_done;
-               ios->private = &wait;
-       }
-
-       kref_init(&ios->kref);
-
-       for (i = 0; i < ios->numdevs; i++) {
-               struct osd_request *or = ios->per_dev[i].or;
-
-               if (!or)
-                       continue;
-
-               kref_get(&ios->kref);
-               osd_execute_request_async(or, _done_io, ios);
-       }
-
-       kref_put(&ios->kref, _last_io);
-
-       if (sync) {
-               wait_for_completion(&wait);
-               status = saved_done_fn(ios);
-       }
-
-       return status;
+       objlayout_io_set_result(&objios->oir, comp,
+                               &pooid, osd_pri_2_pnfs_err(oep),
+                               dev_offset, dev_len, !ios->reading);
 }
 
 /*
  * read
  */
-static ssize_t _read_done(struct objio_state *ios)
+static void _read_done(struct ore_io_state *ios, void *private)
 {
+       struct objio_state *objios = private;
        ssize_t status;
-       int ret = _io_check(ios, false);
+       int ret = ore_check_io(ios, &__on_dev_error);
 
-       _io_free(ios);
+       /* FIXME: _io_free(ios) can we dealocate the libosd resources; */
 
        if (likely(!ret))
                status = ios->length;
        else
                status = ret;
 
-       objlayout_read_done(&ios->ol_state, status, ios->ol_state.sync);
-       return status;
+       objlayout_read_done(&objios->oir, status, objios->sync);
 }
 
-static int _read_mirrors(struct objio_state *ios, unsigned cur_comp)
+int objio_read_pagelist(struct nfs_read_data *rdata)
 {
-       struct osd_request *or = NULL;
-       struct _objio_per_comp *per_dev = &ios->per_dev[cur_comp];
-       unsigned dev = per_dev->dev;
-       struct pnfs_osd_object_cred *cred =
-                       &ios->layout->comps[cur_comp];
-       struct osd_obj_id obj = {
-               .partition = cred->oc_object_id.oid_partition_id,
-               .id = cred->oc_object_id.oid_object_id,
-       };
+       struct objio_state *objios;
        int ret;
 
-       or = osd_start_request(_io_od(ios, dev), GFP_KERNEL);
-       if (unlikely(!or)) {
-               ret = -ENOMEM;
-               goto err;
-       }
-       per_dev->or = or;
-
-       osd_req_read(or, &obj, per_dev->offset, per_dev->bio, per_dev->length);
-
-       ret = osd_finalize_request(or, 0, cred->oc_cap.cred, NULL);
-       if (ret) {
-               dprintk("%s: Faild to osd_finalize_request() => %d\n",
-                       __func__, ret);
-               goto err;
-       }
-
-       dprintk("%s:[%d] dev=%d obj=0x%llx start=0x%llx length=0x%lx\n",
-               __func__, cur_comp, dev, obj.id, _LLU(per_dev->offset),
-               per_dev->length);
-
-err:
-       return ret;
-}
-
-static ssize_t _read_exec(struct objio_state *ios)
-{
-       unsigned i;
-       int ret;
-
-       for (i = 0; i < ios->numdevs; i += ios->layout->mirrors_p1) {
-               if (!ios->per_dev[i].length)
-                       continue;
-               ret = _read_mirrors(ios, i);
-               if (unlikely(ret))
-                       goto err;
-       }
-
-       ios->done = _read_done;
-       return _io_exec(ios); /* In sync mode exec returns the io status */
-
-err:
-       _io_free(ios);
-       return ret;
-}
-
-ssize_t objio_read_pagelist(struct objlayout_io_state *ol_state)
-{
-       struct objio_state *ios = container_of(ol_state, struct objio_state,
-                                              ol_state);
-       int ret;
-
-       ret = _io_rw_pagelist(ios, GFP_KERNEL);
+       ret = objio_alloc_io_state(NFS_I(rdata->inode)->layout, true,
+                       rdata->lseg, rdata->args.pages, rdata->args.pgbase,
+                       rdata->args.offset, rdata->args.count, rdata,
+                       GFP_KERNEL, &objios);
        if (unlikely(ret))
                return ret;
 
-       return _read_exec(ios);
+       objios->ios->done = _read_done;
+       dprintk("%s: offset=0x%llx length=0x%x\n", __func__,
+               rdata->args.offset, rdata->args.count);
+       return ore_read(objios->ios);
 }
 
 /*
  * write
  */
-static ssize_t _write_done(struct objio_state *ios)
+static void _write_done(struct ore_io_state *ios, void *private)
 {
+       struct objio_state *objios = private;
        ssize_t status;
-       int ret = _io_check(ios, true);
+       int ret = ore_check_io(ios, &__on_dev_error);
 
-       _io_free(ios);
+       /* FIXME: _io_free(ios) can we dealocate the libosd resources; */
 
        if (likely(!ret)) {
                /* FIXME: should be based on the OSD's persistence model
                 * See OSD2r05 Section 4.13 Data persistence model */
-               ios->ol_state.committed = NFS_FILE_SYNC;
+               objios->oir.committed = NFS_FILE_SYNC;
                status = ios->length;
        } else {
                status = ret;
        }
 
-       objlayout_write_done(&ios->ol_state, status, ios->ol_state.sync);
-       return status;
+       objlayout_write_done(&objios->oir, status, objios->sync);
 }
 
-static int _write_mirrors(struct objio_state *ios, unsigned cur_comp)
+static struct page *__r4w_get_page(void *priv, u64 offset, bool *uptodate)
 {
-       struct _objio_per_comp *master_dev = &ios->per_dev[cur_comp];
-       unsigned dev = ios->per_dev[cur_comp].dev;
-       unsigned last_comp = cur_comp + ios->layout->mirrors_p1;
-       int ret;
-
-       for (; cur_comp < last_comp; ++cur_comp, ++dev) {
-               struct osd_request *or = NULL;
-               struct pnfs_osd_object_cred *cred =
-                                       &ios->layout->comps[cur_comp];
-               struct osd_obj_id obj = {
-                       .partition = cred->oc_object_id.oid_partition_id,
-                       .id = cred->oc_object_id.oid_object_id,
-               };
-               struct _objio_per_comp *per_dev = &ios->per_dev[cur_comp];
-               struct bio *bio;
-
-               or = osd_start_request(_io_od(ios, dev), GFP_NOFS);
-               if (unlikely(!or)) {
-                       ret = -ENOMEM;
-                       goto err;
-               }
-               per_dev->or = or;
-
-               if (per_dev != master_dev) {
-                       bio = bio_kmalloc(GFP_NOFS,
-                                         master_dev->bio->bi_max_vecs);
-                       if (unlikely(!bio)) {
-                               dprintk("Faild to allocate BIO size=%u\n",
-                                       master_dev->bio->bi_max_vecs);
-                               ret = -ENOMEM;
-                               goto err;
-                       }
-
-                       __bio_clone(bio, master_dev->bio);
-                       bio->bi_bdev = NULL;
-                       bio->bi_next = NULL;
-                       per_dev->bio = bio;
-                       per_dev->dev = dev;
-                       per_dev->length = master_dev->length;
-                       per_dev->offset =  master_dev->offset;
-               } else {
-                       bio = master_dev->bio;
-                       bio->bi_rw |= REQ_WRITE;
-               }
-
-               osd_req_write(or, &obj, per_dev->offset, bio, per_dev->length);
+       struct objio_state *objios = priv;
+       struct nfs_write_data *wdata = objios->oir.rpcdata;
+       pgoff_t index = offset / PAGE_SIZE;
+       struct page *page = find_get_page(wdata->inode->i_mapping, index);
 
-               ret = osd_finalize_request(or, 0, cred->oc_cap.cred, NULL);
-               if (ret) {
-                       dprintk("%s: Faild to osd_finalize_request() => %d\n",
-                               __func__, ret);
-                       goto err;
+       if (!page) {
+               page = find_or_create_page(wdata->inode->i_mapping,
+                                               index, GFP_NOFS);
+               if (unlikely(!page)) {
+                       dprintk("%s: grab_cache_page Failed index=0x%lx\n",
+                               __func__, index);
+                       return NULL;
                }
-
-               dprintk("%s:[%d] dev=%d obj=0x%llx start=0x%llx length=0x%lx\n",
-                       __func__, cur_comp, dev, obj.id, _LLU(per_dev->offset),
-                       per_dev->length);
+               unlock_page(page);
        }
+       if (PageDirty(page) || PageWriteback(page))
+               *uptodate = true;
+       else
+               *uptodate = PageUptodate(page);
+       dprintk("%s: index=0x%lx uptodate=%d\n", __func__, index, *uptodate);
+       return page;
+}
 
-err:
-       return ret;
+static void __r4w_put_page(void *priv, struct page *page)
+{
+       dprintk("%s: index=0x%lx\n", __func__, page->index);
+       page_cache_release(page);
+       return;
 }
 
-static ssize_t _write_exec(struct objio_state *ios)
+static const struct _ore_r4w_op _r4w_op = {
+       .get_page = &__r4w_get_page,
+       .put_page = &__r4w_put_page,
+};
+
+int objio_write_pagelist(struct nfs_write_data *wdata, int how)
 {
-       unsigned i;
+       struct objio_state *objios;
        int ret;
 
-       for (i = 0; i < ios->numdevs; i += ios->layout->mirrors_p1) {
-               if (!ios->per_dev[i].length)
-                       continue;
-               ret = _write_mirrors(ios, i);
-               if (unlikely(ret))
-                       goto err;
-       }
-
-       ios->done = _write_done;
-       return _io_exec(ios); /* In sync mode exec returns the io->status */
+       ret = objio_alloc_io_state(NFS_I(wdata->inode)->layout, false,
+                       wdata->lseg, wdata->args.pages, wdata->args.pgbase,
+                       wdata->args.offset, wdata->args.count, wdata, GFP_NOFS,
+                       &objios);
+       if (unlikely(ret))
+               return ret;
 
-err:
-       _io_free(ios);
-       return ret;
-}
+       objios->sync = 0 != (how & FLUSH_SYNC);
+       objios->ios->r4w = &_r4w_op;
 
-ssize_t objio_write_pagelist(struct objlayout_io_state *ol_state, bool stable)
-{
-       struct objio_state *ios = container_of(ol_state, struct objio_state,
-                                              ol_state);
-       int ret;
+       if (!objios->sync)
+               objios->ios->done = _write_done;
 
-       /* TODO: ios->stable = stable; */
-       ret = _io_rw_pagelist(ios, GFP_NOFS);
+       dprintk("%s: offset=0x%llx length=0x%x\n", __func__,
+               wdata->args.offset, wdata->args.count);
+       ret = ore_write(objios->ios);
        if (unlikely(ret))
                return ret;
 
-       return _write_exec(ios);
+       if (objios->sync)
+               _write_done(objios->ios, objios);
+
+       return 0;
 }
 
 static bool objio_pg_test(struct nfs_pageio_descriptor *pgio,
@@ -997,7 +533,7 @@ static bool objio_pg_test(struct nfs_pageio_descriptor *pgio,
                return false;
 
        return pgio->pg_count + req->wb_bytes <=
-                       OBJIO_LSEG(pgio->pg_lseg)->max_io_size;
+                       OBJIO_LSEG(pgio->pg_lseg)->layout.max_io_length;
 }
 
 static const struct nfs_pageio_ops objio_pg_read_ops = {
index 1d06f8e..72074e3 100644 (file)
@@ -156,77 +156,39 @@ last_byte_offset(u64 start, u64 len)
        return end > start ? end - 1 : NFS4_MAX_UINT64;
 }
 
-static struct objlayout_io_state *
-objlayout_alloc_io_state(struct pnfs_layout_hdr *pnfs_layout_type,
-                       struct page **pages,
-                       unsigned pgbase,
-                       loff_t offset,
-                       size_t count,
-                       struct pnfs_layout_segment *lseg,
-                       void *rpcdata,
-                       gfp_t gfp_flags)
+void _fix_verify_io_params(struct pnfs_layout_segment *lseg,
+                          struct page ***p_pages, unsigned *p_pgbase,
+                          u64 offset, unsigned long count)
 {
-       struct objlayout_io_state *state;
        u64 lseg_end_offset;
 
-       dprintk("%s: allocating io_state\n", __func__);
-       if (objio_alloc_io_state(lseg, &state, gfp_flags))
-               return NULL;
-
        BUG_ON(offset < lseg->pls_range.offset);
        lseg_end_offset = end_offset(lseg->pls_range.offset,
                                     lseg->pls_range.length);
        BUG_ON(offset >= lseg_end_offset);
-       if (offset + count > lseg_end_offset) {
-               count = lseg->pls_range.length -
-                               (offset - lseg->pls_range.offset);
-               dprintk("%s: truncated count %Zd\n", __func__, count);
-       }
+       WARN_ON(offset + count > lseg_end_offset);
 
-       if (pgbase > PAGE_SIZE) {
-               pages += pgbase >> PAGE_SHIFT;
-               pgbase &= ~PAGE_MASK;
+       if (*p_pgbase > PAGE_SIZE) {
+               dprintk("%s: pgbase(0x%x) > PAGE_SIZE\n", __func__, *p_pgbase);
+               *p_pages += *p_pgbase >> PAGE_SHIFT;
+               *p_pgbase &= ~PAGE_MASK;
        }
-
-       INIT_LIST_HEAD(&state->err_list);
-       state->lseg = lseg;
-       state->rpcdata = rpcdata;
-       state->pages = pages;
-       state->pgbase = pgbase;
-       state->nr_pages = (pgbase + count + PAGE_SIZE - 1) >> PAGE_SHIFT;
-       state->offset = offset;
-       state->count = count;
-       state->sync = 0;
-
-       return state;
-}
-
-static void
-objlayout_free_io_state(struct objlayout_io_state *state)
-{
-       dprintk("%s: freeing io_state\n", __func__);
-       if (unlikely(!state))
-               return;
-
-       objio_free_io_state(state);
 }
 
 /*
  * I/O done common code
  */
 static void
-objlayout_iodone(struct objlayout_io_state *state)
+objlayout_iodone(struct objlayout_io_res *oir)
 {
-       dprintk("%s: state %p status\n", __func__, state);
-
-       if (likely(state->status >= 0)) {
-               objlayout_free_io_state(state);
+       if (likely(oir->status >= 0)) {
+               objio_free_result(oir);
        } else {
-               struct objlayout *objlay = OBJLAYOUT(state->lseg->pls_layout);
+               struct objlayout *objlay = oir->objlay;
 
                spin_lock(&objlay->lock);
                objlay->delta_space_valid = OBJ_DSU_INVALID;
-               list_add(&objlay->err_list, &state->err_list);
+               list_add(&objlay->err_list, &oir->err_list);
                spin_unlock(&objlay->lock);
        }
 }
@@ -238,13 +200,13 @@ objlayout_iodone(struct objlayout_io_state *state)
  * the error for later reporting at layout-return.
  */
 void
-objlayout_io_set_result(struct objlayout_io_state *state, unsigned index,
+objlayout_io_set_result(struct objlayout_io_res *oir, unsigned index,
                        struct pnfs_osd_objid *pooid, int osd_error,
                        u64 offset, u64 length, bool is_write)
 {
-       struct pnfs_osd_ioerr *ioerr = &state->ioerrs[index];
+       struct pnfs_osd_ioerr *ioerr = &oir->ioerrs[index];
 
-       BUG_ON(index >= state->num_comps);
+       BUG_ON(index >= oir->num_comps);
        if (osd_error) {
                ioerr->oer_component = *pooid;
                ioerr->oer_comp_offset = offset;
@@ -285,21 +247,18 @@ static void _rpc_read_complete(struct work_struct *work)
 }
 
 void
-objlayout_read_done(struct objlayout_io_state *state, ssize_t status, bool sync)
+objlayout_read_done(struct objlayout_io_res *oir, ssize_t status, bool sync)
 {
-       int eof = state->eof;
-       struct nfs_read_data *rdata;
+       struct nfs_read_data *rdata = oir->rpcdata;
 
-       state->status = status;
-       dprintk("%s: Begin status=%zd eof=%d\n", __func__, status, eof);
-       rdata = state->rpcdata;
-       rdata->task.tk_status = status;
-       if (status >= 0) {
+       oir->status = rdata->task.tk_status = status;
+       if (status >= 0)
                rdata->res.count = status;
-               rdata->res.eof = eof;
-       }
-       objlayout_iodone(state);
-       /* must not use state after this point */
+       objlayout_iodone(oir);
+       /* must not use oir after this point */
+
+       dprintk("%s: Return status=%zd eof=%d sync=%d\n", __func__,
+               status, rdata->res.eof, sync);
 
        if (sync)
                pnfs_ld_read_done(rdata);
@@ -317,40 +276,36 @@ objlayout_read_pagelist(struct nfs_read_data *rdata)
 {
        loff_t offset = rdata->args.offset;
        size_t count = rdata->args.count;
-       struct objlayout_io_state *state;
-       ssize_t status = 0;
+       int err;
        loff_t eof;
 
-       dprintk("%s: Begin inode %p offset %llu count %d\n",
-               __func__, rdata->inode, offset, (int)count);
-
        eof = i_size_read(rdata->inode);
        if (unlikely(offset + count > eof)) {
                if (offset >= eof) {
-                       status = 0;
+                       err = 0;
                        rdata->res.count = 0;
                        rdata->res.eof = 1;
+                       /*FIXME: do we need to call pnfs_ld_read_done() */
                        goto out;
                }
                count = eof - offset;
        }
 
-       state = objlayout_alloc_io_state(NFS_I(rdata->inode)->layout,
-                                        rdata->args.pages, rdata->args.pgbase,
-                                        offset, count,
-                                        rdata->lseg, rdata,
-                                        GFP_KERNEL);
-       if (unlikely(!state)) {
-               status = -ENOMEM;
-               goto out;
-       }
+       rdata->res.eof = (offset + count) >= eof;
+       _fix_verify_io_params(rdata->lseg, &rdata->args.pages,
+                             &rdata->args.pgbase,
+                             rdata->args.offset, rdata->args.count);
 
-       state->eof = state->offset + state->count >= eof;
+       dprintk("%s: inode(%lx) offset 0x%llx count 0x%Zx eof=%d\n",
+               __func__, rdata->inode->i_ino, offset, count, rdata->res.eof);
 
-       status = objio_read_pagelist(state);
+       err = objio_read_pagelist(rdata);
  out:
-       dprintk("%s: Return status %Zd\n", __func__, status);
-       rdata->pnfs_error = status;
+       if (unlikely(err)) {
+               rdata->pnfs_error = err;
+               dprintk("%s: Returned Error %d\n", __func__, err);
+               return PNFS_NOT_ATTEMPTED;
+       }
        return PNFS_ATTEMPTED;
 }
 
@@ -371,26 +326,20 @@ static void _rpc_write_complete(struct work_struct *work)
 }
 
 void
-objlayout_write_done(struct objlayout_io_state *state, ssize_t status,
-                    bool sync)
+objlayout_write_done(struct objlayout_io_res *oir, ssize_t status, bool sync)
 {
-       struct nfs_write_data *wdata;
+       struct nfs_write_data *wdata = oir->rpcdata;
 
-       dprintk("%s: Begin\n", __func__);
-       wdata = state->rpcdata;
-       state->status = status;
-       wdata->task.tk_status = status;
+       oir->status = wdata->task.tk_status = status;
        if (status >= 0) {
                wdata->res.count = status;
-               wdata->verf.committed = state->committed;
-               dprintk("%s: Return status %d committed %d\n",
-                       __func__, wdata->task.tk_status,
-                       wdata->verf.committed);
-       } else
-               dprintk("%s: Return status %d\n",
-                       __func__, wdata->task.tk_status);
-       objlayout_iodone(state);
-       /* must not use state after this point */
+               wdata->verf.committed = oir->committed;
+       }
+       objlayout_iodone(oir);
+       /* must not use oir after this point */
+
+       dprintk("%s: Return status %zd committed %d sync=%d\n", __func__,
+               status, wdata->verf.committed, sync);
 
        if (sync)
                pnfs_ld_write_done(wdata);
@@ -407,30 +356,18 @@ enum pnfs_try_status
 objlayout_write_pagelist(struct nfs_write_data *wdata,
                         int how)
 {
-       struct objlayout_io_state *state;
-       ssize_t status;
-
-       dprintk("%s: Begin inode %p offset %llu count %u\n",
-               __func__, wdata->inode, wdata->args.offset, wdata->args.count);
-
-       state = objlayout_alloc_io_state(NFS_I(wdata->inode)->layout,
-                                        wdata->args.pages,
-                                        wdata->args.pgbase,
-                                        wdata->args.offset,
-                                        wdata->args.count,
-                                        wdata->lseg, wdata,
-                                        GFP_NOFS);
-       if (unlikely(!state)) {
-               status = -ENOMEM;
-               goto out;
-       }
+       int err;
 
-       state->sync = how & FLUSH_SYNC;
+       _fix_verify_io_params(wdata->lseg, &wdata->args.pages,
+                             &wdata->args.pgbase,
+                             wdata->args.offset, wdata->args.count);
 
-       status = objio_write_pagelist(state, how & FLUSH_STABLE);
- out:
-       dprintk("%s: Return status %Zd\n", __func__, status);
-       wdata->pnfs_error = status;
+       err = objio_write_pagelist(wdata, how);
+       if (unlikely(err)) {
+               wdata->pnfs_error = err;
+               dprintk("%s: Returned Error %d\n", __func__, err);
+               return PNFS_NOT_ATTEMPTED;
+       }
        return PNFS_ATTEMPTED;
 }
 
@@ -537,14 +474,14 @@ merge_ioerr(struct pnfs_osd_ioerr *dest_err,
 static void
 encode_accumulated_error(struct objlayout *objlay, __be32 *p)
 {
-       struct objlayout_io_state *state, *tmp;
+       struct objlayout_io_res *oir, *tmp;
        struct pnfs_osd_ioerr accumulated_err = {.oer_errno = 0};
 
-       list_for_each_entry_safe(state, tmp, &objlay->err_list, err_list) {
+       list_for_each_entry_safe(oir, tmp, &objlay->err_list, err_list) {
                unsigned i;
 
-               for (i = 0; i < state->num_comps; i++) {
-                       struct pnfs_osd_ioerr *ioerr = &state->ioerrs[i];
+               for (i = 0; i < oir->num_comps; i++) {
+                       struct pnfs_osd_ioerr *ioerr = &oir->ioerrs[i];
 
                        if (!ioerr->oer_errno)
                                continue;
@@ -563,8 +500,8 @@ encode_accumulated_error(struct objlayout *objlay, __be32 *p)
 
                        merge_ioerr(&accumulated_err, ioerr);
                }
-               list_del(&state->err_list);
-               objlayout_free_io_state(state);
+               list_del(&oir->err_list);
+               objio_free_result(oir);
        }
 
        pnfs_osd_xdr_encode_ioerr(p, &accumulated_err);
@@ -576,7 +513,7 @@ objlayout_encode_layoutreturn(struct pnfs_layout_hdr *pnfslay,
                              const struct nfs4_layoutreturn_args *args)
 {
        struct objlayout *objlay = OBJLAYOUT(pnfslay);
-       struct objlayout_io_state *state, *tmp;
+       struct objlayout_io_res *oir, *tmp;
        __be32 *start;
 
        dprintk("%s: Begin\n", __func__);
@@ -585,13 +522,13 @@ objlayout_encode_layoutreturn(struct pnfs_layout_hdr *pnfslay,
 
        spin_lock(&objlay->lock);
 
-       list_for_each_entry_safe(state, tmp, &objlay->err_list, err_list) {
+       list_for_each_entry_safe(oir, tmp, &objlay->err_list, err_list) {
                __be32 *last_xdr = NULL, *p;
                unsigned i;
                int res = 0;
 
-               for (i = 0; i < state->num_comps; i++) {
-                       struct pnfs_osd_ioerr *ioerr = &state->ioerrs[i];
+               for (i = 0; i < oir->num_comps; i++) {
+                       struct pnfs_osd_ioerr *ioerr = &oir->ioerrs[i];
 
                        if (!ioerr->oer_errno)
                                continue;
@@ -615,7 +552,7 @@ objlayout_encode_layoutreturn(struct pnfs_layout_hdr *pnfslay,
                        }
 
                        last_xdr = p;
-                       pnfs_osd_xdr_encode_ioerr(p, &state->ioerrs[i]);
+                       pnfs_osd_xdr_encode_ioerr(p, &oir->ioerrs[i]);
                }
 
                /* TODO: use xdr_write_pages */
@@ -631,8 +568,8 @@ objlayout_encode_layoutreturn(struct pnfs_layout_hdr *pnfslay,
                        encode_accumulated_error(objlay, last_xdr);
                        goto loop_done;
                }
-               list_del(&state->err_list);
-               objlayout_free_io_state(state);
+               list_del(&oir->err_list);
+               objio_free_result(oir);
        }
 loop_done:
        spin_unlock(&objlay->lock);
index a8244c8..8ec3472 100644 (file)
@@ -74,19 +74,11 @@ OBJLAYOUT(struct pnfs_layout_hdr *lo)
  * per-I/O operation state
  * embedded in objects provider io_state data structure
  */
-struct objlayout_io_state {
-       struct pnfs_layout_segment *lseg;
-
-       struct page **pages;
-       unsigned pgbase;
-       unsigned nr_pages;
-       unsigned long count;
-       loff_t offset;
-       bool sync;
+struct objlayout_io_res {
+       struct objlayout *objlay;
 
        void *rpcdata;
        int status;             /* res */
-       int eof;                /* res */
        int committed;          /* res */
 
        /* Error reporting (layout_return) */
@@ -100,6 +92,18 @@ struct objlayout_io_state {
        struct pnfs_osd_ioerr *ioerrs;
 };
 
+static inline
+void objlayout_init_ioerrs(struct objlayout_io_res *oir, unsigned num_comps,
+                       struct pnfs_osd_ioerr *ioerrs, void *rpcdata,
+                       struct pnfs_layout_hdr *pnfs_layout_type)
+{
+       oir->objlay = OBJLAYOUT(pnfs_layout_type);
+       oir->rpcdata = rpcdata;
+       INIT_LIST_HEAD(&oir->err_list);
+       oir->num_comps = num_comps;
+       oir->ioerrs = ioerrs;
+}
+
 /*
  * Raid engine I/O API
  */
@@ -110,28 +114,24 @@ extern int objio_alloc_lseg(struct pnfs_layout_segment **outp,
        gfp_t gfp_flags);
 extern void objio_free_lseg(struct pnfs_layout_segment *lseg);
 
-extern int objio_alloc_io_state(
-       struct pnfs_layout_segment *lseg,
-       struct objlayout_io_state **outp,
-       gfp_t gfp_flags);
-extern void objio_free_io_state(struct objlayout_io_state *state);
+/* objio_free_result will free these @oir structs recieved from
+ * objlayout_{read,write}_done
+ */
+extern void objio_free_result(struct objlayout_io_res *oir);
 
-extern ssize_t objio_read_pagelist(struct objlayout_io_state *ol_state);
-extern ssize_t objio_write_pagelist(struct objlayout_io_state *ol_state,
-                                   bool stable);
+extern int objio_read_pagelist(struct nfs_read_data *rdata);
+extern int objio_write_pagelist(struct nfs_write_data *wdata, int how);
 
 /*
  * callback API
  */
-extern void objlayout_io_set_result(struct objlayout_io_state *state,
+extern void objlayout_io_set_result(struct objlayout_io_res *oir,
                        unsigned index, struct pnfs_osd_objid *pooid,
                        int osd_error, u64 offset, u64 length, bool is_write);
 
 static inline void
-objlayout_add_delta_space_used(struct objlayout_io_state *state, s64 space_used)
+objlayout_add_delta_space_used(struct objlayout *objlay, s64 space_used)
 {
-       struct objlayout *objlay = OBJLAYOUT(state->lseg->pls_layout);
-
        /* If one of the I/Os errored out and the delta_space_used was
         * invalid we render the complete report as invalid. Protocol mandate
         * the DSU be accurate or not reported.
@@ -144,9 +144,9 @@ objlayout_add_delta_space_used(struct objlayout_io_state *state, s64 space_used)
        spin_unlock(&objlay->lock);
 }
 
-extern void objlayout_read_done(struct objlayout_io_state *state,
+extern void objlayout_read_done(struct objlayout_io_res *oir,
                                ssize_t status, bool sync);
-extern void objlayout_write_done(struct objlayout_io_state *state,
+extern void objlayout_write_done(struct objlayout_io_res *oir,
                                 ssize_t status, bool sync);
 
 extern int objlayout_get_deviceinfo(struct pnfs_layout_hdr *pnfslay,
index b60970c..0a5ff5c 100644 (file)
@@ -41,7 +41,7 @@ nfs_page_free(struct nfs_page *p)
 
 /**
  * nfs_create_request - Create an NFS read/write request.
- * @file: file descriptor to use
+ * @ctx: open context to use
  * @inode: inode to which the request is attached
  * @page: page to write
  * @offset: starting offset within the page for the write
index ee73d9a..a2478bc 100644 (file)
@@ -1443,17 +1443,31 @@ pnfs_layoutcommit_inode(struct inode *inode, bool sync)
        /* Note kzalloc ensures data->res.seq_res.sr_slot == NULL */
        data = kzalloc(sizeof(*data), GFP_NOFS);
        if (!data) {
-               mark_inode_dirty_sync(inode);
                status = -ENOMEM;
                goto out;
        }
 
+       if (!test_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags))
+               goto out_free;
+
+       if (test_and_set_bit(NFS_INO_LAYOUTCOMMITTING, &nfsi->flags)) {
+               if (!sync) {
+                       status = -EAGAIN;
+                       goto out_free;
+               }
+               status = wait_on_bit_lock(&nfsi->flags, NFS_INO_LAYOUTCOMMITTING,
+                                       nfs_wait_bit_killable, TASK_KILLABLE);
+               if (status)
+                       goto out_free;
+       }
+
        INIT_LIST_HEAD(&data->lseg_list);
        spin_lock(&inode->i_lock);
        if (!test_and_clear_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) {
+               clear_bit(NFS_INO_LAYOUTCOMMITTING, &nfsi->flags);
                spin_unlock(&inode->i_lock);
-               kfree(data);
-               goto out;
+               wake_up_bit(&nfsi->flags, NFS_INO_LAYOUTCOMMITTING);
+               goto out_free;
        }
 
        pnfs_list_write_lseg(inode, &data->lseg_list);
@@ -1475,6 +1489,11 @@ pnfs_layoutcommit_inode(struct inode *inode, bool sync)
 
        status = nfs4_proc_layoutcommit(data, sync);
 out:
+       if (status)
+               mark_inode_dirty_sync(inode);
        dprintk("<-- %s status %d\n", __func__, status);
        return status;
+out_free:
+       kfree(data);
+       goto out;
 }
index 2219c88..b016b8a 100644 (file)
@@ -1243,7 +1243,6 @@ void nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data)
 {
        struct nfs_writeargs    *argp = &data->args;
        struct nfs_writeres     *resp = &data->res;
-       struct nfs_server       *server = NFS_SERVER(data->inode);
        int status;
 
        dprintk("NFS: %5u nfs_writeback_done (status %d)\n",
@@ -1277,7 +1276,7 @@ void nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data)
                if (time_before(complain, jiffies)) {
                        dprintk("NFS:       faulty NFS server %s:"
                                " (committed = %d) != (stable = %d)\n",
-                               server->nfs_client->cl_hostname,
+                               NFS_SERVER(data->inode)->nfs_client->cl_hostname,
                                resp->verf->committed, argp->stable);
                        complain = jiffies + 300 * HZ;
                }
index dc5a1bf..52cd976 100644 (file)
@@ -256,6 +256,8 @@ static void nfsd_last_thread(struct svc_serv *serv)
        nfsd_serv = NULL;
        nfsd_shutdown();
 
+       svc_rpcb_cleanup(serv);
+
        printk(KERN_WARNING "nfsd: last server has exited, flushing export "
                            "cache\n");
        nfsd_export_flush();
index 048b59d..c70111e 100644 (file)
@@ -78,6 +78,28 @@ config SQUASHFS_XZ
 
          If unsure, say N.
 
+config SQUASHFS_4K_DEVBLK_SIZE
+       bool "Use 4K device block size?"
+       depends on SQUASHFS
+       help
+         By default Squashfs sets the dev block size (sb_min_blocksize)
+         to 1K or the smallest block size supported by the block device
+         (if larger).  This, because blocks are packed together and
+         unaligned in Squashfs, should reduce latency.
+
+         This, however, gives poor performance on MTD NAND devices where
+         the optimal I/O size is 4K (even though the devices can support
+         smaller block sizes).
+
+         Using a 4K device block size may also improve overall I/O
+         performance for some file access patterns (e.g. sequential
+         accesses of files in filesystem order) on all media.
+
+         Setting this option will force Squashfs to use a 4K device block
+         size by default.
+
+         If unsure, say N.
+
 config SQUASHFS_EMBEDDED
        bool "Additional option for memory-constrained systems"
        depends on SQUASHFS
index b4a4e53..e8e1464 100644 (file)
 #define SQUASHFS_FILE_SIZE             131072
 #define SQUASHFS_FILE_LOG              17
 
+/* default size of block device I/O */
+#ifdef CONFIG_SQUASHFS_4K_DEVBLK_SIZE
+#define SQUASHFS_DEVBLK_SIZE 4096
+#else
+#define SQUASHFS_DEVBLK_SIZE 1024
+#endif
+
 #define SQUASHFS_FILE_MAX_SIZE         1048576
 #define SQUASHFS_FILE_MAX_LOG          20
 
index 7438850..2da1715 100644 (file)
@@ -95,7 +95,7 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent)
        }
        msblk = sb->s_fs_info;
 
-       msblk->devblksize = sb_min_blocksize(sb, BLOCK_SIZE);
+       msblk->devblksize = sb_min_blocksize(sb, SQUASHFS_DEVBLK_SIZE);
        msblk->devblksize_log2 = ffz(~msblk->devblksize);
 
        mutex_init(&msblk->read_data_mutex);
index 8244924..9cf04a1 100644 (file)
@@ -76,7 +76,7 @@ EXPORT_SYMBOL(vfs_statfs);
 int user_statfs(const char __user *pathname, struct kstatfs *st)
 {
        struct path path;
-       int error = user_path(pathname, &path);
+       int error = user_path_at(AT_FDCWD, pathname, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &path);
        if (!error) {
                error = vfs_statfs(&path, st);
                path_put(&path);
index e6e28f3..9eabffb 100644 (file)
@@ -47,6 +47,9 @@ enum {
  * @muxval: a number usually used to poke into some mux regiser to
  * mux in the signal to this channel
  * @cctl_opt: default options for the channel control register
+ * @device_fc: Flow Controller Settings for ccfg register. Only valid for slave
+ * channels. Fill with 'true' if peripheral should be flow controller. Direction
+ * will be selected at Runtime.
  * @addr: source/target address in physical memory for this DMA channel,
  * can be the address of a FIFO register for burst requests for example.
  * This can be left undefined if the PrimeCell API is used for configuring
@@ -65,6 +68,7 @@ struct pl08x_channel_data {
        int max_signal;
        u32 muxval;
        u32 cctl;
+       bool device_fc;
        dma_addr_t addr;
        bool circular_buffer;
        bool single;
@@ -77,13 +81,11 @@ struct pl08x_channel_data {
  * @addr: current address
  * @maxwidth: the maximum width of a transfer on this bus
  * @buswidth: the width of this bus in bytes: 1, 2 or 4
- * @fill_bytes: bytes required to fill to the next bus memory boundary
  */
 struct pl08x_bus_data {
        dma_addr_t addr;
        u8 maxwidth;
        u8 buswidth;
-       size_t fill_bytes;
 };
 
 /**
@@ -104,17 +106,35 @@ struct pl08x_phy_chan {
 };
 
 /**
+ * struct pl08x_sg - structure containing data per sg
+ * @src_addr: src address of sg
+ * @dst_addr: dst address of sg
+ * @len: transfer len in bytes
+ * @node: node for txd's dsg_list
+ */
+struct pl08x_sg {
+       dma_addr_t src_addr;
+       dma_addr_t dst_addr;
+       size_t len;
+       struct list_head node;
+};
+
+/**
  * struct pl08x_txd - wrapper for struct dma_async_tx_descriptor
+ * @tx: async tx descriptor
+ * @node: node for txd list for channels
+ * @dsg_list: list of children sg's
+ * @direction: direction of transfer
  * @llis_bus: DMA memory address (physical) start for the LLIs
  * @llis_va: virtual memory address start for the LLIs
+ * @cctl: control reg values for current txd
+ * @ccfg: config reg values for current txd
  */
 struct pl08x_txd {
        struct dma_async_tx_descriptor tx;
        struct list_head node;
+       struct list_head dsg_list;
        enum dma_data_direction direction;
-       dma_addr_t src_addr;
-       dma_addr_t dst_addr;
-       size_t len;
        dma_addr_t llis_bus;
        struct pl08x_lli *llis_va;
        /* Default cctl value for LLIs */
index cbee7de..d12f077 100644 (file)
@@ -19,12 +19,8 @@ struct dma_pl330_peri {
         * Peri_Req i/f of the DMAC that is
         * peripheral could be reached from.
         */
-       u8 peri_id; /* {0, 31} */
+       u8 peri_id; /* specific dma id */
        enum pl330_reqtype rqtype;
-
-       /* For M->D and D->M Channels */
-       int burst_sz; /* in power of 2 */
-       dma_addr_t fifo_addr;
 };
 
 struct dma_pl330_platdata {
index ce33e68..a3c071c 100644 (file)
@@ -269,14 +269,6 @@ extern void bvec_free_bs(struct bio_set *, struct bio_vec *, unsigned int);
 extern unsigned int bvec_nr_vecs(unsigned short idx);
 
 /*
- * Allow queuer to specify a completion CPU for this bio
- */
-static inline void bio_set_completion_cpu(struct bio *bio, unsigned int cpu)
-{
-       bio->bi_comp_cpu = cpu;
-}
-
-/*
  * bio_set is used to allow other portions of the IO system to
  * allocate their own private memory pools for bio and iovec structures.
  * These memory pools in turn all allocate from the bio_slab
index 71fc53b..4053cbd 100644 (file)
@@ -59,8 +59,6 @@ struct bio {
 
        unsigned int            bi_max_vecs;    /* max bvl_vecs we can hold */
 
-       unsigned int            bi_comp_cpu;    /* completion CPU */
-
        atomic_t                bi_cnt;         /* pin count */
 
        struct bio_vec          *bi_io_vec;     /* the actual vec list */
@@ -93,11 +91,10 @@ struct bio {
 #define BIO_BOUNCED    5       /* bio is a bounce bio */
 #define BIO_USER_MAPPED 6      /* contains user pages */
 #define BIO_EOPNOTSUPP 7       /* not supported */
-#define BIO_CPU_AFFINE 8       /* complete bio on same CPU as submitted */
-#define BIO_NULL_MAPPED 9      /* contains invalid user pages */
-#define BIO_FS_INTEGRITY 10    /* fs owns integrity data, not block layer */
-#define BIO_QUIET      11      /* Make BIO Quiet */
-#define BIO_MAPPED_INTEGRITY 12/* integrity metadata has been remapped */
+#define BIO_NULL_MAPPED 8      /* contains invalid user pages */
+#define BIO_FS_INTEGRITY 9     /* fs owns integrity data, not block layer */
+#define BIO_QUIET      10      /* Make BIO Quiet */
+#define BIO_MAPPED_INTEGRITY 11/* integrity metadata has been remapped */
 #define bio_flagged(bio, flag) ((bio)->bi_flags & (1 << (flag)))
 
 /*
index 7fbaa91..5267cd2 100644 (file)
@@ -195,7 +195,7 @@ struct request_pm_state
 #include <linux/elevator.h>
 
 typedef void (request_fn_proc) (struct request_queue *q);
-typedef int (make_request_fn) (struct request_queue *q, struct bio *bio);
+typedef void (make_request_fn) (struct request_queue *q, struct bio *bio);
 typedef int (prep_rq_fn) (struct request_queue *, struct request *);
 typedef void (unprep_rq_fn) (struct request_queue *, struct request *);
 
@@ -680,6 +680,8 @@ extern int scsi_cmd_ioctl(struct request_queue *, struct gendisk *, fmode_t,
 extern int sg_scsi_ioctl(struct request_queue *, struct gendisk *, fmode_t,
                         struct scsi_ioctl_command __user *);
 
+extern void blk_queue_bio(struct request_queue *q, struct bio *bio);
+
 /*
  * A queue has just exitted congestion.  Note this in the global counter of
  * congested queues, and wake up anyone who was waiting for requests to be
@@ -863,16 +865,22 @@ struct request_queue *blk_alloc_queue_node(gfp_t, int);
 extern void blk_put_queue(struct request_queue *);
 
 /*
- * Note: Code in between changing the blk_plug list/cb_list or element of such
- * lists is preemptable, but such code can't do sleep (or be very careful),
- * otherwise data is corrupted. For details, please check schedule() where
- * blk_schedule_flush_plug() is called.
+ * blk_plug permits building a queue of related requests by holding the I/O
+ * fragments for a short period. This allows merging of sequential requests
+ * into single larger request. As the requests are moved from a per-task list to
+ * the device's request_queue in a batch, this results in improved scalability
+ * as the lock contention for request_queue lock is reduced.
+ *
+ * It is ok not to disable preemption when adding the request to the plug list
+ * or when attempting a merge, because blk_schedule_flush_list() will only flush
+ * the plug list when the task sleeps by itself. For details, please see
+ * schedule() where blk_schedule_flush_plug() is called.
  */
 struct blk_plug {
-       unsigned long magic;
-       struct list_head list;
-       struct list_head cb_list;
-       unsigned int should_sort;
+       unsigned long magic; /* detect uninitialized use-cases */
+       struct list_head list; /* requests */
+       struct list_head cb_list; /* md requires an unplug callback */
+       unsigned int should_sort; /* list to be sorted before flushing? */
 };
 #define BLK_MAX_REQUEST_COUNT 16
 
@@ -1189,20 +1197,6 @@ static inline uint64_t rq_io_start_time_ns(struct request *req)
 }
 #endif
 
-#ifdef CONFIG_BLK_DEV_THROTTLING
-extern int blk_throtl_init(struct request_queue *q);
-extern void blk_throtl_exit(struct request_queue *q);
-extern int blk_throtl_bio(struct request_queue *q, struct bio **bio);
-#else /* CONFIG_BLK_DEV_THROTTLING */
-static inline int blk_throtl_bio(struct request_queue *q, struct bio **bio)
-{
-       return 0;
-}
-
-static inline int blk_throtl_init(struct request_queue *q) { return 0; }
-static inline int blk_throtl_exit(struct request_queue *q) { return 0; }
-#endif /* CONFIG_BLK_DEV_THROTTLING */
-
 #define MODULE_ALIAS_BLOCKDEV(major,minor) \
        MODULE_ALIAS("block-major-" __stringify(major) "-" __stringify(minor))
 #define MODULE_ALIAS_BLOCKDEV_MAJOR(major) \
index b1a635a..6cb60fd 100644 (file)
@@ -196,13 +196,9 @@ static inline void cpu_hotplug_driver_unlock(void)
 #endif         /* CONFIG_HOTPLUG_CPU */
 
 #ifdef CONFIG_PM_SLEEP_SMP
-extern int suspend_cpu_hotplug;
-
 extern int disable_nonboot_cpus(void);
 extern void enable_nonboot_cpus(void);
 #else /* !CONFIG_PM_SLEEP_SMP */
-#define suspend_cpu_hotplug    0
-
 static inline int disable_nonboot_cpus(void) { return 0; }
 static inline void enable_nonboot_cpus(void) {}
 #endif /* !CONFIG_PM_SLEEP_SMP */
index be86ae1..e13117c 100644 (file)
@@ -42,6 +42,9 @@ struct dma_map_ops {
        int (*mapping_error)(struct device *dev, dma_addr_t dma_addr);
        int (*dma_supported)(struct device *dev, u64 mask);
        int (*set_dma_mask)(struct device *dev, u64 mask);
+#ifdef ARCH_HAS_DMA_GET_REQUIRED_MASK
+       u64 (*get_required_mask)(struct device *dev);
+#endif
        int is_phys;
 };
 
index 8fbf40e..ace51af 100644 (file)
@@ -24,8 +24,7 @@
 #include <linux/device.h>
 #include <linux/uio.h>
 #include <linux/dma-direction.h>
-
-struct scatterlist;
+#include <linux/scatterlist.h>
 
 /**
  * typedef dma_cookie_t - an opaque DMA cookie
@@ -519,6 +518,16 @@ static inline int dmaengine_slave_config(struct dma_chan *chan,
                        (unsigned long)config);
 }
 
+static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_single(
+       struct dma_chan *chan, void *buf, size_t len,
+       enum dma_data_direction dir, unsigned long flags)
+{
+       struct scatterlist sg;
+       sg_init_one(&sg, buf, len);
+
+       return chan->device->device_prep_slave_sg(chan, &sg, 1, dir, flags);
+}
+
 static inline int dmaengine_terminate_all(struct dma_chan *chan)
 {
        return dmaengine_device_control(chan, DMA_TERMINATE_ALL, 0);
index d800d51..1d0f7a2 100644 (file)
@@ -38,6 +38,12 @@ struct elevator_ops
        elevator_merged_fn *elevator_merged_fn;
        elevator_merge_req_fn *elevator_merge_req_fn;
        elevator_allow_merge_fn *elevator_allow_merge_fn;
+
+       /*
+        * Used for both plugged list and elevator merging and in the
+        * former case called without queue_lock.  Read comment on top of
+        * attempt_plug_merge() for details.
+        */
        elevator_bio_merged_fn *elevator_bio_merged_fn;
 
        elevator_dispatch_fn *elevator_dispatch_fn;
index a49b529..a5386e3 100644 (file)
@@ -143,14 +143,9 @@ static inline void set_freezable_with_signal(void)
 #define wait_event_freezekillable(wq, condition)                       \
 ({                                                                     \
        int __retval;                                                   \
-       do {                                                            \
-               __retval = wait_event_killable(wq,                      \
-                               (condition) || freezing(current));      \
-               if (__retval && !freezing(current))                     \
-                       break;                                          \
-               else if (!(condition))                                  \
-                       __retval = -ERESTARTSYS;                        \
-       } while (try_to_freeze());                                      \
+       freezer_do_not_count();                                         \
+       __retval = wait_event_killable(wq, (condition));                \
+       freezer_count();                                                \
        __retval;                                                       \
 })
 
index 6957350..9de31bc 100644 (file)
@@ -131,6 +131,7 @@ struct hd_struct {
 #define GENHD_FL_EXT_DEVT                      64 /* allow extended devt */
 #define GENHD_FL_NATIVE_CAPACITY               128
 #define GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE    256
+#define GENHD_FL_NO_PART_SCAN                  512
 
 enum {
        DISK_EVENT_MEDIA_CHANGE                 = 1 << 0, /* media changed */
@@ -238,9 +239,10 @@ static inline int disk_max_parts(struct gendisk *disk)
        return disk->minors;
 }
 
-static inline bool disk_partitionable(struct gendisk *disk)
+static inline bool disk_part_scan_enabled(struct gendisk *disk)
 {
-       return disk_max_parts(disk) > 1;
+       return disk_max_parts(disk) > 1 &&
+               !(disk->flags & GENHD_FL_NO_PART_SCAN);
 }
 
 static inline dev_t disk_devt(struct gendisk *disk)
index 683d698..11a41a8 100644 (file)
@@ -73,8 +73,8 @@ struct loop_device {
  */
 enum {
        LO_FLAGS_READ_ONLY      = 1,
-       LO_FLAGS_USE_AOPS       = 2,
        LO_FLAGS_AUTOCLEAR      = 4,
+       LO_FLAGS_PARTSCAN       = 8,
 };
 
 #include <asm/posix_types.h>   /* for __kernel_old_dev_t */
index 60a137b..ab2c634 100644 (file)
@@ -229,6 +229,7 @@ struct nfs_inode {
 #define NFS_INO_COMMIT         (7)             /* inode is committing unstable writes */
 #define NFS_INO_PNFS_COMMIT    (8)             /* use pnfs code for commit */
 #define NFS_INO_LAYOUTCOMMIT   (9)             /* layoutcommit required */
+#define NFS_INO_LAYOUTCOMMITTING (10)          /* layoutcommit inflight */
 
 static inline struct nfs_inode *NFS_I(const struct inode *inode)
 {
index f01ba8a..0e89aa0 100644 (file)
@@ -321,6 +321,16 @@ static inline struct device_node *of_parse_phandle(struct device_node *np,
        return NULL;
 }
 
+static inline int of_alias_get_id(struct device_node *np, const char *stem)
+{
+       return -ENOSYS;
+}
+
+static inline int of_machine_is_compatible(const char *compat)
+{
+       return 0;
+}
+
 #define of_match_ptr(_ptr)     NULL
 #define of_match_node(_matches, _node) NULL
 #endif /* CONFIG_OF */
index 87a9208..ee94b33 100644 (file)
@@ -97,11 +97,11 @@ static inline int opp_disable(struct device *dev, unsigned long freq)
        return 0;
 }
 
-struct srcu_notifier_head *opp_get_notifier(struct device *dev)
+static inline struct srcu_notifier_head *opp_get_notifier(struct device *dev)
 {
        return ERR_PTR(-EINVAL);
 }
-#endif         /* CONFIG_PM */
+#endif         /* CONFIG_PM_OPP */
 
 #if defined(CONFIG_CPU_FREQ) && defined(CONFIG_PM_OPP)
 int opp_init_cpufreq_table(struct device *dev,
index 1679ff6..3fdf251 100644 (file)
 
 #define PCI_VENDOR_ID_XEN              0x5853
 #define PCI_DEVICE_ID_XEN_PLATFORM     0x0001
+
+#define PCI_VENDOR_ID_OCZ              0x1b85
index 8bffe9a..0efa1f1 100644 (file)
@@ -131,8 +131,6 @@ struct plat_sci_port {
 
        struct plat_sci_port_ops        *ops;
 
-       struct device   *dma_dev;
-
        unsigned int    dma_slave_tx;
        unsigned int    dma_slave_rx;
 };
index 492486a..3d8f9c4 100644 (file)
@@ -136,6 +136,8 @@ void                rpc_shutdown_client(struct rpc_clnt *);
 void           rpc_release_client(struct rpc_clnt *);
 void           rpc_task_release_client(struct rpc_task *);
 
+int            rpcb_create_local(void);
+void           rpcb_put_local(void);
 int            rpcb_register(u32, u32, int, unsigned short);
 int            rpcb_v4_register(const u32 program, const u32 version,
                                 const struct sockaddr *address,
index d8d5d93..35b37b1 100644 (file)
@@ -413,6 +413,7 @@ struct svc_procedure {
 /*
  * Function prototypes.
  */
+void svc_rpcb_cleanup(struct svc_serv *serv);
 struct svc_serv *svc_create(struct svc_program *, unsigned int,
                            void (*shutdown)(struct svc_serv *));
 struct svc_rqst *svc_prepare_thread(struct svc_serv *serv,
index fc839bf..e26db03 100644 (file)
@@ -201,6 +201,10 @@ int arch_update_cpu_topology(void);
        .balance_interval       = 64,                                   \
 }
 
+#ifndef SD_NODES_PER_DOMAIN
+#define SD_NODES_PER_DOMAIN 16
+#endif
+
 #ifdef CONFIG_SCHED_BOOK
 #ifndef SD_BOOK_INIT
 #error Please define an appropriate SD_BOOK_INIT in include/asm/topology.h!!!
index 225560c..4b752d5 100644 (file)
@@ -653,6 +653,10 @@ struct v4l2_buffer {
 #define V4L2_BUF_FLAG_ERROR    0x0040
 #define V4L2_BUF_FLAG_TIMECODE 0x0100  /* timecode field is valid */
 #define V4L2_BUF_FLAG_INPUT     0x0200  /* input field is valid */
+#define V4L2_BUF_FLAG_PREPARED 0x0400  /* Buffer is prepared for queuing */
+/* Cache handling flags */
+#define V4L2_BUF_FLAG_NO_CACHE_INVALIDATE      0x0800
+#define V4L2_BUF_FLAG_NO_CACHE_CLEAN           0x1000
 
 /*
  *     O V E R L A Y   P R E V I E W
@@ -1165,6 +1169,7 @@ enum v4l2_power_line_frequency {
        V4L2_CID_POWER_LINE_FREQUENCY_DISABLED  = 0,
        V4L2_CID_POWER_LINE_FREQUENCY_50HZ      = 1,
        V4L2_CID_POWER_LINE_FREQUENCY_60HZ      = 2,
+       V4L2_CID_POWER_LINE_FREQUENCY_AUTO      = 3,
 };
 #define V4L2_CID_HUE_AUTO                      (V4L2_CID_BASE+25)
 #define V4L2_CID_WHITE_BALANCE_TEMPERATURE     (V4L2_CID_BASE+26)
@@ -2138,6 +2143,23 @@ struct v4l2_dbg_chip_ident {
        __u32 revision;    /* chip revision, chip specific */
 } __attribute__ ((packed));
 
+/**
+ * struct v4l2_create_buffers - VIDIOC_CREATE_BUFS argument
+ * @index:     on return, index of the first created buffer
+ * @count:     entry: number of requested buffers,
+ *             return: number of created buffers
+ * @memory:    buffer memory type
+ * @format:    frame format, for which buffers are requested
+ * @reserved:  future extensions
+ */
+struct v4l2_create_buffers {
+       __u32                   index;
+       __u32                   count;
+       enum v4l2_memory        memory;
+       struct v4l2_format      format;
+       __u32                   reserved[8];
+};
+
 /*
  *     I O C T L   C O D E S   F O R   V I D E O   D E V I C E S
  *
@@ -2228,6 +2250,11 @@ struct v4l2_dbg_chip_ident {
 #define        VIDIOC_SUBSCRIBE_EVENT   _IOW('V', 90, struct v4l2_event_subscription)
 #define        VIDIOC_UNSUBSCRIBE_EVENT _IOW('V', 91, struct v4l2_event_subscription)
 
+/* Experimental, the below two ioctls may change over the next couple of kernel
+   versions */
+#define VIDIOC_CREATE_BUFS     _IOWR('V', 92, struct v4l2_create_buffers)
+#define VIDIOC_PREPARE_BUF     _IOWR('V', 93, struct v4l2_buffer)
+
 /* Reminder: when adding new ioctls please add support for them to
    drivers/media/video/v4l2-compat-ioctl32.c as well! */
 
index 548bf11..00dbb7c 100644 (file)
 #ifndef __OV772X_H__
 #define __OV772X_H__
 
-#include <media/soc_camera.h>
-
 /* for flags */
 #define OV772X_FLAG_VFLIP      (1 << 0) /* Vertical flip image */
 #define OV772X_FLAG_HFLIP      (1 << 1) /* Horizontal flip image */
-#define OV772X_FLAG_8BIT       (1 << 2) /* default 10 bit */
 
 /*
  * for Edge ctrl
@@ -32,22 +29,23 @@ struct ov772x_edge_ctrl {
        unsigned char lower;
 };
 
-#define OV772X_MANUAL_EDGE_CTRL        0x80 /* un-used bit of strength */
-#define EDGE_STRENGTH_MASK     0x1F
-#define EDGE_THRESHOLD_MASK    0x0F
-#define EDGE_UPPER_MASK                0xFF
-#define EDGE_LOWER_MASK                0xFF
+#define OV772X_MANUAL_EDGE_CTRL                0x80 /* un-used bit of strength */
+#define OV772X_EDGE_STRENGTH_MASK      0x1F
+#define OV772X_EDGE_THRESHOLD_MASK     0x0F
+#define OV772X_EDGE_UPPER_MASK         0xFF
+#define OV772X_EDGE_LOWER_MASK         0xFF
 
 #define OV772X_AUTO_EDGECTRL(u, l)     \
 {                                      \
-       .upper = (u & EDGE_UPPER_MASK), \
-       .lower = (l & EDGE_LOWER_MASK), \
+       .upper = (u & OV772X_EDGE_UPPER_MASK),  \
+       .lower = (l & OV772X_EDGE_LOWER_MASK),  \
 }
 
-#define OV772X_MANUAL_EDGECTRL(s, t)                                   \
-{                                                                      \
-       .strength  = (s & EDGE_STRENGTH_MASK) | OV772X_MANUAL_EDGE_CTRL,\
-       .threshold = (t & EDGE_THRESHOLD_MASK),                         \
+#define OV772X_MANUAL_EDGECTRL(s, t)                   \
+{                                                      \
+       .strength  = (s & OV772X_EDGE_STRENGTH_MASK) |  \
+                       OV772X_MANUAL_EDGE_CTRL,        \
+       .threshold = (t & OV772X_EDGE_THRESHOLD_MASK),  \
 }
 
 /*
diff --git a/include/media/s5k6aa.h b/include/media/s5k6aa.h
new file mode 100644 (file)
index 0000000..ba34f70
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * S5K6AAFX camera sensor driver header
+ *
+ * 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 S5K6AA_H
+#define S5K6AA_H
+
+#include <media/v4l2-mediabus.h>
+
+/**
+ * struct s5k6aa_gpio - data structure describing a GPIO
+ * @gpio:  GPIO number
+ * @level: indicates active state of the @gpio
+ */
+struct s5k6aa_gpio {
+       int gpio;
+       int level;
+};
+
+/**
+ * struct s5k6aa_platform_data - s5k6aa driver platform data
+ * @set_power:   an additional callback to the board code, called
+ *               after enabling the regulators and before switching
+ *               the sensor off
+ * @mclk_frequency: sensor's master clock frequency in Hz
+ * @gpio_reset:  GPIO driving RESET pin
+ * @gpio_stby:   GPIO driving STBY pin
+ * @nlanes:      maximum number of MIPI-CSI lanes used
+ * @horiz_flip:  default horizontal image flip value, non zero to enable
+ * @vert_flip:   default vertical image flip value, non zero to enable
+ */
+
+struct s5k6aa_platform_data {
+       int (*set_power)(int enable);
+       unsigned long mclk_frequency;
+       struct s5k6aa_gpio gpio_reset;
+       struct s5k6aa_gpio gpio_stby;
+       enum v4l2_mbus_type bus_type;
+       u8 nlanes;
+       u8 horiz_flip;
+       u8 vert_flip;
+};
+
+#endif /* S5K6AA_H */
index 7582952..b1377b9 100644 (file)
 #ifndef SOC_CAMERA_H
 #define SOC_CAMERA_H
 
+#include <linux/bitops.h>
 #include <linux/device.h>
 #include <linux/mutex.h>
 #include <linux/pm.h>
 #include <linux/videodev2.h>
 #include <media/videobuf-core.h>
 #include <media/videobuf2-core.h>
+#include <media/v4l2-ctrls.h>
 #include <media/v4l2-device.h>
 
 struct file;
@@ -37,8 +39,8 @@ struct soc_camera_device {
        unsigned char iface;            /* Host number */
        unsigned char devnum;           /* Device number per host */
        struct soc_camera_sense *sense; /* See comment in struct definition */
-       struct soc_camera_ops *ops;
        struct video_device *vdev;
+       struct v4l2_ctrl_handler ctrl_handler;
        const struct soc_camera_format_xlate *current_fmt;
        struct soc_camera_format_xlate *user_formats;
        int num_user_formats;
@@ -93,14 +95,10 @@ struct soc_camera_host_ops {
        int (*reqbufs)(struct soc_camera_device *, struct v4l2_requestbuffers *);
        int (*querycap)(struct soc_camera_host *, struct v4l2_capability *);
        int (*set_bus_param)(struct soc_camera_device *, __u32);
-       int (*get_ctrl)(struct soc_camera_device *, struct v4l2_control *);
-       int (*set_ctrl)(struct soc_camera_device *, struct v4l2_control *);
        int (*get_parm)(struct soc_camera_device *, struct v4l2_streamparm *);
        int (*set_parm)(struct soc_camera_device *, struct v4l2_streamparm *);
        int (*enum_fsizes)(struct soc_camera_device *, struct v4l2_frmsizeenum *);
        unsigned int (*poll)(struct file *, poll_table *);
-       const struct v4l2_queryctrl *controls;
-       int num_controls;
 };
 
 #define SOCAM_SENSOR_INVERT_PCLK       (1 << 0)
@@ -193,13 +191,6 @@ struct soc_camera_format_xlate {
        const struct soc_mbus_pixelfmt *host_fmt;
 };
 
-struct soc_camera_ops {
-       unsigned long (*query_bus_param)(struct soc_camera_device *);
-       int (*set_bus_param)(struct soc_camera_device *, unsigned long);
-       const struct v4l2_queryctrl *controls;
-       int num_controls;
-};
-
 #define SOCAM_SENSE_PCLK_CHANGED       (1 << 0)
 
 /**
@@ -226,65 +217,18 @@ struct soc_camera_sense {
        unsigned long pixel_clock;
 };
 
-static inline struct v4l2_queryctrl const *soc_camera_find_qctrl(
-       struct soc_camera_ops *ops, int id)
-{
-       int i;
-
-       for (i = 0; i < ops->num_controls; i++)
-               if (ops->controls[i].id == id)
-                       return &ops->controls[i];
-
-       return NULL;
-}
-
-#define SOCAM_MASTER                   (1 << 0)
-#define SOCAM_SLAVE                    (1 << 1)
-#define SOCAM_HSYNC_ACTIVE_HIGH                (1 << 2)
-#define SOCAM_HSYNC_ACTIVE_LOW         (1 << 3)
-#define SOCAM_VSYNC_ACTIVE_HIGH                (1 << 4)
-#define SOCAM_VSYNC_ACTIVE_LOW         (1 << 5)
-#define SOCAM_DATAWIDTH_4              (1 << 6)
-#define SOCAM_DATAWIDTH_8              (1 << 7)
-#define SOCAM_DATAWIDTH_9              (1 << 8)
-#define SOCAM_DATAWIDTH_10             (1 << 9)
-#define SOCAM_DATAWIDTH_15             (1 << 10)
-#define SOCAM_DATAWIDTH_16             (1 << 11)
-#define SOCAM_PCLK_SAMPLE_RISING       (1 << 12)
-#define SOCAM_PCLK_SAMPLE_FALLING      (1 << 13)
-#define SOCAM_DATA_ACTIVE_HIGH         (1 << 14)
-#define SOCAM_DATA_ACTIVE_LOW          (1 << 15)
-#define SOCAM_MIPI_1LANE               (1 << 16)
-#define SOCAM_MIPI_2LANE               (1 << 17)
-#define SOCAM_MIPI_3LANE               (1 << 18)
-#define SOCAM_MIPI_4LANE               (1 << 19)
-#define SOCAM_MIPI     (SOCAM_MIPI_1LANE | SOCAM_MIPI_2LANE | \
-                       SOCAM_MIPI_3LANE | SOCAM_MIPI_4LANE)
+#define SOCAM_DATAWIDTH(x)     BIT((x) - 1)
+#define SOCAM_DATAWIDTH_4      SOCAM_DATAWIDTH(4)
+#define SOCAM_DATAWIDTH_8      SOCAM_DATAWIDTH(8)
+#define SOCAM_DATAWIDTH_9      SOCAM_DATAWIDTH(9)
+#define SOCAM_DATAWIDTH_10     SOCAM_DATAWIDTH(10)
+#define SOCAM_DATAWIDTH_15     SOCAM_DATAWIDTH(15)
+#define SOCAM_DATAWIDTH_16     SOCAM_DATAWIDTH(16)
 
 #define SOCAM_DATAWIDTH_MASK (SOCAM_DATAWIDTH_4 | SOCAM_DATAWIDTH_8 | \
                              SOCAM_DATAWIDTH_9 | SOCAM_DATAWIDTH_10 | \
                              SOCAM_DATAWIDTH_15 | SOCAM_DATAWIDTH_16)
 
-static inline unsigned long soc_camera_bus_param_compatible(
-                       unsigned long camera_flags, unsigned long bus_flags)
-{
-       unsigned long common_flags, hsync, vsync, pclk, data, buswidth, mode;
-       unsigned long mipi;
-
-       common_flags = camera_flags & bus_flags;
-
-       hsync = common_flags & (SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_LOW);
-       vsync = common_flags & (SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW);
-       pclk = common_flags & (SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING);
-       data = common_flags & (SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATA_ACTIVE_LOW);
-       mode = common_flags & (SOCAM_MASTER | SOCAM_SLAVE);
-       buswidth = common_flags & SOCAM_DATAWIDTH_MASK;
-       mipi = common_flags & SOCAM_MIPI;
-
-       return ((!hsync || !vsync || !pclk || !data || !mode || !buswidth) && !mipi) ? 0 :
-               common_flags;
-}
-
 static inline void soc_camera_limit_side(int *start, int *length,
                unsigned int start_min,
                unsigned int length_min, unsigned int length_max)
@@ -300,23 +244,37 @@ static inline void soc_camera_limit_side(int *start, int *length,
                *start = start_min + length_max - *length;
 }
 
-extern unsigned long soc_camera_apply_sensor_flags(struct soc_camera_link *icl,
-                                                  unsigned long flags);
+unsigned long soc_camera_apply_sensor_flags(struct soc_camera_link *icl,
+                                           unsigned long flags);
+unsigned long soc_camera_apply_board_flags(struct soc_camera_link *icl,
+                                          const struct v4l2_mbus_config *cfg);
 
 /* This is only temporary here - until v4l2-subdev begins to link to video_device */
 #include <linux/i2c.h>
-static inline struct video_device *soc_camera_i2c_to_vdev(struct i2c_client *client)
+static inline struct video_device *soc_camera_i2c_to_vdev(const struct i2c_client *client)
+{
+       struct v4l2_subdev *sd = i2c_get_clientdata(client);
+       struct soc_camera_device *icd = (struct soc_camera_device *)sd->grp_id;
+       return icd ? icd->vdev : NULL;
+}
+
+static inline struct soc_camera_link *soc_camera_i2c_to_link(const struct i2c_client *client)
+{
+       return client->dev.platform_data;
+}
+
+static inline struct v4l2_subdev *soc_camera_vdev_to_subdev(const struct video_device *vdev)
 {
-       struct soc_camera_device *icd = client->dev.platform_data;
-       return icd->vdev;
+       struct soc_camera_device *icd = dev_get_drvdata(vdev->parent);
+       return soc_camera_to_subdev(icd);
 }
 
-static inline struct soc_camera_device *soc_camera_from_vb2q(struct vb2_queue *vq)
+static inline struct soc_camera_device *soc_camera_from_vb2q(const struct vb2_queue *vq)
 {
        return container_of(vq, struct soc_camera_device, vb2_vidq);
 }
 
-static inline struct soc_camera_device *soc_camera_from_vbq(struct videobuf_queue *vq)
+static inline struct soc_camera_device *soc_camera_from_vbq(const struct videobuf_queue *vq)
 {
        return container_of(vq, struct soc_camera_device, vb_vidq);
 }
index 74f0fa1..8aa4200 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <linux/videodev2.h>
 #include <media/soc_camera.h>
+#include <media/v4l2-mediabus.h>
 
 struct device;
 
@@ -20,7 +21,8 @@ struct soc_camera_platform_info {
        const char *format_name;
        unsigned long format_depth;
        struct v4l2_mbus_framefmt format;
-       unsigned long bus_param;
+       unsigned long mbus_param;
+       enum v4l2_mbus_type mbus_type;
        struct soc_camera_device *icd;
        int (*set_capture)(struct soc_camera_platform_info *info, int enable);
 };
index fae4325..73f1e7e 100644 (file)
@@ -82,5 +82,7 @@ const struct soc_mbus_pixelfmt *soc_mbus_get_fmtdesc(
 s32 soc_mbus_bytes_per_line(u32 width, const struct soc_mbus_pixelfmt *mf);
 int soc_mbus_samples_per_pixel(const struct soc_mbus_pixelfmt *mf,
                        unsigned int *numerator, unsigned int *denominator);
+unsigned int soc_mbus_config_compatible(const struct v4l2_mbus_config *cfg,
+                                       unsigned int flags);
 
 #endif
index dd9f1e7..4d1c74a 100644 (file)
@@ -122,6 +122,8 @@ struct v4l2_ioctl_ops {
        int (*vidioc_qbuf)    (struct file *file, void *fh, struct v4l2_buffer *b);
        int (*vidioc_dqbuf)   (struct file *file, void *fh, struct v4l2_buffer *b);
 
+       int (*vidioc_create_bufs)(struct file *file, void *fh, struct v4l2_create_buffers *b);
+       int (*vidioc_prepare_buf)(struct file *file, void *fh, struct v4l2_buffer *b);
 
        int (*vidioc_overlay) (struct file *file, void *fh, unsigned int i);
        int (*vidioc_g_fbuf)   (struct file *file, void *fh,
index 257da1a..f0f3358 100644 (file)
@@ -158,6 +158,7 @@ struct v4l2_subdev_core_ops {
        int (*s_ext_ctrls)(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls);
        int (*try_ext_ctrls)(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls);
        int (*querymenu)(struct v4l2_subdev *sd, struct v4l2_querymenu *qm);
+       int (*g_std)(struct v4l2_subdev *sd, v4l2_std_id *norm);
        int (*s_std)(struct v4l2_subdev *sd, v4l2_std_id norm);
        long (*ioctl)(struct v4l2_subdev *sd, unsigned int cmd, void *arg);
 #ifdef CONFIG_VIDEO_ADV_DEBUG
@@ -534,13 +535,13 @@ struct v4l2_subdev {
        void *dev_priv;
        void *host_priv;
        /* subdev device node */
-       struct video_device devnode;
+       struct video_device *devnode;
 };
 
 #define media_entity_to_v4l2_subdev(ent) \
        container_of(ent, struct v4l2_subdev, entity)
 #define vdev_to_v4l2_subdev(vdev) \
-       container_of(vdev, struct v4l2_subdev, devnode)
+       video_get_drvdata(vdev)
 
 /*
  * Used for storing subdev information per file handle
index ea55c08..a15d1f1 100644 (file)
@@ -105,6 +105,7 @@ enum vb2_fileio_flags {
 /**
  * enum vb2_buffer_state - current video buffer state
  * @VB2_BUF_STATE_DEQUEUED:    buffer under userspace control
+ * @VB2_BUF_STATE_PREPARED:    buffer prepared in videobuf and by the driver
  * @VB2_BUF_STATE_QUEUED:      buffer queued in videobuf, but not in driver
  * @VB2_BUF_STATE_ACTIVE:      buffer queued in driver and possibly used
  *                             in a hardware operation
@@ -116,6 +117,7 @@ enum vb2_fileio_flags {
  */
 enum vb2_buffer_state {
        VB2_BUF_STATE_DEQUEUED,
+       VB2_BUF_STATE_PREPARED,
        VB2_BUF_STATE_QUEUED,
        VB2_BUF_STATE_ACTIVE,
        VB2_BUF_STATE_DONE,
@@ -167,13 +169,21 @@ struct vb2_buffer {
 /**
  * struct vb2_ops - driver-specific callbacks
  *
- * @queue_setup:       called from a VIDIOC_REQBUFS handler, before
- *                     memory allocation; driver should return the required
- *                     number of buffers in num_buffers, the required number
- *                     of planes per buffer in num_planes; the size of each
- *                     plane should be set in the sizes[] array and optional
- *                     per-plane allocator specific context in alloc_ctxs[]
- *                     array
+ * @queue_setup:       called from VIDIOC_REQBUFS and VIDIOC_CREATE_BUFS
+ *                     handlers before memory allocation, or, if
+ *                     *num_planes != 0, after the allocation to verify a
+ *                     smaller number of buffers. Driver should return
+ *                     the required number of buffers in *num_buffers, the
+ *                     required number of planes per buffer in *num_planes; the
+ *                     size of each plane should be set in the sizes[] array
+ *                     and optional per-plane allocator specific context in the
+ *                     alloc_ctxs[] array. When called from VIDIOC_REQBUFS,
+ *                     fmt == NULL, the driver has to use the currently
+ *                     configured format and *num_buffers is the total number
+ *                     of buffers, that are being allocated. When called from
+ *                     VIDIOC_CREATE_BUFS, fmt != NULL and it describes the
+ *                     target frame format. In this case *num_buffers are being
+ *                     allocated additionally to q->num_buffers.
  * @wait_prepare:      release any locks taken while calling vb2 functions;
  *                     it is called before an ioctl needs to wait for a new
  *                     buffer to arrive; required to avoid a deadlock in
@@ -186,11 +196,11 @@ struct vb2_buffer {
  *                     perform additional buffer-related initialization;
  *                     initialization failure (return != 0) will prevent
  *                     queue setup from completing successfully; optional
- * @buf_prepare:       called every time the buffer is queued from userspace;
- *                     drivers may perform any initialization required before
- *                     each hardware operation in this callback;
- *                     if an error is returned, the buffer will not be queued
- *                     in driver; optional
+ * @buf_prepare:       called every time the buffer is queued from userspace
+ *                     and from the VIDIOC_PREPARE_BUF ioctl; drivers may
+ *                     perform any initialization required before each hardware
+ *                     operation in this callback; if an error is returned, the
+ *                     buffer will not be queued in driver; optional
  * @buf_finish:                called before every dequeue of the buffer back to
  *                     userspace; drivers may perform any operations required
  *                     before userspace accesses the buffer; optional
@@ -216,9 +226,9 @@ struct vb2_buffer {
  *                     pre-queued buffers before calling STREAMON
  */
 struct vb2_ops {
-       int (*queue_setup)(struct vb2_queue *q, unsigned int *num_buffers,
-                          unsigned int *num_planes, unsigned int sizes[],
-                          void *alloc_ctxs[]);
+       int (*queue_setup)(struct vb2_queue *q, const struct v4l2_format *fmt,
+                          unsigned int *num_buffers, unsigned int *num_planes,
+                          unsigned int sizes[], void *alloc_ctxs[]);
 
        void (*wait_prepare)(struct vb2_queue *q);
        void (*wait_finish)(struct vb2_queue *q);
@@ -298,6 +308,9 @@ int vb2_wait_for_all_buffers(struct vb2_queue *q);
 int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b);
 int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req);
 
+int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create);
+int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b);
+
 int vb2_queue_init(struct vb2_queue *q);
 
 void vb2_queue_release(struct vb2_queue *q);
@@ -309,6 +322,13 @@ int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type);
 int vb2_streamoff(struct vb2_queue *q, enum v4l2_buf_type type);
 
 int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma);
+#ifndef CONFIG_MMU
+unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
+                                   unsigned long addr,
+                                   unsigned long len,
+                                   unsigned long pgoff,
+                                   unsigned long flags);
+#endif
 unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait);
 size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count,
                loff_t *ppos, int nonblock);
index 3d5d6db..9324488 100644 (file)
@@ -57,6 +57,36 @@ typedef uint64_t blkif_sector_t;
  * "feature-flush-cache" node!
  */
 #define BLKIF_OP_FLUSH_DISKCACHE   3
+
+/*
+ * Recognised only if "feature-discard" is present in backend xenbus info.
+ * The "feature-discard" node contains a boolean indicating whether trim
+ * (ATA) or unmap (SCSI) - conviently called discard requests are likely
+ * to succeed or fail. Either way, a discard request
+ * may fail at any time with BLKIF_RSP_EOPNOTSUPP if it is unsupported by
+ * the underlying block-device hardware. The boolean simply indicates whether
+ * or not it is worthwhile for the frontend to attempt discard requests.
+ * If a backend does not recognise BLKIF_OP_DISCARD, it should *not*
+ * create the "feature-discard" node!
+ *
+ * Discard operation is a request for the underlying block device to mark
+ * extents to be erased. However, discard does not guarantee that the blocks
+ * will be erased from the device - it is just a hint to the device
+ * controller that these blocks are no longer in use. What the device
+ * controller does with that information is left to the controller.
+ * Discard operations are passed with sector_number as the
+ * sector index to begin discard operations at and nr_sectors as the number of
+ * sectors to be discarded. The specified sectors should be discarded if the
+ * underlying block device supports trim (ATA) or unmap (SCSI) operations,
+ * or a BLKIF_RSP_EOPNOTSUPP  should be returned.
+ * More information about trim/unmap operations at:
+ * http://t13.org/Documents/UploadedDocuments/docs2008/
+ *     e07154r6-Data_Set_Management_Proposal_for_ATA-ACS2.doc
+ * http://www.seagate.com/staticfiles/support/disc/manuals/
+ *     Interface%20manuals/100293068c.pdf
+ */
+#define BLKIF_OP_DISCARD           5
+
 /*
  * Maximum scatter/gather segments per request.
  * This is carefully chosen so that sizeof(struct blkif_ring) <= PAGE_SIZE.
@@ -74,6 +104,11 @@ struct blkif_request_rw {
        } seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
 };
 
+struct blkif_request_discard {
+       blkif_sector_t sector_number;
+       uint64_t nr_sectors;
+};
+
 struct blkif_request {
        uint8_t        operation;    /* BLKIF_OP_???                         */
        uint8_t        nr_segments;  /* number of segments                   */
@@ -81,6 +116,7 @@ struct blkif_request {
        uint64_t       id;           /* private guest value, echoed in resp  */
        union {
                struct blkif_request_rw rw;
+               struct blkif_request_discard discard;
        } u;
 };
 
index 12b7458..aa39dd7 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/stop_machine.h>
 #include <linux/mutex.h>
 #include <linux/gfp.h>
+#include <linux/suspend.h>
 
 #ifdef CONFIG_SMP
 /* Serializes the updates to cpu_online_mask, cpu_present_mask */
@@ -476,6 +477,79 @@ static int alloc_frozen_cpus(void)
        return 0;
 }
 core_initcall(alloc_frozen_cpus);
+
+/*
+ * Prevent regular CPU hotplug from racing with the freezer, by disabling CPU
+ * hotplug when tasks are about to be frozen. Also, don't allow the freezer
+ * to continue until any currently running CPU hotplug operation gets
+ * completed.
+ * To modify the 'cpu_hotplug_disabled' flag, we need to acquire the
+ * 'cpu_add_remove_lock'. And this same lock is also taken by the regular
+ * CPU hotplug path and released only after it is complete. Thus, we
+ * (and hence the freezer) will block here until any currently running CPU
+ * hotplug operation gets completed.
+ */
+void cpu_hotplug_disable_before_freeze(void)
+{
+       cpu_maps_update_begin();
+       cpu_hotplug_disabled = 1;
+       cpu_maps_update_done();
+}
+
+
+/*
+ * When tasks have been thawed, re-enable regular CPU hotplug (which had been
+ * disabled while beginning to freeze tasks).
+ */
+void cpu_hotplug_enable_after_thaw(void)
+{
+       cpu_maps_update_begin();
+       cpu_hotplug_disabled = 0;
+       cpu_maps_update_done();
+}
+
+/*
+ * When callbacks for CPU hotplug notifications are being executed, we must
+ * ensure that the state of the system with respect to the tasks being frozen
+ * or not, as reported by the notification, remains unchanged *throughout the
+ * duration* of the execution of the callbacks.
+ * Hence we need to prevent the freezer from racing with regular CPU hotplug.
+ *
+ * This synchronization is implemented by mutually excluding regular CPU
+ * hotplug and Suspend/Hibernate call paths by hooking onto the Suspend/
+ * Hibernate notifications.
+ */
+static int
+cpu_hotplug_pm_callback(struct notifier_block *nb,
+                       unsigned long action, void *ptr)
+{
+       switch (action) {
+
+       case PM_SUSPEND_PREPARE:
+       case PM_HIBERNATION_PREPARE:
+               cpu_hotplug_disable_before_freeze();
+               break;
+
+       case PM_POST_SUSPEND:
+       case PM_POST_HIBERNATION:
+               cpu_hotplug_enable_after_thaw();
+               break;
+
+       default:
+               return NOTIFY_DONE;
+       }
+
+       return NOTIFY_OK;
+}
+
+
+int cpu_hotplug_pm_sync_init(void)
+{
+       pm_notifier(cpu_hotplug_pm_callback, 0);
+       return 0;
+}
+core_initcall(cpu_hotplug_pm_sync_init);
+
 #endif /* CONFIG_PM_SLEEP_SMP */
 
 /**
index 66a594e..7b01de9 100644 (file)
@@ -67,7 +67,7 @@ static void fake_signal_wake_up(struct task_struct *p)
        unsigned long flags;
 
        spin_lock_irqsave(&p->sighand->siglock, flags);
-       signal_wake_up(p, 1);
+       signal_wake_up(p, 0);
        spin_unlock_irqrestore(&p->sighand->siglock, flags);
 }
 
index 1c1797d..5167d99 100644 (file)
@@ -386,8 +386,7 @@ static int pm_qos_power_open(struct inode *inode, struct file *filp)
                pm_qos_add_request(req, pm_qos_class, PM_QOS_DEFAULT_VALUE);
                filp->private_data = req;
 
-               if (filp->private_data)
-                       return 0;
+               return 0;
        }
        return -EPERM;
 }
index d87c6e5..0e9344a 100644 (file)
@@ -7087,8 +7087,6 @@ static int __init isolated_cpu_setup(char *str)
 
 __setup("isolcpus=", isolated_cpu_setup);
 
-#define SD_NODES_PER_DOMAIN 16
-
 #ifdef CONFIG_NUMA
 
 /**
index 1481de6..434fb4f 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/init.h>
 #include <linux/hash.h>
 #include <linux/highmem.h>
+#include <linux/bootmem.h>
 #include <asm/tlbflush.h>
 
 #include <trace/events/block.h>
@@ -26,12 +27,10 @@ static mempool_t *page_pool, *isa_page_pool;
 #ifdef CONFIG_HIGHMEM
 static __init int init_emergency_pool(void)
 {
-       struct sysinfo i;
-       si_meminfo(&i);
-       si_swapinfo(&i);
-
-       if (!i.totalhigh)
+#ifndef CONFIG_MEMORY_HOTPLUG
+       if (max_pfn <= max_low_pfn)
                return 0;
+#endif
 
        page_pool = mempool_create_page_pool(POOL_SIZE, 0);
        BUG_ON(!page_pool);
index 4cb70dc..e50502d 100644 (file)
@@ -129,6 +129,9 @@ unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int flags)
        for (i = 0; i < groups ; i++)
                if (cred->uc_gids[i] != GROUP_AT(acred->group_info, i))
                        return 0;
+       if (groups < NFS_NGROUPS &&
+           cred->uc_gids[groups] != NOGROUP)
+               return 0;
        return 1;
 }
 
index f588b85..8761bf8 100644 (file)
@@ -114,6 +114,9 @@ static struct rpc_program   rpcb_program;
 static struct rpc_clnt *       rpcb_local_clnt;
 static struct rpc_clnt *       rpcb_local_clnt4;
 
+DEFINE_SPINLOCK(rpcb_clnt_lock);
+unsigned int                   rpcb_users;
+
 struct rpcbind_args {
        struct rpc_xprt *       r_xprt;
 
@@ -161,6 +164,56 @@ static void rpcb_map_release(void *data)
        kfree(map);
 }
 
+static int rpcb_get_local(void)
+{
+       int cnt;
+
+       spin_lock(&rpcb_clnt_lock);
+       if (rpcb_users)
+               rpcb_users++;
+       cnt = rpcb_users;
+       spin_unlock(&rpcb_clnt_lock);
+
+       return cnt;
+}
+
+void rpcb_put_local(void)
+{
+       struct rpc_clnt *clnt = rpcb_local_clnt;
+       struct rpc_clnt *clnt4 = rpcb_local_clnt4;
+       int shutdown;
+
+       spin_lock(&rpcb_clnt_lock);
+       if (--rpcb_users == 0) {
+               rpcb_local_clnt = NULL;
+               rpcb_local_clnt4 = NULL;
+       }
+       shutdown = !rpcb_users;
+       spin_unlock(&rpcb_clnt_lock);
+
+       if (shutdown) {
+               /*
+                * cleanup_rpcb_clnt - remove xprtsock's sysctls, unregister
+                */
+               if (clnt4)
+                       rpc_shutdown_client(clnt4);
+               if (clnt)
+                       rpc_shutdown_client(clnt);
+       }
+}
+
+static void rpcb_set_local(struct rpc_clnt *clnt, struct rpc_clnt *clnt4)
+{
+       /* Protected by rpcb_create_local_mutex */
+       rpcb_local_clnt = clnt;
+       rpcb_local_clnt4 = clnt4;
+       smp_wmb(); 
+       rpcb_users = 1;
+       dprintk("RPC:       created new rpcb local clients (rpcb_local_clnt: "
+                       "%p, rpcb_local_clnt4: %p)\n", rpcb_local_clnt,
+                       rpcb_local_clnt4);
+}
+
 /*
  * Returns zero on success, otherwise a negative errno value
  * is returned.
@@ -205,9 +258,7 @@ static int rpcb_create_local_unix(void)
                clnt4 = NULL;
        }
 
-       /* Protected by rpcb_create_local_mutex */
-       rpcb_local_clnt = clnt;
-       rpcb_local_clnt4 = clnt4;
+       rpcb_set_local(clnt, clnt4);
 
 out:
        return result;
@@ -259,9 +310,7 @@ static int rpcb_create_local_net(void)
                clnt4 = NULL;
        }
 
-       /* Protected by rpcb_create_local_mutex */
-       rpcb_local_clnt = clnt;
-       rpcb_local_clnt4 = clnt4;
+       rpcb_set_local(clnt, clnt4);
 
 out:
        return result;
@@ -271,16 +320,16 @@ out:
  * Returns zero on success, otherwise a negative errno value
  * is returned.
  */
-static int rpcb_create_local(void)
+int rpcb_create_local(void)
 {
        static DEFINE_MUTEX(rpcb_create_local_mutex);
        int result = 0;
 
-       if (rpcb_local_clnt)
+       if (rpcb_get_local())
                return result;
 
        mutex_lock(&rpcb_create_local_mutex);
-       if (rpcb_local_clnt)
+       if (rpcb_get_local())
                goto out;
 
        if (rpcb_create_local_unix() != 0)
@@ -382,11 +431,6 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port)
        struct rpc_message msg = {
                .rpc_argp       = &map,
        };
-       int error;
-
-       error = rpcb_create_local();
-       if (error)
-               return error;
 
        dprintk("RPC:       %sregistering (%u, %u, %d, %u) with local "
                        "rpcbind\n", (port ? "" : "un"),
@@ -522,11 +566,7 @@ int rpcb_v4_register(const u32 program, const u32 version,
        struct rpc_message msg = {
                .rpc_argp       = &map,
        };
-       int error;
 
-       error = rpcb_create_local();
-       if (error)
-               return error;
        if (rpcb_local_clnt4 == NULL)
                return -EPROTONOSUPPORT;
 
@@ -1060,15 +1100,3 @@ static struct rpc_program rpcb_program = {
        .version        = rpcb_version,
        .stats          = &rpcb_stats,
 };
-
-/**
- * cleanup_rpcb_clnt - remove xprtsock's sysctls, unregister
- *
- */
-void cleanup_rpcb_clnt(void)
-{
-       if (rpcb_local_clnt4)
-               rpc_shutdown_client(rpcb_local_clnt4);
-       if (rpcb_local_clnt)
-               rpc_shutdown_client(rpcb_local_clnt);
-}
index 9d08091..8ec9778 100644 (file)
@@ -61,8 +61,6 @@ static struct pernet_operations sunrpc_net_ops = {
 
 extern struct cache_detail unix_gid_cache;
 
-extern void cleanup_rpcb_clnt(void);
-
 static int __init
 init_sunrpc(void)
 {
@@ -102,7 +100,6 @@ out:
 static void __exit
 cleanup_sunrpc(void)
 {
-       cleanup_rpcb_clnt();
        rpcauth_remove_module();
        cleanup_socket_xprt();
        svc_cleanup_xprt_sock();
index dd5cc00..6e03888 100644 (file)
@@ -366,6 +366,42 @@ svc_pool_for_cpu(struct svc_serv *serv, int cpu)
        return &serv->sv_pools[pidx % serv->sv_nrpools];
 }
 
+static int svc_rpcb_setup(struct svc_serv *serv)
+{
+       int err;
+
+       err = rpcb_create_local();
+       if (err)
+               return err;
+
+       /* Remove any stale portmap registrations */
+       svc_unregister(serv);
+       return 0;
+}
+
+void svc_rpcb_cleanup(struct svc_serv *serv)
+{
+       svc_unregister(serv);
+       rpcb_put_local();
+}
+EXPORT_SYMBOL_GPL(svc_rpcb_cleanup);
+
+static int svc_uses_rpcbind(struct svc_serv *serv)
+{
+       struct svc_program      *progp;
+       unsigned int            i;
+
+       for (progp = serv->sv_program; progp; progp = progp->pg_next) {
+               for (i = 0; i < progp->pg_nvers; i++) {
+                       if (progp->pg_vers[i] == NULL)
+                               continue;
+                       if (progp->pg_vers[i]->vs_hidden == 0)
+                               return 1;
+               }
+       }
+
+       return 0;
+}
 
 /*
  * Create an RPC service
@@ -431,8 +467,15 @@ __svc_create(struct svc_program *prog, unsigned int bufsize, int npools,
                spin_lock_init(&pool->sp_lock);
        }
 
-       /* Remove any stale portmap registrations */
-       svc_unregister(serv);
+       if (svc_uses_rpcbind(serv)) {
+               if (svc_rpcb_setup(serv) < 0) {
+                       kfree(serv->sv_pools);
+                       kfree(serv);
+                       return NULL;
+               }
+               if (!serv->sv_shutdown)
+                       serv->sv_shutdown = svc_rpcb_cleanup;
+       }
 
        return serv;
 }
@@ -500,7 +543,6 @@ svc_destroy(struct svc_serv *serv)
        if (svc_serv_is_pooled(serv))
                svc_pool_map_put();
 
-       svc_unregister(serv);
        kfree(serv->sv_pools);
        kfree(serv);
 }
index 978fe1a..59edb12 100644 (file)
@@ -1081,12 +1081,12 @@ static int snd_ctl_elem_init_enum_names(struct user_element *ue)
        char *names, *p;
        size_t buf_len, name_len;
        unsigned int i;
+       const uintptr_t user_ptrval = ue->info.value.enumerated.names_ptr;
 
        if (ue->info.value.enumerated.names_length > 64 * 1024)
                return -EINVAL;
 
-       names = memdup_user(
-               (const void __user *)ue->info.value.enumerated.names_ptr,
+       names = memdup_user((const void __user *)user_ptrval,
                ue->info.value.enumerated.names_length);
        if (IS_ERR(names))
                return PTR_ERR(names);
index a70ee7f..031e215 100644 (file)
@@ -272,7 +272,14 @@ static int snd_hwdep_control_ioctl(struct snd_card *card,
                        if (get_user(device, (int __user *)arg))
                                return -EFAULT;
                        mutex_lock(&register_mutex);
-                       device = device < 0 ? 0 : device + 1;
+
+                       if (device < 0)
+                               device = 0;
+                       else if (device < SNDRV_MINOR_HWDEPS)
+                               device++;
+                       else
+                               device = SNDRV_MINOR_HWDEPS;
+
                        while (device < SNDRV_MINOR_HWDEPS) {
                                if (snd_hwdep_search(card, device))
                                        break;
index 72e5885..7e7d078 100644 (file)
@@ -756,8 +756,6 @@ static int get_line_from_fw(char *buf, int size, struct firmware *fw)
        }
        if (!fw->size)
                return 0;
-       if (size < fw->size)
-               size = fw->size;
 
        for (len = 0; len < fw->size; len++) {
                if (!*p)
index bd7fc99..096507d 100644 (file)
@@ -3063,12 +3063,12 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
          .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
          .class_mask = 0xffffff,
          .driver_data = AZX_DRIVER_CTX | AZX_DCAPS_CTX_WORKAROUND |
-         AZX_DCAPS_RIRB_PRE_DELAY },
+         AZX_DCAPS_RIRB_PRE_DELAY | AZX_DCAPS_POSFIX_LPIB },
 #else
        /* this entry seems still valid -- i.e. without emu20kx chip */
        { PCI_DEVICE(0x1102, 0x0009),
          .driver_data = AZX_DRIVER_CTX | AZX_DCAPS_CTX_WORKAROUND |
-         AZX_DCAPS_RIRB_PRE_DELAY },
+         AZX_DCAPS_RIRB_PRE_DELAY | AZX_DCAPS_POSFIX_LPIB },
 #endif
        /* Vortex86MX */
        { PCI_DEVICE(0x17f3, 0x3010), .driver_data = AZX_DRIVER_GENERIC },
index 81e12c0..dcbea0d 100644 (file)
@@ -442,6 +442,8 @@ struct auto_pin_cfg {
        (cfg & AC_DEFCFG_SEQUENCE)
 #define get_defcfg_device(cfg) \
        ((cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT)
+#define get_defcfg_misc(cfg) \
+       ((cfg & AC_DEFCFG_MISC) >> AC_DEFCFG_MISC_SHIFT)
 
 /* bit-flags for snd_hda_parse_pin_def_config() behavior */
 #define HDA_PINCFG_NO_HP_FIXUP (1 << 0) /* no HP-split */
@@ -509,6 +511,11 @@ int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid);
 static inline bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid)
 {
        return (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_PRES_DETECT) &&
+               /* disable MISC_NO_PRESENCE check because it may break too
+                * many devices
+                */
+               /*(get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid) &
+                 AC_DEFCFG_MISC_NO_PRESENCE)) &&*/
                (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP);
 }
 
index 3425401..aac3bfa 100644 (file)
@@ -1006,7 +1006,6 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
        unsigned int caps, config;
        int pin_idx;
        struct hdmi_spec_per_pin *per_pin;
-       struct hdmi_eld *eld;
        int err;
 
        caps = snd_hda_param_read(codec, pin_nid, AC_PAR_PIN_CAP);
@@ -1023,7 +1022,6 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
 
        pin_idx = spec->num_pins;
        per_pin = &spec->pins[pin_idx];
-       eld = &per_pin->sink_eld;
 
        per_pin->pin_nid = pin_nid;
 
@@ -1576,7 +1574,7 @@ static int nvhdmi_8ch_7x_pcm_prepare(struct hda_pcm_stream *hinfo,
                                     struct snd_pcm_substream *substream)
 {
        int chs;
-       unsigned int dataDCC1, dataDCC2, channel_id;
+       unsigned int dataDCC2, channel_id;
        int i;
        struct hdmi_spec *spec = codec->spec;
        struct hda_spdif_out *spdif =
@@ -1586,7 +1584,6 @@ static int nvhdmi_8ch_7x_pcm_prepare(struct hda_pcm_stream *hinfo,
 
        chs = substream->runtime->channels;
 
-       dataDCC1 = AC_DIG1_ENABLE | AC_DIG1_COPYRIGHT;
        dataDCC2 = 0x2;
 
        /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
index 8f93b97..9693059 100644 (file)
@@ -1604,27 +1604,29 @@ static void alc_auto_init_digital(struct hda_codec *codec)
 static void alc_auto_parse_digital(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       int i, err;
+       int i, err, nums;
        hda_nid_t dig_nid;
 
        /* support multiple SPDIFs; the secondary is set up as a slave */
+       nums = 0;
        for (i = 0; i < spec->autocfg.dig_outs; i++) {
                hda_nid_t conn[4];
                err = snd_hda_get_connections(codec,
                                              spec->autocfg.dig_out_pins[i],
                                              conn, ARRAY_SIZE(conn));
-               if (err < 0)
+               if (err <= 0)
                        continue;
                dig_nid = conn[0]; /* assume the first element is audio-out */
-               if (!i) {
+               if (!nums) {
                        spec->multiout.dig_out_nid = dig_nid;
                        spec->dig_out_type = spec->autocfg.dig_out_type[0];
                } else {
                        spec->multiout.slave_dig_outs = spec->slave_dig_outs;
-                       if (i >= ARRAY_SIZE(spec->slave_dig_outs) - 1)
+                       if (nums >= ARRAY_SIZE(spec->slave_dig_outs) - 1)
                                break;
-                       spec->slave_dig_outs[i - 1] = dig_nid;
+                       spec->slave_dig_outs[nums - 1] = dig_nid;
                }
+               nums++;
        }
 
        if (spec->autocfg.dig_in_pin) {
@@ -2270,6 +2272,7 @@ static int alc_build_pcms(struct hda_codec *codec)
        struct alc_spec *spec = codec->spec;
        struct hda_pcm *info = spec->pcm_rec;
        const struct hda_pcm_stream *p;
+       bool have_multi_adcs;
        int i;
 
        codec->num_pcms = 1;
@@ -2348,8 +2351,11 @@ static int alc_build_pcms(struct hda_codec *codec)
        /* If the use of more than one ADC is requested for the current
         * model, configure a second analog capture-only PCM.
         */
+       have_multi_adcs = (spec->num_adc_nids > 1) &&
+               !spec->dyn_adc_switch && !spec->auto_mic &&
+               (!spec->input_mux || spec->input_mux->num_items > 1);
        /* Additional Analaog capture for index #2 */
-       if (spec->alt_dac_nid || spec->num_adc_nids > 1) {
+       if (spec->alt_dac_nid || have_multi_adcs) {
                codec->num_pcms = 3;
                info = spec->pcm_rec + 2;
                info->name = spec->stream_name_analog;
@@ -2365,7 +2371,7 @@ static int alc_build_pcms(struct hda_codec *codec)
                                alc_pcm_null_stream;
                        info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0;
                }
-               if (spec->num_adc_nids > 1) {
+               if (have_multi_adcs) {
                        p = spec->stream_analog_alt_capture;
                        if (!p)
                                p = &alc_pcm_analog_alt_capture;
@@ -2657,7 +2663,6 @@ static int alc_auto_fill_adc_caps(struct hda_codec *codec)
        hda_nid_t *adc_nids = spec->private_adc_nids;
        hda_nid_t *cap_nids = spec->private_capsrc_nids;
        int max_nums = ARRAY_SIZE(spec->private_adc_nids);
-       bool indep_capsrc = false;
        int i, nums = 0;
 
        nid = codec->start_nid;
@@ -2679,13 +2684,11 @@ static int alc_auto_fill_adc_caps(struct hda_codec *codec)
                                break;
                        if (type == AC_WID_AUD_SEL) {
                                cap_nids[nums] = src;
-                               indep_capsrc = true;
                                break;
                        }
                        n = snd_hda_get_conn_list(codec, src, &list);
                        if (n > 1) {
                                cap_nids[nums] = src;
-                               indep_capsrc = true;
                                break;
                        } else if (n != 1)
                                break;
@@ -3326,6 +3329,12 @@ static void alc_auto_set_output_and_unmute(struct hda_codec *codec,
        if (nid)
                snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
                                    AMP_OUT_ZERO);
+
+       /* unmute DAC if it's not assigned to a mixer */
+       nid = alc_look_for_out_mute_nid(codec, pin, dac);
+       if (nid == mix && nid_has_mute(codec, dac, HDA_OUTPUT))
+               snd_hda_codec_write(codec, dac, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+                                   AMP_OUT_ZERO);
 }
 
 static void alc_auto_init_multi_out(struct hda_codec *codec)
index 59a52a4..de4c360 100644 (file)
@@ -3791,9 +3791,10 @@ static int is_dual_headphones(struct hda_codec *codec)
 }
 
 
-static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out, hda_nid_t dig_in)
+static int stac92xx_parse_auto_config(struct hda_codec *codec)
 {
        struct sigmatel_spec *spec = codec->spec;
+       hda_nid_t dig_out = 0, dig_in = 0;
        int hp_swap = 0;
        int i, err;
 
@@ -3976,6 +3977,22 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out
        if (spec->multiout.max_channels > 2)
                spec->surr_switch = 1;
 
+       /* find digital out and in converters */
+       for (i = codec->start_nid; i < codec->start_nid + codec->num_nodes; i++) {
+               unsigned int wid_caps = get_wcaps(codec, i);
+               if (wid_caps & AC_WCAP_DIGITAL) {
+                       switch (get_wcaps_type(wid_caps)) {
+                       case AC_WID_AUD_OUT:
+                               if (!dig_out)
+                                       dig_out = i;
+                               break;
+                       case AC_WID_AUD_IN:
+                               if (!dig_in)
+                                       dig_in = i;
+                               break;
+                       }
+               }
+       }
        if (spec->autocfg.dig_outs)
                spec->multiout.dig_out_nid = dig_out;
        if (dig_in && spec->autocfg.dig_in_pin)
@@ -5279,7 +5296,7 @@ static int patch_stac925x(struct hda_codec *codec)
        spec->capvols = stac925x_capvols;
        spec->capsws = stac925x_capsws;
 
-       err = stac92xx_parse_auto_config(codec, 0x8, 0x7);
+       err = stac92xx_parse_auto_config(codec);
        if (!err) {
                if (spec->board_config < 0) {
                        printk(KERN_WARNING "hda_codec: No auto-config is "
@@ -5420,7 +5437,7 @@ again:
        spec->num_pwrs = ARRAY_SIZE(stac92hd73xx_pwr_nids);
        spec->pwr_nids = stac92hd73xx_pwr_nids;
 
-       err = stac92xx_parse_auto_config(codec, 0x25, 0x27);
+       err = stac92xx_parse_auto_config(codec);
 
        if (!err) {
                if (spec->board_config < 0) {
@@ -5629,26 +5646,8 @@ again:
                stac92xx_set_config_regs(codec,
                                stac92hd83xxx_brd_tbl[spec->board_config]);
 
-       switch (codec->vendor_id) {
-       case 0x111d76d1:
-       case 0x111d76d9:
-       case 0x111d76df:
-       case 0x111d76e5:
-       case 0x111d7666:
-       case 0x111d7667:
-       case 0x111d7668:
-       case 0x111d7669:
-       case 0x111d76e3:
-       case 0x111d7604:
-       case 0x111d76d4:
-       case 0x111d7605:
-       case 0x111d76d5:
-       case 0x111d76e7:
-               if (spec->board_config == STAC_92HD83XXX_PWR_REF)
-                       break;
+       if (spec->board_config != STAC_92HD83XXX_PWR_REF)
                spec->num_pwrs = 0;
-               break;
-       }
 
        codec->patch_ops = stac92xx_patch_ops;
 
@@ -5675,7 +5674,7 @@ again:
        }
 #endif 
 
-       err = stac92xx_parse_auto_config(codec, 0x1d, 0);
+       err = stac92xx_parse_auto_config(codec);
        if (!err) {
                if (spec->board_config < 0) {
                        printk(KERN_WARNING "hda_codec: No auto-config is "
@@ -5996,7 +5995,7 @@ again:
 
        spec->multiout.dac_nids = spec->dac_nids;
 
-       err = stac92xx_parse_auto_config(codec, 0x21, 0);
+       err = stac92xx_parse_auto_config(codec);
        if (!err) {
                if (spec->board_config < 0) {
                        printk(KERN_WARNING "hda_codec: No auto-config is "
@@ -6105,7 +6104,7 @@ static int patch_stac922x(struct hda_codec *codec)
 
        spec->multiout.dac_nids = spec->dac_nids;
        
-       err = stac92xx_parse_auto_config(codec, 0x08, 0x09);
+       err = stac92xx_parse_auto_config(codec);
        if (!err) {
                if (spec->board_config < 0) {
                        printk(KERN_WARNING "hda_codec: No auto-config is "
@@ -6230,7 +6229,7 @@ static int patch_stac927x(struct hda_codec *codec)
        spec->aloopback_shift = 0;
        spec->eapd_switch = 1;
 
-       err = stac92xx_parse_auto_config(codec, 0x1e, 0x20);
+       err = stac92xx_parse_auto_config(codec);
        if (!err) {
                if (spec->board_config < 0) {
                        printk(KERN_WARNING "hda_codec: No auto-config is "
@@ -6355,7 +6354,7 @@ static int patch_stac9205(struct hda_codec *codec)
                break;
        }
 
-       err = stac92xx_parse_auto_config(codec, 0x1f, 0x20);
+       err = stac92xx_parse_auto_config(codec);
        if (!err) {
                if (spec->board_config < 0) {
                        printk(KERN_WARNING "hda_codec: No auto-config is "
@@ -6460,7 +6459,7 @@ static int patch_stac9872(struct hda_codec *codec)
        spec->capvols = stac9872_capvols;
        spec->capsws = stac9872_capsws;
 
-       err = stac92xx_parse_auto_config(codec, 0x10, 0x12);
+       err = stac92xx_parse_auto_config(codec);
        if (err < 0) {
                stac92xx_free(codec);
                return -EINVAL;
@@ -6565,6 +6564,18 @@ static const struct hda_codec_preset snd_hda_preset_sigmatel[] = {
        { .id = 0x111d76e3, .name = "92HD98BXX", .patch = patch_stac92hd83xxx},
        { .id = 0x111d76e5, .name = "92HD99BXX", .patch = patch_stac92hd83xxx},
        { .id = 0x111d76e7, .name = "92HD90BXX", .patch = patch_stac92hd83xxx},
+       { .id = 0x111d76e8, .name = "92HD66B1X5", .patch = patch_stac92hd83xxx},
+       { .id = 0x111d76e9, .name = "92HD66B2X5", .patch = patch_stac92hd83xxx},
+       { .id = 0x111d76ea, .name = "92HD66B3X5", .patch = patch_stac92hd83xxx},
+       { .id = 0x111d76eb, .name = "92HD66C1X5", .patch = patch_stac92hd83xxx},
+       { .id = 0x111d76ec, .name = "92HD66C2X5", .patch = patch_stac92hd83xxx},
+       { .id = 0x111d76ed, .name = "92HD66C3X5", .patch = patch_stac92hd83xxx},
+       { .id = 0x111d76ee, .name = "92HD66B1X3", .patch = patch_stac92hd83xxx},
+       { .id = 0x111d76ef, .name = "92HD66B2X3", .patch = patch_stac92hd83xxx},
+       { .id = 0x111d76f0, .name = "92HD66B3X3", .patch = patch_stac92hd83xxx},
+       { .id = 0x111d76f1, .name = "92HD66C1X3", .patch = patch_stac92hd83xxx},
+       { .id = 0x111d76f2, .name = "92HD66C2X3", .patch = patch_stac92hd83xxx},
+       { .id = 0x111d76f3, .name = "92HD66C3/65", .patch = patch_stac92hd83xxx},
        {} /* terminator */
 };
 
index 417d62a..0b020a9 100644 (file)
@@ -3700,13 +3700,8 @@ static const struct hda_verb vt1812_init_verbs[] = {
 static void set_widgets_power_state_vt1812(struct hda_codec *codec)
 {
        struct via_spec *spec = codec->spec;
-       int imux_is_smixer =
-       snd_hda_codec_read(codec, 0x13, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 3;
        unsigned int parm;
        unsigned int present;
-       /* MUX10 (1eh) = stereo mixer */
-       imux_is_smixer =
-       snd_hda_codec_read(codec, 0x1e, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 5;
        /* inputs */
        /* PW 5/6/7 (29h/2ah/2bh) */
        parm = AC_PWRST_D3;
index 6a5b387..45b2055 100644 (file)
 #include <asm/pgtable.h>
 #include <asm/cacheflush.h>
 
+#ifdef CONFIG_KVM_GUEST
+#include <linux/kvm_para.h>
+#else
+#define kvm_para_available() (0)
+#endif
+
 MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
 MODULE_DESCRIPTION("Intel 82801AA,82901AB,i810,i820,i830,i840,i845,MX440; SiS 7012; Ali 5455");
 MODULE_LICENSE("GPL");
@@ -77,6 +83,7 @@ static int buggy_semaphore;
 static int buggy_irq = -1; /* auto-check */
 static int xbox;
 static int spdif_aclink = -1;
+static int inside_vm = -1;
 
 module_param(index, int, 0444);
 MODULE_PARM_DESC(index, "Index value for Intel i8x0 soundcard.");
@@ -94,6 +101,8 @@ module_param(xbox, bool, 0444);
 MODULE_PARM_DESC(xbox, "Set to 1 for Xbox, if you have problems with the AC'97 codec detection.");
 module_param(spdif_aclink, int, 0444);
 MODULE_PARM_DESC(spdif_aclink, "S/PDIF over AC-link.");
+module_param(inside_vm, bool, 0444);
+MODULE_PARM_DESC(inside_vm, "KVM/Parallels optimization.");
 
 /* just for backward compatibility */
 static int enable;
@@ -400,6 +409,7 @@ struct intel8x0 {
        unsigned buggy_irq: 1;          /* workaround for buggy mobos */
        unsigned xbox: 1;               /* workaround for Xbox AC'97 detection */
        unsigned buggy_semaphore: 1;    /* workaround for buggy codec semaphore */
+       unsigned inside_vm: 1;          /* enable VM optimization */
 
        int spdif_idx;  /* SPDIF BAR index; *_SPBAR or -1 if use PCMOUT */
        unsigned int sdm_saved; /* SDM reg value */
@@ -1065,8 +1075,11 @@ static snd_pcm_uframes_t snd_intel8x0_pcm_pointer(struct snd_pcm_substream *subs
                        udelay(10);
                        continue;
                }
-               if (civ == igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV) &&
-                   ptr1 == igetword(chip, ichdev->reg_offset + ichdev->roff_picb))
+               if (civ != igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV))
+                       continue;
+               if (chip->inside_vm)
+                       break;
+               if (ptr1 == igetword(chip, ichdev->reg_offset + ichdev->roff_picb))
                        break;
        } while (timeout--);
        ptr = ichdev->last_pos;
@@ -2984,6 +2997,10 @@ static int __devinit snd_intel8x0_create(struct snd_card *card,
        if (xbox)
                chip->xbox = 1;
 
+       chip->inside_vm = inside_vm;
+       if (inside_vm)
+               printk(KERN_INFO "intel8x0: enable KVM optimization\n");
+
        if (pci->vendor == PCI_VENDOR_ID_INTEL &&
            pci->device == PCI_DEVICE_ID_INTEL_440MX)
                chip->fix_nocache = 1; /* enable workaround */
@@ -3226,6 +3243,14 @@ static int __devinit snd_intel8x0_probe(struct pci_dev *pci,
                        buggy_irq = 0;
        }
 
+       if (inside_vm < 0) {
+               /* detect KVM and Parallels virtual environments */
+               inside_vm = kvm_para_available();
+#if defined(__i386__) || defined(__x86_64__)
+               inside_vm = inside_vm || boot_cpu_has(X86_FEATURE_HYPERVISOR);
+#endif
+       }
+
        if ((err = snd_intel8x0_create(card, pci, pci_id->driver_data,
                                       &chip)) < 0) {
                snd_card_free(card);
index 1c6d1e1..f742202 100644 (file)
@@ -151,7 +151,7 @@ MODULE_FIRMWARE("digiface_firmware_rev11.bin");
 #define HDSP_PROGRAM           0x020
 #define HDSP_CONFIG_MODE_0     0x040
 #define HDSP_CONFIG_MODE_1     0x080
-#define HDSP_VERSION_BIT       0x100
+#define HDSP_VERSION_BIT       (0x100 | HDSP_S_LOAD)
 #define HDSP_BIGENDIAN_MODE     0x200
 #define HDSP_RD_MULTIPLE        0x400
 #define HDSP_9652_ENABLE_MIXER  0x800
index 6e2f7ef..15a6c3b 100644 (file)
@@ -520,16 +520,9 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
 #define HDSPM_DMA_AREA_BYTES (HDSPM_MAX_CHANNELS * HDSPM_CHANNEL_BUFFER_BYTES)
 #define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024)
 
-/* revisions >= 230 indicate AES32 card */
-#define HDSPM_MADI_ANCIENT_REV 204
-#define HDSPM_MADI_OLD_REV     207
-#define HDSPM_MADI_REV         210
 #define HDSPM_RAYDAT_REV       211
 #define HDSPM_AIO_REV          212
 #define HDSPM_MADIFACE_REV     213
-#define HDSPM_AES_REV          240
-#define HDSPM_AES32_REV                234
-#define HDSPM_AES32_OLD_REV    233
 
 /* speed factor modes */
 #define HDSPM_SPEED_SINGLE 0
@@ -6253,7 +6246,7 @@ static int snd_hdspm_hwdep_ioctl(struct snd_hwdep *hw, struct file *file,
                        status.card_specific.madi.madi_input =
                                (statusregister & HDSPM_AB_int) ? 1 : 0;
                        status.card_specific.madi.channel_format =
-                               (statusregister & HDSPM_TX_64ch) ? 1 : 0;
+                               (statusregister & HDSPM_RX_64ch) ? 1 : 0;
                        /* TODO: Mac driver sets it when f_s>48kHz */
                        status.card_specific.madi.frame_format = 0;
 
@@ -6503,13 +6496,6 @@ static int __devinit snd_hdspm_create(struct snd_card *card,
        strcpy(card->driver, "HDSPM");
 
        switch (hdspm->firmware_rev) {
-       case HDSPM_MADI_REV:
-       case HDSPM_MADI_OLD_REV:
-       case HDSPM_MADI_ANCIENT_REV:
-               hdspm->io_type = MADI;
-               hdspm->card_name = "RME MADI";
-               hdspm->midiPorts = 3;
-               break;
        case HDSPM_RAYDAT_REV:
                hdspm->io_type = RayDAT;
                hdspm->card_name = "RME RayDAT";
@@ -6525,17 +6511,25 @@ static int __devinit snd_hdspm_create(struct snd_card *card,
                hdspm->card_name = "RME MADIface";
                hdspm->midiPorts = 1;
                break;
-       case HDSPM_AES_REV:
-       case HDSPM_AES32_REV:
-       case HDSPM_AES32_OLD_REV:
-               hdspm->io_type = AES32;
-               hdspm->card_name = "RME AES32";
-               hdspm->midiPorts = 2;
-               break;
        default:
-               snd_printk(KERN_ERR "HDSPM: unknown firmware revision %x\n",
+               if ((hdspm->firmware_rev == 0xf0) ||
+                       ((hdspm->firmware_rev >= 0xe6) &&
+                                       (hdspm->firmware_rev <= 0xea))) {
+                       hdspm->io_type = AES32;
+                       hdspm->card_name = "RME AES32";
+                       hdspm->midiPorts = 2;
+               } else if ((hdspm->firmware_rev == 0xd5) ||
+                       ((hdspm->firmware_rev >= 0xc8)  &&
+                               (hdspm->firmware_rev <= 0xcf))) {
+                       hdspm->io_type = MADI;
+                       hdspm->card_name = "RME MADI";
+                       hdspm->midiPorts = 3;
+               } else {
+                       snd_printk(KERN_ERR
+                               "HDSPM: unknown firmware revision %x\n",
                                hdspm->firmware_rev);
-               return -ENODEV;
+                       return -ENODEV;
+               }
        }
 
        err = pci_enable_device(pci);
index ab27dbc..336de8f 100644 (file)
@@ -430,6 +430,7 @@ static int tlv320aic23_set_dai_fmt(struct snd_soc_dai *codec_dai,
                iface_reg |= TLV320AIC23_MS_MASTER;
                break;
        case SND_SOC_DAIFMT_CBS_CFS:
+               iface_reg &= ~TLV320AIC23_MS_MASTER;
                break;
        default:
                return -EINVAL;
index 7a49390..87d5ef1 100644 (file)
@@ -1023,6 +1023,7 @@ static int aic3x_set_dai_fmt(struct snd_soc_dai *codec_dai,
                break;
        case SND_SOC_DAIFMT_CBS_CFS:
                aic3x->master = 0;
+               iface_areg &= ~(BIT_CLK_MASTER | WORD_CLK_MASTER);
                break;
        default:
                return -EINVAL;
index 5d88c99..42d9039 100644 (file)
@@ -2361,13 +2361,17 @@ static int wm5100_gpio_direction_out(struct gpio_chip *chip,
 {
        struct wm5100_priv *wm5100 = gpio_to_wm5100(chip);
        struct snd_soc_codec *codec = wm5100->codec;
-       int val;
+       int val, ret;
 
        val = (1 << WM5100_GP1_FN_SHIFT) | (!!value << WM5100_GP1_LVL_SHIFT);
 
-       return snd_soc_update_bits(codec, WM5100_GPIO_CTRL_1 + offset,
-                                  WM5100_GP1_FN_MASK | WM5100_GP1_DIR |
-                                  WM5100_GP1_LVL, val);
+       ret = snd_soc_update_bits(codec, WM5100_GPIO_CTRL_1 + offset,
+                                 WM5100_GP1_FN_MASK | WM5100_GP1_DIR |
+                                 WM5100_GP1_LVL, val);
+       if (ret < 0)
+               return ret;
+       else
+               return 0;
 }
 
 static int wm5100_gpio_get(struct gpio_chip *chip, unsigned offset)
index 8d0347c..076bdb9 100644 (file)
@@ -151,7 +151,7 @@ static int wm8711_hw_params(struct snd_pcm_substream *substream,
 {
        struct snd_soc_codec *codec = dai->codec;
        struct wm8711_priv *wm8711 =  snd_soc_codec_get_drvdata(codec);
-       u16 iface = snd_soc_read(codec, WM8711_IFACE) & 0xfffc;
+       u16 iface = snd_soc_read(codec, WM8711_IFACE) & 0xfff3;
        int i = get_coeff(wm8711->sysclk, params_rate(params));
        u16 srate = (coeff_div[i].sr << 2) |
                (coeff_div[i].bosr << 1) | coeff_div[i].usb;
@@ -232,7 +232,7 @@ static int wm8711_set_dai_fmt(struct snd_soc_dai *codec_dai,
                unsigned int fmt)
 {
        struct snd_soc_codec *codec = codec_dai->codec;
-       u16 iface = 0;
+       u16 iface = snd_soc_read(codec, WM8711_IFACE) & 0x000c;
 
        /* set master/slave audio interface */
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
index 9fc8f4c..285ef87 100644 (file)
@@ -867,7 +867,7 @@ SOC_ENUM("Right Capture Mode", rin_mode),
 SOC_DOUBLE_R("Capture Volume", WM8904_ANALOGUE_LEFT_INPUT_0,
             WM8904_ANALOGUE_RIGHT_INPUT_0, 0, 31, 0),
 SOC_DOUBLE_R("Capture Switch", WM8904_ANALOGUE_LEFT_INPUT_0,
-            WM8904_ANALOGUE_RIGHT_INPUT_0, 7, 1, 0),
+            WM8904_ANALOGUE_RIGHT_INPUT_0, 7, 1, 1),
 
 SOC_SINGLE("High Pass Filter Switch", WM8904_ADC_DIGITAL_0, 4, 1, 0),
 SOC_ENUM("High Pass Filter Mode", hpf_mode),
index dc5cb31..de9ec9b 100644 (file)
@@ -621,7 +621,7 @@ static int wm8940_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
 
        switch (div_id) {
        case WM8940_BCLKDIV:
-               reg = snd_soc_read(codec, WM8940_CLOCK) & 0xFFEF3;
+               reg = snd_soc_read(codec, WM8940_CLOCK) & 0xFFE3;
                ret = snd_soc_write(codec, WM8940_CLOCK, reg | (div << 2));
                break;
        case WM8940_MCLKDIV:
index f60dfa1..91d3c6d 100644 (file)
@@ -1961,7 +1961,13 @@ static int wm8962_readable_register(struct snd_soc_codec *codec, unsigned int re
 
 static int wm8962_reset(struct snd_soc_codec *codec)
 {
-       return snd_soc_write(codec, WM8962_SOFTWARE_RESET, 0x6243);
+       int ret;
+
+       ret = snd_soc_write(codec, WM8962_SOFTWARE_RESET, 0x6243);
+       if (ret != 0)
+               return ret;
+
+       return snd_soc_write(codec, WM8962_PLL_SOFTWARE_RESET, 0);
 }
 
 static const DECLARE_TLV_DB_SCALE(inpga_tlv, -2325, 75, 0);
@@ -2360,15 +2366,14 @@ static int sysclk_event(struct snd_soc_dapm_widget *w,
 
                        snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1,
                                            WM8962_FLL_ENA, WM8962_FLL_ENA);
-                       if (wm8962->irq) {
-                               timeout = msecs_to_jiffies(5);
-                               timeout = wait_for_completion_timeout(&wm8962->fll_lock,
-                                                                     timeout);
-
-                               if (timeout == 0)
-                                       dev_err(codec->dev,
-                                               "Timed out starting FLL\n");
-                       }
+
+                       timeout = msecs_to_jiffies(5);
+                       timeout = wait_for_completion_timeout(&wm8962->fll_lock,
+                                                             timeout);
+
+                       if (wm8962->irq && timeout == 0)
+                               dev_err(codec->dev,
+                                       "Timed out starting FLL\n");
                }
                break;
 
@@ -4029,6 +4034,11 @@ static int wm8962_probe(struct snd_soc_codec *codec)
        snd_soc_update_bits(codec, WM8962_CLOCKING2,
                            WM8962_CLKREG_OVD, WM8962_CLKREG_OVD);
 
+       /* Ensure that the oscillator and PLLs are disabled */
+       snd_soc_update_bits(codec, WM8962_PLL2,
+                           WM8962_OSC_ENA | WM8962_PLL2_ENA | WM8962_PLL3_ENA,
+                           0);
+
        regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
 
        if (pdata) {
index b5e922f..bad91b4 100644 (file)
@@ -271,7 +271,10 @@ static int s3c_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
 
        writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL);
 
-       s3c2410_dma_ctrl(dma_data->channel, S3C2410_DMAOP_STARTED);
+       if (!dma_data->ops)
+               dma_data->ops = samsung_dma_get_ops();
+
+       dma_data->ops->started(dma_data->channel);
 
        return 0;
 }
@@ -317,7 +320,10 @@ static int s3c_ac97_mic_trigger(struct snd_pcm_substream *substream,
 
        writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL);
 
-       s3c2410_dma_ctrl(dma_data->channel, S3C2410_DMAOP_STARTED);
+       if (!dma_data->ops)
+               dma_data->ops = samsung_dma_get_ops();
+
+       dma_data->ops->started(dma_data->channel);
 
        return 0;
 }
index 9465588..2d622b6 100644 (file)
@@ -54,7 +54,6 @@ struct runtime_data {
        spinlock_t lock;
        int state;
        unsigned int dma_loaded;
-       unsigned int dma_limit;
        unsigned int dma_period;
        dma_addr_t dma_start;
        dma_addr_t dma_pos;
@@ -62,77 +61,79 @@ struct runtime_data {
        struct s3c_dma_params *params;
 };
 
+static void audio_buffdone(void *data);
+
 /* dma_enqueue
  *
  * place a dma buffer onto the queue for the dma system
  * to handle.
-*/
+ */
 static void dma_enqueue(struct snd_pcm_substream *substream)
 {
        struct runtime_data *prtd = substream->runtime->private_data;
        dma_addr_t pos = prtd->dma_pos;
        unsigned int limit;
-       int ret;
+       struct samsung_dma_prep_info dma_info;
 
        pr_debug("Entered %s\n", __func__);
 
-       if (s3c_dma_has_circular())
-               limit = (prtd->dma_end - prtd->dma_start) / prtd->dma_period;
-       else
-               limit = prtd->dma_limit;
+       limit = (prtd->dma_end - prtd->dma_start) / prtd->dma_period;
 
        pr_debug("%s: loaded %d, limit %d\n",
                                __func__, prtd->dma_loaded, limit);
 
-       while (prtd->dma_loaded < limit) {
-               unsigned long len = prtd->dma_period;
+       dma_info.cap = (samsung_dma_has_circular() ? DMA_CYCLIC : DMA_SLAVE);
+       dma_info.direction =
+               (substream->stream == SNDRV_PCM_STREAM_PLAYBACK
+               ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+       dma_info.fp = audio_buffdone;
+       dma_info.fp_param = substream;
+       dma_info.period = prtd->dma_period;
+       dma_info.len = prtd->dma_period*limit;
 
+       while (prtd->dma_loaded < limit) {
                pr_debug("dma_loaded: %d\n", prtd->dma_loaded);
 
-               if ((pos + len) > prtd->dma_end) {
-                       len  = prtd->dma_end - pos;
-                       pr_debug("%s: corrected dma len %ld\n", __func__, len);
+               if ((pos + dma_info.period) > prtd->dma_end) {
+                       dma_info.period  = prtd->dma_end - pos;
+                       pr_debug("%s: corrected dma len %ld\n",
+                                       __func__, dma_info.period);
                }
 
-               ret = s3c2410_dma_enqueue(prtd->params->channel,
-                       substream, pos, len);
+               dma_info.buf = pos;
+               prtd->params->ops->prepare(prtd->params->ch, &dma_info);
 
-               if (ret == 0) {
-                       prtd->dma_loaded++;
-                       pos += prtd->dma_period;
-                       if (pos >= prtd->dma_end)
-                               pos = prtd->dma_start;
-               } else
-                       break;
+               prtd->dma_loaded++;
+               pos += prtd->dma_period;
+               if (pos >= prtd->dma_end)
+                       pos = prtd->dma_start;
        }
 
        prtd->dma_pos = pos;
 }
 
-static void audio_buffdone(struct s3c2410_dma_chan *channel,
-                               void *dev_id, int size,
-                               enum s3c2410_dma_buffresult result)
+static void audio_buffdone(void *data)
 {
-       struct snd_pcm_substream *substream = dev_id;
-       struct runtime_data *prtd;
+       struct snd_pcm_substream *substream = data;
+       struct runtime_data *prtd = substream->runtime->private_data;
 
        pr_debug("Entered %s\n", __func__);
 
-       if (result == S3C2410_RES_ABORT || result == S3C2410_RES_ERR)
-               return;
-
-       prtd = substream->runtime->private_data;
+       if (prtd->state & ST_RUNNING) {
+               prtd->dma_pos += prtd->dma_period;
+               if (prtd->dma_pos >= prtd->dma_end)
+                       prtd->dma_pos = prtd->dma_start;
 
-       if (substream)
-               snd_pcm_period_elapsed(substream);
+               if (substream)
+                       snd_pcm_period_elapsed(substream);
 
-       spin_lock(&prtd->lock);
-       if (prtd->state & ST_RUNNING && !s3c_dma_has_circular()) {
-               prtd->dma_loaded--;
-               dma_enqueue(substream);
+               spin_lock(&prtd->lock);
+               if (!samsung_dma_has_circular()) {
+                       prtd->dma_loaded--;
+                       dma_enqueue(substream);
+               }
+               spin_unlock(&prtd->lock);
        }
-
-       spin_unlock(&prtd->lock);
 }
 
 static int dma_hw_params(struct snd_pcm_substream *substream,
@@ -144,8 +145,7 @@ static int dma_hw_params(struct snd_pcm_substream *substream,
        unsigned long totbytes = params_buffer_bytes(params);
        struct s3c_dma_params *dma =
                snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
-       int ret = 0;
-
+       struct samsung_dma_info dma_info;
 
        pr_debug("Entered %s\n", __func__);
 
@@ -163,30 +163,26 @@ static int dma_hw_params(struct snd_pcm_substream *substream,
                pr_debug("params %p, client %p, channel %d\n", prtd->params,
                        prtd->params->client, prtd->params->channel);
 
-               ret = s3c2410_dma_request(prtd->params->channel,
-                                         prtd->params->client, NULL);
-
-               if (ret < 0) {
-                       printk(KERN_ERR "failed to get dma channel\n");
-                       return ret;
-               }
-
-               /* use the circular buffering if we have it available. */
-               if (s3c_dma_has_circular())
-                       s3c2410_dma_setflags(prtd->params->channel,
-                                            S3C2410_DMAF_CIRCULAR);
+               prtd->params->ops = samsung_dma_get_ops();
+
+               dma_info.cap = (samsung_dma_has_circular() ?
+                       DMA_CYCLIC : DMA_SLAVE);
+               dma_info.client = prtd->params->client;
+               dma_info.direction =
+                       (substream->stream == SNDRV_PCM_STREAM_PLAYBACK
+                       ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+               dma_info.width = prtd->params->dma_size;
+               dma_info.fifo = prtd->params->dma_addr;
+               prtd->params->ch = prtd->params->ops->request(
+                               prtd->params->channel, &dma_info);
        }
 
-       s3c2410_dma_set_buffdone_fn(prtd->params->channel,
-                                   audio_buffdone);
-
        snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
 
        runtime->dma_bytes = totbytes;
 
        spin_lock_irq(&prtd->lock);
        prtd->dma_loaded = 0;
-       prtd->dma_limit = runtime->hw.periods_min;
        prtd->dma_period = params_period_bytes(params);
        prtd->dma_start = runtime->dma_addr;
        prtd->dma_pos = prtd->dma_start;
@@ -202,11 +198,12 @@ static int dma_hw_free(struct snd_pcm_substream *substream)
 
        pr_debug("Entered %s\n", __func__);
 
-       /* TODO - do we need to ensure DMA flushed */
        snd_pcm_set_runtime_buffer(substream, NULL);
 
        if (prtd->params) {
-               s3c2410_dma_free(prtd->params->channel, prtd->params->client);
+               prtd->params->ops->flush(prtd->params->ch);
+               prtd->params->ops->release(prtd->params->ch,
+                                       prtd->params->client);
                prtd->params = NULL;
        }
 
@@ -225,23 +222,9 @@ static int dma_prepare(struct snd_pcm_substream *substream)
        if (!prtd->params)
                return 0;
 
-       /* channel needs configuring for mem=>device, increment memory addr,
-        * sync to pclk, half-word transfers to the IIS-FIFO. */
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               s3c2410_dma_devconfig(prtd->params->channel,
-                                     S3C2410_DMASRC_MEM,
-                                     prtd->params->dma_addr);
-       } else {
-               s3c2410_dma_devconfig(prtd->params->channel,
-                                     S3C2410_DMASRC_HW,
-                                     prtd->params->dma_addr);
-       }
-
-       s3c2410_dma_config(prtd->params->channel,
-                          prtd->params->dma_size);
-
        /* flush the DMA channel */
-       s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_FLUSH);
+       prtd->params->ops->flush(prtd->params->ch);
+
        prtd->dma_loaded = 0;
        prtd->dma_pos = prtd->dma_start;
 
@@ -265,14 +248,14 @@ static int dma_trigger(struct snd_pcm_substream *substream, int cmd)
        case SNDRV_PCM_TRIGGER_RESUME:
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
                prtd->state |= ST_RUNNING;
-               s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_START);
+               prtd->params->ops->trigger(prtd->params->ch);
                break;
 
        case SNDRV_PCM_TRIGGER_STOP:
        case SNDRV_PCM_TRIGGER_SUSPEND:
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
                prtd->state &= ~ST_RUNNING;
-               s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_STOP);
+               prtd->params->ops->stop(prtd->params->ch);
                break;
 
        default:
@@ -291,21 +274,12 @@ dma_pointer(struct snd_pcm_substream *substream)
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct runtime_data *prtd = runtime->private_data;
        unsigned long res;
-       dma_addr_t src, dst;
 
        pr_debug("Entered %s\n", __func__);
 
-       spin_lock(&prtd->lock);
-       s3c2410_dma_getposition(prtd->params->channel, &src, &dst);
-
-       if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
-               res = dst - prtd->dma_start;
-       else
-               res = src - prtd->dma_start;
-
-       spin_unlock(&prtd->lock);
+       res = prtd->dma_pos - prtd->dma_start;
 
-       pr_debug("Pointer %x %x\n", src, dst);
+       pr_debug("Pointer offset: %lu\n", res);
 
        /* we seem to be getting the odd error from the pcm library due
         * to out-of-bounds pointers. this is maybe due to the dma engine
index c506592..7d1ead7 100644 (file)
@@ -6,7 +6,7 @@
  *  Free Software Foundation;  either version 2 of the  License, or (at your
  *  option) any later version.
  *
- *  ALSA PCM interface for the Samsung S3C24xx CPU
+ *  ALSA PCM interface for the Samsung SoC
  */
 
 #ifndef _S3C_AUDIO_H
@@ -17,6 +17,8 @@ struct s3c_dma_params {
        int channel;                            /* Channel ID */
        dma_addr_t dma_addr;
        int dma_size;                   /* Size of the DMA transfer */
+       unsigned ch;
+       struct samsung_dma_ops *ops;
 };
 
 #endif
index 67bec76..c0609c2 100644 (file)
@@ -459,7 +459,8 @@ static void kill_stream_urbs(struct ua101_stream *stream)
        unsigned int i;
 
        for (i = 0; i < stream->queue_length; ++i)
-               usb_kill_urb(&stream->urbs[i]->urb);
+               if (stream->urbs[i])
+                       usb_kill_urb(&stream->urbs[i]->urb);
 }
 
 static int enable_iso_interface(struct ua101 *ua, unsigned int intf_index)
@@ -484,6 +485,9 @@ static void disable_iso_interface(struct ua101 *ua, unsigned int intf_index)
 {
        struct usb_host_interface *alts;
 
+       if (!ua->intf[intf_index])
+               return;
+
        alts = ua->intf[intf_index]->cur_altsetting;
        if (alts->desc.bAlternateSetting != 0) {
                int err = usb_set_interface(ua->dev,
@@ -1144,27 +1148,37 @@ static void free_stream_urbs(struct ua101_stream *stream)
 {
        unsigned int i;
 
-       for (i = 0; i < stream->queue_length; ++i)
+       for (i = 0; i < stream->queue_length; ++i) {
                kfree(stream->urbs[i]);
+               stream->urbs[i] = NULL;
+       }
 }
 
 static void free_usb_related_resources(struct ua101 *ua,
                                       struct usb_interface *interface)
 {
        unsigned int i;
+       struct usb_interface *intf;
 
+       mutex_lock(&ua->mutex);
        free_stream_urbs(&ua->capture);
        free_stream_urbs(&ua->playback);
+       mutex_unlock(&ua->mutex);
        free_stream_buffers(ua, &ua->capture);
        free_stream_buffers(ua, &ua->playback);
 
-       for (i = 0; i < ARRAY_SIZE(ua->intf); ++i)
-               if (ua->intf[i]) {
-                       usb_set_intfdata(ua->intf[i], NULL);
-                       if (ua->intf[i] != interface)
+       for (i = 0; i < ARRAY_SIZE(ua->intf); ++i) {
+               mutex_lock(&ua->mutex);
+               intf = ua->intf[i];
+               ua->intf[i] = NULL;
+               mutex_unlock(&ua->mutex);
+               if (intf) {
+                       usb_set_intfdata(intf, NULL);
+                       if (intf != interface)
                                usb_driver_release_interface(&ua101_driver,
-                                                            ua->intf[i]);
+                                                            intf);
                }
+       }
 }
 
 static void ua101_card_free(struct snd_card *card)