Merge branch 'akpm' (Andrew's patch-bomb)
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 29 Mar 2012 00:19:27 +0000 (17:19 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 29 Mar 2012 00:19:28 +0000 (17:19 -0700)
Merge third batch of patches from Andrew Morton:
 - Some MM stragglers
 - core SMP library cleanups (on_each_cpu_mask)
 - Some IPI optimisations
 - kexec
 - kdump
 - IPMI
 - the radix-tree iterator work
 - various other misc bits.

 "That'll do for -rc1.  I still have ~10 patches for 3.4, will send
  those along when they've baked a little more."

* emailed from Andrew Morton <akpm@linux-foundation.org>: (35 commits)
  backlight: fix typo in tosa_lcd.c
  crc32: add help text for the algorithm select option
  mm: move hugepage test examples to tools/testing/selftests/vm
  mm: move slabinfo.c to tools/vm
  mm: move page-types.c from Documentation to tools/vm
  selftests/Makefile: make `run_tests' depend on `all'
  selftests: launch individual selftests from the main Makefile
  radix-tree: use iterators in find_get_pages* functions
  radix-tree: rewrite gang lookup using iterator
  radix-tree: introduce bit-optimized iterator
  fs/proc/namespaces.c: prevent crash when ns_entries[] is empty
  nbd: rename the nbd_device variable from lo to nbd
  pidns: add reboot_pid_ns() to handle the reboot syscall
  sysctl: use bitmap library functions
  ipmi: use locks on watchdog timeout set on reboot
  ipmi: simplify locking
  ipmi: fix message handling during panics
  ipmi: use a tasklet for handling received messages
  ipmi: increase KCS timeouts
  ipmi: decrease the IPMI message transaction time in interrupt mode
  ...

2222 files changed:
Documentation/ABI/testing/sysfs-block-dm [new file with mode: 0644]
Documentation/ABI/testing/sysfs-driver-samsung-laptop
Documentation/clk.txt [new file with mode: 0644]
Documentation/device-mapper/thin-provisioning.txt
Documentation/device-mapper/verity.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arm/atmel-at91.txt
Documentation/devicetree/bindings/arm/atmel-pmc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arm/spear.txt [new file with mode: 0644]
Documentation/devicetree/bindings/gpio/gpio-omap.txt [new file with mode: 0644]
Documentation/devicetree/bindings/gpio/gpio-twl4030.txt [new file with mode: 0644]
Documentation/devicetree/bindings/gpio/gpio_i2c.txt [new file with mode: 0644]
Documentation/devicetree/bindings/gpio/sodaville.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mtd/atmel-nand.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mtd/nand.txt [new file with mode: 0644]
Documentation/devicetree/bindings/usb/atmel-usb.txt [new file with mode: 0644]
Documentation/devicetree/bindings/usb/tegra-usb.txt
Documentation/dma-buf-sharing.txt
Documentation/gpio.txt
Documentation/i2c/busses/i2c-i801
Documentation/kernel-parameters.txt
Documentation/laptops/asus-laptop.txt
Documentation/laptops/sony-laptop.txt
Documentation/virtual/kvm/api.txt
Documentation/virtual/kvm/ppc-pv.txt
Documentation/watchdog/00-INDEX [deleted file]
Documentation/watchdog/convert_drivers_to_kernel_api.txt
Documentation/watchdog/watchdog-kernel-api.txt
MAINTAINERS
arch/alpha/boot/bootp.c
arch/alpha/boot/bootpz.c
arch/alpha/boot/head.S
arch/alpha/boot/main.c
arch/alpha/include/asm/atomic.h
arch/alpha/include/asm/auxvec.h
arch/alpha/include/asm/core_lca.h
arch/alpha/include/asm/core_mcpcia.h
arch/alpha/include/asm/core_t2.h
arch/alpha/include/asm/elf.h
arch/alpha/include/asm/exec.h [new file with mode: 0644]
arch/alpha/include/asm/fpu.h
arch/alpha/include/asm/io.h
arch/alpha/include/asm/irqflags.h
arch/alpha/include/asm/mce.h [new file with mode: 0644]
arch/alpha/include/asm/mmu_context.h
arch/alpha/include/asm/pal.h
arch/alpha/include/asm/pgtable.h
arch/alpha/include/asm/setup.h
arch/alpha/include/asm/special_insns.h [new file with mode: 0644]
arch/alpha/include/asm/spinlock.h
arch/alpha/include/asm/switch_to.h [new file with mode: 0644]
arch/alpha/include/asm/system.h [deleted file]
arch/alpha/include/asm/xchg.h
arch/alpha/kernel/core_apecs.c
arch/alpha/kernel/core_cia.c
arch/alpha/kernel/core_t2.c
arch/alpha/kernel/err_impl.h
arch/alpha/kernel/head.S
arch/alpha/kernel/irq.c
arch/alpha/kernel/irq_alpha.c
arch/alpha/kernel/osf_sys.c
arch/alpha/kernel/process.c
arch/alpha/kernel/ptrace.c
arch/alpha/kernel/setup.c
arch/alpha/kernel/sys_alcor.c
arch/alpha/kernel/sys_cabriolet.c
arch/alpha/kernel/sys_dp264.c
arch/alpha/kernel/sys_eb64p.c
arch/alpha/kernel/sys_eiger.c
arch/alpha/kernel/sys_jensen.c
arch/alpha/kernel/sys_marvel.c
arch/alpha/kernel/sys_miata.c
arch/alpha/kernel/sys_mikasa.c
arch/alpha/kernel/sys_nautilus.c
arch/alpha/kernel/sys_noritake.c
arch/alpha/kernel/sys_rawhide.c
arch/alpha/kernel/sys_ruffian.c
arch/alpha/kernel/sys_rx164.c
arch/alpha/kernel/sys_sable.c
arch/alpha/kernel/sys_sio.c
arch/alpha/kernel/sys_sx164.c
arch/alpha/kernel/sys_takara.c
arch/alpha/kernel/sys_titan.c
arch/alpha/kernel/sys_wildfire.c
arch/alpha/kernel/traps.c
arch/alpha/kernel/vmlinux.lds.S
arch/alpha/lib/stacktrace.c
arch/alpha/mm/fault.c
arch/alpha/mm/init.c
arch/alpha/oprofile/common.c
arch/alpha/oprofile/op_model_ev4.c
arch/alpha/oprofile/op_model_ev5.c
arch/alpha/oprofile/op_model_ev6.c
arch/alpha/oprofile/op_model_ev67.c
arch/arm/Makefile
arch/arm/boot/dts/at91sam9g20.dtsi
arch/arm/boot/dts/at91sam9g25ek.dts
arch/arm/boot/dts/at91sam9g45.dtsi
arch/arm/boot/dts/at91sam9m10g45ek.dts
arch/arm/boot/dts/at91sam9x5.dtsi
arch/arm/boot/dts/at91sam9x5cm.dtsi
arch/arm/boot/dts/db8500.dtsi [new file with mode: 0644]
arch/arm/boot/dts/exynos5250-smdk5250.dts [new file with mode: 0644]
arch/arm/boot/dts/exynos5250.dtsi [new file with mode: 0644]
arch/arm/boot/dts/kirkwood-dreamplug.dts
arch/arm/boot/dts/kirkwood.dtsi
arch/arm/boot/dts/snowball.dts [new file with mode: 0644]
arch/arm/boot/dts/spear600-evb.dts [new file with mode: 0644]
arch/arm/boot/dts/spear600.dtsi [new file with mode: 0644]
arch/arm/boot/dts/tegra-cardhu.dts
arch/arm/boot/dts/tegra-seaboard.dts
arch/arm/boot/dts/tegra20.dtsi
arch/arm/boot/dts/usb_a9g20-dab-mmx.dtsi [new file with mode: 0644]
arch/arm/boot/dts/usb_a9g20.dts
arch/arm/common/via82c505.c
arch/arm/configs/at91sam9g20_defconfig
arch/arm/configs/u8500_defconfig
arch/arm/include/asm/atomic.h
arch/arm/include/asm/barrier.h [new file with mode: 0644]
arch/arm/include/asm/bitops.h
arch/arm/include/asm/bug.h
arch/arm/include/asm/cmpxchg.h [new file with mode: 0644]
arch/arm/include/asm/compiler.h [new file with mode: 0644]
arch/arm/include/asm/cp15.h [new file with mode: 0644]
arch/arm/include/asm/div64.h
arch/arm/include/asm/dma.h
arch/arm/include/asm/domain.h
arch/arm/include/asm/exec.h [new file with mode: 0644]
arch/arm/include/asm/hardware/iop3xx.h
arch/arm/include/asm/io.h
arch/arm/include/asm/mmu.h
arch/arm/include/asm/processor.h
arch/arm/include/asm/switch_to.h [new file with mode: 0644]
arch/arm/include/asm/system.h
arch/arm/include/asm/system_info.h [new file with mode: 0644]
arch/arm/include/asm/system_misc.h [new file with mode: 0644]
arch/arm/include/asm/uaccess.h
arch/arm/kernel/armksyms.c
arch/arm/kernel/elf.c
arch/arm/kernel/entry-armv.S
arch/arm/kernel/fiq.c
arch/arm/kernel/head-nommu.S
arch/arm/kernel/head.S
arch/arm/kernel/hw_breakpoint.c
arch/arm/kernel/irq.c
arch/arm/kernel/kprobes-common.c
arch/arm/kernel/machine_kexec.c
arch/arm/kernel/process.c
arch/arm/kernel/ptrace.c
arch/arm/kernel/setup.c
arch/arm/kernel/sleep.S
arch/arm/kernel/tcm.c
arch/arm/kernel/thumbee.c
arch/arm/kernel/traps.c
arch/arm/mach-at91/Kconfig
arch/arm/mach-at91/at91rm9200.c
arch/arm/mach-at91/at91sam9260.c
arch/arm/mach-at91/at91sam9261.c
arch/arm/mach-at91/at91sam9263.c
arch/arm/mach-at91/at91sam9g45.c
arch/arm/mach-at91/at91sam9rl.c
arch/arm/mach-at91/at91sam9x5.c
arch/arm/mach-at91/board-afeb-9260v1.c
arch/arm/mach-at91/board-cam60.c
arch/arm/mach-at91/board-cpu9krea.c
arch/arm/mach-at91/board-dt.c
arch/arm/mach-at91/board-kb9202.c
arch/arm/mach-at91/board-neocore926.c
arch/arm/mach-at91/board-qil-a9260.c
arch/arm/mach-at91/board-rm9200dk.c
arch/arm/mach-at91/board-sam9-l9260.c
arch/arm/mach-at91/board-sam9260ek.c
arch/arm/mach-at91/board-sam9261ek.c
arch/arm/mach-at91/board-sam9263ek.c
arch/arm/mach-at91/board-sam9g20ek.c
arch/arm/mach-at91/board-sam9m10g45ek.c
arch/arm/mach-at91/board-sam9rlek.c
arch/arm/mach-at91/board-snapper9260.c
arch/arm/mach-at91/board-stamp9g20.c
arch/arm/mach-at91/board-usb-a926x.c
arch/arm/mach-at91/board-yl-9200.c
arch/arm/mach-at91/clock.c
arch/arm/mach-at91/generic.h
arch/arm/mach-at91/include/mach/at91_shdwc.h
arch/arm/mach-at91/include/mach/at91sam9x5.h
arch/arm/mach-at91/include/mach/board.h
arch/arm/mach-at91/include/mach/system_rev.h
arch/arm/mach-at91/pm.c
arch/arm/mach-at91/setup.c
arch/arm/mach-clps711x/common.c
arch/arm/mach-clps711x/p720t-leds.c
arch/arm/mach-davinci/board-da850-evm.c
arch/arm/mach-davinci/board-dm644x-evm.c
arch/arm/mach-davinci/davinci.h
arch/arm/mach-davinci/dm644x.c
arch/arm/mach-ebsa110/core.c
arch/arm/mach-ebsa110/leds.c
arch/arm/mach-exynos/Kconfig
arch/arm/mach-exynos/Makefile
arch/arm/mach-exynos/clock-exynos4.c
arch/arm/mach-exynos/clock-exynos5.c [new file with mode: 0644]
arch/arm/mach-exynos/common.c
arch/arm/mach-exynos/common.h
arch/arm/mach-exynos/dev-ahci.c
arch/arm/mach-exynos/dev-audio.c
arch/arm/mach-exynos/dev-uart.c [new file with mode: 0644]
arch/arm/mach-exynos/dma.c
arch/arm/mach-exynos/hotplug.c
arch/arm/mach-exynos/include/mach/debug-macro.S
arch/arm/mach-exynos/include/mach/gpio.h
arch/arm/mach-exynos/include/mach/irqs.h
arch/arm/mach-exynos/include/mach/map.h
arch/arm/mach-exynos/include/mach/regs-clock.h
arch/arm/mach-exynos/include/mach/regs-gpio.h
arch/arm/mach-exynos/include/mach/regs-pmu.h
arch/arm/mach-exynos/include/mach/uncompress.h
arch/arm/mach-exynos/mach-exynos4-dt.c
arch/arm/mach-exynos/mach-exynos5-dt.c [new file with mode: 0644]
arch/arm/mach-exynos/mct.c
arch/arm/mach-exynos/platsmp.c
arch/arm/mach-exynos/pm_domains.c
arch/arm/mach-exynos/setup-i2c0.c
arch/arm/mach-footbridge/common.c
arch/arm/mach-footbridge/dc21285-timer.c
arch/arm/mach-footbridge/dc21285.c
arch/arm/mach-footbridge/ebsa285-leds.c
arch/arm/mach-footbridge/netwinder-hw.c
arch/arm/mach-footbridge/netwinder-leds.c
arch/arm/mach-imx/dma-v1.c
arch/arm/mach-imx/mach-imx6q.c
arch/arm/mach-imx/mach-mx51_efikamx.c
arch/arm/mach-imx/mach-mx51_efikasb.c
arch/arm/mach-integrator/core.c
arch/arm/mach-integrator/leds.c
arch/arm/mach-integrator/pci.c
arch/arm/mach-integrator/pci_v3.c
arch/arm/mach-iop33x/uart.c
arch/arm/mach-ixp2000/core.c
arch/arm/mach-ixp2000/enp2611.c
arch/arm/mach-ixp2000/ixdp2400.c
arch/arm/mach-ixp2000/ixdp2800.c
arch/arm/mach-ixp2000/ixdp2x00.c
arch/arm/mach-ixp2000/ixdp2x01.c
arch/arm/mach-ixp2000/pci.c
arch/arm/mach-ixp23xx/core.c
arch/arm/mach-ixp23xx/espresso.c
arch/arm/mach-ixp23xx/ixdp2351.c
arch/arm/mach-ixp23xx/pci.c
arch/arm/mach-ixp23xx/roadrunner.c
arch/arm/mach-ixp4xx/common-pci.c
arch/arm/mach-ixp4xx/goramo_mlr.c
arch/arm/mach-kirkwood/Makefile
arch/arm/mach-kirkwood/board-dreamplug.c [new file with mode: 0644]
arch/arm/mach-kirkwood/board-dt.c
arch/arm/mach-kirkwood/common.c
arch/arm/mach-kirkwood/common.h
arch/arm/mach-ks8695/time.c
arch/arm/mach-lpc32xx/Kconfig
arch/arm/mach-lpc32xx/clock.c
arch/arm/mach-lpc32xx/common.c
arch/arm/mach-lpc32xx/common.h
arch/arm/mach-lpc32xx/include/mach/board.h [new file with mode: 0644]
arch/arm/mach-lpc32xx/irq.c
arch/arm/mach-lpc32xx/phy3250.c
arch/arm/mach-mmp/common.c
arch/arm/mach-mmp/pxa168.c
arch/arm/mach-msm/board-sapphire.c
arch/arm/mach-mxs/system.c
arch/arm/mach-omap1/id.c
arch/arm/mach-omap1/leds-h2p2-debug.c
arch/arm/mach-omap1/leds-innovator.c
arch/arm/mach-omap1/leds-osk.c
arch/arm/mach-omap1/mux.c
arch/arm/mach-omap1/time.c
arch/arm/mach-omap1/timer32k.c
arch/arm/mach-omap2/board-4430sdp.c
arch/arm/mach-omap2/board-omap3touchbook.c
arch/arm/mach-omap2/board-omap4panda.c
arch/arm/mach-omap2/board-rx51-peripherals.c
arch/arm/mach-omap2/mux.c
arch/arm/mach-omap2/omap-mpuss-lowpower.c
arch/arm/mach-omap2/pm24xx.c
arch/arm/mach-omap2/pm34xx.c
arch/arm/mach-omap2/pm44xx.c
arch/arm/mach-omap2/sleep44xx.S
arch/arm/mach-orion5x/common.c
arch/arm/mach-orion5x/dns323-setup.c
arch/arm/mach-orion5x/ls-chl-setup.c
arch/arm/mach-orion5x/ls_hgl-setup.c
arch/arm/mach-orion5x/lsmini-setup.c
arch/arm/mach-pnx4008/core.c
arch/arm/mach-pnx4008/dma.c
arch/arm/mach-pnx4008/irq.c
arch/arm/mach-pnx4008/time.c
arch/arm/mach-pxa/cm-x300.c
arch/arm/mach-pxa/colibri-pxa3xx.c
arch/arm/mach-pxa/corgi.c
arch/arm/mach-pxa/generic.c
arch/arm/mach-pxa/leds-idp.c
arch/arm/mach-pxa/leds-lubbock.c
arch/arm/mach-pxa/leds-mainstone.c
arch/arm/mach-pxa/magician.c
arch/arm/mach-pxa/poodle.c
arch/arm/mach-pxa/reset.c
arch/arm/mach-pxa/viper.c
arch/arm/mach-pxa/zeus.c
arch/arm/mach-realview/core.c
arch/arm/mach-realview/hotplug.c
arch/arm/mach-rpc/riscpc.c
arch/arm/mach-s3c24xx/s3c2410.c
arch/arm/mach-s3c24xx/s3c2412.c
arch/arm/mach-s3c24xx/s3c2416.c
arch/arm/mach-s3c24xx/s3c2443.c
arch/arm/mach-s3c24xx/s3c244x.c
arch/arm/mach-s3c64xx/common.c
arch/arm/mach-s3c64xx/mach-crag6410-module.c
arch/arm/mach-s5p64x0/common.c
arch/arm/mach-s5pc100/common.c
arch/arm/mach-sa1100/generic.c
arch/arm/mach-sa1100/leds-assabet.c
arch/arm/mach-sa1100/leds-badge4.c
arch/arm/mach-sa1100/leds-cerf.c
arch/arm/mach-sa1100/leds-hackkit.c
arch/arm/mach-sa1100/leds-lart.c
arch/arm/mach-sa1100/pm.c
arch/arm/mach-shark/leds.c
arch/arm/mach-shmobile/board-ap4evb.c
arch/arm/mach-shmobile/board-mackerel.c
arch/arm/mach-shmobile/cpuidle.c
arch/arm/mach-shmobile/include/mach/system.h
arch/arm/mach-shmobile/pm-r8a7779.c
arch/arm/mach-shmobile/pm-sh7372.c
arch/arm/mach-shmobile/setup-sh7372.c
arch/arm/mach-shmobile/suspend.c
arch/arm/mach-spear6xx/Kconfig
arch/arm/mach-spear6xx/Makefile
arch/arm/mach-spear6xx/clock.c
arch/arm/mach-spear6xx/spear600.c [deleted file]
arch/arm/mach-spear6xx/spear600_evb.c [deleted file]
arch/arm/mach-spear6xx/spear6xx.c
arch/arm/mach-tegra/Makefile
arch/arm/mach-tegra/board-dt-tegra30.c
arch/arm/mach-tegra/common.c
arch/arm/mach-tegra/cpu-tegra.c
arch/arm/mach-tegra/flowctrl.c [new file with mode: 0644]
arch/arm/mach-tegra/flowctrl.h
arch/arm/mach-tegra/fuse.c
arch/arm/mach-tegra/fuse.h
arch/arm/mach-tegra/headsmp.S
arch/arm/mach-tegra/hotplug.c
arch/arm/mach-tegra/include/mach/iomap.h
arch/arm/mach-tegra/include/mach/powergate.h
arch/arm/mach-tegra/platsmp.c
arch/arm/mach-tegra/powergate.c
arch/arm/mach-tegra/reset.c [new file with mode: 0644]
arch/arm/mach-tegra/reset.h [new file with mode: 0644]
arch/arm/mach-ux500/Kconfig
arch/arm/mach-ux500/Makefile.boot
arch/arm/mach-ux500/board-mop500-sdi.c
arch/arm/mach-ux500/board-mop500.c
arch/arm/mach-ux500/board-mop500.h
arch/arm/mach-ux500/board-u5500-sdi.c
arch/arm/mach-ux500/board-u5500.c
arch/arm/mach-ux500/cache-l2x0.c
arch/arm/mach-ux500/cpu-db5500.c
arch/arm/mach-ux500/cpu-db8500.c
arch/arm/mach-ux500/cpu.c
arch/arm/mach-ux500/devices-common.c
arch/arm/mach-ux500/devices-common.h
arch/arm/mach-ux500/devices-db5500.h
arch/arm/mach-ux500/devices-db8500.h
arch/arm/mach-ux500/dma-db5500.c
arch/arm/mach-ux500/include/mach/db8500-regs.h
arch/arm/mach-ux500/include/mach/irqs-board-mop500.h
arch/arm/mach-ux500/include/mach/setup.h
arch/arm/mach-ux500/include/mach/usb.h
arch/arm/mach-ux500/timer.c
arch/arm/mach-ux500/usb.c
arch/arm/mach-versatile/core.c
arch/arm/mach-versatile/pci.c
arch/arm/mach-vexpress/hotplug.c
arch/arm/mach-w90x900/cpu.c
arch/arm/mm/alignment.c
arch/arm/mm/cache-feroceon-l2.c
arch/arm/mm/cache-tauros2.c
arch/arm/mm/cache-xsc3l2.c
arch/arm/mm/fault.c
arch/arm/mm/flush.c
arch/arm/mm/idmap.c
arch/arm/mm/ioremap.c
arch/arm/mm/mmu.c
arch/arm/mm/pgd.c
arch/arm/mm/proc-fa526.S
arch/arm/nwfpe/fpa11.c
arch/arm/plat-iop/i2c.c
arch/arm/plat-iop/pci.c
arch/arm/plat-iop/restart.c
arch/arm/plat-mxc/system.c
arch/arm/plat-omap/debug-leds.c
arch/arm/plat-omap/dma.c
arch/arm/plat-omap/include/plat/gpio.h
arch/arm/plat-orion/common.c
arch/arm/plat-orion/include/plat/audio.h
arch/arm/plat-pxa/dma.c
arch/arm/plat-s3c24xx/cpu.c
arch/arm/plat-s3c24xx/dma.c
arch/arm/plat-s5p/Kconfig
arch/arm/plat-s5p/Makefile
arch/arm/plat-s5p/clock.c
arch/arm/plat-s5p/irq-pm.c
arch/arm/plat-samsung/cpu.c
arch/arm/plat-samsung/include/plat/cpu.h
arch/arm/plat-samsung/include/plat/devs.h
arch/arm/plat-samsung/include/plat/s5p-clock.h
arch/arm/plat-samsung/include/plat/uncompress.h
arch/arm/plat-samsung/irq-vic-timer.c
arch/arm/plat-samsung/time.c
arch/arm/plat-spear/restart.c
arch/arm/vfp/vfpmodule.c
arch/avr32/boards/atngw100/setup.c
arch/avr32/boards/atstk1000/atstk1002.c
arch/avr32/include/asm/atomic.h
arch/avr32/include/asm/barrier.h [new file with mode: 0644]
arch/avr32/include/asm/bitops.h
arch/avr32/include/asm/bug.h
arch/avr32/include/asm/cmpxchg.h [new file with mode: 0644]
arch/avr32/include/asm/exec.h [new file with mode: 0644]
arch/avr32/include/asm/special_insns.h [new file with mode: 0644]
arch/avr32/include/asm/switch_to.h [new file with mode: 0644]
arch/avr32/include/asm/system.h [deleted file]
arch/avr32/mach-at32ap/cpufreq.c
arch/avr32/mach-at32ap/include/mach/board.h
arch/avr32/oprofile/op_model_avr32.c
arch/blackfin/include/asm/system.h [deleted file]
arch/c6x/include/asm/Kbuild
arch/c6x/include/asm/barrier.h [new file with mode: 0644]
arch/c6x/include/asm/bitops.h
arch/c6x/include/asm/bug.h [new file with mode: 0644]
arch/c6x/include/asm/cmpxchg.h [new file with mode: 0644]
arch/c6x/include/asm/exec.h [new file with mode: 0644]
arch/c6x/include/asm/processor.h
arch/c6x/include/asm/setup.h
arch/c6x/include/asm/special_insns.h [new file with mode: 0644]
arch/c6x/include/asm/switch_to.h [new file with mode: 0644]
arch/c6x/include/asm/system.h [deleted file]
arch/c6x/kernel/irq.c
arch/c6x/kernel/setup.c
arch/c6x/kernel/soc.c
arch/c6x/kernel/time.c
arch/c6x/kernel/traps.c
arch/c6x/platforms/timer64.c
arch/cris/arch-v10/drivers/ds1302.c
arch/cris/arch-v10/drivers/gpio.c
arch/cris/arch-v10/drivers/i2c.c
arch/cris/arch-v10/drivers/pcf8563.c
arch/cris/arch-v10/drivers/sync_serial.c
arch/cris/arch-v10/kernel/debugport.c
arch/cris/arch-v10/kernel/dma.c
arch/cris/arch-v10/kernel/io_interface_mux.c
arch/cris/arch-v10/kernel/process.c
arch/cris/arch-v10/kernel/ptrace.c
arch/cris/arch-v10/kernel/setup.c
arch/cris/arch-v10/kernel/signal.c
arch/cris/arch-v10/kernel/traps.c
arch/cris/arch-v32/drivers/i2c.c
arch/cris/arch-v32/drivers/mach-a3/gpio.c
arch/cris/arch-v32/drivers/mach-fs/gpio.c
arch/cris/arch-v32/kernel/debugport.c
arch/cris/arch-v32/kernel/fasttimer.c
arch/cris/arch-v32/kernel/ptrace.c
arch/cris/arch-v32/mach-a3/dma.c
arch/cris/arch-v32/mach-fs/dma.c
arch/cris/include/arch-v10/arch/elf.h
arch/cris/include/arch-v32/arch/elf.h
arch/cris/include/arch-v32/arch/system.h
arch/cris/include/asm/atomic.h
arch/cris/include/asm/barrier.h [new file with mode: 0644]
arch/cris/include/asm/bitops.h
arch/cris/include/asm/cmpxchg.h [new file with mode: 0644]
arch/cris/include/asm/exec.h [new file with mode: 0644]
arch/cris/include/asm/processor.h
arch/cris/include/asm/switch_to.h [new file with mode: 0644]
arch/cris/include/asm/system.h [deleted file]
arch/cris/kernel/irq.c
arch/cris/kernel/process.c
arch/cris/kernel/ptrace.c
arch/cris/kernel/setup.c
arch/cris/kernel/traps.c
arch/cris/mm/fault.c
arch/frv/include/asm/atomic.h
arch/frv/include/asm/barrier.h [new file with mode: 0644]
arch/frv/include/asm/bug.h
arch/frv/include/asm/cmpxchg.h [new file with mode: 0644]
arch/frv/include/asm/exec.h [new file with mode: 0644]
arch/frv/include/asm/switch_to.h [new file with mode: 0644]
arch/frv/include/asm/system.h [deleted file]
arch/frv/kernel/debug-stub.c
arch/frv/kernel/gdb-io.c
arch/frv/kernel/gdb-stub.c
arch/frv/kernel/irq-mb93091.c
arch/frv/kernel/irq-mb93093.c
arch/frv/kernel/irq-mb93493.c
arch/frv/kernel/irq.c
arch/frv/kernel/process.c
arch/frv/kernel/ptrace.c
arch/frv/kernel/traps.c
arch/frv/mm/fault.c
arch/frv/mm/init.c
arch/frv/mm/kmap.c
arch/h8300/include/asm/atomic.h
arch/h8300/include/asm/barrier.h [new file with mode: 0644]
arch/h8300/include/asm/bitops.h
arch/h8300/include/asm/bug.h
arch/h8300/include/asm/cmpxchg.h [new file with mode: 0644]
arch/h8300/include/asm/exec.h [new file with mode: 0644]
arch/h8300/include/asm/processor.h
arch/h8300/include/asm/switch_to.h [new file with mode: 0644]
arch/h8300/include/asm/system.h [deleted file]
arch/h8300/kernel/irq.c
arch/h8300/kernel/process.c
arch/h8300/kernel/ptrace.c
arch/h8300/kernel/traps.c
arch/h8300/mm/fault.c
arch/h8300/mm/init.c
arch/h8300/mm/kmap.c
arch/h8300/mm/memory.c
arch/hexagon/include/asm/atomic.h
arch/hexagon/include/asm/barrier.h [new file with mode: 0644]
arch/hexagon/include/asm/bitops.h
arch/hexagon/include/asm/cmpxchg.h [new file with mode: 0644]
arch/hexagon/include/asm/exec.h [new file with mode: 0644]
arch/hexagon/include/asm/switch_to.h [new file with mode: 0644]
arch/hexagon/include/asm/system.h [deleted file]
arch/hexagon/kernel/ptrace.c
arch/hexagon/kernel/smp.c
arch/hexagon/kernel/vm_events.c
arch/ia64/dig/setup.c
arch/ia64/hp/common/sba_iommu.c
arch/ia64/hp/sim/boot/bootloader.c
arch/ia64/hp/sim/boot/fw-emu.c
arch/ia64/hp/sim/simeth.c
arch/ia64/include/asm/acpi.h
arch/ia64/include/asm/atomic.h
arch/ia64/include/asm/auxvec.h
arch/ia64/include/asm/barrier.h [new file with mode: 0644]
arch/ia64/include/asm/exec.h [new file with mode: 0644]
arch/ia64/include/asm/futex.h
arch/ia64/include/asm/io.h
arch/ia64/include/asm/irqflags.h
arch/ia64/include/asm/kexec.h
arch/ia64/include/asm/kvm.h
arch/ia64/include/asm/kvm_host.h
arch/ia64/include/asm/mca_asm.h
arch/ia64/include/asm/page.h
arch/ia64/include/asm/pci.h
arch/ia64/include/asm/pgtable.h
arch/ia64/include/asm/processor.h
arch/ia64/include/asm/sal.h
arch/ia64/include/asm/setup.h
arch/ia64/include/asm/sn/pda.h
arch/ia64/include/asm/spinlock.h
arch/ia64/include/asm/switch_to.h [new file with mode: 0644]
arch/ia64/include/asm/system.h [deleted file]
arch/ia64/include/asm/uv/uv.h
arch/ia64/kernel/acpi.c
arch/ia64/kernel/efi.c
arch/ia64/kernel/fsys.S
arch/ia64/kernel/gate.S
arch/ia64/kernel/gate.lds.S
arch/ia64/kernel/head.S
arch/ia64/kernel/iosapic.c
arch/ia64/kernel/irq_ia64.c
arch/ia64/kernel/ivt.S
arch/ia64/kernel/machvec.c
arch/ia64/kernel/mca.c
arch/ia64/kernel/mca_drv.c
arch/ia64/kernel/patch.c
arch/ia64/kernel/pci-dma.c
arch/ia64/kernel/perfmon.c
arch/ia64/kernel/ptrace.c
arch/ia64/kernel/setup.c
arch/ia64/kernel/smp.c
arch/ia64/kernel/smpboot.c
arch/ia64/kernel/time.c
arch/ia64/kernel/traps.c
arch/ia64/kernel/uncached.c
arch/ia64/kernel/unwind.c
arch/ia64/kernel/vmlinux.lds.S
arch/ia64/kvm/kvm-ia64.c
arch/ia64/mm/fault.c
arch/ia64/mm/init.c
arch/ia64/oprofile/backtrace.c
arch/ia64/pci/pci.c
arch/ia64/sn/kernel/setup.c
arch/ia64/sn/kernel/sn2/prominfo_proc.c
arch/ia64/sn/kernel/sn2/sn2_smp.c
arch/ia64/sn/kernel/sn2/timer.c
arch/ia64/sn/kernel/tiocx.c
arch/ia64/xen/xensetup.S
arch/m32r/include/asm/atomic.h
arch/m32r/include/asm/barrier.h [new file with mode: 0644]
arch/m32r/include/asm/bitops.h
arch/m32r/include/asm/cmpxchg.h [new file with mode: 0644]
arch/m32r/include/asm/dcache_clear.h [new file with mode: 0644]
arch/m32r/include/asm/exec.h [new file with mode: 0644]
arch/m32r/include/asm/local.h
arch/m32r/include/asm/spinlock.h
arch/m32r/include/asm/switch_to.h [new file with mode: 0644]
arch/m32r/include/asm/system.h [deleted file]
arch/m32r/kernel/ptrace.c
arch/m32r/kernel/traps.c
arch/m32r/mm/fault-nommu.c
arch/m32r/mm/fault.c
arch/m32r/platforms/m32104ut/setup.c
arch/m32r/platforms/m32700ut/setup.c
arch/m32r/platforms/mappi/setup.c
arch/m32r/platforms/mappi2/setup.c
arch/m32r/platforms/mappi3/setup.c
arch/m32r/platforms/oaks32r/setup.c
arch/m32r/platforms/opsput/setup.c
arch/m32r/platforms/usrv/setup.c
arch/m68k/amiga/amisound.c
arch/m68k/amiga/config.c
arch/m68k/apollo/config.c
arch/m68k/atari/ataints.c
arch/m68k/atari/atasound.c
arch/m68k/atari/config.c
arch/m68k/bvme6000/config.c
arch/m68k/bvme6000/rtc.c
arch/m68k/hp300/time.c
arch/m68k/include/asm/atomic.h
arch/m68k/include/asm/barrier.h [new file with mode: 0644]
arch/m68k/include/asm/cmpxchg.h [new file with mode: 0644]
arch/m68k/include/asm/exec.h [new file with mode: 0644]
arch/m68k/include/asm/sun3xflop.h
arch/m68k/include/asm/switch_to.h [new file with mode: 0644]
arch/m68k/include/asm/system.h [deleted file]
arch/m68k/kernel/ints.c
arch/m68k/kernel/irq.c
arch/m68k/kernel/process.c
arch/m68k/kernel/ptrace.c
arch/m68k/kernel/traps.c
arch/m68k/kernel/vectors.c
arch/m68k/mac/config.c
arch/m68k/mac/misc.c
arch/m68k/mm/fault.c
arch/m68k/mm/init_mm.c
arch/m68k/mm/init_no.c
arch/m68k/mm/kmap.c
arch/m68k/mm/memory.c
arch/m68k/mm/motorola.c
arch/m68k/mm/sun3mmu.c
arch/m68k/mvme147/config.c
arch/m68k/mvme16x/config.c
arch/m68k/mvme16x/rtc.c
arch/m68k/platform/68328/config.c
arch/m68k/platform/68328/timers.c
arch/m68k/platform/68360/config.c
arch/m68k/platform/68EZ328/config.c
arch/m68k/platform/68VZ328/config.c
arch/m68k/q40/config.c
arch/m68k/q40/q40ints.c
arch/m68k/sun3/intersil.c
arch/m68k/sun3/mmu_emu.c
arch/m68k/sun3/prom/console.c
arch/m68k/sun3x/config.c
arch/m68k/sun3x/time.c
arch/microblaze/include/asm/atomic.h
arch/microblaze/include/asm/barrier.h [new file with mode: 0644]
arch/microblaze/include/asm/cmpxchg.h [new file with mode: 0644]
arch/microblaze/include/asm/exec.h [new file with mode: 0644]
arch/microblaze/include/asm/page.h
arch/microblaze/include/asm/processor.h
arch/microblaze/include/asm/setup.h
arch/microblaze/include/asm/switch_to.h [new file with mode: 0644]
arch/microblaze/include/asm/system.h [deleted file]
arch/microblaze/kernel/cpu/pvr.c
arch/microblaze/kernel/microblaze_ksyms.c
arch/microblaze/kernel/process.c
arch/microblaze/kernel/prom.c
arch/microblaze/kernel/setup.c
arch/microblaze/kernel/timer.c
arch/microblaze/kernel/traps.c
arch/microblaze/lib/memcpy.c
arch/microblaze/mm/fault.c
arch/mips/cavium-octeon/setup.c
arch/mips/cavium-octeon/smp.c
arch/mips/dec/ecc-berr.c
arch/mips/dec/kn01-berr.c
arch/mips/dec/kn02xa-berr.c
arch/mips/dec/wbflush.c
arch/mips/emma/markeins/irq.c
arch/mips/fw/arc/misc.c
arch/mips/include/asm/atomic.h
arch/mips/include/asm/barrier.h
arch/mips/include/asm/cmpxchg.h
arch/mips/include/asm/dma.h
arch/mips/include/asm/exec.h [new file with mode: 0644]
arch/mips/include/asm/mach-au1x00/au1000_dma.h
arch/mips/include/asm/processor.h
arch/mips/include/asm/setup.h
arch/mips/include/asm/switch_to.h [new file with mode: 0644]
arch/mips/include/asm/system.h [deleted file]
arch/mips/include/asm/txx9/jmr3927.h
arch/mips/kernel/cpu-bugs64.c
arch/mips/kernel/cpu-probe.c
arch/mips/kernel/irq-rm7000.c
arch/mips/kernel/irq-rm9000.c
arch/mips/kernel/irq.c
arch/mips/kernel/irq_cpu.c
arch/mips/kernel/mips-mt.c
arch/mips/kernel/process.c
arch/mips/kernel/ptrace.c
arch/mips/kernel/ptrace32.c
arch/mips/kernel/rtlx.c
arch/mips/kernel/setup.c
arch/mips/kernel/signal.c
arch/mips/kernel/signal32.c
arch/mips/kernel/signal_n32.c
arch/mips/kernel/smp-bmips.c
arch/mips/kernel/smp-cmp.c
arch/mips/kernel/smp-mt.c
arch/mips/kernel/smp.c
arch/mips/kernel/smtc-proc.c
arch/mips/kernel/smtc.c
arch/mips/kernel/spram.c
arch/mips/kernel/syscall.c
arch/mips/kernel/traps.c
arch/mips/kernel/unaligned.c
arch/mips/kernel/vpe.c
arch/mips/lasat/reset.c
arch/mips/math-emu/dsemul.c
arch/mips/mipssim/sim_smtc.c
arch/mips/mipssim/sim_time.c
arch/mips/mm/c-octeon.c
arch/mips/mm/c-r3k.c
arch/mips/mm/c-r4k.c
arch/mips/mm/c-tx39.c
arch/mips/mm/fault.c
arch/mips/mm/page.c
arch/mips/mm/sc-ip22.c
arch/mips/mm/sc-mips.c
arch/mips/mm/sc-r5k.c
arch/mips/mm/tlb-r3k.c
arch/mips/mm/tlb-r4k.c
arch/mips/mm/tlb-r8k.c
arch/mips/mm/tlbex.c
arch/mips/mti-malta/malta-init.c
arch/mips/mti-malta/malta-int.c
arch/mips/mti-malta/malta-time.c
arch/mips/netlogic/common/irq.c
arch/mips/pmc-sierra/msp71xx/msp_irq_cic.c
arch/mips/pmc-sierra/msp71xx/msp_irq_per.c
arch/mips/pmc-sierra/msp71xx/msp_irq_slp.c
arch/mips/pmc-sierra/yosemite/irq.c
arch/mips/pmc-sierra/yosemite/prom.c
arch/mips/pnx833x/common/interrupts.c
arch/mips/powertv/asic/asic_int.c
arch/mips/powertv/asic/irq_asic.c
arch/mips/powertv/init.c
arch/mips/rb532/irq.c
arch/mips/sgi-ip22/ip22-berr.c
arch/mips/sgi-ip22/ip22-reset.c
arch/mips/sgi-ip22/ip28-berr.c
arch/mips/sgi-ip27/ip27-irq.c
arch/mips/sgi-ip27/ip27-reset.c
arch/mips/sgi-ip32/ip32-irq.c
arch/mips/sgi-ip32/ip32-reset.c
arch/mips/sibyte/bcm1480/irq.c
arch/mips/sibyte/common/sb_tbprof.c
arch/mips/sibyte/sb1250/bus_watcher.c
arch/mips/sibyte/sb1250/irq.c
arch/mips/sni/reset.c
arch/mips/vr41xx/common/irq.c
arch/mips/vr41xx/common/pmu.c
arch/mn10300/include/asm/atomic.h
arch/mn10300/include/asm/barrier.h [new file with mode: 0644]
arch/mn10300/include/asm/cmpxchg.h [new file with mode: 0644]
arch/mn10300/include/asm/dma.h
arch/mn10300/include/asm/exec.h [new file with mode: 0644]
arch/mn10300/include/asm/switch_to.h [new file with mode: 0644]
arch/mn10300/include/asm/system.h [deleted file]
arch/mn10300/kernel/entry.S
arch/mn10300/kernel/fpu.c
arch/mn10300/kernel/gdb-io-serial.c
arch/mn10300/kernel/gdb-io-ttysm.c
arch/mn10300/kernel/gdb-stub.c
arch/mn10300/kernel/mn10300-serial.c
arch/mn10300/kernel/mn10300-watchdog.c
arch/mn10300/kernel/process.c
arch/mn10300/kernel/ptrace.c
arch/mn10300/kernel/setup.c
arch/mn10300/kernel/smp-low.S
arch/mn10300/kernel/smp.c
arch/mn10300/kernel/traps.c
arch/mn10300/lib/bitops.c
arch/mn10300/mm/fault.c
arch/mn10300/mm/init.c
arch/mn10300/mm/misalignment.c
arch/mn10300/mm/pgtable.c
arch/mn10300/mm/tlb-smp.c
arch/mn10300/proc-mn2ws0050/proc-init.c
arch/openrisc/include/asm/Kbuild
arch/openrisc/include/asm/system.h [deleted file]
arch/openrisc/kernel/idle.c
arch/openrisc/kernel/process.c
arch/openrisc/kernel/prom.c
arch/openrisc/kernel/ptrace.c
arch/openrisc/kernel/setup.c
arch/openrisc/kernel/traps.c
arch/openrisc/mm/init.c
arch/openrisc/mm/tlb.c
arch/parisc/include/asm/atomic.h
arch/parisc/include/asm/barrier.h [new file with mode: 0644]
arch/parisc/include/asm/delay.h
arch/parisc/include/asm/dma.h
arch/parisc/include/asm/exec.h [new file with mode: 0644]
arch/parisc/include/asm/ldcw.h [new file with mode: 0644]
arch/parisc/include/asm/processor.h
arch/parisc/include/asm/psw.h
arch/parisc/include/asm/special_insns.h [new file with mode: 0644]
arch/parisc/include/asm/spinlock.h
arch/parisc/include/asm/switch_to.h [new file with mode: 0644]
arch/parisc/include/asm/system.h [deleted file]
arch/parisc/include/asm/thread_info.h
arch/parisc/include/asm/timex.h
arch/parisc/include/asm/uaccess.h
arch/parisc/kernel/cache.c
arch/parisc/kernel/firmware.c
arch/parisc/kernel/pci.c
arch/parisc/kernel/ptrace.c
arch/parisc/kernel/smp.c
arch/parisc/kernel/traps.c
arch/parisc/lib/bitops.c
arch/powerpc/boot/.gitignore
arch/powerpc/include/asm/atomic.h
arch/powerpc/include/asm/auxvec.h
arch/powerpc/include/asm/barrier.h [new file with mode: 0644]
arch/powerpc/include/asm/bug.h
arch/powerpc/include/asm/cache.h
arch/powerpc/include/asm/cmpxchg.h [new file with mode: 0644]
arch/powerpc/include/asm/debug.h [new file with mode: 0644]
arch/powerpc/include/asm/dma.h
arch/powerpc/include/asm/exec.h [new file with mode: 0644]
arch/powerpc/include/asm/hw_breakpoint.h
arch/powerpc/include/asm/iommu.h
arch/powerpc/include/asm/irq.h
arch/powerpc/include/asm/kvm.h
arch/powerpc/include/asm/kvm_book3s.h
arch/powerpc/include/asm/kvm_book3s_32.h
arch/powerpc/include/asm/kvm_book3s_64.h
arch/powerpc/include/asm/kvm_e500.h
arch/powerpc/include/asm/kvm_host.h
arch/powerpc/include/asm/kvm_para.h
arch/powerpc/include/asm/kvm_ppc.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/pci-bridge.h
arch/powerpc/include/asm/perf_event_server.h
arch/powerpc/include/asm/ppc-opcode.h
arch/powerpc/include/asm/processor.h
arch/powerpc/include/asm/reg.h
arch/powerpc/include/asm/reg_booke.h
arch/powerpc/include/asm/rtas.h
arch/powerpc/include/asm/runlatch.h [new file with mode: 0644]
arch/powerpc/include/asm/setup.h
arch/powerpc/include/asm/smp.h
arch/powerpc/include/asm/switch_to.h [new file with mode: 0644]
arch/powerpc/include/asm/system.h [deleted file]
arch/powerpc/include/asm/udbg.h
arch/powerpc/include/asm/vio.h
arch/powerpc/kernel/align.c
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/cputable.c
arch/powerpc/kernel/crash.c
arch/powerpc/kernel/exceptions-64s.S
arch/powerpc/kernel/idle.c
arch/powerpc/kernel/irq.c
arch/powerpc/kernel/kprobes.c
arch/powerpc/kernel/kvm.c
arch/powerpc/kernel/kvm_emul.S
arch/powerpc/kernel/lparcfg.c
arch/powerpc/kernel/ppc_ksyms.c
arch/powerpc/kernel/process.c
arch/powerpc/kernel/prom.c
arch/powerpc/kernel/prom_init.c
arch/powerpc/kernel/ptrace.c
arch/powerpc/kernel/ptrace32.c
arch/powerpc/kernel/rtas.c
arch/powerpc/kernel/setup-common.c
arch/powerpc/kernel/setup_32.c
arch/powerpc/kernel/setup_64.c
arch/powerpc/kernel/signal.c
arch/powerpc/kernel/signal_32.c
arch/powerpc/kernel/signal_64.c
arch/powerpc/kernel/smp.c
arch/powerpc/kernel/softemu8xx.c
arch/powerpc/kernel/swsusp.c
arch/powerpc/kernel/swsusp_64.c
arch/powerpc/kernel/sys_ppc32.c
arch/powerpc/kernel/sysfs.c
arch/powerpc/kernel/traps.c
arch/powerpc/kernel/udbg.c
arch/powerpc/kernel/vdso.c
arch/powerpc/kernel/vio.c
arch/powerpc/kvm/Kconfig
arch/powerpc/kvm/book3s.c
arch/powerpc/kvm/book3s_32_mmu_host.c
arch/powerpc/kvm/book3s_64_mmu_host.c
arch/powerpc/kvm/book3s_64_mmu_hv.c
arch/powerpc/kvm/book3s_emulate.c
arch/powerpc/kvm/book3s_hv.c
arch/powerpc/kvm/book3s_hv_builtin.c
arch/powerpc/kvm/book3s_hv_rm_mmu.c
arch/powerpc/kvm/book3s_hv_rmhandlers.S
arch/powerpc/kvm/book3s_paired_singles.c
arch/powerpc/kvm/book3s_pr.c
arch/powerpc/kvm/booke.c
arch/powerpc/kvm/booke.h
arch/powerpc/kvm/booke_emulate.c
arch/powerpc/kvm/booke_interrupts.S
arch/powerpc/kvm/e500.c
arch/powerpc/kvm/e500_emulate.c
arch/powerpc/kvm/e500_tlb.c
arch/powerpc/kvm/e500_tlb.h
arch/powerpc/kvm/emulate.c
arch/powerpc/kvm/powerpc.c
arch/powerpc/kvm/trace.h
arch/powerpc/lib/alloc.c
arch/powerpc/lib/copyuser_power7_vmx.c
arch/powerpc/mm/44x_mmu.c
arch/powerpc/mm/fault.c
arch/powerpc/mm/hash_utils_64.c
arch/powerpc/mm/hugetlbpage.c
arch/powerpc/mm/init_32.c
arch/powerpc/mm/init_64.c
arch/powerpc/mm/numa.c
arch/powerpc/mm/pgtable_32.c
arch/powerpc/mm/pgtable_64.c
arch/powerpc/oprofile/common.c
arch/powerpc/oprofile/op_model_7450.c
arch/powerpc/oprofile/op_model_cell.c
arch/powerpc/oprofile/op_model_fsl_emb.c
arch/powerpc/oprofile/op_model_power4.c
arch/powerpc/oprofile/op_model_rs64.c
arch/powerpc/perf/core-book3s.c
arch/powerpc/perf/power4-pmu.c
arch/powerpc/perf/ppc970-pmu.c
arch/powerpc/platforms/52xx/lite5200_pm.c
arch/powerpc/platforms/82xx/pq2.c
arch/powerpc/platforms/83xx/km83xx.c
arch/powerpc/platforms/83xx/mpc832x_mds.c
arch/powerpc/platforms/83xx/mpc834x_itx.c
arch/powerpc/platforms/83xx/mpc834x_mds.c
arch/powerpc/platforms/83xx/mpc836x_mds.c
arch/powerpc/platforms/83xx/sbc834x.c
arch/powerpc/platforms/83xx/suspend.c
arch/powerpc/platforms/85xx/corenet_ds.c
arch/powerpc/platforms/85xx/ge_imp3a.c
arch/powerpc/platforms/85xx/ksi8560.c
arch/powerpc/platforms/85xx/mpc8536_ds.c
arch/powerpc/platforms/85xx/mpc85xx_ads.c
arch/powerpc/platforms/85xx/mpc85xx_cds.c
arch/powerpc/platforms/85xx/mpc85xx_ds.c
arch/powerpc/platforms/85xx/mpc85xx_mds.c
arch/powerpc/platforms/85xx/mpc85xx_rdb.c
arch/powerpc/platforms/85xx/p1010rdb.c
arch/powerpc/platforms/85xx/p1023_rds.c
arch/powerpc/platforms/85xx/p2041_rdb.c
arch/powerpc/platforms/85xx/p3041_ds.c
arch/powerpc/platforms/85xx/p4080_ds.c
arch/powerpc/platforms/85xx/p5020_ds.c
arch/powerpc/platforms/85xx/sbc8548.c
arch/powerpc/platforms/85xx/sbc8560.c
arch/powerpc/platforms/85xx/socrates.c
arch/powerpc/platforms/85xx/stx_gp3.c
arch/powerpc/platforms/85xx/tqm85xx.c
arch/powerpc/platforms/85xx/xes_mpc85xx.c
arch/powerpc/platforms/86xx/gef_ppc9a.c
arch/powerpc/platforms/86xx/gef_sbc310.c
arch/powerpc/platforms/86xx/gef_sbc610.c
arch/powerpc/platforms/86xx/mpc8610_hpcd.c
arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
arch/powerpc/platforms/86xx/pic.c
arch/powerpc/platforms/86xx/sbc8641d.c
arch/powerpc/platforms/8xx/mpc86xads_setup.c
arch/powerpc/platforms/8xx/mpc885ads_setup.c
arch/powerpc/platforms/8xx/tqm8xx_setup.c
arch/powerpc/platforms/cell/beat_htab.c
arch/powerpc/platforms/cell/smp.c
arch/powerpc/platforms/embedded6xx/c2k.c
arch/powerpc/platforms/embedded6xx/holly.c
arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
arch/powerpc/platforms/embedded6xx/prpmc2800.c
arch/powerpc/platforms/embedded6xx/storcenter.c
arch/powerpc/platforms/fsl_uli1575.c
arch/powerpc/platforms/maple/setup.c
arch/powerpc/platforms/maple/time.c
arch/powerpc/platforms/pasemi/setup.c
arch/powerpc/platforms/powermac/bootx_init.c
arch/powerpc/platforms/powermac/cpufreq_32.c
arch/powerpc/platforms/powermac/nvram.c
arch/powerpc/platforms/powermac/setup.c
arch/powerpc/platforms/powermac/time.c
arch/powerpc/platforms/powernv/smp.c
arch/powerpc/platforms/ps3/mm.c
arch/powerpc/platforms/pseries/dtl.c
arch/powerpc/platforms/pseries/eeh.c
arch/powerpc/platforms/pseries/eeh_dev.c
arch/powerpc/platforms/pseries/hotplug-cpu.c
arch/powerpc/platforms/pseries/io_event_irq.c
arch/powerpc/platforms/pseries/iommu.c
arch/powerpc/platforms/pseries/processor_idle.c
arch/powerpc/platforms/pseries/ras.c
arch/powerpc/platforms/pseries/smp.c
arch/powerpc/platforms/wsp/chroma.c
arch/powerpc/platforms/wsp/psr2.c
arch/powerpc/platforms/wsp/wsp_pci.c
arch/powerpc/sysdev/cpm_common.c
arch/powerpc/sysdev/fsl_soc.c
arch/powerpc/sysdev/msi_bitmap.c
arch/powerpc/sysdev/tsi108_dev.c
arch/powerpc/xmon/xmon.c
arch/s390/crypto/crypt_s390.h
arch/s390/include/asm/atomic.h
arch/s390/include/asm/barrier.h [new file with mode: 0644]
arch/s390/include/asm/ctl_reg.h [new file with mode: 0644]
arch/s390/include/asm/elf.h
arch/s390/include/asm/exec.h [new file with mode: 0644]
arch/s390/include/asm/facility.h [new file with mode: 0644]
arch/s390/include/asm/kvm.h
arch/s390/include/asm/kvm_host.h
arch/s390/include/asm/mmu.h
arch/s390/include/asm/mmu_context.h
arch/s390/include/asm/processor.h
arch/s390/include/asm/setup.h
arch/s390/include/asm/smp.h
arch/s390/include/asm/switch_to.h [new file with mode: 0644]
arch/s390/include/asm/system.h [deleted file]
arch/s390/include/asm/uaccess.h
arch/s390/kernel/asm-offsets.c
arch/s390/kernel/compat_signal.c
arch/s390/kernel/cpcmd.c
arch/s390/kernel/dis.c
arch/s390/kernel/early.c
arch/s390/kernel/lgr.c
arch/s390/kernel/machine_kexec.c
arch/s390/kernel/os_info.c
arch/s390/kernel/process.c
arch/s390/kernel/ptrace.c
arch/s390/kernel/setup.c
arch/s390/kernel/signal.c
arch/s390/kernel/suspend.c
arch/s390/kernel/traps.c
arch/s390/kernel/vdso.c
arch/s390/kvm/Kconfig
arch/s390/kvm/diag.c
arch/s390/kvm/intercept.c
arch/s390/kvm/interrupt.c
arch/s390/kvm/kvm-s390.c
arch/s390/kvm/kvm-s390.h
arch/s390/kvm/priv.c
arch/s390/kvm/sigp.c
arch/s390/mm/fault.c
arch/s390/mm/init.c
arch/s390/mm/maccess.c
arch/s390/mm/pgtable.c
arch/s390/oprofile/hwsampler.c
arch/score/include/asm/atomic.h
arch/score/include/asm/barrier.h [new file with mode: 0644]
arch/score/include/asm/bitops.h
arch/score/include/asm/bug.h
arch/score/include/asm/cmpxchg.h [new file with mode: 0644]
arch/score/include/asm/exec.h [new file with mode: 0644]
arch/score/include/asm/switch_to.h [new file with mode: 0644]
arch/score/include/asm/system.h [deleted file]
arch/sh/boards/mach-microdev/irq.c
arch/sh/include/asm/atomic-irq.h
arch/sh/include/asm/atomic.h
arch/sh/include/asm/auxvec.h
arch/sh/include/asm/barrier.h [new file with mode: 0644]
arch/sh/include/asm/bitops.h
arch/sh/include/asm/bl_bit.h [new file with mode: 0644]
arch/sh/include/asm/bl_bit_32.h [new file with mode: 0644]
arch/sh/include/asm/bl_bit_64.h [new file with mode: 0644]
arch/sh/include/asm/bug.h
arch/sh/include/asm/cache_insns.h [new file with mode: 0644]
arch/sh/include/asm/cache_insns_32.h [new file with mode: 0644]
arch/sh/include/asm/cache_insns_64.h [new file with mode: 0644]
arch/sh/include/asm/cmpxchg-irq.h
arch/sh/include/asm/cmpxchg.h [new file with mode: 0644]
arch/sh/include/asm/exec.h [new file with mode: 0644]
arch/sh/include/asm/futex-irq.h
arch/sh/include/asm/io.h
arch/sh/include/asm/processor.h
arch/sh/include/asm/ptrace.h
arch/sh/include/asm/setup.h
arch/sh/include/asm/switch_to.h [new file with mode: 0644]
arch/sh/include/asm/switch_to_32.h [new file with mode: 0644]
arch/sh/include/asm/switch_to_64.h [new file with mode: 0644]
arch/sh/include/asm/system.h [deleted file]
arch/sh/include/asm/system_32.h [deleted file]
arch/sh/include/asm/system_64.h [deleted file]
arch/sh/include/asm/traps.h [new file with mode: 0644]
arch/sh/include/asm/traps_32.h [new file with mode: 0644]
arch/sh/include/asm/traps_64.h [new file with mode: 0644]
arch/sh/include/asm/uaccess.h
arch/sh/kernel/cpu/init.c
arch/sh/kernel/cpu/irq/imask.c
arch/sh/kernel/cpu/sh2a/opcode_helper.c
arch/sh/kernel/cpu/sh4/fpu.c
arch/sh/kernel/hw_breakpoint.c
arch/sh/kernel/idle.c
arch/sh/kernel/io_trapped.c
arch/sh/kernel/process_32.c
arch/sh/kernel/process_64.c
arch/sh/kernel/ptrace_32.c
arch/sh/kernel/ptrace_64.c
arch/sh/kernel/reboot.c
arch/sh/kernel/signal_32.c
arch/sh/kernel/smp.c
arch/sh/kernel/traps.c
arch/sh/kernel/traps_32.c
arch/sh/kernel/traps_64.c
arch/sh/math-emu/math.c
arch/sh/mm/fault_32.c
arch/sh/mm/fault_64.c
arch/sh/mm/flush-sh4.c
arch/sh/mm/pmb.c
arch/sh/mm/tlb-pteaex.c
arch/sh/mm/tlb-sh3.c
arch/sh/mm/tlb-sh4.c
arch/sh/mm/tlbflush_64.c
arch/sparc/include/asm/atomic_32.h
arch/sparc/include/asm/atomic_64.h
arch/sparc/include/asm/auxio_32.h
arch/sparc/include/asm/barrier.h [new file with mode: 0644]
arch/sparc/include/asm/barrier_32.h [new file with mode: 0644]
arch/sparc/include/asm/barrier_64.h [new file with mode: 0644]
arch/sparc/include/asm/bug.h
arch/sparc/include/asm/cacheflush_32.h
arch/sparc/include/asm/cacheflush_64.h
arch/sparc/include/asm/cmpxchg.h [new file with mode: 0644]
arch/sparc/include/asm/cmpxchg_32.h [new file with mode: 0644]
arch/sparc/include/asm/cmpxchg_64.h [new file with mode: 0644]
arch/sparc/include/asm/cpu_type.h [new file with mode: 0644]
arch/sparc/include/asm/exec.h [new file with mode: 0644]
arch/sparc/include/asm/floppy_32.h
arch/sparc/include/asm/futex_64.h
arch/sparc/include/asm/io_32.h
arch/sparc/include/asm/io_64.h
arch/sparc/include/asm/irqflags_32.h
arch/sparc/include/asm/mmu_context_64.h
arch/sparc/include/asm/ns87303.h
arch/sparc/include/asm/perfctr.h
arch/sparc/include/asm/pgtable_32.h
arch/sparc/include/asm/pgtable_64.h
arch/sparc/include/asm/processor.h
arch/sparc/include/asm/processor_64.h
arch/sparc/include/asm/ptrace.h
arch/sparc/include/asm/setup.h
arch/sparc/include/asm/switch_to.h [new file with mode: 0644]
arch/sparc/include/asm/switch_to_32.h [new file with mode: 0644]
arch/sparc/include/asm/switch_to_64.h [new file with mode: 0644]
arch/sparc/include/asm/system.h [deleted file]
arch/sparc/include/asm/system_32.h [deleted file]
arch/sparc/include/asm/system_64.h [deleted file]
arch/sparc/include/asm/timer_32.h
arch/sparc/include/asm/uaccess_64.h
arch/sparc/include/asm/vio.h
arch/sparc/kernel/auxio_32.c
arch/sparc/kernel/devices.c
arch/sparc/kernel/ds.c
arch/sparc/kernel/irq.h
arch/sparc/kernel/irq_64.c
arch/sparc/kernel/kgdb_32.c
arch/sparc/kernel/module.c
arch/sparc/kernel/muldiv.c
arch/sparc/kernel/nmi.c
arch/sparc/kernel/pcr.c
arch/sparc/kernel/perf_event.c
arch/sparc/kernel/process_32.c
arch/sparc/kernel/process_64.c
arch/sparc/kernel/ptrace_32.c
arch/sparc/kernel/ptrace_64.c
arch/sparc/kernel/reboot.c
arch/sparc/kernel/setup_32.c
arch/sparc/kernel/setup_64.c
arch/sparc/kernel/signal32.c
arch/sparc/kernel/signal_32.c
arch/sparc/kernel/signal_64.c
arch/sparc/kernel/sigutil_32.c
arch/sparc/kernel/sigutil_64.c
arch/sparc/kernel/sparc_ksyms_64.c
arch/sparc/kernel/time_32.c
arch/sparc/kernel/traps_32.c
arch/sparc/kernel/traps_64.c
arch/sparc/kernel/unaligned_32.c
arch/sparc/kernel/unaligned_64.c
arch/sparc/kernel/vio.c
arch/sparc/kernel/visemul.c
arch/sparc/math-emu/math_64.c
arch/sparc/mm/btfixup.c
arch/sparc/mm/fault_32.c
arch/sparc/mm/init_32.c
arch/sparc/mm/init_64.c
arch/sparc/mm/init_64.h
arch/sparc/mm/loadmmu.c
arch/sparc/mm/tsb.c
arch/sparc/prom/console_32.c
arch/sparc/prom/console_64.c
arch/sparc/prom/misc_32.c
arch/sparc/prom/misc_64.c
arch/sparc/prom/p1275.c
arch/sparc/prom/ranges.c
arch/tile/include/asm/atomic.h
arch/tile/include/asm/atomic_32.h
arch/tile/include/asm/atomic_64.h
arch/tile/include/asm/barrier.h [new file with mode: 0644]
arch/tile/include/asm/bitops_32.h
arch/tile/include/asm/bitops_64.h
arch/tile/include/asm/cacheflush.h
arch/tile/include/asm/exec.h [new file with mode: 0644]
arch/tile/include/asm/pgtable.h
arch/tile/include/asm/setup.h
arch/tile/include/asm/spinlock_32.h
arch/tile/include/asm/switch_to.h [new file with mode: 0644]
arch/tile/include/asm/system.h [deleted file]
arch/tile/include/asm/timex.h
arch/tile/include/asm/unaligned.h
arch/tile/kernel/early_printk.c
arch/tile/kernel/proc.c
arch/tile/kernel/process.c
arch/tile/kernel/regs_32.S
arch/tile/kernel/regs_64.S
arch/tile/kernel/single_step.c
arch/tile/kernel/traps.c
arch/tile/mm/elf.c
arch/tile/mm/fault.c
arch/tile/mm/init.c
arch/tile/mm/pgtable.c
arch/um/include/asm/fixmap.h
arch/unicore32/include/asm/Kbuild
arch/unicore32/include/asm/barrier.h [new file with mode: 0644]
arch/unicore32/include/asm/bug.h [new file with mode: 0644]
arch/unicore32/include/asm/cmpxchg.h [new file with mode: 0644]
arch/unicore32/include/asm/exec.h [new file with mode: 0644]
arch/unicore32/include/asm/hwdef-copro.h [new file with mode: 0644]
arch/unicore32/include/asm/io.h
arch/unicore32/include/asm/switch_to.h [new file with mode: 0644]
arch/unicore32/include/asm/system.h [deleted file]
arch/unicore32/include/asm/uaccess.h
arch/unicore32/kernel/dma.c
arch/unicore32/kernel/head.S
arch/unicore32/kernel/hibernate.c
arch/unicore32/kernel/irq.c
arch/unicore32/kernel/ksyms.c
arch/unicore32/kernel/process.c
arch/unicore32/kernel/setup.h
arch/unicore32/kernel/traps.c
arch/unicore32/mm/alignment.c
arch/unicore32/mm/fault.c
arch/unicore32/mm/flush.c
arch/unicore32/mm/mm.h
arch/x86/Kconfig
arch/x86/ia32/ia32_aout.c
arch/x86/include/asm/apic.h
arch/x86/include/asm/auxvec.h
arch/x86/include/asm/barrier.h [new file with mode: 0644]
arch/x86/include/asm/bug.h
arch/x86/include/asm/cacheflush.h
arch/x86/include/asm/elf.h
arch/x86/include/asm/exec.h [new file with mode: 0644]
arch/x86/include/asm/futex.h
arch/x86/include/asm/i387.h
arch/x86/include/asm/kvm.h
arch/x86/include/asm/kvm_emulate.h
arch/x86/include/asm/kvm_host.h
arch/x86/include/asm/local.h
arch/x86/include/asm/mc146818rtc.h
arch/x86/include/asm/page_types.h
arch/x86/include/asm/perf_event.h
arch/x86/include/asm/processor.h
arch/x86/include/asm/segment.h
arch/x86/include/asm/special_insns.h [new file with mode: 0644]
arch/x86/include/asm/stackprotector.h
arch/x86/include/asm/switch_to.h [new file with mode: 0644]
arch/x86/include/asm/system.h [deleted file]
arch/x86/include/asm/tlbflush.h
arch/x86/include/asm/tsc.h
arch/x86/include/asm/virtext.h
arch/x86/include/asm/x86_init.h
arch/x86/kernel/acpi/cstate.c
arch/x86/kernel/apm_32.c
arch/x86/kernel/cpu/mcheck/p5.c
arch/x86/kernel/cpu/mcheck/therm_throt.c
arch/x86/kernel/cpu/mcheck/winchip.c
arch/x86/kernel/cpu/mtrr/generic.c
arch/x86/kernel/cpuid.c
arch/x86/kernel/i8259.c
arch/x86/kernel/irqinit.c
arch/x86/kernel/kgdb.c
arch/x86/kernel/kvmclock.c
arch/x86/kernel/ldt.c
arch/x86/kernel/machine_kexec_32.c
arch/x86/kernel/mca_32.c
arch/x86/kernel/module.c
arch/x86/kernel/msr.c
arch/x86/kernel/paravirt.c
arch/x86/kernel/pci-calgary_64.c
arch/x86/kernel/process.c
arch/x86/kernel/process_32.c
arch/x86/kernel/process_64.c
arch/x86/kernel/ptrace.c
arch/x86/kernel/setup.c
arch/x86/kernel/smpboot.c
arch/x86/kernel/tce_64.c
arch/x86/kernel/tls.c
arch/x86/kernel/traps.c
arch/x86/kernel/tsc.c
arch/x86/kernel/x86_init.c
arch/x86/kvm/cpuid.c
arch/x86/kvm/cpuid.h
arch/x86/kvm/emulate.c
arch/x86/kvm/i8259.c
arch/x86/kvm/lapic.c
arch/x86/kvm/mmu.c
arch/x86/kvm/mmu_audit.c
arch/x86/kvm/pmu.c
arch/x86/kvm/svm.c
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
arch/x86/mm/init.c
arch/x86/mm/init_32.c
arch/x86/mm/init_64.c
arch/x86/mm/pgtable_32.c
arch/x86/platform/ce4100/falconfalls.dts
arch/x86/platform/geode/Makefile
arch/x86/platform/geode/geos.c [new file with mode: 0644]
arch/x86/power/cpu.c
arch/x86/power/hibernate_32.c
arch/xtensa/include/asm/atomic.h
arch/xtensa/include/asm/barrier.h [new file with mode: 0644]
arch/xtensa/include/asm/bitops.h
arch/xtensa/include/asm/cmpxchg.h [new file with mode: 0644]
arch/xtensa/include/asm/exec.h [new file with mode: 0644]
arch/xtensa/include/asm/setup.h
arch/xtensa/include/asm/switch_to.h [new file with mode: 0644]
arch/xtensa/include/asm/system.h [deleted file]
arch/xtensa/include/asm/uaccess.h
arch/xtensa/kernel/process.c
arch/xtensa/kernel/ptrace.c
arch/xtensa/kernel/setup.c
arch/xtensa/kernel/traps.c
arch/xtensa/mm/fault.c
arch/xtensa/mm/tlb.c
drivers/acpi/ec.c
drivers/acpi/processor_driver.c
drivers/acpi/video_detect.c
drivers/atm/eni.c
drivers/atm/firestream.c
drivers/atm/horizon.c
drivers/atm/idt77105.c
drivers/atm/iphase.c
drivers/atm/suni.c
drivers/atm/zatm.c
drivers/base/dma-buf.c
drivers/block/floppy.c
drivers/block/hd.c
drivers/block/nbd.c
drivers/block/sunvdc.c
drivers/block/xd.c
drivers/bluetooth/bt3c_cs.c
drivers/bluetooth/btuart_cs.c
drivers/bluetooth/dtl1_cs.c
drivers/char/apm-emulation.c
drivers/char/ds1302.c
drivers/char/efirtc.c
drivers/char/genrtc.c
drivers/char/hpet.c
drivers/char/ipmi/ipmi_devintf.c
drivers/char/ipmi/ipmi_msghandler.c
drivers/char/ipmi/ipmi_si_intf.c
drivers/char/ipmi/ipmi_watchdog.c
drivers/char/lp.c
drivers/char/mbcs.c
drivers/char/mspec.c
drivers/char/mwave/3780i.c
drivers/char/nvram.c
drivers/char/nwflash.c
drivers/char/pcmcia/synclink_cs.c
drivers/char/rtc.c
drivers/char/sonypi.c
drivers/char/xilinx_hwicap/xilinx_hwicap.c
drivers/clk/Kconfig
drivers/clk/Makefile
drivers/clk/clk-divider.c [new file with mode: 0644]
drivers/clk/clk-fixed-rate.c [new file with mode: 0644]
drivers/clk/clk-gate.c [new file with mode: 0644]
drivers/clk/clk-mux.c [new file with mode: 0644]
drivers/clk/clk.c [new file with mode: 0644]
drivers/cpufreq/db8500-cpufreq.c
drivers/cpufreq/omap-cpufreq.c
drivers/cpufreq/powernow-k7.c
drivers/edac/Kconfig
drivers/edac/edac_mc.c
drivers/edac/i5100_edac.c
drivers/edac/i5400_edac.c
drivers/edac/ppc4xx_edac.c
drivers/edac/sb_edac.c
drivers/firewire/core-cdev.c
drivers/firewire/core-device.c
drivers/firewire/core-topology.c
drivers/firewire/ohci.c
drivers/firewire/sbp2.c
drivers/gpio/Kconfig
drivers/gpio/Makefile
drivers/gpio/gpio-davinci.c
drivers/gpio/gpio-ep93xx.c
drivers/gpio/gpio-lpc32xx.c
drivers/gpio/gpio-mc9s08dz60.c [new file with mode: 0644]
drivers/gpio/gpio-omap.c
drivers/gpio/gpio-pl061.c
drivers/gpio/gpio-samsung.c
drivers/gpio/gpio-sodaville.c [new file with mode: 0644]
drivers/gpio/gpio-stmpe.c
drivers/gpio/gpio-tegra.c
drivers/gpio/gpio-tps65910.c
drivers/gpio/gpio-twl4030.c
drivers/gpio/gpiolib.c
drivers/gpu/drm/gma500/mdfld_dsi_output.c
drivers/gpu/drm/nouveau/nouveau_connector.c
drivers/gpu/drm/nouveau/nouveau_i2c.c
drivers/gpu/drm/nouveau/nouveau_state.c
drivers/gpu/drm/radeon/atombios_crtc.c
drivers/gpu/drm/radeon/atombios_dp.c
drivers/gpu/drm/radeon/atombios_encoders.c
drivers/gpu/drm/radeon/evergreen_cs.c
drivers/gpu/drm/radeon/evergreend.h
drivers/gpu/drm/radeon/r600_cs.c
drivers/gpu/drm/radeon/r600d.h
drivers/gpu/drm/radeon/radeon_object.c
drivers/gpu/drm/radeon/reg_srcs/cayman
drivers/gpu/drm/radeon/reg_srcs/evergreen
drivers/gpu/drm/radeon/reg_srcs/r600
drivers/hwmon/fschmd.c
drivers/hwmon/mc13783-adc.c
drivers/hwmon/w83793.c
drivers/i2c/algos/i2c-algo-bit.c
drivers/i2c/algos/i2c-algo-pca.c
drivers/i2c/algos/i2c-algo-pcf.c
drivers/i2c/algos/i2c-algo-pcf.h
drivers/i2c/busses/Kconfig
drivers/i2c/busses/i2c-acorn.c
drivers/i2c/busses/i2c-gpio.c
drivers/i2c/busses/i2c-i801.c
drivers/i2c/busses/i2c-isch.c
drivers/i2c/i2c-boardinfo.c
drivers/i2c/i2c-core.c
drivers/i2c/i2c-core.h
drivers/i2c/i2c-dev.c
drivers/i2c/i2c-smbus.c
drivers/i2c/muxes/pca9541.c
drivers/i2c/muxes/pca954x.c
drivers/ide/ide-cs.c
drivers/ide/qd65xx.c
drivers/infiniband/hw/ehca/ehca_reqs.c
drivers/input/joydev.c
drivers/input/joystick/amijoy.c
drivers/input/misc/88pm860x_onkey.c
drivers/input/mouse/amimouse.c
drivers/input/mouse/atarimouse.c
drivers/input/serio/hp_sdc.c
drivers/input/serio/maceps2.c
drivers/input/serio/rpckbd.c
drivers/input/serio/sa1111ps2.c
drivers/input/touchscreen/mc13783_ts.c
drivers/isdn/hardware/avm/avm_cs.c
drivers/isdn/hisax/avma1_cs.c
drivers/isdn/hisax/elsa_cs.c
drivers/isdn/hisax/sedlbauer_cs.c
drivers/isdn/hisax/teles_cs.c
drivers/isdn/i4l/isdn_bsdcomp.c
drivers/isdn/pcbit/layer2.c
drivers/leds/leds-88pm860x.c
drivers/macintosh/macio-adb.c
drivers/macintosh/therm_adt746x.c
drivers/macintosh/therm_pm72.c
drivers/macintosh/therm_windtunnel.c
drivers/macintosh/via-cuda.c
drivers/macintosh/via-macii.c
drivers/macintosh/via-pmu.c
drivers/macintosh/via-pmu68k.c
drivers/macintosh/windfarm_lm75_sensor.c
drivers/macintosh/windfarm_pm121.c
drivers/macintosh/windfarm_pm81.c
drivers/macintosh/windfarm_pm91.c
drivers/macintosh/windfarm_smu_controls.c
drivers/macintosh/windfarm_smu_sensors.c
drivers/md/Kconfig
drivers/md/Makefile
drivers/md/dm-bufio.c
drivers/md/dm-bufio.h
drivers/md/dm-crypt.c
drivers/md/dm-delay.c
drivers/md/dm-exception-store.c
drivers/md/dm-flakey.c
drivers/md/dm-ioctl.c
drivers/md/dm-linear.c
drivers/md/dm-log.c
drivers/md/dm-mpath.c
drivers/md/dm-queue-length.c
drivers/md/dm-raid.c
drivers/md/dm-raid1.c
drivers/md/dm-round-robin.c
drivers/md/dm-service-time.c
drivers/md/dm-stripe.c
drivers/md/dm-table.c
drivers/md/dm-thin-metadata.c
drivers/md/dm-thin-metadata.h
drivers/md/dm-thin.c
drivers/md/dm-verity.c [new file with mode: 0644]
drivers/md/dm.c
drivers/md/persistent-data/dm-btree-internal.h
drivers/md/persistent-data/dm-btree-remove.c
drivers/md/persistent-data/dm-btree.c
drivers/md/persistent-data/dm-space-map-common.c
drivers/media/dvb/dvb-core/dmxdev.c
drivers/media/dvb/firewire/firedtv-fw.c
drivers/media/dvb/ttpci/av7110.c
drivers/media/media-devnode.c
drivers/media/video/ivtv/ivtv-driver.h
drivers/media/video/v4l2-common.c
drivers/media/video/v4l2-dev.c
drivers/message/i2o/i2o_scsi.c
drivers/mfd/88pm860x-core.c
drivers/mfd/88pm860x-i2c.c
drivers/mfd/Kconfig
drivers/mfd/Makefile
drivers/mfd/ab8500-core.c
drivers/mfd/ab8500-i2c.c
drivers/mfd/anatop-mfd.c [new file with mode: 0644]
drivers/mfd/asic3.c
drivers/mfd/da9052-core.c
drivers/mfd/da9052-i2c.c
drivers/mfd/da9052-spi.c
drivers/mfd/db8500-prcmu.c
drivers/mfd/dbx500-prcmu-regs.h
drivers/mfd/mc13xxx-core.c
drivers/mfd/mcp-core.c
drivers/mfd/mcp-sa11x0.c
drivers/mfd/mfd-core.c
drivers/mfd/omap-usb-host.c
drivers/mfd/pcf50633-core.c
drivers/mfd/pcf50633-gpio.c
drivers/mfd/pcf50633-irq.c
drivers/mfd/rc5t583-irq.c [new file with mode: 0644]
drivers/mfd/rc5t583.c [new file with mode: 0644]
drivers/mfd/s5m-core.c
drivers/mfd/s5m-irq.c
drivers/mfd/sm501.c
drivers/mfd/stmpe.c
drivers/mfd/tps65090.c [new file with mode: 0644]
drivers/mfd/tps65217.c [new file with mode: 0644]
drivers/mfd/tps65910-irq.c
drivers/mfd/tps65910.c
drivers/mfd/twl-core.c
drivers/mfd/twl-core.h
drivers/mfd/twl4030-irq.c
drivers/mfd/twl6030-irq.c
drivers/mfd/wm831x-spi.c
drivers/mfd/wm8400-core.c
drivers/mfd/wm8994-core.c
drivers/mfd/wm8994-regmap.c
drivers/misc/sgi-gru/gru_instructions.h
drivers/misc/sgi-xp/xp.h
drivers/mmc/card/block.c
drivers/mtd/devices/pmc551.c
drivers/mtd/devices/slram.c
drivers/mtd/maps/pcmciamtd.c
drivers/mtd/nand/atmel_nand.c
drivers/mtd/nand/bcm_umi_nand.c
drivers/net/appletalk/cops.c
drivers/net/appletalk/ltpc.c
drivers/net/arcnet/com20020_cs.c
drivers/net/bonding/bond_main.c
drivers/net/can/slcan.c
drivers/net/cris/eth_v10.c
drivers/net/ethernet/3com/3c574_cs.c
drivers/net/ethernet/3com/3c589_cs.c
drivers/net/ethernet/8390/3c503.c
drivers/net/ethernet/8390/ac3200.c
drivers/net/ethernet/8390/apne.c
drivers/net/ethernet/8390/ax88796.c
drivers/net/ethernet/8390/axnet_cs.c
drivers/net/ethernet/8390/e2100.c
drivers/net/ethernet/8390/es3210.c
drivers/net/ethernet/8390/etherh.c
drivers/net/ethernet/8390/hp-plus.c
drivers/net/ethernet/8390/hp.c
drivers/net/ethernet/8390/lib8390.c
drivers/net/ethernet/8390/lne390.c
drivers/net/ethernet/8390/mac8390.c
drivers/net/ethernet/8390/ne-h8300.c
drivers/net/ethernet/8390/ne.c
drivers/net/ethernet/8390/ne2.c
drivers/net/ethernet/8390/ne2k-pci.c
drivers/net/ethernet/8390/ne3210.c
drivers/net/ethernet/8390/pcnet_cs.c
drivers/net/ethernet/8390/smc-mca.c
drivers/net/ethernet/8390/smc-ultra.c
drivers/net/ethernet/8390/smc-ultra32.c
drivers/net/ethernet/8390/stnic.c
drivers/net/ethernet/8390/wd.c
drivers/net/ethernet/8390/zorro8390.c
drivers/net/ethernet/alteon/acenic.c
drivers/net/ethernet/amd/7990.c
drivers/net/ethernet/amd/am79c961a.c
drivers/net/ethernet/amd/amd8111e.c
drivers/net/ethernet/amd/declance.c
drivers/net/ethernet/amd/hplance.c
drivers/net/ethernet/amd/mvme147.c
drivers/net/ethernet/amd/nmclan_cs.c
drivers/net/ethernet/amd/sunlance.c
drivers/net/ethernet/broadcom/tg3.c
drivers/net/ethernet/cirrus/cs89x0.c
drivers/net/ethernet/cirrus/mac89x0.c
drivers/net/ethernet/dlink/de600.c
drivers/net/ethernet/dlink/de620.c
drivers/net/ethernet/fujitsu/at1700.c
drivers/net/ethernet/fujitsu/eth16i.c
drivers/net/ethernet/fujitsu/fmvj18x_cs.c
drivers/net/ethernet/i825xx/3c507.c
drivers/net/ethernet/i825xx/3c527.c
drivers/net/ethernet/i825xx/eepro.c
drivers/net/ethernet/i825xx/eexpress.c
drivers/net/ethernet/i825xx/ether1.c
drivers/net/ethernet/i825xx/znet.c
drivers/net/ethernet/ibm/ibmveth.c
drivers/net/ethernet/korina.c
drivers/net/ethernet/marvell/mv643xx_eth.c
drivers/net/ethernet/marvell/pxa168_eth.c
drivers/net/ethernet/natsemi/jazzsonic.c
drivers/net/ethernet/natsemi/macsonic.c
drivers/net/ethernet/natsemi/ns83820.c
drivers/net/ethernet/neterion/s2io.c
drivers/net/ethernet/nvidia/forcedeth.c
drivers/net/ethernet/realtek/atp.c
drivers/net/ethernet/realtek/r8169.c
drivers/net/ethernet/seeq/ether3.c
drivers/net/ethernet/seeq/seeq8005.c
drivers/net/ethernet/smsc/smc91c92_cs.c
drivers/net/ethernet/sun/cassini.c
drivers/net/ethernet/sun/sunbmac.c
drivers/net/ethernet/sun/sungem.c
drivers/net/ethernet/sun/sunhme.c
drivers/net/ethernet/sun/sunqe.c
drivers/net/ethernet/sun/sunvnet.c
drivers/net/ethernet/tundra/tsi108_eth.c
drivers/net/ethernet/xircom/xirc2ps_cs.c
drivers/net/hamradio/6pack.c
drivers/net/hamradio/baycom_par.c
drivers/net/hamradio/bpqether.c
drivers/net/hamradio/mkiss.c
drivers/net/hamradio/scc.c
drivers/net/hamradio/yam.c
drivers/net/hippi/rrunner.c
drivers/net/irda/donauboe.c
drivers/net/loopback.c
drivers/net/plip/plip.c
drivers/net/slip/slhc.c
drivers/net/slip/slip.c
drivers/net/tokenring/3c359.c
drivers/net/tokenring/abyss.c
drivers/net/tokenring/ibmtr_cs.c
drivers/net/tokenring/lanstreamer.c
drivers/net/tokenring/madgemc.c
drivers/net/tokenring/olympic.c
drivers/net/tokenring/proteon.c
drivers/net/tokenring/skisa.c
drivers/net/tokenring/smctr.c
drivers/net/tokenring/tms380tr.c
drivers/net/tokenring/tmspci.c
drivers/net/tun.c
drivers/net/wan/dlci.c
drivers/net/wan/dscc4.c
drivers/net/wan/hd64570.c
drivers/net/wan/hd64572.c
drivers/net/wan/lapbether.c
drivers/net/wan/sdla.c
drivers/net/wan/x25_asy.c
drivers/net/wireless/airo.c
drivers/net/wireless/airo_cs.c
drivers/net/wireless/atmel.c
drivers/net/wireless/atmel_cs.c
drivers/net/wireless/prism54/islpci_mgt.c
drivers/net/wireless/ray_cs.c
drivers/net/wireless/wl3501_cs.c
drivers/nubus/nubus.c
drivers/of/Kconfig
drivers/of/Makefile
drivers/of/gpio.c
drivers/of/of_mtd.c [new file with mode: 0644]
drivers/parisc/dino.c
drivers/parisc/iosapic.c
drivers/parisc/lba_pci.c
drivers/pcmcia/cs.c
drivers/pcmcia/i82092.c
drivers/pcmcia/i82365.c
drivers/pcmcia/m32r_cfc.c
drivers/pcmcia/m32r_pcc.c
drivers/pcmcia/m8xx_pcmcia.c
drivers/pcmcia/pd6729.c
drivers/pcmcia/pxa2xx_base.c
drivers/pcmcia/sa11xx_base.c
drivers/pcmcia/soc_common.c
drivers/pcmcia/socket_sysfs.c
drivers/pcmcia/tcic.c
drivers/pcmcia/xxs1500_ss.c
drivers/platform/x86/Kconfig
drivers/platform/x86/Makefile
drivers/platform/x86/acer-wmi.c
drivers/platform/x86/acerhdf.c
drivers/platform/x86/amilo-rfkill.c
drivers/platform/x86/apple-gmux.c [new file with mode: 0644]
drivers/platform/x86/asus-laptop.c
drivers/platform/x86/asus-nb-wmi.c
drivers/platform/x86/asus-wmi.c
drivers/platform/x86/asus-wmi.h
drivers/platform/x86/asus_acpi.c [deleted file]
drivers/platform/x86/compal-laptop.c
drivers/platform/x86/dell-laptop.c
drivers/platform/x86/eeepc-laptop.c
drivers/platform/x86/eeepc-wmi.c
drivers/platform/x86/hdaps.c
drivers/platform/x86/intel_mid_powerbtn.c
drivers/platform/x86/intel_mid_thermal.c
drivers/platform/x86/intel_oaktrail.c
drivers/platform/x86/samsung-laptop.c
drivers/platform/x86/sony-laptop.c
drivers/platform/x86/thinkpad_acpi.c
drivers/platform/x86/toshiba_acpi.c
drivers/platform/x86/xo1-rfkill.c
drivers/pnp/pnpbios/bioscalls.c
drivers/pnp/pnpbios/core.c
drivers/rtc/rtc-88pm860x.c
drivers/rtc/rtc-mv.c
drivers/s390/char/sclp_cmd.c
drivers/s390/cio/crw.c
drivers/s390/crypto/ap_bus.c
drivers/sbus/char/flash.c
drivers/sbus/char/openprom.c
drivers/sbus/char/uctrl.c
drivers/scsi/53c700.c
drivers/scsi/BusLogic.c
drivers/scsi/advansys.c
drivers/scsi/aha152x.c
drivers/scsi/aha1542.c
drivers/scsi/aha1740.c
drivers/scsi/arcmsr/arcmsr_hba.c
drivers/scsi/arm/acornscsi.c
drivers/scsi/arm/cumana_1.c
drivers/scsi/arm/oak.c
drivers/scsi/atp870u.c
drivers/scsi/dtc.c
drivers/scsi/fd_mcs.c
drivers/scsi/fdomain.c
drivers/scsi/g_NCR5380.c
drivers/scsi/gdth.c
drivers/scsi/ibmmca.c
drivers/scsi/ibmvscsi/ibmvfc.c
drivers/scsi/ibmvscsi/ibmvscsi.c
drivers/scsi/ibmvscsi/ibmvstgt.c
drivers/scsi/in2000.c
drivers/scsi/mac53c94.c
drivers/scsi/mac_scsi.c
drivers/scsi/mesh.c
drivers/scsi/ncr53c8xx.c
drivers/scsi/nsp32.c
drivers/scsi/osst.c
drivers/scsi/pas16.c
drivers/scsi/qla1280.c
drivers/scsi/qlogicpti.c
drivers/scsi/st.c
drivers/scsi/sun3_scsi.c
drivers/scsi/sun3_scsi_vme.c
drivers/scsi/sym53c416.c
drivers/scsi/t128.c
drivers/scsi/u14-34f.c
drivers/scsi/ultrastor.c
drivers/scsi/wd7000.c
drivers/spi/spi-omap-uwire.c
drivers/spi/spi-orion.c
drivers/staging/comedi/drivers.c
drivers/staging/comedi/drivers/cb_pcidas64.c
drivers/staging/comedi/drivers/mite.c
drivers/staging/crystalhd/bc_dts_defs.h
drivers/staging/crystalhd/crystalhd.h
drivers/staging/crystalhd/crystalhd_lnx.h
drivers/staging/crystalhd/crystalhd_misc.h
drivers/staging/et131x/et131x.c
drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c
drivers/staging/media/go7007/go7007-driver.c
drivers/staging/media/go7007/go7007-i2c.c
drivers/staging/media/go7007/go7007-v4l2.c
drivers/staging/media/go7007/snd-go7007.c
drivers/staging/media/lirc/lirc_serial.c
drivers/staging/media/lirc/lirc_sir.c
drivers/staging/mei/wd.c
drivers/staging/panel/panel.c
drivers/staging/sbe-2t3e3/io.c
drivers/staging/ste_rmi4/Makefile
drivers/staging/telephony/phonedev.c
drivers/staging/tidspbridge/include/dspbridge/host_os.h
drivers/staging/wlags49_h2/wl_cs.c
drivers/staging/wlags49_h2/wl_main.c
drivers/staging/wlags49_h2/wl_netdev.c
drivers/staging/wlags49_h2/wl_pci.c
drivers/staging/wlags49_h2/wl_util.c
drivers/tty/amiserial.c
drivers/tty/hvc/hvc_vio.c
drivers/tty/hvc/hvcs.c
drivers/tty/isicom.c
drivers/tty/moxa.c
drivers/tty/mxser.c
drivers/tty/n_hdlc.c
drivers/tty/n_tty.c
drivers/tty/pty.c
drivers/tty/serial/21285.c
drivers/tty/serial/68328serial.c
drivers/tty/serial/8250/serial_cs.c
drivers/tty/serial/crisv10.c
drivers/tty/serial/dz.c
drivers/tty/serial/icom.c
drivers/tty/serial/msm_serial_hs.c
drivers/tty/serial/sunhv.c
drivers/tty/serial/sunsab.c
drivers/tty/serial/sunsu.c
drivers/tty/serial/sunzilog.c
drivers/tty/serial/zs.c
drivers/tty/synclink.c
drivers/tty/synclink_gt.c
drivers/tty/synclinkmp.c
drivers/tty/tty_io.c
drivers/tty/tty_ioctl.c
drivers/tty/vt/vt.c
drivers/usb/Kconfig
drivers/usb/gadget/Kconfig
drivers/usb/gadget/amd5536udc.c
drivers/usb/gadget/at91_udc.c
drivers/usb/gadget/dummy_hcd.c
drivers/usb/gadget/fsl_udc_core.c
drivers/usb/gadget/goku_udc.c
drivers/usb/gadget/langwell_udc.c
drivers/usb/gadget/mv_udc_core.c
drivers/usb/gadget/net2272.c
drivers/usb/gadget/net2280.c
drivers/usb/gadget/omap_udc.c
drivers/usb/gadget/printer.c
drivers/usb/gadget/pxa25x_udc.c
drivers/usb/gadget/rndis.c
drivers/usb/gadget/s3c2410_udc.c
drivers/usb/host/ehci-atmel.c
drivers/usb/host/ehci-hcd.c
drivers/usb/host/isp116x-hcd.c
drivers/usb/host/isp1362-hcd.c
drivers/usb/host/ohci-at91.c
drivers/usb/host/ohci-hcd.c
drivers/usb/host/oxu210hp-hcd.c
drivers/usb/host/sl811-hcd.c
drivers/usb/host/u132-hcd.c
drivers/usb/host/uhci-hcd.c
drivers/video/amifb.c
drivers/video/backlight/88pm860x_bl.c
drivers/video/backlight/apple_bl.c
drivers/video/bt431.h
drivers/video/bt455.h
drivers/video/console/fbcon.c
drivers/video/console/newport_con.c
drivers/video/cyber2000fb.c
drivers/video/dnfb.c
drivers/video/neofb.c
drivers/video/pmag-ba-fb.c
drivers/video/pmagb-b-fb.c
drivers/video/q40fb.c
drivers/video/savage/savagefb_driver.c
drivers/virtio/config.c
drivers/watchdog/Kconfig
drivers/watchdog/acquirewdt.c
drivers/watchdog/advantechwdt.c
drivers/watchdog/alim1535_wdt.c
drivers/watchdog/alim7101_wdt.c
drivers/watchdog/ar7_wdt.c
drivers/watchdog/at32ap700x_wdt.c
drivers/watchdog/at91rm9200_wdt.c
drivers/watchdog/at91sam9_wdt.c
drivers/watchdog/ath79_wdt.c
drivers/watchdog/bcm47xx_wdt.c
drivers/watchdog/bcm63xx_wdt.c
drivers/watchdog/bfin_wdt.c
drivers/watchdog/booke_wdt.c
drivers/watchdog/coh901327_wdt.c
drivers/watchdog/cpu5wdt.c
drivers/watchdog/cpwd.c
drivers/watchdog/dw_wdt.c
drivers/watchdog/ep93xx_wdt.c
drivers/watchdog/eurotechwdt.c
drivers/watchdog/f71808e_wdt.c
drivers/watchdog/gef_wdt.c
drivers/watchdog/geodewdt.c
drivers/watchdog/hpwdt.c
drivers/watchdog/i6300esb.c
drivers/watchdog/iTCO_vendor_support.c
drivers/watchdog/iTCO_wdt.c
drivers/watchdog/ib700wdt.c
drivers/watchdog/ibmasr.c
drivers/watchdog/imx2_wdt.c
drivers/watchdog/indydog.c
drivers/watchdog/intel_scu_watchdog.c
drivers/watchdog/intel_scu_watchdog.h
drivers/watchdog/iop_wdt.c
drivers/watchdog/it8712f_wdt.c
drivers/watchdog/it87_wdt.c
drivers/watchdog/ixp2000_wdt.c
drivers/watchdog/ixp4xx_wdt.c
drivers/watchdog/jz4740_wdt.c
drivers/watchdog/ks8695_wdt.c
drivers/watchdog/lantiq_wdt.c
drivers/watchdog/m54xx_wdt.c
drivers/watchdog/machzwd.c
drivers/watchdog/max63xx_wdt.c
drivers/watchdog/mixcomwd.c
drivers/watchdog/mpc8xxx_wdt.c
drivers/watchdog/mpcore_wdt.c
drivers/watchdog/mv64x60_wdt.c
drivers/watchdog/nuc900_wdt.c
drivers/watchdog/nv_tco.c
drivers/watchdog/octeon-wdt-main.c
drivers/watchdog/of_xilinx_wdt.c
drivers/watchdog/omap_wdt.c
drivers/watchdog/orion_wdt.c
drivers/watchdog/pc87413_wdt.c
drivers/watchdog/pcwd.c
drivers/watchdog/pcwd_pci.c
drivers/watchdog/pcwd_usb.c
drivers/watchdog/pika_wdt.c
drivers/watchdog/pnx4008_wdt.c
drivers/watchdog/pnx833x_wdt.c
drivers/watchdog/rc32434_wdt.c
drivers/watchdog/riowd.c
drivers/watchdog/s3c2410_wdt.c
drivers/watchdog/sa1100_wdt.c
drivers/watchdog/sb_wdog.c
drivers/watchdog/sbc60xxwdt.c
drivers/watchdog/sbc7240_wdt.c
drivers/watchdog/sbc8360.c
drivers/watchdog/sbc_epx_c3.c
drivers/watchdog/sbc_fitpc2_wdt.c
drivers/watchdog/sc1200wdt.c
drivers/watchdog/sc520_wdt.c
drivers/watchdog/sch311x_wdt.c
drivers/watchdog/scx200_wdt.c
drivers/watchdog/shwdt.c
drivers/watchdog/smsc37b787_wdt.c
drivers/watchdog/softdog.c
drivers/watchdog/sp5100_tco.c
drivers/watchdog/sp805_wdt.c
drivers/watchdog/stmp3xxx_wdt.c
drivers/watchdog/ts72xx_wdt.c
drivers/watchdog/twl4030_wdt.c
drivers/watchdog/txx9wdt.c
drivers/watchdog/via_wdt.c
drivers/watchdog/w83627hf_wdt.c
drivers/watchdog/w83697hf_wdt.c
drivers/watchdog/w83697ug_wdt.c
drivers/watchdog/w83877f_wdt.c
drivers/watchdog/w83977f_wdt.c
drivers/watchdog/wafer5823wdt.c
drivers/watchdog/watchdog_core.c
drivers/watchdog/watchdog_dev.c
drivers/watchdog/wdrtas.c
drivers/watchdog/wdt.c
drivers/watchdog/wdt285.c
drivers/watchdog/wdt977.c
drivers/watchdog/wdt_pci.c
drivers/watchdog/wm831x_wdt.c
drivers/watchdog/wm8350_wdt.c
drivers/watchdog/xen_wdt.c
fs/binfmt_aout.c
fs/binfmt_elf.c
fs/binfmt_elf_fdpic.c
fs/binfmt_flat.c
fs/coda/inode.c
fs/coda/psdev.c
fs/coda/upcall.c
fs/eventpoll.c
fs/exec.c
fs/jbd2/commit.c
fs/jbd2/journal.c
fs/ncpfs/file.c
fs/ncpfs/inode.c
fs/ncpfs/mmap.c
fs/nfs/client.c
fs/nfs/direct.c
fs/nfs/file.c
fs/nfs/getroot.c
fs/nfs/inode.c
fs/nfs/read.c
fs/nfs/super.c
fs/proc/inode.c
fs/reiserfs/journal.c
fs/ufs/inode.c
fs/ufs/super.c
fs/xfs/xfs_alloc.c
fs/xfs/xfs_alloc.h
fs/xfs/xfs_attr.c
fs/xfs/xfs_attr_leaf.c
fs/xfs/xfs_bmap.c
fs/xfs/xfs_buf.h
fs/xfs/xfs_da_btree.c
fs/xfs/xfs_discard.c
fs/xfs/xfs_dquot.c
fs/xfs/xfs_iget.c
fs/xfs/xfs_inode.h
fs/xfs/xfs_ioctl.c
fs/xfs/xfs_itable.c
fs/xfs/xfs_log.c
fs/xfs/xfs_log_recover.c
fs/xfs/xfs_rtalloc.c
fs/xfs/xfs_super.c
fs/xfs/xfs_trace.h
include/acpi/platform/aclinux.h
include/asm-generic/atomic.h
include/asm-generic/barrier.h [new file with mode: 0644]
include/asm-generic/bitops/atomic.h
include/asm-generic/cmpxchg.h
include/asm-generic/exec.h [new file with mode: 0644]
include/asm-generic/gpio.h
include/asm-generic/switch_to.h [new file with mode: 0644]
include/asm-generic/system.h [deleted file]
include/asm-generic/vmlinux.lds.h
include/linux/acpi.h
include/linux/apple_bl.h [new file with mode: 0644]
include/linux/clk-private.h [new file with mode: 0644]
include/linux/clk-provider.h [new file with mode: 0644]
include/linux/clk.h
include/linux/cnt32_to_63.h
include/linux/debug_locks.h
include/linux/dma-buf.h
include/linux/edac.h
include/linux/efi.h
include/linux/gpio.h
include/linux/i2c-algo-bit.h
include/linux/i2c-algo-pcf.h
include/linux/i2c-dev.h
include/linux/i2c-mux.h
include/linux/i2c-smbus.h
include/linux/i2c.h
include/linux/i2c/twl.h
include/linux/ide.h
include/linux/interrupt.h
include/linux/kvm.h
include/linux/kvm_host.h
include/linux/llist.h
include/linux/lsm_audit.h
include/linux/mfd/88pm860x.h
include/linux/mfd/abx500.h
include/linux/mfd/abx500/ab8500-gpio.h
include/linux/mfd/abx500/ab8500-sysctrl.h
include/linux/mfd/abx500/ab8500.h
include/linux/mfd/anatop.h [new file with mode: 0644]
include/linux/mfd/da9052/da9052.h
include/linux/mfd/db8500-prcmu.h
include/linux/mfd/dbx500-prcmu.h
include/linux/mfd/mc13xxx.h
include/linux/mfd/rc5t583.h [new file with mode: 0644]
include/linux/mfd/stmpe.h
include/linux/mfd/tps65090.h [new file with mode: 0644]
include/linux/mfd/tps65217.h [new file with mode: 0644]
include/linux/mfd/tps65910.h
include/linux/mfd/wm8994/pdata.h
include/linux/mm.h
include/linux/module.h
include/linux/moduleparam.h
include/linux/mtd/map.h
include/linux/of.h
include/linux/of_gpio.h
include/linux/of_mtd.h [new file with mode: 0644]
include/linux/parport.h
include/linux/platform_data/atmel.h [new file with mode: 0644]
include/linux/regulator/ab8500.h
include/linux/rwsem.h
include/linux/sched.h
include/linux/skbuff.h
include/linux/slab.h
include/linux/slub_def.h
include/linux/spi/orion_spi.h
include/linux/spinlock.h
include/linux/stop_machine.h
include/linux/tty.h
include/linux/wait.h
include/linux/watchdog.h
include/xen/xen-ops.h
init/main.c
kernel/debug/debug_core.c
kernel/debug/kdb/kdb_bt.c
kernel/dma.c
kernel/kexec.c
kernel/module.c
kernel/params.c
kernel/rwsem.c
kernel/sched/core.c
kernel/signal.c
kernel/sysctl.c
lib/llist.c
lib/raid6/altivec.uc
mm/slab.c
mm/slub.c
net/802/fc.c
net/802/fddi.c
net/802/hippi.c
net/802/tr.c
net/atm/clip.c
net/ax25/af_ax25.c
net/ax25/ax25_addr.c
net/ax25/ax25_dev.c
net/ax25/ax25_ds_in.c
net/ax25/ax25_ds_subr.c
net/ax25/ax25_ds_timer.c
net/ax25/ax25_iface.c
net/ax25/ax25_in.c
net/ax25/ax25_ip.c
net/ax25/ax25_out.c
net/ax25/ax25_route.c
net/ax25/ax25_std_in.c
net/ax25/ax25_std_subr.c
net/ax25/ax25_std_timer.c
net/ax25/ax25_subr.c
net/ax25/ax25_timer.c
net/ax25/ax25_uid.c
net/bluetooth/bnep/sock.c
net/bluetooth/cmtp/sock.c
net/bluetooth/hci_conn.c
net/bluetooth/hci_core.c
net/bluetooth/hci_event.c
net/bluetooth/hci_sock.c
net/bluetooth/l2cap_core.c
net/bluetooth/rfcomm/sock.c
net/bluetooth/sco.c
net/core/datagram.c
net/core/dev.c
net/core/filter.c
net/core/gen_estimator.c
net/core/rtnetlink.c
net/core/scm.c
net/core/skbuff.c
net/core/sock.c
net/core/utils.c
net/decnet/af_decnet.c
net/decnet/dn_dev.c
net/decnet/dn_nsp_in.c
net/decnet/dn_nsp_out.c
net/econet/af_econet.c
net/ethernet/eth.c
net/ipv4/af_inet.c
net/ipv4/arp.c
net/ipv4/devinet.c
net/ipv4/fib_frontend.c
net/ipv4/fib_semantics.c
net/ipv4/fib_trie.c
net/ipv4/icmp.c
net/ipv4/igmp.c
net/ipv4/ip_input.c
net/ipv4/ip_output.c
net/ipv4/ipmr.c
net/ipv4/ping.c
net/ipv4/route.c
net/ipv4/udp.c
net/ipv6/af_inet6.c
net/ipv6/icmp.c
net/ipv6/ip6mr.c
net/irda/irlan/irlan_client.c
net/irda/irlan/irlan_common.c
net/irda/irlan/irlan_provider.c
net/irda/timer.c
net/lapb/lapb_iface.c
net/lapb/lapb_in.c
net/lapb/lapb_out.c
net/lapb/lapb_subr.c
net/lapb/lapb_timer.c
net/netfilter/ipvs/ip_vs_app.c
net/netfilter/ipvs/ip_vs_proto.c
net/netfilter/nfnetlink.c
net/netrom/af_netrom.c
net/netrom/nr_dev.c
net/netrom/nr_in.c
net/netrom/nr_out.c
net/netrom/nr_route.c
net/netrom/nr_subr.c
net/netrom/nr_timer.c
net/openvswitch/datapath.c
net/packet/af_packet.c
net/rose/af_rose.c
net/rose/rose_dev.c
net/rose/rose_in.c
net/rose/rose_link.c
net/rose/rose_out.c
net/rose/rose_route.c
net/rose/rose_subr.c
net/rose/rose_timer.c
net/sunrpc/clnt.c
security/apparmor/domain.c
security/apparmor/file.c
security/selinux/include/avc.h
security/selinux/include/xfrm.h
sound/oss/os.h
sound/oss/vidc.c
sound/oss/waveartist.c
sound/pci/asihpi/hpios.h
sound/pci/aw2/aw2-saa7146.c
virt/kvm/assigned-dev.c
virt/kvm/kvm_main.c

diff --git a/Documentation/ABI/testing/sysfs-block-dm b/Documentation/ABI/testing/sysfs-block-dm
new file mode 100644 (file)
index 0000000..87ca569
--- /dev/null
@@ -0,0 +1,25 @@
+What:          /sys/block/dm-<num>/dm/name
+Date:          January 2009
+KernelVersion: 2.6.29
+Contact:       dm-devel@redhat.com
+Description:   Device-mapper device name.
+               Read-only string containing mapped device name.
+Users:         util-linux, device-mapper udev rules
+
+What:          /sys/block/dm-<num>/dm/uuid
+Date:          January 2009
+KernelVersion: 2.6.29
+Contact:       dm-devel@redhat.com
+Description:   Device-mapper device UUID.
+               Read-only string containing DM-UUID or empty string
+               if DM-UUID is not set.
+Users:         util-linux, device-mapper udev rules
+
+What:          /sys/block/dm-<num>/dm/suspended
+Date:          June 2009
+KernelVersion: 2.6.31
+Contact:       dm-devel@redhat.com
+Description:   Device-mapper device suspend state.
+               Contains the value 1 while the device is suspended.
+               Otherwise it contains 0. Read-only attribute.
+Users:         util-linux, device-mapper udev rules
index e82e7c2..678819a 100644 (file)
@@ -17,3 +17,21 @@ Description: Some Samsung laptops have different "performance levels"
                Specifically, not all support the "overclock" option,
                and it's still unknown if this value even changes
                anything, other than making the user feel a bit better.
+
+What:          /sys/devices/platform/samsung/battery_life_extender
+Date:          December 1, 2011
+KernelVersion: 3.3
+Contact:       Corentin Chary <corentin.chary@gmail.com>
+Description:   Max battery charge level can be modified, battery cycle
+               life can be extended by reducing the max battery charge
+               level.
+               0 means normal battery mode (100% charge)
+               1 means battery life extender mode (80% charge)
+
+What:          /sys/devices/platform/samsung/usb_charge
+Date:          December 1, 2011
+KernelVersion: 3.3
+Contact:       Corentin Chary <corentin.chary@gmail.com>
+Description:   Use your USB ports to charge devices, even
+               when your laptop is powered off.
+               1 means enabled, 0 means disabled.
diff --git a/Documentation/clk.txt b/Documentation/clk.txt
new file mode 100644 (file)
index 0000000..1943fae
--- /dev/null
@@ -0,0 +1,233 @@
+               The Common Clk Framework
+               Mike Turquette <mturquette@ti.com>
+
+This document endeavours to explain the common clk framework details,
+and how to port a platform over to this framework.  It is not yet a
+detailed explanation of the clock api in include/linux/clk.h, but
+perhaps someday it will include that information.
+
+       Part 1 - introduction and interface split
+
+The common clk framework is an interface to control the clock nodes
+available on various devices today.  This may come in the form of clock
+gating, rate adjustment, muxing or other operations.  This framework is
+enabled with the CONFIG_COMMON_CLK option.
+
+The interface itself is divided into two halves, each shielded from the
+details of its counterpart.  First is the common definition of struct
+clk which unifies the framework-level accounting and infrastructure that
+has traditionally been duplicated across a variety of platforms.  Second
+is a common implementation of the clk.h api, defined in
+drivers/clk/clk.c.  Finally there is struct clk_ops, whose operations
+are invoked by the clk api implementation.
+
+The second half of the interface is comprised of the hardware-specific
+callbacks registered with struct clk_ops and the corresponding
+hardware-specific structures needed to model a particular clock.  For
+the remainder of this document any reference to a callback in struct
+clk_ops, such as .enable or .set_rate, implies the hardware-specific
+implementation of that code.  Likewise, references to struct clk_foo
+serve as a convenient shorthand for the implementation of the
+hardware-specific bits for the hypothetical "foo" hardware.
+
+Tying the two halves of this interface together is struct clk_hw, which
+is defined in struct clk_foo and pointed to within struct clk.  This
+allows easy for navigation between the two discrete halves of the common
+clock interface.
+
+       Part 2 - common data structures and api
+
+Below is the common struct clk definition from
+include/linux/clk-private.h, modified for brevity:
+
+       struct clk {
+               const char              *name;
+               const struct clk_ops    *ops;
+               struct clk_hw           *hw;
+               char                    **parent_names;
+               struct clk              **parents;
+               struct clk              *parent;
+               struct hlist_head       children;
+               struct hlist_node       child_node;
+               ...
+       };
+
+The members above make up the core of the clk tree topology.  The clk
+api itself defines several driver-facing functions which operate on
+struct clk.  That api is documented in include/linux/clk.h.
+
+Platforms and devices utilizing the common struct clk use the struct
+clk_ops pointer in struct clk to perform the hardware-specific parts of
+the operations defined in clk.h:
+
+       struct clk_ops {
+               int             (*prepare)(struct clk_hw *hw);
+               void            (*unprepare)(struct clk_hw *hw);
+               int             (*enable)(struct clk_hw *hw);
+               void            (*disable)(struct clk_hw *hw);
+               int             (*is_enabled)(struct clk_hw *hw);
+               unsigned long   (*recalc_rate)(struct clk_hw *hw,
+                                               unsigned long parent_rate);
+               long            (*round_rate)(struct clk_hw *hw, unsigned long,
+                                               unsigned long *);
+               int             (*set_parent)(struct clk_hw *hw, u8 index);
+               u8              (*get_parent)(struct clk_hw *hw);
+               int             (*set_rate)(struct clk_hw *hw, unsigned long);
+               void            (*init)(struct clk_hw *hw);
+       };
+
+       Part 3 - hardware clk implementations
+
+The strength of the common struct clk comes from its .ops and .hw pointers
+which abstract the details of struct clk from the hardware-specific bits, and
+vice versa.  To illustrate consider the simple gateable clk implementation in
+drivers/clk/clk-gate.c:
+
+struct clk_gate {
+       struct clk_hw   hw;
+       void __iomem    *reg;
+       u8              bit_idx;
+       ...
+};
+
+struct clk_gate contains struct clk_hw hw as well as hardware-specific
+knowledge about which register and bit controls this clk's gating.
+Nothing about clock topology or accounting, such as enable_count or
+notifier_count, is needed here.  That is all handled by the common
+framework code and struct clk.
+
+Let's walk through enabling this clk from driver code:
+
+       struct clk *clk;
+       clk = clk_get(NULL, "my_gateable_clk");
+
+       clk_prepare(clk);
+       clk_enable(clk);
+
+The call graph for clk_enable is very simple:
+
+clk_enable(clk);
+       clk->ops->enable(clk->hw);
+       [resolves to...]
+               clk_gate_enable(hw);
+               [resolves struct clk gate with to_clk_gate(hw)]
+                       clk_gate_set_bit(gate);
+
+And the definition of clk_gate_set_bit:
+
+static void clk_gate_set_bit(struct clk_gate *gate)
+{
+       u32 reg;
+
+       reg = __raw_readl(gate->reg);
+       reg |= BIT(gate->bit_idx);
+       writel(reg, gate->reg);
+}
+
+Note that to_clk_gate is defined as:
+
+#define to_clk_gate(_hw) container_of(_hw, struct clk_gate, clk)
+
+This pattern of abstraction is used for every clock hardware
+representation.
+
+       Part 4 - supporting your own clk hardware
+
+When implementing support for a new type of clock it only necessary to
+include the following header:
+
+#include <linux/clk-provider.h>
+
+include/linux/clk.h is included within that header and clk-private.h
+must never be included from the code which implements the operations for
+a clock.  More on that below in Part 5.
+
+To construct a clk hardware structure for your platform you must define
+the following:
+
+struct clk_foo {
+       struct clk_hw hw;
+       ... hardware specific data goes here ...
+};
+
+To take advantage of your data you'll need to support valid operations
+for your clk:
+
+struct clk_ops clk_foo_ops {
+       .enable         = &clk_foo_enable;
+       .disable        = &clk_foo_disable;
+};
+
+Implement the above functions using container_of:
+
+#define to_clk_foo(_hw) container_of(_hw, struct clk_foo, hw)
+
+int clk_foo_enable(struct clk_hw *hw)
+{
+       struct clk_foo *foo;
+
+       foo = to_clk_foo(hw);
+
+       ... perform magic on foo ...
+
+       return 0;
+};
+
+Below is a matrix detailing which clk_ops are mandatory based upon the
+hardware capbilities of that clock.  A cell marked as "y" means
+mandatory, a cell marked as "n" implies that either including that
+callback is invalid or otherwise uneccesary.  Empty cells are either
+optional or must be evaluated on a case-by-case basis.
+
+                           clock hardware characteristics
+            -----------------------------------------------------------
+             | gate | change rate | single parent | multiplexer | root |
+             |------|-------------|---------------|-------------|------|
+.prepare     |      |             |               |             |      |
+.unprepare   |      |             |               |             |      |
+             |      |             |               |             |      |
+.enable      | y    |             |               |             |      |
+.disable     | y    |             |               |             |      |
+.is_enabled  | y    |             |               |             |      |
+             |      |             |               |             |      |
+.recalc_rate |      | y           |               |             |      |
+.round_rate  |      | y           |               |             |      |
+.set_rate    |      | y           |               |             |      |
+             |      |             |               |             |      |
+.set_parent  |      |             | n             | y           | n    |
+.get_parent  |      |             | n             | y           | n    |
+             |      |             |               |             |      |
+.init        |      |             |               |             |      |
+            -----------------------------------------------------------
+
+Finally, register your clock at run-time with a hardware-specific
+registration function.  This function simply populates struct clk_foo's
+data and then passes the common struct clk parameters to the framework
+with a call to:
+
+clk_register(...)
+
+See the basic clock types in drivers/clk/clk-*.c for examples.
+
+       Part 5 - static initialization of clock data
+
+For platforms with many clocks (often numbering into the hundreds) it
+may be desirable to statically initialize some clock data.  This
+presents a problem since the definition of struct clk should be hidden
+from everyone except for the clock core in drivers/clk/clk.c.
+
+To get around this problem struct clk's definition is exposed in
+include/linux/clk-private.h along with some macros for more easily
+initializing instances of the basic clock types.  These clocks must
+still be initialized with the common clock framework via a call to
+__clk_init.
+
+clk-private.h must NEVER be included by code which implements struct
+clk_ops callbacks, nor must it be included by any logic which pokes
+around inside of struct clk at run-time.  To do so is a layering
+violation.
+
+To better enforce this policy, always follow this simple rule: any
+statically initialized clock data MUST be defined in a separate file
+from the logic that implements its ops.  Basically separate the logic
+from the data and all is well.
index 1ff044d..3370bc4 100644 (file)
@@ -75,10 +75,12 @@ less sharing than average you'll need a larger-than-average metadata device.
 
 As a guide, we suggest you calculate the number of bytes to use in the
 metadata device as 48 * $data_dev_size / $data_block_size but round it up
-to 2MB if the answer is smaller.  The largest size supported is 16GB.
+to 2MB if the answer is smaller.  If you're creating large numbers of
+snapshots which are recording large amounts of change, you may find you
+need to increase this.
 
-If you're creating large numbers of snapshots which are recording large
-amounts of change, you may need find you need to increase this.
+The largest size supported is 16GB: If the device is larger,
+a warning will be issued and the excess space will not be used.
 
 Reloading a pool table
 ----------------------
@@ -167,6 +169,38 @@ ii) Using an internal snapshot.
 
     dmsetup create snap --table "0 2097152 thin /dev/mapper/pool 1"
 
+External snapshots
+------------------
+
+You can use an external _read only_ device as an origin for a
+thinly-provisioned volume.  Any read to an unprovisioned area of the
+thin device will be passed through to the origin.  Writes trigger
+the allocation of new blocks as usual.
+
+One use case for this is VM hosts that want to run guests on
+thinly-provisioned volumes but have the base image on another device
+(possibly shared between many VMs).
+
+You must not write to the origin device if you use this technique!
+Of course, you may write to the thin device and take internal snapshots
+of the thin volume.
+
+i) Creating a snapshot of an external device
+
+  This is the same as creating a thin device.
+  You don't mention the origin at this stage.
+
+    dmsetup message /dev/mapper/pool 0 "create_thin 0"
+
+ii) Using a snapshot of an external device.
+
+  Append an extra parameter to the thin target specifying the origin:
+
+    dmsetup create snap --table "0 2097152 thin /dev/mapper/pool 0 /dev/image"
+
+  N.B. All descendants (internal snapshots) of this snapshot require the
+  same extra origin parameter.
+
 Deactivation
 ------------
 
@@ -189,7 +223,13 @@ i) Constructor
              <low water mark (blocks)> [<number of feature args> [<arg>]*]
 
     Optional feature arguments:
-    - 'skip_block_zeroing': skips the zeroing of newly-provisioned blocks.
+
+      skip_block_zeroing: Skip the zeroing of newly-provisioned blocks.
+
+      ignore_discard: Disable discard support.
+
+      no_discard_passdown: Don't pass discards down to the underlying
+                          data device, but just remove the mapping.
 
     Data block size must be between 64KB (128 sectors) and 1GB
     (2097152 sectors) inclusive.
@@ -237,16 +277,6 @@ iii) Messages
 
        Deletes a thin device.  Irreversible.
 
-    trim <dev id> <new size in sectors>
-
-       Delete mappings from the end of a thin device.  Irreversible.
-       You might want to use this if you're reducing the size of
-       your thinly-provisioned device.  In many cases, due to the
-       sharing of blocks between devices, it is not possible to
-       determine in advance how much space 'trim' will release.  (In
-       future a userspace tool might be able to perform this
-       calculation.)
-
     set_transaction_id <current id> <new id>
 
        Userland volume managers, such as LVM, need a way to
@@ -262,7 +292,7 @@ iii) Messages
 
 i) Constructor
 
-    thin <pool dev> <dev id>
+    thin <pool dev> <dev id> [<external origin dev>]
 
     pool dev:
        the thin-pool device, e.g. /dev/mapper/my_pool or 253:0
@@ -271,6 +301,11 @@ i) Constructor
        the internal device identifier of the device to be
        activated.
 
+    external origin dev:
+       an optional block device outside the pool to be treated as a
+       read-only snapshot origin: reads to unprovisioned areas of the
+       thin target will be mapped to this device.
+
 The pool doesn't store any size against the thin devices.  If you
 load a thin target that is smaller than you've been using previously,
 then you'll have no access to blocks mapped beyond the end.  If you
diff --git a/Documentation/device-mapper/verity.txt b/Documentation/device-mapper/verity.txt
new file mode 100644 (file)
index 0000000..32e4879
--- /dev/null
@@ -0,0 +1,194 @@
+dm-verity
+==========
+
+Device-Mapper's "verity" target provides transparent integrity checking of
+block devices using a cryptographic digest provided by the kernel crypto API.
+This target is read-only.
+
+Construction Parameters
+=======================
+    <version> <dev> <hash_dev> <hash_start>
+    <data_block_size> <hash_block_size>
+    <num_data_blocks> <hash_start_block>
+    <algorithm> <digest> <salt>
+
+<version>
+    This is the version number of the on-disk format.
+
+    0 is the original format used in the Chromium OS.
+       The salt is appended when hashing, digests are stored continuously and
+       the rest of the block is padded with zeros.
+
+    1 is the current format that should be used for new devices.
+       The salt is prepended when hashing and each digest is
+       padded with zeros to the power of two.
+
+<dev>
+    This is the device containing the data the integrity of which needs to be
+    checked.  It may be specified as a path, like /dev/sdaX, or a device number,
+    <major>:<minor>.
+
+<hash_dev>
+    This is the device that that supplies the hash tree data.  It may be
+    specified similarly to the device path and may be the same device.  If the
+    same device is used, the hash_start should be outside of the dm-verity
+    configured device size.
+
+<data_block_size>
+    The block size on a data device.  Each block corresponds to one digest on
+    the hash device.
+
+<hash_block_size>
+    The size of a hash block.
+
+<num_data_blocks>
+    The number of data blocks on the data device.  Additional blocks are
+    inaccessible.  You can place hashes to the same partition as data, in this
+    case hashes are placed after <num_data_blocks>.
+
+<hash_start_block>
+    This is the offset, in <hash_block_size>-blocks, from the start of hash_dev
+    to the root block of the hash tree.
+
+<algorithm>
+    The cryptographic hash algorithm used for this device.  This should
+    be the name of the algorithm, like "sha1".
+
+<digest>
+    The hexadecimal encoding of the cryptographic hash of the root hash block
+    and the salt.  This hash should be trusted as there is no other authenticity
+    beyond this point.
+
+<salt>
+    The hexadecimal encoding of the salt value.
+
+Theory of operation
+===================
+
+dm-verity is meant to be setup as part of a verified boot path.  This
+may be anything ranging from a boot using tboot or trustedgrub to just
+booting from a known-good device (like a USB drive or CD).
+
+When a dm-verity device is configured, it is expected that the caller
+has been authenticated in some way (cryptographic signatures, etc).
+After instantiation, all hashes will be verified on-demand during
+disk access.  If they cannot be verified up to the root node of the
+tree, the root hash, then the I/O will fail.  This should identify
+tampering with any data on the device and the hash data.
+
+Cryptographic hashes are used to assert the integrity of the device on a
+per-block basis.  This allows for a lightweight hash computation on first read
+into the page cache.  Block hashes are stored linearly-aligned to the nearest
+block the size of a page.
+
+Hash Tree
+---------
+
+Each node in the tree is a cryptographic hash.  If it is a leaf node, the hash
+is of some block data on disk.  If it is an intermediary node, then the hash is
+of a number of child nodes.
+
+Each entry in the tree is a collection of neighboring nodes that fit in one
+block.  The number is determined based on block_size and the size of the
+selected cryptographic digest algorithm.  The hashes are linearly-ordered in
+this entry and any unaligned trailing space is ignored but included when
+calculating the parent node.
+
+The tree looks something like:
+
+alg = sha256, num_blocks = 32768, block_size = 4096
+
+                                 [   root    ]
+                                /    . . .    \
+                     [entry_0]                 [entry_1]
+                    /  . . .  \                 . . .   \
+         [entry_0_0]   . . .  [entry_0_127]    . . . .  [entry_1_127]
+           / ... \             /   . . .  \             /           \
+     blk_0 ... blk_127  blk_16256   blk_16383      blk_32640 . . . blk_32767
+
+
+On-disk format
+==============
+
+Below is the recommended on-disk format. The verity kernel code does not
+read the on-disk header. It only reads the hash blocks which directly
+follow the header. It is expected that a user-space tool will verify the
+integrity of the verity_header and then call dmsetup with the correct
+parameters. Alternatively, the header can be omitted and the dmsetup
+parameters can be passed via the kernel command-line in a rooted chain
+of trust where the command-line is verified.
+
+The on-disk format is especially useful in cases where the hash blocks
+are on a separate partition. The magic number allows easy identification
+of the partition contents. Alternatively, the hash blocks can be stored
+in the same partition as the data to be verified. In such a configuration
+the filesystem on the partition would be sized a little smaller than
+the full-partition, leaving room for the hash blocks.
+
+struct superblock {
+       uint8_t signature[8]
+               "verity\0\0";
+
+       uint8_t version;
+               1 - current format
+
+       uint8_t data_block_bits;
+               log2(data block size)
+
+       uint8_t hash_block_bits;
+               log2(hash block size)
+
+       uint8_t pad1[1];
+               zero padding
+
+       uint16_t salt_size;
+               big-endian salt size
+
+       uint8_t pad2[2];
+               zero padding
+
+       uint32_t data_blocks_hi;
+               big-endian high 32 bits of the 64-bit number of data blocks
+
+       uint32_t data_blocks_lo;
+               big-endian low 32 bits of the 64-bit number of data blocks
+
+       uint8_t algorithm[16];
+               cryptographic algorithm
+
+       uint8_t salt[384];
+               salt (the salt size is specified above)
+
+       uint8_t pad3[88];
+               zero padding to 512-byte boundary
+}
+
+Directly following the header (and with sector number padded to the next hash
+block boundary) are the hash blocks which are stored a depth at a time
+(starting from the root), sorted in order of increasing index.
+
+Status
+======
+V (for Valid) is returned if every check performed so far was valid.
+If any check failed, C (for Corruption) is returned.
+
+Example
+=======
+
+Setup a device:
+  dmsetup create vroot --table \
+    "0 2097152 "\
+    "verity 1 /dev/sda1 /dev/sda2 4096 4096 2097152 1 "\
+    "4392712ba01368efdf14b05c76f9e4df0d53664630b5d48632ed17a137f39076 "\
+    "1234000000000000000000000000000000000000000000000000000000000000"
+
+A command line tool veritysetup is available to compute or verify
+the hash tree or activate the kernel driver.  This is available from
+the LVM2 upstream repository and may be supplied as a package called
+device-mapper-verity-tools:
+    git://sources.redhat.com/git/lvm2
+    http://sourceware.org/git/?p=lvm2.git
+    http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/verity?cvsroot=lvm2
+
+veritysetup -a vroot /dev/sda1 /dev/sda2 \
+       4392712ba01368efdf14b05c76f9e4df0d53664630b5d48632ed17a137f39076
index 1aeaf6f..ecc81e3 100644 (file)
@@ -30,3 +30,63 @@ One interrupt per TC channel in a TC block:
                reg = <0xfffdc000 0x100>;
                interrupts = <26 4 27 4 28 4>;
        };
+
+RSTC Reset Controller required properties:
+- compatible: Should be "atmel,<chip>-rstc".
+  <chip> can be "at91sam9260" or "at91sam9g45"
+- reg: Should contain registers location and length
+
+Example:
+
+       rstc@fffffd00 {
+               compatible = "atmel,at91sam9260-rstc";
+               reg = <0xfffffd00 0x10>;
+       };
+
+RAMC SDRAM/DDR Controller required properties:
+- compatible: Should be "atmel,at91sam9260-sdramc",
+                       "atmel,at91sam9g45-ddramc",
+- reg: Should contain registers location and length
+  For at91sam9263 and at91sam9g45 you must specify 2 entries.
+
+Examples:
+
+       ramc0: ramc@ffffe800 {
+               compatible = "atmel,at91sam9g45-ddramc";
+               reg = <0xffffe800 0x200>;
+       };
+
+       ramc0: ramc@ffffe400 {
+               compatible = "atmel,at91sam9g45-ddramc";
+               reg = <0xffffe400 0x200
+                      0xffffe600 0x200>;
+       };
+
+SHDWC Shutdown Controller
+
+required properties:
+- compatible: Should be "atmel,<chip>-shdwc".
+  <chip> can be "at91sam9260", "at91sam9rl" or "at91sam9x5".
+- reg: Should contain registers location and length
+
+optional properties:
+- atmel,wakeup-mode: String, operation mode of the wakeup mode.
+  Supported values are: "none", "high", "low", "any".
+- atmel,wakeup-counter: Counter on Wake-up 0 (between 0x0 and 0xf).
+
+optional at91sam9260 properties:
+- atmel,wakeup-rtt-timer: boolean to enable Real-time Timer Wake-up.
+
+optional at91sam9rl properties:
+- atmel,wakeup-rtc-timer: boolean to enable Real-time Clock Wake-up.
+- atmel,wakeup-rtt-timer: boolean to enable Real-time Timer Wake-up.
+
+optional at91sam9x5 properties:
+- atmel,wakeup-rtc-timer: boolean to enable Real-time Clock Wake-up.
+
+Example:
+
+       rstc@fffffd00 {
+               compatible = "atmel,at91sam9260-rstc";
+               reg = <0xfffffd00 0x10>;
+       };
diff --git a/Documentation/devicetree/bindings/arm/atmel-pmc.txt b/Documentation/devicetree/bindings/arm/atmel-pmc.txt
new file mode 100644 (file)
index 0000000..389bed5
--- /dev/null
@@ -0,0 +1,11 @@
+* Power Management Controller (PMC)
+
+Required properties:
+- compatible: Should be "atmel,at91rm9200-pmc"
+- reg: Should contain PMC registers location and length
+
+Examples:
+       pmc: pmc@fffffc00 {
+               compatible = "atmel,at91rm9200-pmc";
+               reg = <0xfffffc00 0x100>;
+       };
diff --git a/Documentation/devicetree/bindings/arm/spear.txt b/Documentation/devicetree/bindings/arm/spear.txt
new file mode 100644 (file)
index 0000000..f8e54f0
--- /dev/null
@@ -0,0 +1,8 @@
+ST SPEAr Platforms Device Tree Bindings
+---------------------------------------
+
+Boards with the ST SPEAr600 SoC shall have the following properties:
+
+Required root node property:
+
+compatible = "st,spear600";
diff --git a/Documentation/devicetree/bindings/gpio/gpio-omap.txt b/Documentation/devicetree/bindings/gpio/gpio-omap.txt
new file mode 100644 (file)
index 0000000..bff51a2
--- /dev/null
@@ -0,0 +1,36 @@
+OMAP GPIO controller bindings
+
+Required properties:
+- compatible:
+  - "ti,omap2-gpio" for OMAP2 controllers
+  - "ti,omap3-gpio" for OMAP3 controllers
+  - "ti,omap4-gpio" for OMAP4 controllers
+- #gpio-cells : Should be two.
+  - first cell is the pin number
+  - second cell is used to specify optional parameters (unused)
+- gpio-controller : Marks the device node as a GPIO controller.
+- #interrupt-cells : Should be 2.
+- interrupt-controller: Mark the device node as an interrupt controller
+  The first cell is the GPIO number.
+  The second cell is used to specify flags:
+    bits[3:0] trigger type and level flags:
+      1 = low-to-high edge triggered.
+      2 = high-to-low edge triggered.
+      4 = active high level-sensitive.
+      8 = active low level-sensitive.
+
+OMAP specific properties:
+- ti,hwmods: Name of the hwmod associated to the GPIO:
+  "gpio<X>", <X> being the 1-based instance number from the HW spec
+
+
+Example:
+
+gpio4: gpio4 {
+    compatible = "ti,omap4-gpio";
+    ti,hwmods = "gpio4";
+    #gpio-cells = <2>;
+    gpio-controller;
+    #interrupt-cells = <2>;
+    interrupt-controller;
+};
diff --git a/Documentation/devicetree/bindings/gpio/gpio-twl4030.txt b/Documentation/devicetree/bindings/gpio/gpio-twl4030.txt
new file mode 100644 (file)
index 0000000..16695d9
--- /dev/null
@@ -0,0 +1,23 @@
+twl4030 GPIO controller bindings
+
+Required properties:
+- compatible:
+  - "ti,twl4030-gpio" for twl4030 GPIO controller
+- #gpio-cells : Should be two.
+  - first cell is the pin number
+  - second cell is used to specify optional parameters (unused)
+- gpio-controller : Marks the device node as a GPIO controller.
+- #interrupt-cells : Should be 2.
+- interrupt-controller: Mark the device node as an interrupt controller
+  The first cell is the GPIO number.
+  The second cell is not used.
+
+Example:
+
+twl_gpio: gpio {
+    compatible = "ti,twl4030-gpio";
+    #gpio-cells = <2>;
+    gpio-controller;
+    #interrupt-cells = <2>;
+    interrupt-controller;
+};
diff --git a/Documentation/devicetree/bindings/gpio/gpio_i2c.txt b/Documentation/devicetree/bindings/gpio/gpio_i2c.txt
new file mode 100644 (file)
index 0000000..4f8ec94
--- /dev/null
@@ -0,0 +1,32 @@
+Device-Tree bindings for i2c gpio driver
+
+Required properties:
+       - compatible = "i2c-gpio";
+       - gpios: sda and scl gpio
+
+
+Optional properties:
+       - i2c-gpio,sda-open-drain: sda as open drain
+       - i2c-gpio,scl-open-drain: scl as open drain
+       - i2c-gpio,scl-output-only: scl as output only
+       - i2c-gpio,delay-us: delay between GPIO operations (may depend on each platform)
+       - i2c-gpio,timeout-ms: timeout to get data
+
+Example nodes:
+
+i2c@0 {
+       compatible = "i2c-gpio";
+       gpios = <&pioA 23 0 /* sda */
+                &pioA 24 0 /* scl */
+               >;
+       i2c-gpio,sda-open-drain;
+       i2c-gpio,scl-open-drain;
+       i2c-gpio,delay-us = <2>;        /* ~100 kHz */
+       #address-cells = <1>;
+       #size-cells = <0>;
+
+       rv3029c2@56 {
+               compatible = "rv3029c2";
+               reg = <0x56>;
+       };
+};
diff --git a/Documentation/devicetree/bindings/gpio/sodaville.txt b/Documentation/devicetree/bindings/gpio/sodaville.txt
new file mode 100644 (file)
index 0000000..563eff2
--- /dev/null
@@ -0,0 +1,48 @@
+GPIO controller on CE4100 / Sodaville SoCs
+==========================================
+
+The bindings for CE4100's GPIO controller match the generic description
+which is covered by the gpio.txt file in this folder.
+
+The only additional property is the intel,muxctl property which holds the
+value which is written into the MUXCNTL register.
+
+There is no compatible property for now because the driver is probed via
+PCI id (vendor 0x8086 device 0x2e67).
+
+The interrupt specifier consists of two cells encoded as follows:
+ - <1st cell>: The interrupt-number that identifies the interrupt source.
+ - <2nd cell>: The level-sense information, encoded as follows:
+               4 - active high level-sensitive
+               8 - active low level-sensitive
+
+Example of the GPIO device and one user:
+
+       pcigpio: gpio@b,1 {
+                       /* two cells for GPIO and interrupt */
+                       #gpio-cells = <2>;
+                       #interrupt-cells = <2>;
+                       compatible = "pci8086,2e67.2",
+                                          "pci8086,2e67",
+                                          "pciclassff0000",
+                                          "pciclassff00";
+
+                       reg = <0x15900 0x0 0x0 0x0 0x0>;
+                       /* Interrupt line of the gpio device */
+                       interrupts = <15 1>;
+                       /* It is an interrupt and GPIO controller itself */
+                       interrupt-controller;
+                       gpio-controller;
+                       intel,muxctl = <0>;
+       };
+
+       testuser@20 {
+                       compatible = "example,testuser";
+                       /* User the 11th GPIO line as an active high triggered
+                        * level interrupt
+                        */
+                       interrupts = <11 8>;
+                       interrupt-parent = <&pcigpio>;
+                       /* Use this GPIO also with the gpio functions */
+                       gpios = <&pcigpio 11 0>;
+       };
diff --git a/Documentation/devicetree/bindings/mtd/atmel-nand.txt b/Documentation/devicetree/bindings/mtd/atmel-nand.txt
new file mode 100644 (file)
index 0000000..5903ecf
--- /dev/null
@@ -0,0 +1,41 @@
+Atmel NAND flash
+
+Required properties:
+- compatible : "atmel,at91rm9200-nand".
+- reg : should specify localbus address and size used for the chip,
+       and if availlable the ECC.
+- atmel,nand-addr-offset : offset for the address latch.
+- atmel,nand-cmd-offset : offset for the command latch.
+- #address-cells, #size-cells : Must be present if the device has sub-nodes
+  representing partitions.
+
+- gpios : specifies the gpio pins to control the NAND device. detect is an
+  optional gpio and may be set to 0 if not present.
+
+Optional properties:
+- nand-ecc-mode : String, operation mode of the NAND ecc mode, soft by default.
+  Supported values are: "none", "soft", "hw", "hw_syndrome", "hw_oob_first",
+  "soft_bch".
+- nand-bus-width : 8 or 16 bus width if not present 8
+- nand-on-flash-bbt: boolean to enable on flash bbt option if not present false
+
+Examples:
+nand0: nand@40000000,0 {
+       compatible = "atmel,at91rm9200-nand";
+       #address-cells = <1>;
+       #size-cells = <1>;
+       reg = <0x40000000 0x10000000
+              0xffffe800 0x200
+             >;
+       atmel,nand-addr-offset = <21>;
+       atmel,nand-cmd-offset = <22>;
+       nand-on-flash-bbt;
+       nand-ecc-mode = "soft";
+       gpios = <&pioC 13 0
+                &pioC 14 0
+                0
+               >;
+       partition@0 {
+               ...
+       };
+};
diff --git a/Documentation/devicetree/bindings/mtd/nand.txt b/Documentation/devicetree/bindings/mtd/nand.txt
new file mode 100644 (file)
index 0000000..03855c8
--- /dev/null
@@ -0,0 +1,7 @@
+* MTD generic binding
+
+- nand-ecc-mode : String, operation mode of the NAND ecc mode.
+  Supported values are: "none", "soft", "hw", "hw_syndrome", "hw_oob_first",
+  "soft_bch".
+- nand-bus-width : 8 or 16 bus width if not present 8
+- nand-on-flash-bbt: boolean to enable on flash bbt option if not present false
diff --git a/Documentation/devicetree/bindings/usb/atmel-usb.txt b/Documentation/devicetree/bindings/usb/atmel-usb.txt
new file mode 100644 (file)
index 0000000..60bd215
--- /dev/null
@@ -0,0 +1,49 @@
+Atmel SOC USB controllers
+
+OHCI
+
+Required properties:
+ - compatible: Should be "atmel,at91rm9200-ohci" for USB controllers
+   used in host mode.
+ - num-ports: Number of ports.
+ - atmel,vbus-gpio: If present, specifies a gpio that needs to be
+   activated for the bus to be powered.
+ - atmel,oc-gpio: If present, specifies a gpio that needs to be
+   activated for the overcurrent detection.
+
+usb0: ohci@00500000 {
+       compatible = "atmel,at91rm9200-ohci", "usb-ohci";
+       reg = <0x00500000 0x100000>;
+       interrupts = <20 4>;
+       num-ports = <2>;
+};
+
+EHCI
+
+Required properties:
+ - compatible: Should be "atmel,at91sam9g45-ehci" for USB controllers
+   used in host mode.
+
+usb1: ehci@00800000 {
+       compatible = "atmel,at91sam9g45-ehci", "usb-ehci";
+       reg = <0x00800000 0x100000>;
+       interrupts = <22 4>;
+};
+
+AT91 USB device controller
+
+Required properties:
+ - compatible: Should be "atmel,at91rm9200-udc"
+ - reg: Address and length of the register set for the device
+ - interrupts: Should contain macb interrupt
+
+Optional properties:
+ - atmel,vbus-gpio: If present, specifies a gpio that needs to be
+   activated for the bus to be powered.
+
+usb1: gadget@fffa4000 {
+       compatible = "atmel,at91rm9200-udc";
+       reg = <0xfffa4000 0x4000>;
+       interrupts = <10 4>;
+       atmel,vbus-gpio = <&pioC 5 0>;
+};
index 035d63d..007005d 100644 (file)
@@ -11,3 +11,16 @@ Required properties :
  - phy_type : Should be one of "ulpi" or "utmi".
  - nvidia,vbus-gpio : If present, specifies a gpio that needs to be
    activated for the bus to be powered.
+
+Optional properties:
+  - dr_mode : dual role mode. Indicates the working mode for
+   nvidia,tegra20-ehci compatible controllers.  Can be "host", "peripheral",
+   or "otg".  Default to "host" if not defined for backward compatibility.
+      host means this is a host controller
+      peripheral means it is device controller
+      otg means it can operate as either ("on the go")
+  - nvidia,has-legacy-mode : boolean indicates whether this controller can
+    operate in legacy mode (as APX 2500 / 2600). In legacy mode some
+    registers are accessed through the APB_MISC base address instead of
+    the USB controller. Since this is a legacy issue it probably does not
+    warrant a compatible string of its own.
index 225f96d..3bbd5c5 100644 (file)
@@ -32,8 +32,12 @@ The buffer-user
 *IMPORTANT*: [see https://lkml.org/lkml/2011/12/20/211 for more details]
 For this first version, A buffer shared using the dma_buf sharing API:
 - *may* be exported to user space using "mmap" *ONLY* by exporter, outside of
-   this framework.
-- may be used *ONLY* by importers that do not need CPU access to the buffer.
+  this framework.
+- with this new iteration of the dma-buf api cpu access from the kernel has been
+  enable, see below for the details.
+
+dma-buf operations for device dma only
+--------------------------------------
 
 The dma_buf buffer sharing API usage contains the following steps:
 
@@ -219,10 +223,120 @@ NOTES:
    If the exporter chooses not to allow an attach() operation once a
    map_dma_buf() API has been called, it simply returns an error.
 
-Miscellaneous notes:
+Kernel cpu access to a dma-buf buffer object
+--------------------------------------------
+
+The motivation to allow cpu access from the kernel to a dma-buf object from the
+importers side are:
+- fallback operations, e.g. if the devices is connected to a usb bus and the
+  kernel needs to shuffle the data around first before sending it away.
+- full transparency for existing users on the importer side, i.e. userspace
+  should not notice the difference between a normal object from that subsystem
+  and an imported one backed by a dma-buf. This is really important for drm
+  opengl drivers that expect to still use all the existing upload/download
+  paths.
+
+Access to a dma_buf from the kernel context involves three steps:
+
+1. Prepare access, which invalidate any necessary caches and make the object
+   available for cpu access.
+2. Access the object page-by-page with the dma_buf map apis
+3. Finish access, which will flush any necessary cpu caches and free reserved
+   resources.
+
+1. Prepare access
+
+   Before an importer can access a dma_buf object with the cpu from the kernel
+   context, it needs to notify the exporter of the access that is about to
+   happen.
+
+   Interface:
+      int dma_buf_begin_cpu_access(struct dma_buf *dmabuf,
+                                  size_t start, size_t len,
+                                  enum dma_data_direction direction)
+
+   This allows the exporter to ensure that the memory is actually available for
+   cpu access - the exporter might need to allocate or swap-in and pin the
+   backing storage. The exporter also needs to ensure that cpu access is
+   coherent for the given range and access direction. The range and access
+   direction can be used by the exporter to optimize the cache flushing, i.e.
+   access outside of the range or with a different direction (read instead of
+   write) might return stale or even bogus data (e.g. when the exporter needs to
+   copy the data to temporary storage).
+
+   This step might fail, e.g. in oom conditions.
+
+2. Accessing the buffer
+
+   To support dma_buf objects residing in highmem cpu access is page-based using
+   an api similar to kmap. Accessing a dma_buf is done in aligned chunks of
+   PAGE_SIZE size. Before accessing a chunk it needs to be mapped, which returns
+   a pointer in kernel virtual address space. Afterwards the chunk needs to be
+   unmapped again. There is no limit on how often a given chunk can be mapped
+   and unmapped, i.e. the importer does not need to call begin_cpu_access again
+   before mapping the same chunk again.
+
+   Interfaces:
+      void *dma_buf_kmap(struct dma_buf *, unsigned long);
+      void dma_buf_kunmap(struct dma_buf *, unsigned long, void *);
+
+   There are also atomic variants of these interfaces. Like for kmap they
+   facilitate non-blocking fast-paths. Neither the importer nor the exporter (in
+   the callback) is allowed to block when using these.
+
+   Interfaces:
+      void *dma_buf_kmap_atomic(struct dma_buf *, unsigned long);
+      void dma_buf_kunmap_atomic(struct dma_buf *, unsigned long, void *);
+
+   For importers all the restrictions of using kmap apply, like the limited
+   supply of kmap_atomic slots. Hence an importer shall only hold onto at most 2
+   atomic dma_buf kmaps at the same time (in any given process context).
+
+   dma_buf kmap calls outside of the range specified in begin_cpu_access are
+   undefined. If the range is not PAGE_SIZE aligned, kmap needs to succeed on
+   the partial chunks at the beginning and end but may return stale or bogus
+   data outside of the range (in these partial chunks).
+
+   Note that these calls need to always succeed. The exporter needs to complete
+   any preparations that might fail in begin_cpu_access.
+
+3. Finish access
+
+   When the importer is done accessing the range specified in begin_cpu_access,
+   it needs to announce this to the exporter (to facilitate cache flushing and
+   unpinning of any pinned resources). The result of of any dma_buf kmap calls
+   after end_cpu_access is undefined.
+
+   Interface:
+      void dma_buf_end_cpu_access(struct dma_buf *dma_buf,
+                                 size_t start, size_t len,
+                                 enum dma_data_direction dir);
+
+
+Miscellaneous notes
+-------------------
+
 - Any exporters or users of the dma-buf buffer sharing framework must have
   a 'select DMA_SHARED_BUFFER' in their respective Kconfigs.
 
+- In order to avoid fd leaks on exec, the FD_CLOEXEC flag must be set
+  on the file descriptor.  This is not just a resource leak, but a
+  potential security hole.  It could give the newly exec'd application
+  access to buffers, via the leaked fd, to which it should otherwise
+  not be permitted access.
+
+  The problem with doing this via a separate fcntl() call, versus doing it
+  atomically when the fd is created, is that this is inherently racy in a
+  multi-threaded app[3].  The issue is made worse when it is library code
+  opening/creating the file descriptor, as the application may not even be
+  aware of the fd's.
+
+  To avoid this problem, userspace must have a way to request O_CLOEXEC
+  flag be set when the dma-buf fd is created.  So any API provided by
+  the exporting driver to create a dmabuf fd must provide a way to let
+  userspace control setting of O_CLOEXEC flag passed in to dma_buf_fd().
+
 References:
 [1] struct dma_buf_ops in include/linux/dma-buf.h
 [2] All interfaces mentioned above defined in include/linux/dma-buf.h
+[3] https://lwn.net/Articles/236486/
index 792faa3..620a078 100644 (file)
@@ -271,9 +271,26 @@ Some platforms may also use knowledge about what GPIOs are active for
 power management, such as by powering down unused chip sectors and, more
 easily, gating off unused clocks.
 
-Note that requesting a GPIO does NOT cause it to be configured in any
-way; it just marks that GPIO as in use.  Separate code must handle any
-pin setup (e.g. controlling which pin the GPIO uses, pullup/pulldown).
+For GPIOs that use pins known to the pinctrl subsystem, that subsystem should
+be informed of their use; a gpiolib driver's .request() operation may call
+pinctrl_request_gpio(), and a gpiolib driver's .free() operation may call
+pinctrl_free_gpio(). The pinctrl subsystem allows a pinctrl_request_gpio()
+to succeed concurrently with a pin or pingroup being "owned" by a device for
+pin multiplexing.
+
+Any programming of pin multiplexing hardware that is needed to route the
+GPIO signal to the appropriate pin should occur within a GPIO driver's
+.direction_input() or .direction_output() operations, and occur after any
+setup of an output GPIO's value. This allows a glitch-free migration from a
+pin's special function to GPIO. This is sometimes required when using a GPIO
+to implement a workaround on signals typically driven by a non-GPIO HW block.
+
+Some platforms allow some or all GPIO signals to be routed to different pins.
+Similarly, other aspects of the GPIO or pin may need to be configured, such as
+pullup/pulldown. Platform software should arrange that any such details are
+configured prior to gpio_request() being called for those GPIOs, e.g. using
+the pinctrl subsystem's mapping table, so that GPIO users need not be aware
+of these details.
 
 Also note that it's your responsibility to have stopped using a GPIO
 before you free it.
@@ -302,6 +319,8 @@ where 'flags' is currently defined to specify the following properties:
 
        * GPIOF_INIT_LOW        - as output, set initial level to LOW
        * GPIOF_INIT_HIGH       - as output, set initial level to HIGH
+       * GPIOF_OPEN_DRAIN      - gpio pin is open drain type.
+       * GPIOF_OPEN_SOURCE     - gpio pin is open source type.
 
 since GPIOF_INIT_* are only valid when configured as output, so group valid
 combinations as:
@@ -310,8 +329,19 @@ combinations as:
        * GPIOF_OUT_INIT_LOW    - configured as output, initial level LOW
        * GPIOF_OUT_INIT_HIGH   - configured as output, initial level HIGH
 
-In the future, these flags can be extended to support more properties such
-as open-drain status.
+When setting the flag as GPIOF_OPEN_DRAIN then it will assume that pins is
+open drain type. Such pins will not be driven to 1 in output mode. It is
+require to connect pull-up on such pins. By enabling this flag, gpio lib will
+make the direction to input when it is asked to set value of 1 in output mode
+to make the pin HIGH. The pin is make to LOW by driving value 0 in output mode.
+
+When setting the flag as GPIOF_OPEN_SOURCE then it will assume that pins is
+open source type. Such pins will not be driven to 0 in output mode. It is
+require to connect pull-down on such pin. By enabling this flag, gpio lib will
+make the direction to input when it is asked to set value of 0 in output mode
+to make the pin LOW. The pin is make to HIGH by driving value 1 in output mode.
+
+In the future, these flags can be extended to support more properties.
 
 Further more, to ease the claim/release of multiple GPIOs, 'struct gpio' is
 introduced to encapsulate all three fields as:
index 2871fd5..71f55bb 100644 (file)
@@ -20,6 +20,7 @@ Supported adapters:
   * Intel Patsburg (PCH)
   * Intel DH89xxCC (PCH)
   * Intel Panther Point (PCH)
+  * Intel Lynx Point (PCH)
    Datasheets: Publicly available at the Intel website
 
 On Intel Patsburg and later chipsets, both the normal host SMBus controller
index 58eac23..e2f8c29 100644 (file)
@@ -1869,6 +1869,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        shutdown the other cpus.  Instead use the REBOOT_VECTOR
                        irq.
 
+       nomodule        Disable module load
+
        nopat           [X86] Disable PAT (page attribute table extension of
                        pagetables) support.
 
index 803e51f..a1e04d6 100644 (file)
@@ -45,7 +45,7 @@ Status
 Usage
 -----
 
-  Try "modprobe asus_acpi". Check your dmesg (simply type dmesg). You should
+  Try "modprobe asus-laptop". Check your dmesg (simply type dmesg). You should
   see some lines like this :
 
       Asus Laptop Extras version 0.42
index 2bd4e82..0d5ac7f 100644 (file)
@@ -17,6 +17,11 @@ subsystem. See the logs of acpid or /proc/acpi/event and
 devices are created by the driver. Additionally, loading the driver with the
 debug option will report all events in the kernel log.
 
+The "scancodes" passed to the input system (that can be remapped with udev)
+are indexes to the table "sony_laptop_input_keycode_map" in the sony-laptop.c
+module.  For example the "FN/E" key combination (EJECTCD on some models)
+generates the scancode 20 (0x14).
+
 Backlight control:
 ------------------
 If your laptop model supports it, you will find sysfs files in the
index e1d94bf..6386f8c 100644 (file)
@@ -95,7 +95,7 @@ described as 'basic' will be available.
 Capability: basic
 Architectures: all
 Type: system ioctl
-Parameters: none
+Parameters: machine type identifier (KVM_VM_*)
 Returns: a VM fd that can be used to control the new virtual machine.
 
 The new VM has no virtual cpus and no memory.  An mmap() of a VM fd
@@ -103,6 +103,11 @@ will access the virtual machine's physical address space; offset zero
 corresponds to guest physical address zero.  Use of mmap() on a VM fd
 is discouraged if userspace memory allocation (KVM_CAP_USER_MEMORY) is
 available.
+You most certainly want to use 0 as machine type.
+
+In order to create user controlled virtual machines on S390, check
+KVM_CAP_S390_UCONTROL and use the flag KVM_VM_S390_UCONTROL as
+privileged user (CAP_SYS_ADMIN).
 
 4.3 KVM_GET_MSR_INDEX_LIST
 
@@ -213,6 +218,11 @@ allocation of vcpu ids.  For example, if userspace wants
 single-threaded guest vcpus, it should make all vcpu ids be a multiple
 of the number of vcpus per vcore.
 
+For virtual cpus that have been created with S390 user controlled virtual
+machines, the resulting vcpu fd can be memory mapped at page offset
+KVM_S390_SIE_PAGE_OFFSET in order to obtain a memory map of the virtual
+cpu's hardware control block.
+
 4.8 KVM_GET_DIRTY_LOG (vm ioctl)
 
 Capability: basic
@@ -1159,6 +1169,14 @@ following flags are specified:
 
 /* Depends on KVM_CAP_IOMMU */
 #define KVM_DEV_ASSIGN_ENABLE_IOMMU    (1 << 0)
+/* The following two depend on KVM_CAP_PCI_2_3 */
+#define KVM_DEV_ASSIGN_PCI_2_3         (1 << 1)
+#define KVM_DEV_ASSIGN_MASK_INTX       (1 << 2)
+
+If KVM_DEV_ASSIGN_PCI_2_3 is set, the kernel will manage legacy INTx interrupts
+via the PCI-2.3-compliant device-level mask, thus enable IRQ sharing with other
+assigned devices or host devices. KVM_DEV_ASSIGN_MASK_INTX specifies the
+guest's view on the INTx mask, see KVM_ASSIGN_SET_INTX_MASK for details.
 
 The KVM_DEV_ASSIGN_ENABLE_IOMMU flag is a mandatory option to ensure
 isolation of the device.  Usages not specifying this flag are deprecated.
@@ -1399,6 +1417,71 @@ The following flags are defined:
 If datamatch flag is set, the event will be signaled only if the written value
 to the registered address is equal to datamatch in struct kvm_ioeventfd.
 
+4.59 KVM_DIRTY_TLB
+
+Capability: KVM_CAP_SW_TLB
+Architectures: ppc
+Type: vcpu ioctl
+Parameters: struct kvm_dirty_tlb (in)
+Returns: 0 on success, -1 on error
+
+struct kvm_dirty_tlb {
+       __u64 bitmap;
+       __u32 num_dirty;
+};
+
+This must be called whenever userspace has changed an entry in the shared
+TLB, prior to calling KVM_RUN on the associated vcpu.
+
+The "bitmap" field is the userspace address of an array.  This array
+consists of a number of bits, equal to the total number of TLB entries as
+determined by the last successful call to KVM_CONFIG_TLB, rounded up to the
+nearest multiple of 64.
+
+Each bit corresponds to one TLB entry, ordered the same as in the shared TLB
+array.
+
+The array is little-endian: the bit 0 is the least significant bit of the
+first byte, bit 8 is the least significant bit of the second byte, etc.
+This avoids any complications with differing word sizes.
+
+The "num_dirty" field is a performance hint for KVM to determine whether it
+should skip processing the bitmap and just invalidate everything.  It must
+be set to the number of set bits in the bitmap.
+
+4.60 KVM_ASSIGN_SET_INTX_MASK
+
+Capability: KVM_CAP_PCI_2_3
+Architectures: x86
+Type: vm ioctl
+Parameters: struct kvm_assigned_pci_dev (in)
+Returns: 0 on success, -1 on error
+
+Allows userspace to mask PCI INTx interrupts from the assigned device.  The
+kernel will not deliver INTx interrupts to the guest between setting and
+clearing of KVM_ASSIGN_SET_INTX_MASK via this interface.  This enables use of
+and emulation of PCI 2.3 INTx disable command register behavior.
+
+This may be used for both PCI 2.3 devices supporting INTx disable natively and
+older devices lacking this support. Userspace is responsible for emulating the
+read value of the INTx disable bit in the guest visible PCI command register.
+When modifying the INTx disable state, userspace should precede updating the
+physical device command register by calling this ioctl to inform the kernel of
+the new intended INTx mask state.
+
+Note that the kernel uses the device INTx disable bit to internally manage the
+device interrupt state for PCI 2.3 devices.  Reads of this register may
+therefore not match the expected value.  Writes should always use the guest
+intended INTx disable value rather than attempting to read-copy-update the
+current physical device state.  Races between user and kernel updates to the
+INTx disable bit are handled lazily in the kernel.  It's possible the device
+may generate unintended interrupts, but they will not be injected into the
+guest.
+
+See KVM_ASSIGN_DEV_IRQ for the data structure.  The target device is specified
+by assigned_dev_id.  In the flags field, only KVM_DEV_ASSIGN_MASK_INTX is
+evaluated.
+
 4.62 KVM_CREATE_SPAPR_TCE
 
 Capability: KVM_CAP_SPAPR_TCE
@@ -1491,6 +1574,101 @@ following algorithm:
 Some guests configure the LINT1 NMI input to cause a panic, aiding in
 debugging.
 
+4.65 KVM_S390_UCAS_MAP
+
+Capability: KVM_CAP_S390_UCONTROL
+Architectures: s390
+Type: vcpu ioctl
+Parameters: struct kvm_s390_ucas_mapping (in)
+Returns: 0 in case of success
+
+The parameter is defined like this:
+       struct kvm_s390_ucas_mapping {
+               __u64 user_addr;
+               __u64 vcpu_addr;
+               __u64 length;
+       };
+
+This ioctl maps the memory at "user_addr" with the length "length" to
+the vcpu's address space starting at "vcpu_addr". All parameters need to
+be alligned by 1 megabyte.
+
+4.66 KVM_S390_UCAS_UNMAP
+
+Capability: KVM_CAP_S390_UCONTROL
+Architectures: s390
+Type: vcpu ioctl
+Parameters: struct kvm_s390_ucas_mapping (in)
+Returns: 0 in case of success
+
+The parameter is defined like this:
+       struct kvm_s390_ucas_mapping {
+               __u64 user_addr;
+               __u64 vcpu_addr;
+               __u64 length;
+       };
+
+This ioctl unmaps the memory in the vcpu's address space starting at
+"vcpu_addr" with the length "length". The field "user_addr" is ignored.
+All parameters need to be alligned by 1 megabyte.
+
+4.67 KVM_S390_VCPU_FAULT
+
+Capability: KVM_CAP_S390_UCONTROL
+Architectures: s390
+Type: vcpu ioctl
+Parameters: vcpu absolute address (in)
+Returns: 0 in case of success
+
+This call creates a page table entry on the virtual cpu's address space
+(for user controlled virtual machines) or the virtual machine's address
+space (for regular virtual machines). This only works for minor faults,
+thus it's recommended to access subject memory page via the user page
+table upfront. This is useful to handle validity intercepts for user
+controlled virtual machines to fault in the virtual cpu's lowcore pages
+prior to calling the KVM_RUN ioctl.
+
+4.68 KVM_SET_ONE_REG
+
+Capability: KVM_CAP_ONE_REG
+Architectures: all
+Type: vcpu ioctl
+Parameters: struct kvm_one_reg (in)
+Returns: 0 on success, negative value on failure
+
+struct kvm_one_reg {
+       __u64 id;
+       __u64 addr;
+};
+
+Using this ioctl, a single vcpu register can be set to a specific value
+defined by user space with the passed in struct kvm_one_reg, where id
+refers to the register identifier as described below and addr is a pointer
+to a variable with the respective size. There can be architecture agnostic
+and architecture specific registers. Each have their own range of operation
+and their own constants and width. To keep track of the implemented
+registers, find a list below:
+
+  Arch  |       Register        | Width (bits)
+        |                       |
+  PPC   | KVM_REG_PPC_HIOR      | 64
+
+4.69 KVM_GET_ONE_REG
+
+Capability: KVM_CAP_ONE_REG
+Architectures: all
+Type: vcpu ioctl
+Parameters: struct kvm_one_reg (in and out)
+Returns: 0 on success, negative value on failure
+
+This ioctl allows to receive the value of a single register implemented
+in a vcpu. The register to read is indicated by the "id" field of the
+kvm_one_reg struct passed in. On success, the register value can be found
+at the memory location pointed to by "addr".
+
+The list of registers accessible using this interface is identical to the
+list in 4.64.
+
 5. The kvm_run structure
 
 Application code obtains a pointer to the kvm_run structure by
@@ -1651,6 +1829,20 @@ s390 specific.
 
 s390 specific.
 
+               /* KVM_EXIT_S390_UCONTROL */
+               struct {
+                       __u64 trans_exc_code;
+                       __u32 pgm_code;
+               } s390_ucontrol;
+
+s390 specific. A page fault has occurred for a user controlled virtual
+machine (KVM_VM_S390_UNCONTROL) on it's host page table that cannot be
+resolved by the kernel.
+The program code and the translation exception code that were placed
+in the cpu's lowcore are presented here as defined by the z Architecture
+Principles of Operation Book in the Chapter for Dynamic Address Translation
+(DAT)
+
                /* KVM_EXIT_DCR */
                struct {
                        __u32 dcrn;
@@ -1693,6 +1885,29 @@ developer registration required to access it).
                /* Fix the size of the union. */
                char padding[256];
        };
+
+       /*
+        * shared registers between kvm and userspace.
+        * kvm_valid_regs specifies the register classes set by the host
+        * kvm_dirty_regs specified the register classes dirtied by userspace
+        * struct kvm_sync_regs is architecture specific, as well as the
+        * bits for kvm_valid_regs and kvm_dirty_regs
+        */
+       __u64 kvm_valid_regs;
+       __u64 kvm_dirty_regs;
+       union {
+               struct kvm_sync_regs regs;
+               char padding[1024];
+       } s;
+
+If KVM_CAP_SYNC_REGS is defined, these fields allow userspace to access
+certain guest registers without having to call SET/GET_*REGS. Thus we can
+avoid some system call overhead if userspace has to handle the exit.
+Userspace can query the validity of the structure by checking
+kvm_valid_regs for specific bits. These bits are architecture specific
+and usually define the validity of a groups of registers. (e.g. one bit
+ for general purpose registers)
+
 };
 
 6. Capabilities that can be enabled
@@ -1741,3 +1956,45 @@ HTAB address part of SDR1 contains an HVA instead of a GPA, as PAPR keeps the
 HTAB invisible to the guest.
 
 When this capability is enabled, KVM_EXIT_PAPR_HCALL can occur.
+
+6.3 KVM_CAP_SW_TLB
+
+Architectures: ppc
+Parameters: args[0] is the address of a struct kvm_config_tlb
+Returns: 0 on success; -1 on error
+
+struct kvm_config_tlb {
+       __u64 params;
+       __u64 array;
+       __u32 mmu_type;
+       __u32 array_len;
+};
+
+Configures the virtual CPU's TLB array, establishing a shared memory area
+between userspace and KVM.  The "params" and "array" fields are userspace
+addresses of mmu-type-specific data structures.  The "array_len" field is an
+safety mechanism, and should be set to the size in bytes of the memory that
+userspace has reserved for the array.  It must be at least the size dictated
+by "mmu_type" and "params".
+
+While KVM_RUN is active, the shared region is under control of KVM.  Its
+contents are undefined, and any modification by userspace results in
+boundedly undefined behavior.
+
+On return from KVM_RUN, the shared region will reflect the current state of
+the guest's TLB.  If userspace makes any changes, it must call KVM_DIRTY_TLB
+to tell KVM which entries have been changed, prior to calling KVM_RUN again
+on this vcpu.
+
+For mmu types KVM_MMU_FSL_BOOKE_NOHV and KVM_MMU_FSL_BOOKE_HV:
+ - The "params" field is of type "struct kvm_book3e_206_tlb_params".
+ - The "array" field points to an array of type "struct
+   kvm_book3e_206_tlb_entry".
+ - The array consists of all entries in the first TLB, followed by all
+   entries in the second TLB.
+ - Within a TLB, entries are ordered first by increasing set number.  Within a
+   set, entries are ordered by way (increasing ESEL).
+ - The hash for determining set number in TLB0 is: (MAS2 >> 12) & (num_sets - 1)
+   where "num_sets" is the tlb_sizes[] value divided by the tlb_ways[] value.
+ - The tsize field of mas1 shall be set to 4K on TLB0, even though the
+   hardware ignores this value for TLB0.
index 2b7ce19..6e7c370 100644 (file)
@@ -81,28 +81,8 @@ additional registers to the magic page. If you add fields to the magic page,
 also define a new hypercall feature to indicate that the host can give you more
 registers. Only if the host supports the additional features, make use of them.
 
-The magic page has the following layout as described in
-arch/powerpc/include/asm/kvm_para.h:
-
-struct kvm_vcpu_arch_shared {
-       __u64 scratch1;
-       __u64 scratch2;
-       __u64 scratch3;
-       __u64 critical;         /* Guest may not get interrupts if == r1 */
-       __u64 sprg0;
-       __u64 sprg1;
-       __u64 sprg2;
-       __u64 sprg3;
-       __u64 srr0;
-       __u64 srr1;
-       __u64 dar;
-       __u64 msr;
-       __u32 dsisr;
-       __u32 int_pending;      /* Tells the guest if we have an interrupt */
-};
-
-Additions to the page must only occur at the end. Struct fields are always 32
-or 64 bit aligned, depending on them being 32 or 64 bit wide respectively.
+The magic page layout is described by struct kvm_vcpu_arch_shared
+in arch/powerpc/include/asm/kvm_para.h.
 
 Magic page features
 ===================
diff --git a/Documentation/watchdog/00-INDEX b/Documentation/watchdog/00-INDEX
deleted file mode 100644 (file)
index fc9082a..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-00-INDEX
-       - this file.
-convert_drivers_to_kernel_api.txt
-       - how-to for converting old watchdog drivers to the new kernel API.
-hpwdt.txt
-       - information on the HP iLO2 NMI watchdog
-pcwd-watchdog.txt
-       - documentation for Berkshire Products PC Watchdog ISA cards.
-src/
-       - directory holding watchdog related example programs.
-watchdog-api.txt
-       - description of the Linux Watchdog driver API.
-watchdog-kernel-api.txt
-       - description of the Linux WatchDog Timer Driver Core kernel API.
-watchdog-parameters.txt
-       - information on driver parameters (for drivers other than
-         the ones that have driver-specific files here)
-wdt.txt
-       - description of the Watchdog Timer Interfaces for Linux.
index be8119b..271b885 100644 (file)
@@ -59,6 +59,10 @@ Here is a overview of the functions and probably needed actions:
        WDIOC_GETTIMEOUT:
                No preparations needed
 
+       WDIOC_GETTIMELEFT:
+               It needs get_timeleft() callback to be defined. Otherwise it
+               will return EOPNOTSUPP
+
   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
index 9e16246..227f6cd 100644 (file)
@@ -1,6 +1,6 @@
 The Linux WatchDog Timer Driver Core kernel API.
 ===============================================
-Last reviewed: 29-Nov-2011
+Last reviewed: 16-Mar-2012
 
 Wim Van Sebroeck <wim@iguana.be>
 
@@ -77,6 +77,7 @@ struct watchdog_ops {
        int (*ping)(struct watchdog_device *);
        unsigned int (*status)(struct watchdog_device *);
        int (*set_timeout)(struct watchdog_device *, unsigned int);
+       unsigned int (*get_timeleft)(struct watchdog_device *);
        long (*ioctl)(struct watchdog_device *, unsigned int, unsigned long);
 };
 
@@ -117,11 +118,13 @@ they are supported. These optional routines/operations are:
   status of the device is reported with watchdog WDIOF_* status flags/bits.
 * set_timeout: this routine checks and changes the timeout of the watchdog
   timer device. It returns 0 on success, -EINVAL for "parameter out of range"
-  and -EIO for "could not write value to the watchdog". On success the timeout
-  value of the watchdog_device will be changed to the value that was just used
-  to re-program the watchdog timer device.
+  and -EIO for "could not write value to the watchdog". On success this
+  routine should set the timeout value of the watchdog_device to the
+  achieved timeout value (which may be different from the requested one
+  because the watchdog does not necessarily has a 1 second resolution).
   (Note: the WDIOF_SETTIMEOUT needs to be set in the options field of the
   watchdog's info structure).
+* get_timeleft: this routines returns the time that's left before a reset.
 * ioctl: if this routine is present then it will be called first before we do
   our own internal ioctl call handling. This routine should return -ENOIOCTLCMD
   if a command is not supported. The parameters that are passed to the ioctl
index 3d11fa5..f9faade 100644 (file)
@@ -2225,13 +2225,16 @@ W:      http://lanana.org/docs/device-list/index.html
 S:     Maintained
 
 DEVICE-MAPPER  (LVM)
-P:     Alasdair Kergon
+M:     Alasdair Kergon <agk@redhat.com>
+M:     dm-devel@redhat.com
 L:     dm-devel@redhat.com
 W:     http://sources.redhat.com/dm
 Q:     http://patchwork.kernel.org/project/dm-devel/list/
+T:     quilt http://people.redhat.com/agk/patches/linux/editing/
 S:     Maintained
 F:     Documentation/device-mapper/
 F:     drivers/md/dm*
+F:     drivers/md/persistent-data/
 F:     include/linux/device-mapper.h
 F:     include/linux/dm-*.h
 
@@ -5773,6 +5776,12 @@ F:       drivers/media/common/saa7146*
 F:     drivers/media/video/*7146*
 F:     include/media/*7146*
 
+SAMSUNG LAPTOP DRIVER
+M:     Corentin Chary <corentincj@iksaif.net>
+L:     platform-driver-x86@vger.kernel.org
+S:     Maintained
+F:     drivers/platform/x86/samsung-laptop.c
+
 SAMSUNG AUDIO (ASoC) DRIVERS
 M:     Sangbeom Kim <sbkim73@samsung.com>
 L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
index be61670..2a542a5 100644 (file)
@@ -13,7 +13,6 @@
 #include <generated/utsrelease.h>
 #include <linux/mm.h>
 
-#include <asm/system.h>
 #include <asm/console.h>
 #include <asm/hwrpb.h>
 #include <asm/pgtable.h>
index c98865f..d6ad191 100644 (file)
@@ -15,7 +15,6 @@
 #include <generated/utsrelease.h>
 #include <linux/mm.h>
 
-#include <asm/system.h>
 #include <asm/console.h>
 #include <asm/hwrpb.h>
 #include <asm/pgtable.h>
index f3d9808..b06812b 100644 (file)
@@ -4,7 +4,6 @@
  * initial bootloader stuff..
  */
 
-#include <asm/system.h>
 
        .set noreorder
        .globl  __start
index ded57d9..3baf2d1 100644 (file)
@@ -11,7 +11,6 @@
 #include <generated/utsrelease.h>
 #include <linux/mm.h>
 
-#include <asm/system.h>
 #include <asm/console.h>
 #include <asm/hwrpb.h>
 #include <asm/pgtable.h>
index 640f909..f62251e 100644 (file)
@@ -3,7 +3,6 @@
 
 #include <linux/types.h>
 #include <asm/barrier.h>
-#include <asm/system.h>
 
 /*
  * Atomic operations that C can't guarantee us.  Useful for
@@ -169,6 +168,73 @@ static __inline__ long atomic64_sub_return(long i, atomic64_t * v)
        return result;
 }
 
+/*
+ * Atomic exchange routines.
+ */
+
+#define __ASM__MB
+#define ____xchg(type, args...)                __xchg ## type ## _local(args)
+#define ____cmpxchg(type, args...)     __cmpxchg ## type ## _local(args)
+#include <asm/xchg.h>
+
+#define xchg_local(ptr,x)                                              \
+  ({                                                                   \
+     __typeof__(*(ptr)) _x_ = (x);                                     \
+     (__typeof__(*(ptr))) __xchg_local((ptr), (unsigned long)_x_,      \
+                                      sizeof(*(ptr)));                 \
+  })
+
+#define cmpxchg_local(ptr, o, n)                                       \
+  ({                                                                   \
+     __typeof__(*(ptr)) _o_ = (o);                                     \
+     __typeof__(*(ptr)) _n_ = (n);                                     \
+     (__typeof__(*(ptr))) __cmpxchg_local((ptr), (unsigned long)_o_,   \
+                                         (unsigned long)_n_,           \
+                                         sizeof(*(ptr)));              \
+  })
+
+#define cmpxchg64_local(ptr, o, n)                                     \
+  ({                                                                   \
+       BUILD_BUG_ON(sizeof(*(ptr)) != 8);                              \
+       cmpxchg_local((ptr), (o), (n));                                 \
+  })
+
+#ifdef CONFIG_SMP
+#undef __ASM__MB
+#define __ASM__MB      "\tmb\n"
+#endif
+#undef ____xchg
+#undef ____cmpxchg
+#define ____xchg(type, args...)                __xchg ##type(args)
+#define ____cmpxchg(type, args...)     __cmpxchg ##type(args)
+#include <asm/xchg.h>
+
+#define xchg(ptr,x)                                                    \
+  ({                                                                   \
+     __typeof__(*(ptr)) _x_ = (x);                                     \
+     (__typeof__(*(ptr))) __xchg((ptr), (unsigned long)_x_,            \
+                                sizeof(*(ptr)));                       \
+  })
+
+#define cmpxchg(ptr, o, n)                                             \
+  ({                                                                   \
+     __typeof__(*(ptr)) _o_ = (o);                                     \
+     __typeof__(*(ptr)) _n_ = (n);                                     \
+     (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,         \
+                                   (unsigned long)_n_, sizeof(*(ptr)));\
+  })
+
+#define cmpxchg64(ptr, o, n)                                           \
+  ({                                                                   \
+       BUILD_BUG_ON(sizeof(*(ptr)) != 8);                              \
+       cmpxchg((ptr), (o), (n));                                       \
+  })
+
+#undef __ASM__MB
+#undef ____cmpxchg
+
+#define __HAVE_ARCH_CMPXCHG 1
+
 #define atomic64_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), old, new))
 #define atomic64_xchg(v, new) (xchg(&((v)->counter), new))
 
index e96fe88..a3a579d 100644 (file)
@@ -21,4 +21,6 @@
 #define AT_L2_CACHESHAPE       36
 #define AT_L3_CACHESHAPE       37
 
+#define AT_VECTOR_SIZE_ARCH 4 /* entries in ARCH_DLINFO */
+
 #endif /* __ASM_ALPHA_AUXVEC_H */
index f7cb4b4..8ee6c51 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef __ALPHA_LCA__H__
 #define __ALPHA_LCA__H__
 
-#include <asm/system.h>
 #include <asm/compiler.h>
+#include <asm/mce.h>
 
 /*
  * Low Cost Alpha (LCA) definitions (these apply to 21066 and 21068,
index 9f67a05..ad44bef 100644 (file)
@@ -7,6 +7,7 @@
 
 #include <linux/types.h>
 #include <asm/compiler.h>
+#include <asm/mce.h>
 
 /*
  * MCPCIA is the internal name for a core logic chipset which provides
index 91b4680..ade9d92 100644 (file)
@@ -7,7 +7,6 @@
 #include <linux/types.h>
 #include <linux/spinlock.h>
 #include <asm/compiler.h>
-#include <asm/system.h>
 
 /*
  * T2 is the internal name for the core logic chipset which provides
index da5449e..968d999 100644 (file)
@@ -2,6 +2,7 @@
 #define __ASM_ALPHA_ELF_H
 
 #include <asm/auxvec.h>
+#include <asm/special_insns.h>
 
 /* Special values for the st_other field in the symbol table.  */
 
diff --git a/arch/alpha/include/asm/exec.h b/arch/alpha/include/asm/exec.h
new file mode 100644 (file)
index 0000000..4a5a41f
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __ALPHA_EXEC_H
+#define __ALPHA_EXEC_H
+
+#define arch_align_stack(x) (x)
+
+#endif /* __ALPHA_EXEC_H */
index ecb17a7..db00f78 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef __ASM_ALPHA_FPU_H
 #define __ASM_ALPHA_FPU_H
 
+#include <asm/special_insns.h>
+
 /*
  * Alpha floating-point control register defines:
  */
index 56ff965..7a3d38d 100644 (file)
@@ -6,7 +6,6 @@
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <asm/compiler.h>
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/machvec.h>
 #include <asm/hwrpb.h>
index 299bbc7..ffb1726 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef __ALPHA_IRQFLAGS_H
 #define __ALPHA_IRQFLAGS_H
 
-#include <asm/system.h>
+#include <asm/pal.h>
 
 #define IPL_MIN                0
 #define IPL_SW0                1
diff --git a/arch/alpha/include/asm/mce.h b/arch/alpha/include/asm/mce.h
new file mode 100644 (file)
index 0000000..660285b
--- /dev/null
@@ -0,0 +1,83 @@
+#ifndef __ALPHA_MCE_H
+#define __ALPHA_MCE_H
+
+/*
+ * This is the logout header that should be common to all platforms
+ * (assuming they are running OSF/1 PALcode, I guess).
+ */
+struct el_common {
+       unsigned int    size;           /* size in bytes of logout area */
+       unsigned int    sbz1    : 30;   /* should be zero */
+       unsigned int    err2    :  1;   /* second error */
+       unsigned int    retry   :  1;   /* retry flag */
+       unsigned int    proc_offset;    /* processor-specific offset */
+       unsigned int    sys_offset;     /* system-specific offset */
+       unsigned int    code;           /* machine check code */
+       unsigned int    frame_rev;      /* frame revision */
+};
+
+/* Machine Check Frame for uncorrectable errors (Large format)
+ *      --- This is used to log uncorrectable errors such as
+ *          double bit ECC errors.
+ *      --- These errors are detected by both processor and systems.
+ */
+struct el_common_EV5_uncorrectable_mcheck {
+        unsigned long   shadow[8];        /* Shadow reg. 8-14, 25           */
+        unsigned long   paltemp[24];      /* PAL TEMP REGS.                 */
+        unsigned long   exc_addr;         /* Address of excepting instruction*/
+        unsigned long   exc_sum;          /* Summary of arithmetic traps.   */
+        unsigned long   exc_mask;         /* Exception mask (from exc_sum). */
+        unsigned long   pal_base;         /* Base address for PALcode.      */
+        unsigned long   isr;              /* Interrupt Status Reg.          */
+        unsigned long   icsr;             /* CURRENT SETUP OF EV5 IBOX      */
+        unsigned long   ic_perr_stat;     /* I-CACHE Reg. <11> set Data parity
+                                                         <12> set TAG parity*/
+        unsigned long   dc_perr_stat;     /* D-CACHE error Reg. Bits set to 1:
+                                                     <2> Data error in bank 0
+                                                     <3> Data error in bank 1
+                                                     <4> Tag error in bank 0
+                                                     <5> Tag error in bank 1 */
+        unsigned long   va;               /* Effective VA of fault or miss. */
+        unsigned long   mm_stat;          /* Holds the reason for D-stream 
+                                             fault or D-cache parity errors */
+        unsigned long   sc_addr;          /* Address that was being accessed
+                                             when EV5 detected Secondary cache
+                                             failure.                 */
+        unsigned long   sc_stat;          /* Helps determine if the error was
+                                             TAG/Data parity(Secondary Cache)*/
+        unsigned long   bc_tag_addr;      /* Contents of EV5 BC_TAG_ADDR    */
+        unsigned long   ei_addr;          /* Physical address of any transfer
+                                             that is logged in EV5 EI_STAT */
+        unsigned long   fill_syndrome;    /* For correcting ECC errors.     */
+        unsigned long   ei_stat;          /* Helps identify reason of any 
+                                             processor uncorrectable error
+                                             at its external interface.     */
+        unsigned long   ld_lock;          /* Contents of EV5 LD_LOCK register*/
+};
+
+struct el_common_EV6_mcheck {
+       unsigned int FrameSize;         /* Bytes, including this field */
+       unsigned int FrameFlags;        /* <31> = Retry, <30> = Second Error */
+       unsigned int CpuOffset;         /* Offset to CPU-specific info */
+       unsigned int SystemOffset;      /* Offset to system-specific info */
+       unsigned int MCHK_Code;
+       unsigned int MCHK_Frame_Rev;
+       unsigned long I_STAT;           /* EV6 Internal Processor Registers */
+       unsigned long DC_STAT;          /* (See the 21264 Spec) */
+       unsigned long C_ADDR;
+       unsigned long DC1_SYNDROME;
+       unsigned long DC0_SYNDROME;
+       unsigned long C_STAT;
+       unsigned long C_STS;
+       unsigned long MM_STAT;
+       unsigned long EXC_ADDR;
+       unsigned long IER_CM;
+       unsigned long ISUM;
+       unsigned long RESERVED0;
+       unsigned long PAL_BASE;
+       unsigned long I_CTL;
+       unsigned long PCTX;
+};
+
+
+#endif /* __ALPHA_MCE_H */
index 86c08a0..4c51c05 100644 (file)
@@ -7,7 +7,6 @@
  * Copyright (C) 1996, Linus Torvalds
  */
 
-#include <asm/system.h>
 #include <asm/machvec.h>
 #include <asm/compiler.h>
 #include <asm-generic/mm_hooks.h>
index 9b4ba0d..6699ee5 100644 (file)
 #define PAL_retsys     61
 #define PAL_rti                63
 
+#ifdef __KERNEL__
+#ifndef __ASSEMBLY__
+
+extern void halt(void) __attribute__((noreturn));
+#define __halt() __asm__ __volatile__ ("call_pal %0 #halt" : : "i" (PAL_halt))
+
+#define imb() \
+__asm__ __volatile__ ("call_pal %0 #imb" : : "i" (PAL_imb) : "memory")
+
+#define draina() \
+__asm__ __volatile__ ("call_pal %0 #draina" : : "i" (PAL_draina) : "memory")
+
+#define __CALL_PAL_R0(NAME, TYPE)                              \
+extern inline TYPE NAME(void)                                  \
+{                                                              \
+       register TYPE __r0 __asm__("$0");                       \
+       __asm__ __volatile__(                                   \
+               "call_pal %1 # " #NAME                          \
+               :"=r" (__r0)                                    \
+               :"i" (PAL_ ## NAME)                             \
+               :"$1", "$16", "$22", "$23", "$24", "$25");      \
+       return __r0;                                            \
+}
+
+#define __CALL_PAL_W1(NAME, TYPE0)                             \
+extern inline void NAME(TYPE0 arg0)                            \
+{                                                              \
+       register TYPE0 __r16 __asm__("$16") = arg0;             \
+       __asm__ __volatile__(                                   \
+               "call_pal %1 # "#NAME                           \
+               : "=r"(__r16)                                   \
+               : "i"(PAL_ ## NAME), "0"(__r16)                 \
+               : "$1", "$22", "$23", "$24", "$25");            \
+}
+
+#define __CALL_PAL_W2(NAME, TYPE0, TYPE1)                      \
+extern inline void NAME(TYPE0 arg0, TYPE1 arg1)                        \
+{                                                              \
+       register TYPE0 __r16 __asm__("$16") = arg0;             \
+       register TYPE1 __r17 __asm__("$17") = arg1;             \
+       __asm__ __volatile__(                                   \
+               "call_pal %2 # "#NAME                           \
+               : "=r"(__r16), "=r"(__r17)                      \
+               : "i"(PAL_ ## NAME), "0"(__r16), "1"(__r17)     \
+               : "$1", "$22", "$23", "$24", "$25");            \
+}
+
+#define __CALL_PAL_RW1(NAME, RTYPE, TYPE0)                     \
+extern inline RTYPE NAME(TYPE0 arg0)                           \
+{                                                              \
+       register RTYPE __r0 __asm__("$0");                      \
+       register TYPE0 __r16 __asm__("$16") = arg0;             \
+       __asm__ __volatile__(                                   \
+               "call_pal %2 # "#NAME                           \
+               : "=r"(__r16), "=r"(__r0)                       \
+               : "i"(PAL_ ## NAME), "0"(__r16)                 \
+               : "$1", "$22", "$23", "$24", "$25");            \
+       return __r0;                                            \
+}
+
+#define __CALL_PAL_RW2(NAME, RTYPE, TYPE0, TYPE1)              \
+extern inline RTYPE NAME(TYPE0 arg0, TYPE1 arg1)               \
+{                                                              \
+       register RTYPE __r0 __asm__("$0");                      \
+       register TYPE0 __r16 __asm__("$16") = arg0;             \
+       register TYPE1 __r17 __asm__("$17") = arg1;             \
+       __asm__ __volatile__(                                   \
+               "call_pal %3 # "#NAME                           \
+               : "=r"(__r16), "=r"(__r17), "=r"(__r0)          \
+               : "i"(PAL_ ## NAME), "0"(__r16), "1"(__r17)     \
+               : "$1", "$22", "$23", "$24", "$25");            \
+       return __r0;                                            \
+}
+
+__CALL_PAL_W1(cflush, unsigned long);
+__CALL_PAL_R0(rdmces, unsigned long);
+__CALL_PAL_R0(rdps, unsigned long);
+__CALL_PAL_R0(rdusp, unsigned long);
+__CALL_PAL_RW1(swpipl, unsigned long, unsigned long);
+__CALL_PAL_R0(whami, unsigned long);
+__CALL_PAL_W2(wrent, void*, unsigned long);
+__CALL_PAL_W1(wripir, unsigned long);
+__CALL_PAL_W1(wrkgp, unsigned long);
+__CALL_PAL_W1(wrmces, unsigned long);
+__CALL_PAL_RW2(wrperfmon, unsigned long, unsigned long, unsigned long);
+__CALL_PAL_W1(wrusp, unsigned long);
+__CALL_PAL_W1(wrvptptr, unsigned long);
+
+/*
+ * TB routines..
+ */
+#define __tbi(nr,arg,arg1...)                                  \
+({                                                             \
+       register unsigned long __r16 __asm__("$16") = (nr);     \
+       register unsigned long __r17 __asm__("$17"); arg;       \
+       __asm__ __volatile__(                                   \
+               "call_pal %3 #__tbi"                            \
+               :"=r" (__r16),"=r" (__r17)                      \
+               :"0" (__r16),"i" (PAL_tbi) ,##arg1              \
+               :"$0", "$1", "$22", "$23", "$24", "$25");       \
+})
+
+#define tbi(x,y)       __tbi(x,__r17=(y),"1" (__r17))
+#define tbisi(x)       __tbi(1,__r17=(x),"1" (__r17))
+#define tbisd(x)       __tbi(2,__r17=(x),"1" (__r17))
+#define tbis(x)                __tbi(3,__r17=(x),"1" (__r17))
+#define tbiap()                __tbi(-1, /* no second argument */)
+#define tbia()         __tbi(-2, /* no second argument */)
+
+#endif /* !__ASSEMBLY__ */
+#endif /* __KERNEL__ */
+
 #endif /* __ALPHA_PAL_H */
index de98a73..81a4342 100644 (file)
@@ -15,6 +15,7 @@
 #include <asm/page.h>
 #include <asm/processor.h>     /* For TASK_SIZE */
 #include <asm/machvec.h>
+#include <asm/setup.h>
 
 struct mm_struct;
 struct vm_area_struct;
index 2e023a4..b50014b 100644 (file)
@@ -3,4 +3,40 @@
 
 #define COMMAND_LINE_SIZE      256
 
+/*
+ * We leave one page for the initial stack page, and one page for
+ * the initial process structure. Also, the console eats 3 MB for
+ * the initial bootloader (one of which we can reclaim later).
+ */
+#define BOOT_PCB       0x20000000
+#define BOOT_ADDR      0x20000000
+/* Remove when official MILO sources have ELF support: */
+#define BOOT_SIZE      (16*1024)
+
+#ifdef CONFIG_ALPHA_LEGACY_START_ADDRESS
+#define KERNEL_START_PHYS      0x300000 /* Old bootloaders hardcoded this.  */
+#else
+#define KERNEL_START_PHYS      0x1000000 /* required: Wildfire/Titan/Marvel */
+#endif
+
+#define KERNEL_START   (PAGE_OFFSET+KERNEL_START_PHYS)
+#define SWAPPER_PGD    KERNEL_START
+#define INIT_STACK     (PAGE_OFFSET+KERNEL_START_PHYS+0x02000)
+#define EMPTY_PGT      (PAGE_OFFSET+KERNEL_START_PHYS+0x04000)
+#define EMPTY_PGE      (PAGE_OFFSET+KERNEL_START_PHYS+0x08000)
+#define ZERO_PGE       (PAGE_OFFSET+KERNEL_START_PHYS+0x0A000)
+
+#define START_ADDR     (PAGE_OFFSET+KERNEL_START_PHYS+0x10000)
+
+/*
+ * This is setup by the secondary bootstrap loader.  Because
+ * the zero page is zeroed out as soon as the vm system is
+ * initialized, we need to copy things out into a more permanent
+ * place.
+ */
+#define PARAM                  ZERO_PGE
+#define COMMAND_LINE           ((char*)(PARAM + 0x0000))
+#define INITRD_START           (*(unsigned long *) (PARAM+0x100))
+#define INITRD_SIZE            (*(unsigned long *) (PARAM+0x108))
+
 #endif
diff --git a/arch/alpha/include/asm/special_insns.h b/arch/alpha/include/asm/special_insns.h
new file mode 100644 (file)
index 0000000..88d3452
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef __ALPHA_SPECIAL_INSNS_H
+#define __ALPHA_SPECIAL_INSNS_H
+
+enum implver_enum {
+       IMPLVER_EV4,
+       IMPLVER_EV5,
+       IMPLVER_EV6
+};
+
+#ifdef CONFIG_ALPHA_GENERIC
+#define implver()                              \
+({ unsigned long __implver;                    \
+   __asm__ ("implver %0" : "=r"(__implver));   \
+   (enum implver_enum) __implver; })
+#else
+/* Try to eliminate some dead code.  */
+#ifdef CONFIG_ALPHA_EV4
+#define implver() IMPLVER_EV4
+#endif
+#ifdef CONFIG_ALPHA_EV5
+#define implver() IMPLVER_EV5
+#endif
+#if defined(CONFIG_ALPHA_EV6)
+#define implver() IMPLVER_EV6
+#endif
+#endif
+
+enum amask_enum {
+       AMASK_BWX = (1UL << 0),
+       AMASK_FIX = (1UL << 1),
+       AMASK_CIX = (1UL << 2),
+       AMASK_MAX = (1UL << 8),
+       AMASK_PRECISE_TRAP = (1UL << 9),
+};
+
+#define amask(mask)                                            \
+({ unsigned long __amask, __input = (mask);                    \
+   __asm__ ("amask %1,%0" : "=r"(__amask) : "rI"(__input));    \
+   __amask; })
+
+#endif /* __ALPHA_SPECIAL_INSNS_H */
index d0faca1..3bba21e 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ALPHA_SPINLOCK_H
 #define _ALPHA_SPINLOCK_H
 
-#include <asm/system.h>
 #include <linux/kernel.h>
 #include <asm/current.h>
 
diff --git a/arch/alpha/include/asm/switch_to.h b/arch/alpha/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..44c0d4f
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef __ALPHA_SWITCH_TO_H
+#define __ALPHA_SWITCH_TO_H
+
+
+struct task_struct;
+extern struct task_struct *alpha_switch_to(unsigned long, struct task_struct *);
+
+#define switch_to(P,N,L)                                                \
+  do {                                                                  \
+    (L) = alpha_switch_to(virt_to_phys(&task_thread_info(N)->pcb), (P)); \
+    check_mmu_context();                                                \
+  } while (0)
+
+#endif /* __ALPHA_SWITCH_TO_H */
diff --git a/arch/alpha/include/asm/system.h b/arch/alpha/include/asm/system.h
deleted file mode 100644 (file)
index 9f78e69..0000000
+++ /dev/null
@@ -1,354 +0,0 @@
-#ifndef __ALPHA_SYSTEM_H
-#define __ALPHA_SYSTEM_H
-
-#include <asm/pal.h>
-#include <asm/page.h>
-#include <asm/barrier.h>
-
-/*
- * System defines.. Note that this is included both from .c and .S
- * files, so it does only defines, not any C code.
- */
-
-/*
- * We leave one page for the initial stack page, and one page for
- * the initial process structure. Also, the console eats 3 MB for
- * the initial bootloader (one of which we can reclaim later).
- */
-#define BOOT_PCB       0x20000000
-#define BOOT_ADDR      0x20000000
-/* Remove when official MILO sources have ELF support: */
-#define BOOT_SIZE      (16*1024)
-
-#ifdef CONFIG_ALPHA_LEGACY_START_ADDRESS
-#define KERNEL_START_PHYS      0x300000 /* Old bootloaders hardcoded this.  */
-#else
-#define KERNEL_START_PHYS      0x1000000 /* required: Wildfire/Titan/Marvel */
-#endif
-
-#define KERNEL_START   (PAGE_OFFSET+KERNEL_START_PHYS)
-#define SWAPPER_PGD    KERNEL_START
-#define INIT_STACK     (PAGE_OFFSET+KERNEL_START_PHYS+0x02000)
-#define EMPTY_PGT      (PAGE_OFFSET+KERNEL_START_PHYS+0x04000)
-#define EMPTY_PGE      (PAGE_OFFSET+KERNEL_START_PHYS+0x08000)
-#define ZERO_PGE       (PAGE_OFFSET+KERNEL_START_PHYS+0x0A000)
-
-#define START_ADDR     (PAGE_OFFSET+KERNEL_START_PHYS+0x10000)
-
-/*
- * This is setup by the secondary bootstrap loader.  Because
- * the zero page is zeroed out as soon as the vm system is
- * initialized, we need to copy things out into a more permanent
- * place.
- */
-#define PARAM                  ZERO_PGE
-#define COMMAND_LINE           ((char*)(PARAM + 0x0000))
-#define INITRD_START           (*(unsigned long *) (PARAM+0x100))
-#define INITRD_SIZE            (*(unsigned long *) (PARAM+0x108))
-
-#ifndef __ASSEMBLY__
-#include <linux/kernel.h>
-#define AT_VECTOR_SIZE_ARCH 4 /* entries in ARCH_DLINFO */
-
-/*
- * This is the logout header that should be common to all platforms
- * (assuming they are running OSF/1 PALcode, I guess).
- */
-struct el_common {
-       unsigned int    size;           /* size in bytes of logout area */
-       unsigned int    sbz1    : 30;   /* should be zero */
-       unsigned int    err2    :  1;   /* second error */
-       unsigned int    retry   :  1;   /* retry flag */
-       unsigned int    proc_offset;    /* processor-specific offset */
-       unsigned int    sys_offset;     /* system-specific offset */
-       unsigned int    code;           /* machine check code */
-       unsigned int    frame_rev;      /* frame revision */
-};
-
-/* Machine Check Frame for uncorrectable errors (Large format)
- *      --- This is used to log uncorrectable errors such as
- *          double bit ECC errors.
- *      --- These errors are detected by both processor and systems.
- */
-struct el_common_EV5_uncorrectable_mcheck {
-        unsigned long   shadow[8];        /* Shadow reg. 8-14, 25           */
-        unsigned long   paltemp[24];      /* PAL TEMP REGS.                 */
-        unsigned long   exc_addr;         /* Address of excepting instruction*/
-        unsigned long   exc_sum;          /* Summary of arithmetic traps.   */
-        unsigned long   exc_mask;         /* Exception mask (from exc_sum). */
-        unsigned long   pal_base;         /* Base address for PALcode.      */
-        unsigned long   isr;              /* Interrupt Status Reg.          */
-        unsigned long   icsr;             /* CURRENT SETUP OF EV5 IBOX      */
-        unsigned long   ic_perr_stat;     /* I-CACHE Reg. <11> set Data parity
-                                                         <12> set TAG parity*/
-        unsigned long   dc_perr_stat;     /* D-CACHE error Reg. Bits set to 1:
-                                                     <2> Data error in bank 0
-                                                     <3> Data error in bank 1
-                                                     <4> Tag error in bank 0
-                                                     <5> Tag error in bank 1 */
-        unsigned long   va;               /* Effective VA of fault or miss. */
-        unsigned long   mm_stat;          /* Holds the reason for D-stream 
-                                             fault or D-cache parity errors */
-        unsigned long   sc_addr;          /* Address that was being accessed
-                                             when EV5 detected Secondary cache
-                                             failure.                 */
-        unsigned long   sc_stat;          /* Helps determine if the error was
-                                             TAG/Data parity(Secondary Cache)*/
-        unsigned long   bc_tag_addr;      /* Contents of EV5 BC_TAG_ADDR    */
-        unsigned long   ei_addr;          /* Physical address of any transfer
-                                             that is logged in EV5 EI_STAT */
-        unsigned long   fill_syndrome;    /* For correcting ECC errors.     */
-        unsigned long   ei_stat;          /* Helps identify reason of any 
-                                             processor uncorrectable error
-                                             at its external interface.     */
-        unsigned long   ld_lock;          /* Contents of EV5 LD_LOCK register*/
-};
-
-struct el_common_EV6_mcheck {
-       unsigned int FrameSize;         /* Bytes, including this field */
-       unsigned int FrameFlags;        /* <31> = Retry, <30> = Second Error */
-       unsigned int CpuOffset;         /* Offset to CPU-specific info */
-       unsigned int SystemOffset;      /* Offset to system-specific info */
-       unsigned int MCHK_Code;
-       unsigned int MCHK_Frame_Rev;
-       unsigned long I_STAT;           /* EV6 Internal Processor Registers */
-       unsigned long DC_STAT;          /* (See the 21264 Spec) */
-       unsigned long C_ADDR;
-       unsigned long DC1_SYNDROME;
-       unsigned long DC0_SYNDROME;
-       unsigned long C_STAT;
-       unsigned long C_STS;
-       unsigned long MM_STAT;
-       unsigned long EXC_ADDR;
-       unsigned long IER_CM;
-       unsigned long ISUM;
-       unsigned long RESERVED0;
-       unsigned long PAL_BASE;
-       unsigned long I_CTL;
-       unsigned long PCTX;
-};
-
-extern void halt(void) __attribute__((noreturn));
-#define __halt() __asm__ __volatile__ ("call_pal %0 #halt" : : "i" (PAL_halt))
-
-#define switch_to(P,N,L)                                                \
-  do {                                                                  \
-    (L) = alpha_switch_to(virt_to_phys(&task_thread_info(N)->pcb), (P)); \
-    check_mmu_context();                                                \
-  } while (0)
-
-struct task_struct;
-extern struct task_struct *alpha_switch_to(unsigned long, struct task_struct*);
-
-#define imb() \
-__asm__ __volatile__ ("call_pal %0 #imb" : : "i" (PAL_imb) : "memory")
-
-#define draina() \
-__asm__ __volatile__ ("call_pal %0 #draina" : : "i" (PAL_draina) : "memory")
-
-enum implver_enum {
-       IMPLVER_EV4,
-       IMPLVER_EV5,
-       IMPLVER_EV6
-};
-
-#ifdef CONFIG_ALPHA_GENERIC
-#define implver()                              \
-({ unsigned long __implver;                    \
-   __asm__ ("implver %0" : "=r"(__implver));   \
-   (enum implver_enum) __implver; })
-#else
-/* Try to eliminate some dead code.  */
-#ifdef CONFIG_ALPHA_EV4
-#define implver() IMPLVER_EV4
-#endif
-#ifdef CONFIG_ALPHA_EV5
-#define implver() IMPLVER_EV5
-#endif
-#if defined(CONFIG_ALPHA_EV6)
-#define implver() IMPLVER_EV6
-#endif
-#endif
-
-enum amask_enum {
-       AMASK_BWX = (1UL << 0),
-       AMASK_FIX = (1UL << 1),
-       AMASK_CIX = (1UL << 2),
-       AMASK_MAX = (1UL << 8),
-       AMASK_PRECISE_TRAP = (1UL << 9),
-};
-
-#define amask(mask)                                            \
-({ unsigned long __amask, __input = (mask);                    \
-   __asm__ ("amask %1,%0" : "=r"(__amask) : "rI"(__input));    \
-   __amask; })
-
-#define __CALL_PAL_R0(NAME, TYPE)                              \
-extern inline TYPE NAME(void)                                  \
-{                                                              \
-       register TYPE __r0 __asm__("$0");                       \
-       __asm__ __volatile__(                                   \
-               "call_pal %1 # " #NAME                          \
-               :"=r" (__r0)                                    \
-               :"i" (PAL_ ## NAME)                             \
-               :"$1", "$16", "$22", "$23", "$24", "$25");      \
-       return __r0;                                            \
-}
-
-#define __CALL_PAL_W1(NAME, TYPE0)                             \
-extern inline void NAME(TYPE0 arg0)                            \
-{                                                              \
-       register TYPE0 __r16 __asm__("$16") = arg0;             \
-       __asm__ __volatile__(                                   \
-               "call_pal %1 # "#NAME                           \
-               : "=r"(__r16)                                   \
-               : "i"(PAL_ ## NAME), "0"(__r16)                 \
-               : "$1", "$22", "$23", "$24", "$25");            \
-}
-
-#define __CALL_PAL_W2(NAME, TYPE0, TYPE1)                      \
-extern inline void NAME(TYPE0 arg0, TYPE1 arg1)                        \
-{                                                              \
-       register TYPE0 __r16 __asm__("$16") = arg0;             \
-       register TYPE1 __r17 __asm__("$17") = arg1;             \
-       __asm__ __volatile__(                                   \
-               "call_pal %2 # "#NAME                           \
-               : "=r"(__r16), "=r"(__r17)                      \
-               : "i"(PAL_ ## NAME), "0"(__r16), "1"(__r17)     \
-               : "$1", "$22", "$23", "$24", "$25");            \
-}
-
-#define __CALL_PAL_RW1(NAME, RTYPE, TYPE0)                     \
-extern inline RTYPE NAME(TYPE0 arg0)                           \
-{                                                              \
-       register RTYPE __r0 __asm__("$0");                      \
-       register TYPE0 __r16 __asm__("$16") = arg0;             \
-       __asm__ __volatile__(                                   \
-               "call_pal %2 # "#NAME                           \
-               : "=r"(__r16), "=r"(__r0)                       \
-               : "i"(PAL_ ## NAME), "0"(__r16)                 \
-               : "$1", "$22", "$23", "$24", "$25");            \
-       return __r0;                                            \
-}
-
-#define __CALL_PAL_RW2(NAME, RTYPE, TYPE0, TYPE1)              \
-extern inline RTYPE NAME(TYPE0 arg0, TYPE1 arg1)               \
-{                                                              \
-       register RTYPE __r0 __asm__("$0");                      \
-       register TYPE0 __r16 __asm__("$16") = arg0;             \
-       register TYPE1 __r17 __asm__("$17") = arg1;             \
-       __asm__ __volatile__(                                   \
-               "call_pal %3 # "#NAME                           \
-               : "=r"(__r16), "=r"(__r17), "=r"(__r0)          \
-               : "i"(PAL_ ## NAME), "0"(__r16), "1"(__r17)     \
-               : "$1", "$22", "$23", "$24", "$25");            \
-       return __r0;                                            \
-}
-
-__CALL_PAL_W1(cflush, unsigned long);
-__CALL_PAL_R0(rdmces, unsigned long);
-__CALL_PAL_R0(rdps, unsigned long);
-__CALL_PAL_R0(rdusp, unsigned long);
-__CALL_PAL_RW1(swpipl, unsigned long, unsigned long);
-__CALL_PAL_R0(whami, unsigned long);
-__CALL_PAL_W2(wrent, void*, unsigned long);
-__CALL_PAL_W1(wripir, unsigned long);
-__CALL_PAL_W1(wrkgp, unsigned long);
-__CALL_PAL_W1(wrmces, unsigned long);
-__CALL_PAL_RW2(wrperfmon, unsigned long, unsigned long, unsigned long);
-__CALL_PAL_W1(wrusp, unsigned long);
-__CALL_PAL_W1(wrvptptr, unsigned long);
-
-/*
- * TB routines..
- */
-#define __tbi(nr,arg,arg1...)                                  \
-({                                                             \
-       register unsigned long __r16 __asm__("$16") = (nr);     \
-       register unsigned long __r17 __asm__("$17"); arg;       \
-       __asm__ __volatile__(                                   \
-               "call_pal %3 #__tbi"                            \
-               :"=r" (__r16),"=r" (__r17)                      \
-               :"0" (__r16),"i" (PAL_tbi) ,##arg1              \
-               :"$0", "$1", "$22", "$23", "$24", "$25");       \
-})
-
-#define tbi(x,y)       __tbi(x,__r17=(y),"1" (__r17))
-#define tbisi(x)       __tbi(1,__r17=(x),"1" (__r17))
-#define tbisd(x)       __tbi(2,__r17=(x),"1" (__r17))
-#define tbis(x)                __tbi(3,__r17=(x),"1" (__r17))
-#define tbiap()                __tbi(-1, /* no second argument */)
-#define tbia()         __tbi(-2, /* no second argument */)
-
-/*
- * Atomic exchange routines.
- */
-
-#define __ASM__MB
-#define ____xchg(type, args...)                __xchg ## type ## _local(args)
-#define ____cmpxchg(type, args...)     __cmpxchg ## type ## _local(args)
-#include <asm/xchg.h>
-
-#define xchg_local(ptr,x)                                              \
-  ({                                                                   \
-     __typeof__(*(ptr)) _x_ = (x);                                     \
-     (__typeof__(*(ptr))) __xchg_local((ptr), (unsigned long)_x_,      \
-                                      sizeof(*(ptr)));                 \
-  })
-
-#define cmpxchg_local(ptr, o, n)                                       \
-  ({                                                                   \
-     __typeof__(*(ptr)) _o_ = (o);                                     \
-     __typeof__(*(ptr)) _n_ = (n);                                     \
-     (__typeof__(*(ptr))) __cmpxchg_local((ptr), (unsigned long)_o_,   \
-                                         (unsigned long)_n_,           \
-                                         sizeof(*(ptr)));              \
-  })
-
-#define cmpxchg64_local(ptr, o, n)                                     \
-  ({                                                                   \
-       BUILD_BUG_ON(sizeof(*(ptr)) != 8);                              \
-       cmpxchg_local((ptr), (o), (n));                                 \
-  })
-
-#ifdef CONFIG_SMP
-#undef __ASM__MB
-#define __ASM__MB      "\tmb\n"
-#endif
-#undef ____xchg
-#undef ____cmpxchg
-#define ____xchg(type, args...)                __xchg ##type(args)
-#define ____cmpxchg(type, args...)     __cmpxchg ##type(args)
-#include <asm/xchg.h>
-
-#define xchg(ptr,x)                                                    \
-  ({                                                                   \
-     __typeof__(*(ptr)) _x_ = (x);                                     \
-     (__typeof__(*(ptr))) __xchg((ptr), (unsigned long)_x_,            \
-                                sizeof(*(ptr)));                       \
-  })
-
-#define cmpxchg(ptr, o, n)                                             \
-  ({                                                                   \
-     __typeof__(*(ptr)) _o_ = (o);                                     \
-     __typeof__(*(ptr)) _n_ = (n);                                     \
-     (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,         \
-                                   (unsigned long)_n_, sizeof(*(ptr)));\
-  })
-
-#define cmpxchg64(ptr, o, n)                                           \
-  ({                                                                   \
-       BUILD_BUG_ON(sizeof(*(ptr)) != 8);                              \
-       cmpxchg((ptr), (o), (n));                                       \
-  })
-
-#undef __ASM__MB
-#undef ____cmpxchg
-
-#define __HAVE_ARCH_CMPXCHG 1
-
-#endif /* __ASSEMBLY__ */
-
-#define arch_align_stack(x) (x)
-
-#endif
index beba1b8..1d1b436 100644 (file)
@@ -1,4 +1,4 @@
-#ifndef __ALPHA_SYSTEM_H
+#ifndef _ALPHA_ATOMIC_H
 #error Do not include xchg.h directly!
 #else
 /*
index ca46b2c..708c831 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <asm/ptrace.h>
 #include <asm/smp.h>
+#include <asm/mce.h>
 
 #include "proto.h"
 #include "pci_impl.h"
index 1d6ee6c..c44339e 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/bootmem.h>
 
 #include <asm/ptrace.h>
+#include <asm/mce.h>
 
 #include "proto.h"
 #include "pci_impl.h"
index 2f770e9..3ada4f7 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <asm/ptrace.h>
 #include <asm/delay.h>
+#include <asm/mce.h>
 
 #include "proto.h"
 #include "pci_impl.h"
index 0c010ca..ae529c4 100644 (file)
@@ -7,6 +7,8 @@
  *     implementations.
  */
 
+#include <asm/mce.h>
+
 union el_timestamp;
 struct el_subpacket;
 struct ev7_lf_subpackets;
index 4bdd1d2..c352499 100644 (file)
@@ -8,14 +8,12 @@
  */
 
 #include <linux/init.h>
-#include <asm/system.h>
 #include <asm/asm-offsets.h>
+#include <asm/pal.h>
+#include <asm/setup.h>
 
 __HEAD
-.globl swapper_pg_dir
 .globl _stext
-swapper_pg_dir=SWAPPER_PGD
-
        .set noreorder
        .globl  __start
        .ent    __start
index 381431a..2872acc 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/profile.h>
 #include <linux/bitops.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
index 51b7fbd..772ddfd 100644 (file)
@@ -11,6 +11,7 @@
 #include <asm/machvec.h>
 #include <asm/dma.h>
 #include <asm/perf_event.h>
+#include <asm/mce.h>
 
 #include "proto.h"
 #include "irq_impl.h"
index 01e8715..49ee319 100644 (file)
@@ -40,7 +40,6 @@
 #include <asm/fpu.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/sysinfo.h>
 #include <asm/thread_info.h>
 #include <asm/hwrpb.h>
index 89bbe5b..153d3fc 100644 (file)
@@ -31,7 +31,6 @@
 
 #include <asm/reg.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/hwrpb.h>
index e2af5eb..54616f4 100644 (file)
@@ -16,7 +16,6 @@
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/fpu.h>
 
 #include "proto.h"
index 32de560..9e3107c 100644 (file)
@@ -55,7 +55,6 @@ static struct notifier_block alpha_panic_block = {
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/hwrpb.h>
 #include <asm/dma.h>
 #include <asm/mmu_context.h>
index 8606d77..118dc6a 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/bitops.h>
 
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/mmu_context.h>
index 1029619..4c50f8f 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/bitops.h>
 
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/dma.h>
 #include <asm/irq.h>
 #include <asm/mmu_context.h>
index 13f0717..5bf401f 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/bitops.h>
 
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/dma.h>
 #include <asm/irq.h>
 #include <asm/mmu_context.h>
index 3c6c13c..ad40a42 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/bitops.h>
 
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/dma.h>
 #include <asm/irq.h>
 #include <asm/mmu_context.h>
index 35f480d..79d69d7 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/bitops.h>
 
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/dma.h>
 #include <asm/irq.h>
 #include <asm/mmu_context.h>
index 7f1a87f..5a0af11 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/init.h>
 
 #include <asm/ptrace.h>
-#include <asm/system.h>
 
 #define __EXTERN_INLINE inline
 #include <asm/io.h>
index fc8b125..14a4b6a 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/bitops.h>
 
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/dma.h>
 #include <asm/irq.h>
 #include <asm/mmu_context.h>
index 258da68..d5b9776 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/reboot.h>
 
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/dma.h>
 #include <asm/irq.h>
 #include <asm/mmu_context.h>
index c0fd728..5e82dc1 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/bitops.h>
 
 #include <asm/ptrace.h>
-#include <asm/system.h>
+#include <asm/mce.h>
 #include <asm/dma.h>
 #include <asm/irq.h>
 #include <asm/mmu_context.h>
index 4112200..4d4c046 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/bitops.h>
 
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/dma.h>
 #include <asm/irq.h>
 #include <asm/mmu_context.h>
index 2172528..063e594 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/bitops.h>
 
 #include <asm/ptrace.h>
-#include <asm/system.h>
+#include <asm/mce.h>
 #include <asm/dma.h>
 #include <asm/irq.h>
 #include <asm/mmu_context.h>
index a125d6b..dfd510a 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/init.h>
 
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/dma.h>
 #include <asm/irq.h>
 #include <asm/mmu_context.h>
index 2581cbe..a3f4852 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/init.h>
 
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/dma.h>
 #include <asm/irq.h>
 #include <asm/mmu_context.h>
index b172b27..08ee737 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/bitops.h>
 
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/dma.h>
 #include <asm/irq.h>
 #include <asm/mmu_context.h>
index 98d1dbf..8a0aa6d 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/init.h>
 
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/dma.h>
 #include <asm/irq.h>
 #include <asm/mmu_context.h>
index 47bec1e..febd24e 100644 (file)
@@ -20,7 +20,6 @@
 
 #include <asm/compiler.h>
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/dma.h>
 #include <asm/irq.h>
 #include <asm/mmu_context.h>
index 73e1c31..d063b36 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/bitops.h>
 
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/dma.h>
 #include <asm/irq.h>
 #include <asm/mmu_context.h>
@@ -26,6 +25,7 @@
 #include <asm/core_cia.h>
 #include <asm/hwrpb.h>
 #include <asm/tlbflush.h>
+#include <asm/special_insns.h>
 
 #include "proto.h"
 #include "irq_impl.h"
index 2ae99ad..dd0f1ea 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/init.h>
 
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/dma.h>
 #include <asm/irq.h>
 #include <asm/mmu_context.h>
index b8eafa0..2533db2 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/bitops.h>
 
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/dma.h>
 #include <asm/irq.h>
 #include <asm/mmu_context.h>
index 17c85a6..ee18748 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/bitops.h>
 
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/dma.h>
 #include <asm/irq.h>
 #include <asm/mmu_context.h>
index 0414e02..80d987c 100644 (file)
@@ -24,6 +24,7 @@
 #include <asm/sysinfo.h>
 #include <asm/hwrpb.h>
 #include <asm/mmu_context.h>
+#include <asm/special_insns.h>
 
 #include "proto.h"
 
index f937ad1..647b84c 100644 (file)
@@ -2,6 +2,7 @@
 #include <asm/thread_info.h>
 #include <asm/cache.h>
 #include <asm/page.h>
+#include <asm/setup.h>
 
 OUTPUT_FORMAT("elf64-alpha")
 OUTPUT_ARCH(alpha)
@@ -25,6 +26,7 @@ SECTIONS
                *(.fixup)
                *(.gnu.warning)
        } :kernel
+       swapper_pg_dir = SWAPPER_PGD;
        _etext = .;     /* End of text section */
 
        NOTES :kernel :note
index 6d432e4..5e83216 100644 (file)
@@ -1,5 +1,4 @@
 #include <linux/kernel.h>
-#include <asm/system.h>
 
 typedef unsigned int instr;
 
index fadd5f8..5eecab1 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/interrupt.h>
 #include <linux/module.h>
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 
 extern void die_if_kernel(char *,struct pt_regs *,long, unsigned long *);
index 69d0c57..1ad6ca7 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/vmalloc.h>
 #include <linux/gfp.h>
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
@@ -31,6 +30,7 @@
 #include <asm/mmu_context.h>
 #include <asm/console.h>
 #include <asm/tlb.h>
+#include <asm/setup.h>
 
 extern void die_if_kernel(char *,struct pt_regs *,long);
 
index bd8ac53..a0a5d27 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/smp.h>
 #include <linux/errno.h>
 #include <asm/ptrace.h>
-#include <asm/system.h>
 
 #include "op_impl.h"
 
index 80d764d..18aa9b4 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/init.h>
 #include <linux/smp.h>
 #include <asm/ptrace.h>
-#include <asm/system.h>
 
 #include "op_impl.h"
 
index ceea6e1..c32f8a0 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/init.h>
 #include <linux/smp.h>
 #include <asm/ptrace.h>
-#include <asm/system.h>
 
 #include "op_impl.h"
 
index 0869f85..1c84cc2 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/init.h>
 #include <linux/smp.h>
 #include <asm/ptrace.h>
-#include <asm/system.h>
 
 #include "op_impl.h"
 
index 5b9d178..34a57a1 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/init.h>
 #include <linux/smp.h>
 #include <asm/ptrace.h>
-#include <asm/system.h>
 
 #include "op_impl.h"
 
index 0106f75..dcb088e 100644 (file)
@@ -180,6 +180,7 @@ machine-$(CONFIG_ARCH_S5P64X0)              := s5p64x0
 machine-$(CONFIG_ARCH_S5PC100)         := s5pc100
 machine-$(CONFIG_ARCH_S5PV210)         := s5pv210
 machine-$(CONFIG_ARCH_EXYNOS4)         := exynos
+machine-$(CONFIG_ARCH_EXYNOS5)         := exynos
 machine-$(CONFIG_ARCH_SA1100)          := sa1100
 machine-$(CONFIG_ARCH_SHARK)           := shark
 machine-$(CONFIG_ARCH_SHMOBILE)        := shmobile
index a100db0..92f3662 100644 (file)
                                reg = <0xfffff000 0x200>;
                        };
 
+                       ramc0: ramc@ffffea00 {
+                               compatible = "atmel,at91sam9260-sdramc";
+                               reg = <0xffffea00 0x200>;
+                       };
+
+                       pmc: pmc@fffffc00 {
+                               compatible = "atmel,at91rm9200-pmc";
+                               reg = <0xfffffc00 0x100>;
+                       };
+
+                       rstc@fffffd00 {
+                               compatible = "atmel,at91sam9260-rstc";
+                               reg = <0xfffffd00 0x10>;
+                       };
+
+                       shdwc@fffffd10 {
+                               compatible = "atmel,at91sam9260-shdwc";
+                               reg = <0xfffffd10 0x10>;
+                       };
+
                        pit: timer@fffffd30 {
                                compatible = "atmel,at91sam9260-pit";
                                reg = <0xfffffd30 0xf>;
                                interrupts = <21 4>;
                                status = "disabled";
                        };
+
+                       usb1: gadget@fffa4000 {
+                               compatible = "atmel,at91rm9200-udc";
+                               reg = <0xfffa4000 0x4000>;
+                               interrupts = <10 4>;
+                               status = "disabled";
+                       };
+               };
+
+               nand0: nand@40000000 {
+                       compatible = "atmel,at91rm9200-nand";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       reg = <0x40000000 0x10000000
+                              0xffffe800 0x200
+                             >;
+                       atmel,nand-addr-offset = <21>;
+                       atmel,nand-cmd-offset = <22>;
+                       gpios = <&pioC 13 0
+                                &pioC 14 0
+                                0
+                               >;
+                       status = "disabled";
                };
+
+               usb0: ohci@00500000 {
+                       compatible = "atmel,at91rm9200-ohci", "usb-ohci";
+                       reg = <0x00500000 0x100000>;
+                       interrupts = <20 4>;
+                       status = "disabled";
+               };
+       };
+
+       i2c@0 {
+               compatible = "i2c-gpio";
+               gpios = <&pioA 23 0 /* sda */
+                        &pioA 24 0 /* scl */
+                       >;
+               i2c-gpio,sda-open-drain;
+               i2c-gpio,scl-open-drain;
+               i2c-gpio,delay-us = <2>;        /* ~100 kHz */
+               #address-cells = <1>;
+               #size-cells = <0>;
+               status = "disabled";
        };
 };
index e64eb93..ac0dc00 100644 (file)
@@ -15,7 +15,7 @@
        compatible = "atmel,at91sam9g25ek", "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9";
 
        chosen {
-               bootargs = "128M console=ttyS0,115200 mtdparts=atmel_nand:8M(bootstrap/uboot/kernel)ro,-(rootfs) root=/dev/mtdblock1 rw rootfstype=ubifs ubi.mtd=1 root=ubi0:rootfs";
+               bootargs = "128M console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=ubifs ubi.mtd=1 root=ubi0:rootfs";
        };
 
        ahb {
                                status = "okay";
                        };
                };
+
+               usb0: ohci@00600000 {
+                       status = "okay";
+                       num-ports = <2>;
+                       atmel,vbus-gpio = <&pioD 19 0
+                                          &pioD 20 0
+                                         >;
+               };
+
+               usb1: ehci@00700000 {
+                       status = "okay";
+               };
        };
 };
index f779667..3d0c32f 100644 (file)
                                reg = <0xfffff000 0x200>;
                        };
 
+                       ramc0: ramc@ffffe400 {
+                               compatible = "atmel,at91sam9g45-ddramc";
+                               reg = <0xffffe400 0x200
+                                      0xffffe600 0x200>;
+                       };
+
+                       pmc: pmc@fffffc00 {
+                               compatible = "atmel,at91rm9200-pmc";
+                               reg = <0xfffffc00 0x100>;
+                       };
+
+                       rstc@fffffd00 {
+                               compatible = "atmel,at91sam9g45-rstc";
+                               reg = <0xfffffd00 0x10>;
+                       };
+
                        pit: timer@fffffd30 {
                                compatible = "atmel,at91sam9260-pit";
                                reg = <0xfffffd30 0xf>;
                        };
 
 
+                       shdwc@fffffd10 {
+                               compatible = "atmel,at91sam9rl-shdwc";
+                               reg = <0xfffffd10 0x10>;
+                       };
+
                        tcb0: timer@fff7c000 {
                                compatible = "atmel,at91rm9200-tcb";
                                reg = <0xfff7c000 0x100>;
                                status = "disabled";
                        };
                };
+
+               nand0: nand@40000000 {
+                       compatible = "atmel,at91rm9200-nand";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       reg = <0x40000000 0x10000000
+                              0xffffe200 0x200
+                             >;
+                       atmel,nand-addr-offset = <21>;
+                       atmel,nand-cmd-offset = <22>;
+                       gpios = <&pioC 8 0
+                                &pioC 14 0
+                                0
+                               >;
+                       status = "disabled";
+               };
+
+               usb0: ohci@00700000 {
+                       compatible = "atmel,at91rm9200-ohci", "usb-ohci";
+                       reg = <0x00700000 0x100000>;
+                       interrupts = <22 4>;
+                       status = "disabled";
+               };
+
+               usb1: ehci@00800000 {
+                       compatible = "atmel,at91sam9g45-ehci", "usb-ehci";
+                       reg = <0x00800000 0x100000>;
+                       interrupts = <22 4>;
+                       status = "disabled";
+               };
+       };
+
+       i2c@0 {
+               compatible = "i2c-gpio";
+               gpios = <&pioA 20 0 /* sda */
+                        &pioA 21 0 /* scl */
+                       >;
+               i2c-gpio,sda-open-drain;
+               i2c-gpio,scl-open-drain;
+               i2c-gpio,delay-us = <5>;        /* ~100 kHz */
+               #address-cells = <1>;
+               #size-cells = <0>;
+               status = "disabled";
        };
 };
index 15e25f9..c4c8ae4 100644 (file)
        compatible = "atmel,at91sam9m10g45ek", "atmel,at91sam9g45", "atmel,at91sam9";
 
        chosen {
-               bootargs = "mem=64M console=ttyS0,115200 mtdparts=atmel_nand:4M(bootstrap/uboot/kernel)ro,60M(rootfs),-(data) root=/dev/mtdblock1 rw rootfstype=jffs2";
+               bootargs = "mem=64M console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=jffs2";
        };
 
        memory@70000000 {
                reg = <0x70000000 0x4000000>;
        };
 
+       clocks {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
+               main_clock: clock@0 {
+                       compatible = "atmel,osc", "fixed-clock";
+                       clock-frequency = <12000000>;
+               };
+       };
+
        ahb {
                apb {
                        dbgu: serial@ffffee00 {
                                status = "okay";
                        };
                };
+
+               nand0: nand@40000000 {
+                       nand-bus-width = <8>;
+                       nand-ecc-mode = "soft";
+                       nand-on-flash-bbt;
+                       status = "okay";
+
+                       boot@0 {
+                               label = "bootstrap/uboot/kernel";
+                               reg = <0x0 0x400000>;
+                       };
+
+                       rootfs@400000 {
+                               label = "rootfs";
+                               reg = <0x400000 0x3C00000>;
+                       };
+
+                       data@4000000 {
+                               label = "data";
+                               reg = <0x4000000 0xC000000>;
+                       };
+               };
+
+               usb0: ohci@00700000 {
+                       status = "okay";
+                       num-ports = <2>;
+                       atmel,vbus-gpio = <&pioD 1 0
+                                          &pioD 3 0>;
+               };
+
+               usb1: ehci@00800000 {
+                       status = "okay";
+               };
        };
 
        leds {
index a02e636..c111001 100644 (file)
                                reg = <0xfffff000 0x200>;
                        };
 
+                       ramc0: ramc@ffffe800 {
+                               compatible = "atmel,at91sam9g45-ddramc";
+                               reg = <0xffffe800 0x200>;
+                       };
+
+                       pmc: pmc@fffffc00 {
+                               compatible = "atmel,at91rm9200-pmc";
+                               reg = <0xfffffc00 0x100>;
+                       };
+
+                       rstc@fffffe00 {
+                               compatible = "atmel,at91sam9g45-rstc";
+                               reg = <0xfffffe00 0x10>;
+                       };
+
+                       shdwc@fffffe10 {
+                               compatible = "atmel,at91sam9x5-shdwc";
+                               reg = <0xfffffe10 0x10>;
+                       };
+
                        pit: timer@fffffe30 {
                                compatible = "atmel,at91sam9260-pit";
                                reg = <0xfffffe30 0xf>;
                                status = "disabled";
                        };
                };
+
+               nand0: nand@40000000 {
+                       compatible = "atmel,at91rm9200-nand";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       reg = <0x40000000 0x10000000
+                             >;
+                       atmel,nand-addr-offset = <21>;
+                       atmel,nand-cmd-offset = <22>;
+                       gpios = <&pioC 8 0
+                                &pioC 14 0
+                                0
+                               >;
+                       status = "disabled";
+               };
+
+               usb0: ohci@00600000 {
+                       compatible = "atmel,at91rm9200-ohci", "usb-ohci";
+                       reg = <0x00600000 0x100000>;
+                       interrupts = <22 4>;
+                       status = "disabled";
+               };
+
+               usb1: ehci@00700000 {
+                       compatible = "atmel,at91sam9g45-ehci", "usb-ehci";
+                       reg = <0x00700000 0x100000>;
+                       interrupts = <22 4>;
+                       status = "disabled";
+               };
+       };
+
+       i2c@0 {
+               compatible = "i2c-gpio";
+               gpios = <&pioA 30 0 /* sda */
+                        &pioA 31 0 /* scl */
+                       >;
+               i2c-gpio,sda-open-drain;
+               i2c-gpio,scl-open-drain;
+               i2c-gpio,delay-us = <2>;        /* ~100 kHz */
+               #address-cells = <1>;
+               #size-cells = <0>;
+               status = "disabled";
+       };
+
+       i2c@1 {
+               compatible = "i2c-gpio";
+               gpios = <&pioC 0 0 /* sda */
+                        &pioC 1 0 /* scl */
+                       >;
+               i2c-gpio,sda-open-drain;
+               i2c-gpio,scl-open-drain;
+               i2c-gpio,delay-us = <2>;        /* ~100 kHz */
+               #address-cells = <1>;
+               #size-cells = <0>;
+               status = "disabled";
+       };
+
+       i2c@2 {
+               compatible = "i2c-gpio";
+               gpios = <&pioB 4 0 /* sda */
+                        &pioB 5 0 /* scl */
+                       >;
+               i2c-gpio,sda-open-drain;
+               i2c-gpio,scl-open-drain;
+               i2c-gpio,delay-us = <2>;        /* ~100 kHz */
+               #address-cells = <1>;
+               #size-cells = <0>;
+               status = "disabled";
        };
 };
index 64ae3e8..67936f8 100644 (file)
                reg = <0x20000000 0x8000000>;
        };
 
+       clocks {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
+               main_clock: clock@0 {
+                       compatible = "atmel,osc", "fixed-clock";
+                       clock-frequency = <12000000>;
+               };
+       };
+
+       ahb {
+               nand0: nand@40000000 {
+                       nand-bus-width = <8>;
+                       nand-ecc-mode = "soft";
+                       nand-on-flash-bbt;
+                       status = "okay";
+
+                       at91bootstrap@0 {
+                               label = "at91bootstrap";
+                               reg = <0x0 0x40000>;
+                       };
+
+                       uboot@40000 {
+                               label = "u-boot";
+                               reg = <0x40000 0x80000>;
+                       };
+
+                       ubootenv@c0000 {
+                               label = "U-Boot Env";
+                               reg = <0xc0000 0x140000>;
+                       };
+
+                       kernel@200000 {
+                               label = "kernel";
+                               reg = <0x200000 0x600000>;
+                       };
+
+                       rootfs@800000 {
+                               label = "rootfs";
+                               reg = <0x800000 0x1f800000>;
+                       };
+               };
+       };
+
        leds {
                compatible = "gpio-leds";
 
diff --git a/arch/arm/boot/dts/db8500.dtsi b/arch/arm/boot/dts/db8500.dtsi
new file mode 100644 (file)
index 0000000..d73dce6
--- /dev/null
@@ -0,0 +1,275 @@
+/*
+ * Copyright 2012 Linaro Ltd
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+       soc-u9500 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "stericsson,db8500";
+               interrupt-parent = <&intc>;
+               ranges;
+
+               intc: interrupt-controller@a0411000 {
+                       compatible = "arm,cortex-a9-gic";
+                       #interrupt-cells = <3>;
+                       #address-cells = <1>;
+                       interrupt-controller;
+                       interrupt-parent;
+                       reg = <0xa0411000 0x1000>,
+                             <0xa0410100 0x100>;
+               };
+
+               L2: l2-cache {
+                       compatible = "arm,pl310-cache";
+                       reg = <0xa0412000 0x1000>;
+                       interrupts = <0 13 4>;
+                       cache-unified;
+                       cache-level = <2>;
+               };
+
+               pmu {
+                       compatible = "arm,cortex-a9-pmu";
+                       interrupts = <0 7 0x4>;
+               };
+
+               timer@a0410600 {
+                       compatible = "arm,cortex-a9-twd-timer";
+                       reg = <0xa0410600 0x20>;
+                       interrupts = <1 13 0x304>;
+               };
+
+               rtc@80154000 {
+                       compatible = "stericsson,db8500-rtc";
+                       reg = <0x80154000 0x1000>;
+                       interrupts = <0 18 0x4>;
+               };
+
+               gpio0: gpio@8012e000 {
+                       compatible = "stericsson,db8500-gpio",
+                               "stmicroelectronics,nomadik-gpio";
+                       reg =  <0x8012e000 0x80>;
+                       interrupts = <0 119 0x4>;
+                       supports-sleepmode;
+                       gpio-controller;
+               };
+
+               gpio1: gpio@8012e080 {
+                       compatible = "stericsson,db8500-gpio",
+                               "stmicroelectronics,nomadik-gpio";
+                       reg =  <0x8012e080 0x80>;
+                       interrupts = <0 120 0x4>;
+                       supports-sleepmode;
+                       gpio-controller;
+               };
+
+               gpio2: gpio@8000e000 {
+                       compatible = "stericsson,db8500-gpio",
+                               "stmicroelectronics,nomadik-gpio";
+                       reg =  <0x8000e000 0x80>;
+                       interrupts = <0 121 0x4>;
+                       supports-sleepmode;
+                       gpio-controller;
+               };
+
+               gpio3: gpio@8000e080 {
+                       compatible = "stericsson,db8500-gpio",
+                               "stmicroelectronics,nomadik-gpio";
+                       reg =  <0x8000e080 0x80>;
+                       interrupts = <0 122 0x4>;
+                       supports-sleepmode;
+                       gpio-controller;
+               };
+
+               gpio4: gpio@8000e100 {
+                       compatible = "stericsson,db8500-gpio",
+                               "stmicroelectronics,nomadik-gpio";
+                       reg =  <0x8000e100 0x80>;
+                       interrupts = <0 123 0x4>;
+                       supports-sleepmode;
+                       gpio-controller;
+               };
+
+               gpio5: gpio@8000e180 {
+                       compatible = "stericsson,db8500-gpio",
+                               "stmicroelectronics,nomadik-gpio";
+                       reg =  <0x8000e180 0x80>;
+                       interrupts = <0 124 0x4>;
+                       supports-sleepmode;
+                       gpio-controller;
+               };
+
+               gpio6: gpio@8011e000 {
+                       compatible = "stericsson,db8500-gpio",
+                               "stmicroelectronics,nomadik-gpio";
+                       reg =  <0x8011e000 0x80>;
+                       interrupts = <0 125 0x4>;
+                       supports-sleepmode;
+                       gpio-controller;
+               };
+
+               gpio7: gpio@8011e080 {
+                       compatible = "stericsson,db8500-gpio",
+                               "stmicroelectronics,nomadik-gpio";
+                       reg =  <0x8011e080 0x80>;
+                       interrupts = <0 126 0x4>;
+                       supports-sleepmode;
+                       gpio-controller;
+               };
+
+               gpio8: gpio@a03fe000 {
+                       compatible = "stericsson,db8500-gpio",
+                               "stmicroelectronics,nomadik-gpio";
+                       reg =  <0xa03fe000 0x80>;
+                       interrupts = <0 127 0x4>;
+                       supports-sleepmode;
+                       gpio-controller;
+               };
+
+               usb@a03e0000 {
+                       compatible = "stericsson,db8500-musb",
+                               "mentor,musb";
+                       reg = <0xa03e0000 0x10000>;
+                       interrupts = <0 23 0x4>;
+               };
+
+               dma-controller@801C0000 {
+                       compatible = "stericsson,db8500-dma40",
+                                       "stericsson,dma40";
+                       reg = <0x801C0000 0x1000 0x40010000 0x800>;
+                       interrupts = <0 25 0x4>;
+               };
+
+               prcmu@80157000 {
+                       compatible = "stericsson,db8500-prcmu";
+                       reg = <0x80157000 0x1000>;
+                       interrupts = <46 47>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       ab8500@5 {
+                               compatible = "stericsson,ab8500";
+                               reg = <5>; /* mailbox 5 is i2c */
+                               interrupts = <0 40 0x4>;
+                       };
+               };
+
+               i2c@80004000 {
+                       compatible = "stericsson,db8500-i2c", "stmicroelectronics,nomadik-i2c";
+                       reg = <0x80004000 0x1000>;
+                       interrupts = <0 21 0x4>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
+               i2c@80122000 {
+                       compatible = "stericsson,db8500-i2c", "stmicroelectronics,nomadik-i2c";
+                       reg = <0x80122000 0x1000>;
+                       interrupts = <0 22 0x4>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
+               i2c@80128000 {
+                       compatible = "stericsson,db8500-i2c", "stmicroelectronics,nomadik-i2c";
+                       reg = <0x80128000 0x1000>;
+                       interrupts = <0 55 0x4>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
+               i2c@80110000 {
+                       compatible = "stericsson,db8500-i2c", "stmicroelectronics,nomadik-i2c";
+                       reg = <0x80110000 0x1000>;
+                       interrupts = <0 12 0x4>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
+               i2c@8012a000 {
+                       compatible = "stericsson,db8500-i2c", "stmicroelectronics,nomadik-i2c";
+                       reg = <0x8012a000 0x1000>;
+                       interrupts = <0 51 0x4>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
+               ssp@80002000 {
+                       compatible = "arm,pl022", "arm,primecell";
+                       reg = <80002000 0x1000>;
+                       interrupts = <0 14 0x4>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       status = "disabled";
+
+                       // Add one of these for each child device
+                       cs-gpios = <&gpio0 31 &gpio4 14 &gpio4 16 &gpio6 22 &gpio7 0>;
+
+               };
+
+               uart@80120000 {
+                       compatible = "arm,pl011", "arm,primecell";
+                       reg = <0x80120000 0x1000>;
+                       interrupts = <0 11 0x4>;
+                       status = "disabled";
+               };
+               uart@80121000 {
+                       compatible = "arm,pl011", "arm,primecell";
+                       reg = <0x80121000 0x1000>;
+                       interrupts = <0 19 0x4>;
+                       status = "disabled";
+               };
+               uart@80007000 {
+                       compatible = "arm,pl011", "arm,primecell";
+                       reg = <0x80007000 0x1000>;
+                       interrupts = <0 26 0x4>;
+                       status = "disabled";
+               };
+
+               sdi@80126000 {
+                       compatible = "arm,pl18x", "arm,primecell";
+                       reg = <0x80126000 0x1000>;
+                       interrupts = <0 60 0x4>;
+                       status = "disabled";
+               };
+               sdi@80118000 {
+                       compatible = "arm,pl18x", "arm,primecell";
+                       reg = <0x80118000 0x1000>;
+                       interrupts = <0 50 0x4>;
+                       status = "disabled";
+               };
+               sdi@80005000 {
+                       compatible = "arm,pl18x", "arm,primecell";
+                       reg = <0x80005000 0x1000>;
+                       interrupts = <0 41 0x4>;
+                       status = "disabled";
+               };
+               sdi@80119000 {
+                       compatible = "arm,pl18x", "arm,primecell";
+                       reg = <0x80119000 0x1000>;
+                       interrupts = <0 59 0x4>;
+                       status = "disabled";
+               };
+               sdi@80114000 {
+                       compatible = "arm,pl18x", "arm,primecell";
+                       reg = <0x80114000 0x1000>;
+                       interrupts = <0 99 0x4>;
+                       status = "disabled";
+               };
+               sdi@80008000 {
+                       compatible = "arm,pl18x", "arm,primecell";
+                       reg = <0x80114000 0x1000>;
+                       interrupts = <0 100 0x4>;
+                       status = "disabled";
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/exynos5250-smdk5250.dts b/arch/arm/boot/dts/exynos5250-smdk5250.dts
new file mode 100644 (file)
index 0000000..399d17b
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * SAMSUNG SMDK5250 board device tree source
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/dts-v1/;
+/include/ "exynos5250.dtsi"
+
+/ {
+       model = "SAMSUNG SMDK5250 board based on EXYNOS5250";
+       compatible = "samsung,smdk5250", "samsung,exynos5250";
+
+       memory {
+               reg = <0x40000000 0x80000000>;
+       };
+
+       chosen {
+               bootargs = "root=/dev/ram0 rw ramdisk=8192 console=ttySAC1,115200";
+       };
+};
diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi
new file mode 100644 (file)
index 0000000..dfc4335
--- /dev/null
@@ -0,0 +1,413 @@
+/*
+ * SAMSUNG EXYNOS5250 SoC device tree source
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * SAMSUNG EXYNOS5250 SoC device nodes are listed in this file.
+ * EXYNOS5250 based board files can include this file and provide
+ * values for board specfic bindings.
+ *
+ * Note: This file does not include device nodes for all the controllers in
+ * EXYNOS5250 SoC. As device tree coverage for EXYNOS5250 increases,
+ * additional nodes can be added to this file.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/include/ "skeleton.dtsi"
+
+/ {
+       compatible = "samsung,exynos5250";
+       interrupt-parent = <&gic>;
+
+       gic:interrupt-controller@10490000 {
+               compatible = "arm,cortex-a9-gic";
+               #interrupt-cells = <3>;
+               interrupt-controller;
+               reg = <0x10490000 0x1000>, <0x10480000 0x100>;
+       };
+
+       watchdog {
+               compatible = "samsung,s3c2410-wdt";
+               reg = <0x101D0000 0x100>;
+               interrupts = <0 42 0>;
+       };
+
+       rtc {
+               compatible = "samsung,s3c6410-rtc";
+               reg = <0x101E0000 0x100>;
+               interrupts = <0 43 0>, <0 44 0>;
+       };
+
+       sdhci@12200000 {
+               compatible = "samsung,exynos4210-sdhci";
+               reg = <0x12200000 0x100>;
+               interrupts = <0 75 0>;
+       };
+
+       sdhci@12210000 {
+               compatible = "samsung,exynos4210-sdhci";
+               reg = <0x12210000 0x100>;
+               interrupts = <0 76 0>;
+       };
+
+       sdhci@12220000 {
+               compatible = "samsung,exynos4210-sdhci";
+               reg = <0x12220000 0x100>;
+               interrupts = <0 77 0>;
+       };
+
+       sdhci@12230000 {
+               compatible = "samsung,exynos4210-sdhci";
+               reg = <0x12230000 0x100>;
+               interrupts = <0 78 0>;
+       };
+
+       serial@12C00000 {
+               compatible = "samsung,exynos4210-uart";
+               reg = <0x12C00000 0x100>;
+               interrupts = <0 51 0>;
+       };
+
+       serial@12C10000 {
+               compatible = "samsung,exynos4210-uart";
+               reg = <0x12C10000 0x100>;
+               interrupts = <0 52 0>;
+       };
+
+       serial@12C20000 {
+               compatible = "samsung,exynos4210-uart";
+               reg = <0x12C20000 0x100>;
+               interrupts = <0 53 0>;
+       };
+
+       serial@12C30000 {
+               compatible = "samsung,exynos4210-uart";
+               reg = <0x12C30000 0x100>;
+               interrupts = <0 54 0>;
+       };
+
+       i2c@12C60000 {
+               compatible = "samsung,s3c2440-i2c";
+               reg = <0x12C60000 0x100>;
+               interrupts = <0 56 0>;
+       };
+
+       i2c@12C70000 {
+               compatible = "samsung,s3c2440-i2c";
+               reg = <0x12C70000 0x100>;
+               interrupts = <0 57 0>;
+       };
+
+       i2c@12C80000 {
+               compatible = "samsung,s3c2440-i2c";
+               reg = <0x12C80000 0x100>;
+               interrupts = <0 58 0>;
+       };
+
+       i2c@12C90000 {
+               compatible = "samsung,s3c2440-i2c";
+               reg = <0x12C90000 0x100>;
+               interrupts = <0 59 0>;
+       };
+
+       i2c@12CA0000 {
+               compatible = "samsung,s3c2440-i2c";
+               reg = <0x12CA0000 0x100>;
+               interrupts = <0 60 0>;
+       };
+
+       i2c@12CB0000 {
+               compatible = "samsung,s3c2440-i2c";
+               reg = <0x12CB0000 0x100>;
+               interrupts = <0 61 0>;
+       };
+
+       i2c@12CC0000 {
+               compatible = "samsung,s3c2440-i2c";
+               reg = <0x12CC0000 0x100>;
+               interrupts = <0 62 0>;
+       };
+
+       i2c@12CD0000 {
+               compatible = "samsung,s3c2440-i2c";
+               reg = <0x12CD0000 0x100>;
+               interrupts = <0 63 0>;
+       };
+
+       amba {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "arm,amba-bus";
+               interrupt-parent = <&gic>;
+               ranges;
+
+               pdma0: pdma@121A0000 {
+                       compatible = "arm,pl330", "arm,primecell";
+                       reg = <0x121A0000 0x1000>;
+                       interrupts = <0 34 0>;
+               };
+
+               pdma1: pdma@121B0000 {
+                       compatible = "arm,pl330", "arm,primecell";
+                       reg = <0x121B0000 0x1000>;
+                       interrupts = <0 35 0>;
+               };
+
+               mdma0: pdma@10800000 {
+                       compatible = "arm,pl330", "arm,primecell";
+                       reg = <0x10800000 0x1000>;
+                       interrupts = <0 33 0>;
+               };
+
+               mdma1: pdma@11C10000 {
+                       compatible = "arm,pl330", "arm,primecell";
+                       reg = <0x11C10000 0x1000>;
+                       interrupts = <0 124 0>;
+               };
+       };
+
+       gpio-controllers {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               gpio-controller;
+               ranges;
+
+               gpa0: gpio-controller@11400000 {
+                       compatible = "samsung,exynos4-gpio";
+                       reg = <0x11400000 0x20>;
+                       #gpio-cells = <4>;
+               };
+
+               gpa1: gpio-controller@11400020 {
+                       compatible = "samsung,exynos4-gpio";
+                       reg = <0x11400020 0x20>;
+                       #gpio-cells = <4>;
+               };
+
+               gpa2: gpio-controller@11400040 {
+                       compatible = "samsung,exynos4-gpio";
+                       reg = <0x11400040 0x20>;
+                       #gpio-cells = <4>;
+               };
+
+               gpb0: gpio-controller@11400060 {
+                       compatible = "samsung,exynos4-gpio";
+                       reg = <0x11400060 0x20>;
+                       #gpio-cells = <4>;
+               };
+
+               gpb1: gpio-controller@11400080 {
+                       compatible = "samsung,exynos4-gpio";
+                       reg = <0x11400080 0x20>;
+                       #gpio-cells = <4>;
+               };
+
+               gpb2: gpio-controller@114000A0 {
+                       compatible = "samsung,exynos4-gpio";
+                       reg = <0x114000A0 0x20>;
+                       #gpio-cells = <4>;
+               };
+
+               gpb3: gpio-controller@114000C0 {
+                       compatible = "samsung,exynos4-gpio";
+                       reg = <0x114000C0 0x20>;
+                       #gpio-cells = <4>;
+               };
+
+               gpc0: gpio-controller@114000E0 {
+                       compatible = "samsung,exynos4-gpio";
+                       reg = <0x114000E0 0x20>;
+                       #gpio-cells = <4>;
+               };
+
+               gpc1: gpio-controller@11400100 {
+                       compatible = "samsung,exynos4-gpio";
+                       reg = <0x11400100 0x20>;
+                       #gpio-cells = <4>;
+               };
+
+               gpc2: gpio-controller@11400120 {
+                       compatible = "samsung,exynos4-gpio";
+                       reg = <0x11400120 0x20>;
+                       #gpio-cells = <4>;
+               };
+
+               gpc3: gpio-controller@11400140 {
+                       compatible = "samsung,exynos4-gpio";
+                       reg = <0x11400140 0x20>;
+                       #gpio-cells = <4>;
+               };
+
+               gpd0: gpio-controller@11400160 {
+                       compatible = "samsung,exynos4-gpio";
+                       reg = <0x11400160 0x20>;
+                       #gpio-cells = <4>;
+               };
+
+               gpd1: gpio-controller@11400180 {
+                       compatible = "samsung,exynos4-gpio";
+                       reg = <0x11400180 0x20>;
+                       #gpio-cells = <4>;
+               };
+
+               gpy0: gpio-controller@114001A0 {
+                       compatible = "samsung,exynos4-gpio";
+                       reg = <0x114001A0 0x20>;
+                       #gpio-cells = <4>;
+               };
+
+               gpy1: gpio-controller@114001C0 {
+                       compatible = "samsung,exynos4-gpio";
+                       reg = <0x114001C0 0x20>;
+                       #gpio-cells = <4>;
+               };
+
+               gpy2: gpio-controller@114001E0 {
+                       compatible = "samsung,exynos4-gpio";
+                       reg = <0x114001E0 0x20>;
+                       #gpio-cells = <4>;
+               };
+
+               gpy3: gpio-controller@11400200 {
+                       compatible = "samsung,exynos4-gpio";
+                       reg = <0x11400200 0x20>;
+                       #gpio-cells = <4>;
+               };
+
+               gpy4: gpio-controller@11400220 {
+                       compatible = "samsung,exynos4-gpio";
+                       reg = <0x11400220 0x20>;
+                       #gpio-cells = <4>;
+               };
+
+               gpy5: gpio-controller@11400240 {
+                       compatible = "samsung,exynos4-gpio";
+                       reg = <0x11400240 0x20>;
+                       #gpio-cells = <4>;
+               };
+
+               gpy6: gpio-controller@11400260 {
+                       compatible = "samsung,exynos4-gpio";
+                       reg = <0x11400260 0x20>;
+                       #gpio-cells = <4>;
+               };
+
+               gpx0: gpio-controller@11400C00 {
+                       compatible = "samsung,exynos4-gpio";
+                       reg = <0x11400C00 0x20>;
+                       #gpio-cells = <4>;
+               };
+
+               gpx1: gpio-controller@11400C20 {
+                       compatible = "samsung,exynos4-gpio";
+                       reg = <0x11400C20 0x20>;
+                       #gpio-cells = <4>;
+               };
+
+               gpx2: gpio-controller@11400C40 {
+                       compatible = "samsung,exynos4-gpio";
+                       reg = <0x11400C40 0x20>;
+                       #gpio-cells = <4>;
+               };
+
+               gpx3: gpio-controller@11400C60 {
+                       compatible = "samsung,exynos4-gpio";
+                       reg = <0x11400C60 0x20>;
+                       #gpio-cells = <4>;
+               };
+
+               gpe0: gpio-controller@13400000 {
+                       compatible = "samsung,exynos4-gpio";
+                       reg = <0x13400000 0x20>;
+                       #gpio-cells = <4>;
+               };
+
+               gpe1: gpio-controller@13400020 {
+                       compatible = "samsung,exynos4-gpio";
+                       reg = <0x13400020 0x20>;
+                       #gpio-cells = <4>;
+               };
+
+               gpf0: gpio-controller@13400040 {
+                       compatible = "samsung,exynos4-gpio";
+                       reg = <0x13400040 0x20>;
+                       #gpio-cells = <4>;
+               };
+
+               gpf1: gpio-controller@13400060 {
+                       compatible = "samsung,exynos4-gpio";
+                       reg = <0x13400060 0x20>;
+                       #gpio-cells = <4>;
+               };
+
+               gpg0: gpio-controller@13400080 {
+                       compatible = "samsung,exynos4-gpio";
+                       reg = <0x13400080 0x20>;
+                       #gpio-cells = <4>;
+               };
+
+               gpg1: gpio-controller@134000A0 {
+                       compatible = "samsung,exynos4-gpio";
+                       reg = <0x134000A0 0x20>;
+                       #gpio-cells = <4>;
+               };
+
+               gpg2: gpio-controller@134000C0 {
+                       compatible = "samsung,exynos4-gpio";
+                       reg = <0x134000C0 0x20>;
+                       #gpio-cells = <4>;
+               };
+
+               gph0: gpio-controller@134000E0 {
+                       compatible = "samsung,exynos4-gpio";
+                       reg = <0x134000E0 0x20>;
+                       #gpio-cells = <4>;
+               };
+
+               gph1: gpio-controller@13400100 {
+                       compatible = "samsung,exynos4-gpio";
+                       reg = <0x13400100 0x20>;
+                       #gpio-cells = <4>;
+               };
+
+               gpv0: gpio-controller@10D10000 {
+                       compatible = "samsung,exynos4-gpio";
+                       reg = <0x10D10000 0x20>;
+                       #gpio-cells = <4>;
+               };
+
+               gpv1: gpio-controller@10D10020 {
+                       compatible = "samsung,exynos4-gpio";
+                       reg = <0x10D10020 0x20>;
+                       #gpio-cells = <4>;
+               };
+
+               gpv2: gpio-controller@10D10040 {
+                       compatible = "samsung,exynos4-gpio";
+                       reg = <0x10D10040 0x20>;
+                       #gpio-cells = <4>;
+               };
+
+               gpv3: gpio-controller@10D10060 {
+                       compatible = "samsung,exynos4-gpio";
+                       reg = <0x10D10060 0x20>;
+                       #gpio-cells = <4>;
+               };
+
+               gpv4: gpio-controller@10D10080 {
+                       compatible = "samsung,exynos4-gpio";
+                       reg = <0x10D10080 0x20>;
+                       #gpio-cells = <4>;
+               };
+
+               gpz: gpio-controller@03860000 {
+                       compatible = "samsung,exynos4-gpio";
+                       reg = <0x03860000 0x20>;
+                       #gpio-cells = <4>;
+               };
+       };
+};
index 8a5dff8..a5376b8 100644 (file)
@@ -4,7 +4,7 @@
 
 / {
        model = "Globalscale Technologies Dreamplug";
-       compatible = "globalscale,dreamplug-003-ds2001", "globalscale,dreamplug", "marvell,kirkwood-88f6281", "marvell,kirkwood";
+       compatible = "globalscale,dreamplug-003-ds2001", "globalscale,dreamplug", "mrvl,kirkwood-88f6281", "mrvl,kirkwood";
 
        memory {
                device_type = "memory";
                bootargs = "console=ttyS0,115200n8 earlyprintk";
        };
 
-       serial@f1012000 {
-               compatible = "ns16550a";
-               reg = <0xf1012000 0xff>;
-               reg-shift = <2>;
-               interrupts = <33>;
-               clock-frequency = <200000000>;
+       ocp@f1000000 {
+               serial@12000 {
+                       clock-frequency = <200000000>;
+                       status = "ok";
+               };
        };
 };
index 771c6bb..3474ef8 100644 (file)
@@ -1,6 +1,36 @@
 /include/ "skeleton.dtsi"
 
 / {
-       compatible = "marvell,kirkwood";
-};
+       compatible = "mrvl,kirkwood";
+
+       ocp@f1000000 {
+               compatible = "simple-bus";
+               ranges = <0 0xf1000000 0x1000000>;
+               #address-cells = <1>;
+               #size-cells = <1>;
+
+               serial@12000 {
+                       compatible = "ns16550a";
+                       reg = <0x12000 0x100>;
+                       reg-shift = <2>;
+                       interrupts = <33>;
+                       /* set clock-frequency in board dts */
+                       status = "disabled";
+               };
 
+               serial@12100 {
+                       compatible = "ns16550a";
+                       reg = <0x12100 0x100>;
+                       reg-shift = <2>;
+                       interrupts = <34>;
+                       /* set clock-frequency in board dts */
+                       status = "disabled";
+               };
+
+               rtc@10300 {
+                       compatible = "mrvl,kirkwood-rtc", "mrvl,orion-rtc";
+                       reg = <0x10300 0x20>;
+                       interrupts = <53>;
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/snowball.dts b/arch/arm/boot/dts/snowball.dts
new file mode 100644 (file)
index 0000000..359c6d6
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2011 ST-Ericsson AB
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "db8500.dtsi"
+
+/ {
+       model = "Calao Systems Snowball platform with device tree";
+       compatible = "calaosystems,snowball-a9500";
+
+       memory {
+               reg = <0x00000000 0x20000000>;
+       };
+
+       gpio_keys {
+               compatible = "gpio-keys";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               button@1 {
+                       debounce_interval = <50>;
+                       wakeup = <1>;
+                       linux,code = <2>;
+                       label = "userpb";
+                       gpios = <&gpio1 0>;
+               };
+               button@2 {
+                       debounce_interval = <50>;
+                       wakeup = <1>;
+                       linux,code = <3>;
+                       label = "userpb";
+                       gpios = <&gpio4 23>;
+               };
+               button@3 {
+                       debounce_interval = <50>;
+                       wakeup = <1>;
+                       linux,code = <4>;
+                       label = "userpb";
+                       gpios = <&gpio4 23>;
+               };
+               button@4 {
+                       debounce_interval = <50>;
+                       wakeup = <1>;
+                       linux,code = <5>;
+                       label = "userpb";
+                       gpios = <&gpio5 1>;
+               };
+               button@5 {
+                       debounce_interval = <50>;
+                       wakeup = <1>;
+                       linux,code = <6>;
+                       label = "userpb";
+                       gpios = <&gpio5 2>;
+               };
+       };
+
+       leds {
+               compatible = "gpio-leds";
+               used-led {
+                       label = "user_led";
+                       gpios = <&gpio4 14>;
+               };
+       };
+
+       soc-u9500 {
+
+               external-bus@50000000 {
+                       compatible = "simple-bus";
+                       reg = <0x50000000 0x10000000>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges;
+
+                       ethernet@50000000 {
+                               compatible = "smsc,9111";
+                               reg = <0x50000000 0x10000>;
+                               interrupts = <12>;
+                               interrupt-parent = <&gpio4>;
+                       };
+               };
+
+               sdi@80126000 {
+                       status = "enabled";
+                       cd-gpios = <&gpio6 26>;
+               };
+
+               sdi@80114000 {
+                       status = "enabled";
+               };
+
+               uart@80120000 {
+                       status = "okay";
+               };
+
+               uart@80121000 {
+                       status = "okay";
+               };
+
+               uart@80007000 {
+                       status = "okay";
+               };
+
+               i2c@80004000 {
+                       tc3589x@42 {
+                               //compatible = "tc3589x";
+                               reg = <0x42>;
+                               interrupts = <25>;
+                               interrupt-parent = <&gpio6>;
+                       };
+                       tps61052@33 {
+                               //compatible = "tps61052";
+                               reg = <0x33>;
+                       };
+               };
+
+               i2c@80128000 {
+                       lp5521@0x33 {
+                               // compatible = "lp5521";
+                               reg = <0x33>;
+                       };
+                       lp5521@0x34 {
+                               // compatible = "lp5521";
+                               reg = <0x34>;
+                       };
+                       bh1780@0x29 {
+                               // compatible = "rohm,bh1780gli";
+                               reg = <0x33>;
+                       };
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/spear600-evb.dts b/arch/arm/boot/dts/spear600-evb.dts
new file mode 100644 (file)
index 0000000..636292e
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2012 Stefan Roese <sr@denx.de>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "spear600.dtsi"
+
+/ {
+       model = "ST SPEAr600 Evaluation Board";
+       compatible = "st,spear600-evb", "st,spear600";
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       memory {
+               device_type = "memory";
+               reg = <0 0x10000000>;
+       };
+
+       ahb {
+               gmac: ethernet@e0800000 {
+                       phy-mode = "gmii";
+                       status = "okay";
+               };
+
+               apb {
+                       serial@d0000000 {
+                               status = "okay";
+                       };
+
+                       serial@d0080000 {
+                               status = "okay";
+                       };
+
+                       i2c@d0200000 {
+                               clock-frequency = <400000>;
+                               status = "okay";
+                       };
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/spear600.dtsi b/arch/arm/boot/dts/spear600.dtsi
new file mode 100644 (file)
index 0000000..ebe0885
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * Copyright 2012 Stefan Roese <sr@denx.de>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+       compatible = "st,spear600";
+
+       cpus {
+               cpu@0 {
+                       compatible = "arm,arm926ejs";
+               };
+       };
+
+       memory {
+               device_type = "memory";
+               reg = <0 0x40000000>;
+       };
+
+       ahb {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "simple-bus";
+               ranges = <0xd0000000 0xd0000000 0x30000000>;
+
+               vic0: interrupt-controller@f1100000 {
+                       compatible = "arm,pl190-vic";
+                       interrupt-controller;
+                       reg = <0xf1100000 0x1000>;
+                       #interrupt-cells = <1>;
+               };
+
+               vic1: interrupt-controller@f1000000 {
+                       compatible = "arm,pl190-vic";
+                       interrupt-controller;
+                       reg = <0xf1000000 0x1000>;
+                       #interrupt-cells = <1>;
+               };
+
+               gmac: ethernet@e0800000 {
+                       compatible = "st,spear600-gmac";
+                       reg = <0xe0800000 0x8000>;
+                       interrupt-parent = <&vic1>;
+                       interrupts = <24 23>;
+                       interrupt-names = "macirq", "eth_wake_irq";
+                       status = "disabled";
+               };
+
+               fsmc: flash@d1800000 {
+                       compatible = "st,spear600-fsmc-nand";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       reg = <0xd1800000 0x1000        /* FSMC Register */
+                              0xd2000000 0x4000>;      /* NAND Base */
+                       reg-names = "fsmc_regs", "nand_data";
+                       st,ale-off = <0x20000>;
+                       st,cle-off = <0x10000>;
+                       status = "disabled";
+               };
+
+               smi: flash@fc000000 {
+                       compatible = "st,spear600-smi";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       reg = <0xfc000000 0x1000>;
+                       interrupt-parent = <&vic1>;
+                       interrupts = <12>;
+                       status = "disabled";
+               };
+
+               ehci@e1800000 {
+                       compatible = "st,spear600-ehci", "usb-ehci";
+                       reg = <0xe1800000 0x1000>;
+                       interrupt-parent = <&vic1>;
+                       interrupts = <27>;
+                       status = "disabled";
+               };
+
+               ehci@e2000000 {
+                       compatible = "st,spear600-ehci", "usb-ehci";
+                       reg = <0xe2000000 0x1000>;
+                       interrupt-parent = <&vic1>;
+                       interrupts = <29>;
+                       status = "disabled";
+               };
+
+               ohci@e1900000 {
+                       compatible = "st,spear600-ohci", "usb-ohci";
+                       reg = <0xe1900000 0x1000>;
+                       interrupt-parent = <&vic1>;
+                       interrupts = <26>;
+                       status = "disabled";
+               };
+
+               ohci@e2100000 {
+                       compatible = "st,spear600-ohci", "usb-ohci";
+                       reg = <0xe2100000 0x1000>;
+                       interrupt-parent = <&vic1>;
+                       interrupts = <28>;
+                       status = "disabled";
+               };
+
+               apb {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       compatible = "simple-bus";
+                       ranges = <0xd0000000 0xd0000000 0x30000000>;
+
+                       serial@d0000000 {
+                               compatible = "arm,pl011", "arm,primecell";
+                               reg = <0xd0000000 0x1000>;
+                               interrupt-parent = <&vic0>;
+                               interrupts = <24>;
+                               status = "disabled";
+                       };
+
+                       serial@d0080000 {
+                               compatible = "arm,pl011", "arm,primecell";
+                               reg = <0xd0080000 0x1000>;
+                               interrupt-parent = <&vic0>;
+                               interrupts = <25>;
+                               status = "disabled";
+                       };
+
+                       /* local/cpu GPIO */
+                       gpio0: gpio@f0100000 {
+                               #gpio-cells = <2>;
+                               compatible = "arm,pl061", "arm,primecell";
+                               gpio-controller;
+                               reg = <0xf0100000 0x1000>;
+                               interrupt-parent = <&vic0>;
+                               interrupts = <18>;
+                       };
+
+                       /* basic GPIO */
+                       gpio1: gpio@fc980000 {
+                               #gpio-cells = <2>;
+                               compatible = "arm,pl061", "arm,primecell";
+                               gpio-controller;
+                               reg = <0xfc980000 0x1000>;
+                               interrupt-parent = <&vic1>;
+                               interrupts = <19>;
+                       };
+
+                       /* appl GPIO */
+                       gpio2: gpio@d8100000 {
+                               #gpio-cells = <2>;
+                               compatible = "arm,pl061", "arm,primecell";
+                               gpio-controller;
+                               reg = <0xd8100000 0x1000>;
+                               interrupt-parent = <&vic1>;
+                               interrupts = <4>;
+                       };
+
+                       i2c@d0200000 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               compatible = "snps,designware-i2c";
+                               reg = <0xd0200000 0x1000>;
+                               interrupt-parent = <&vic0>;
+                               interrupts = <28>;
+                               status = "disabled";
+                       };
+               };
+       };
+};
index 7326350..ac3fb75 100644 (file)
                clock-frequency = < 408000000 >;
        };
 
+       serial@70006040 {
+               status = "disable";
+       };
+
+       serial@70006200 {
+               status = "disable";
+       };
+
+       serial@70006300 {
+               status = "disable";
+       };
+
+       serial@70006400 {
+               status = "disable";
+       };
+
        i2c@7000c000 {
                clock-frequency = <100000>;
        };
index 876d5c9..dbf1c5a 100644 (file)
 
        usb@c5000000 {
                nvidia,vbus-gpio = <&gpio 24 0>; /* PD0 */
+               dr_mode = "otg";
        };
 
        gpio-keys {
index aff8a17..108e894 100644 (file)
                reg = <0xc5000000 0x4000>;
                interrupts = < 0 20 0x04 >;
                phy_type = "utmi";
+               nvidia,has-legacy-mode;
        };
 
        usb@c5004000 {
diff --git a/arch/arm/boot/dts/usb_a9g20-dab-mmx.dtsi b/arch/arm/boot/dts/usb_a9g20-dab-mmx.dtsi
new file mode 100644 (file)
index 0000000..ad3eca1
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * calao-dab-mmx.dtsi - Device Tree Include file for Calao DAB-MMX Daughter Board
+ *
+ * Copyright (C) 2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Licensed under GPLv2.
+ */
+
+/ {
+       ahb {
+               apb {
+                       usart1: serial@fffb4000 {
+                               status = "okay";
+                       };
+
+                       usart3: serial@fffd0000 {
+                               status = "okay";
+                       };
+               };
+       };
+
+       i2c-gpio@0 {
+               status = "okay";
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               user_led1 {
+                       label = "user_led1";
+                       gpios = <&pioB 20 1>;
+               };
+
+/*
+* led already used by mother board but active as high
+*              user_led2 {
+*                      label = "user_led2";
+*                      gpios = <&pioB 21 1>;
+*              };
+*/
+               user_led3 {
+                       label = "user_led3";
+                       gpios = <&pioB 22 1>;
+               };
+
+               user_led4 {
+                       label = "user_led4";
+                       gpios = <&pioB 23 1>;
+               };
+
+               red {
+                       label = "red";
+                       gpios = <&pioB 24 1>;
+               };
+
+               orange {
+                       label = "orange";
+                       gpios = <&pioB 30 1>;
+               };
+
+               green {
+                       label = "green";
+                       gpios = <&pioB 31 1>;
+               };
+       };
+
+       gpio_keys {
+               compatible = "gpio-keys";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               user_pb1 {
+                       label = "user_pb1";
+                       gpios = <&pioB 25 1>;
+                       linux,code = <0x100>;
+               };
+
+               user_pb2 {
+                       label = "user_pb2";
+                       gpios = <&pioB 13 1>;
+                       linux,code = <0x101>;
+               };
+
+               user_pb3 {
+                       label = "user_pb3";
+                       gpios = <&pioA 26 1>;
+                       linux,code = <0x102>;
+               };
+
+               user_pb4 {
+                       label = "user_pb4";
+                       gpios = <&pioC 9 1>;
+                       linux,code = <0x103>;
+               };
+       };
+};
index d74545a..3b3c4e0 100644 (file)
        compatible = "calao,usb-a9g20", "atmel,at91sam9g20", "atmel,at91sam9";
 
        chosen {
-               bootargs = "mem=64M console=ttyS0,115200 mtdparts=atmel_nand:128k(at91bootstrap),256k(barebox)ro,128k(bareboxenv),128k(bareboxenv2),4M(kernel),120M(rootfs),-(data) root=/dev/mtdblock5 rw rootfstype=ubifs";
+               bootargs = "mem=64M console=ttyS0,115200 root=/dev/mtdblock5 rw rootfstype=ubifs";
        };
 
        memory@20000000 {
                reg = <0x20000000 0x4000000>;
        };
 
+       clocks {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
+               main_clock: clock@0 {
+                       compatible = "atmel,osc", "fixed-clock";
+                       clock-frequency = <12000000>;
+               };
+       };
+
        ahb {
                apb {
                        dbgu: serial@fffff200 {
                                phy-mode = "rmii";
                                status = "okay";
                        };
+
+                       usb1: gadget@fffa4000 {
+                               atmel,vbus-gpio = <&pioC 5 0>;
+                               status = "okay";
+                       };
+               };
+
+               nand0: nand@40000000 {
+                       nand-bus-width = <8>;
+                       nand-ecc-mode = "soft";
+                       nand-on-flash-bbt;
+                       status = "okay";
+
+                       at91bootstrap@0 {
+                               label = "at91bootstrap";
+                               reg = <0x0 0x20000>;
+                       };
+
+                       barebox@20000 {
+                               label = "barebox";
+                               reg = <0x20000 0x40000>;
+                       };
+
+                       bareboxenv@60000 {
+                               label = "bareboxenv";
+                               reg = <0x60000 0x20000>;
+                       };
+
+                       bareboxenv2@80000 {
+                               label = "bareboxenv2";
+                               reg = <0x80000 0x20000>;
+                       };
+
+                       kernel@a0000 {
+                               label = "kernel";
+                               reg = <0xa0000 0x400000>;
+                       };
+
+                       rootfs@4a0000 {
+                               label = "rootfs";
+                               reg = <0x4a0000 0x7800000>;
+                       };
+
+                       data@7ca0000 {
+                               label = "data";
+                               reg = <0x7ca0000 0x8360000>;
+                       };
+               };
+
+               usb0: ohci@00500000 {
+                       num-ports = <2>;
+                       status = "okay";
                };
        };
 
                        gpio-key,wakeup;
                };
        };
+
+       i2c@0 {
+               status = "okay";
+
+               rv3029c2@56 {
+                       compatible = "rv3029c2";
+                       reg = <0x56>;
+               };
+       };
 };
index 67dd2af..1171a50 100644 (file)
@@ -6,7 +6,6 @@
 #include <linux/ioport.h>
 #include <linux/io.h>
 
-#include <asm/system.h>
 
 #include <asm/mach/pci.h>
 
index 9123568..994d331 100644 (file)
@@ -74,6 +74,8 @@ CONFIG_LEGACY_PTY_COUNT=16
 CONFIG_SERIAL_ATMEL=y
 CONFIG_SERIAL_ATMEL_CONSOLE=y
 CONFIG_HW_RANDOM=y
+CONFIG_I2C=y
+CONFIG_I2C_GPIO=y
 CONFIG_SPI=y
 CONFIG_SPI_ATMEL=y
 CONFIG_SPI_SPIDEV=y
@@ -105,6 +107,7 @@ CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_TIMER=y
 CONFIG_LEDS_TRIGGER_HEARTBEAT=y
 CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_RV3029C2=y
 CONFIG_RTC_DRV_AT91SAM9=y
 CONFIG_EXT2_FS=y
 CONFIG_MSDOS_FS=y
index 2d7b6e7..889d73a 100644 (file)
@@ -13,6 +13,7 @@ CONFIG_UX500_SOC_DB8500=y
 CONFIG_MACH_HREFV60=y
 CONFIG_MACH_SNOWBALL=y
 CONFIG_MACH_U5500=y
+CONFIG_MACH_UX500_DT=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_SMP=y
index 86976d0..68374ba 100644 (file)
@@ -13,7 +13,9 @@
 
 #include <linux/compiler.h>
 #include <linux/types.h>
-#include <asm/system.h>
+#include <linux/irqflags.h>
+#include <asm/barrier.h>
+#include <asm/cmpxchg.h>
 
 #define ATOMIC_INIT(i) { (i) }
 
diff --git a/arch/arm/include/asm/barrier.h b/arch/arm/include/asm/barrier.h
new file mode 100644 (file)
index 0000000..44f4a09
--- /dev/null
@@ -0,0 +1,69 @@
+#ifndef __ASM_BARRIER_H
+#define __ASM_BARRIER_H
+
+#ifndef __ASSEMBLY__
+
+#define nop() __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t");
+
+#if __LINUX_ARM_ARCH__ >= 7 ||         \
+       (__LINUX_ARM_ARCH__ == 6 && defined(CONFIG_CPU_32v6K))
+#define sev()  __asm__ __volatile__ ("sev" : : : "memory")
+#define wfe()  __asm__ __volatile__ ("wfe" : : : "memory")
+#define wfi()  __asm__ __volatile__ ("wfi" : : : "memory")
+#endif
+
+#if __LINUX_ARM_ARCH__ >= 7
+#define isb() __asm__ __volatile__ ("isb" : : : "memory")
+#define dsb() __asm__ __volatile__ ("dsb" : : : "memory")
+#define dmb() __asm__ __volatile__ ("dmb" : : : "memory")
+#elif defined(CONFIG_CPU_XSC3) || __LINUX_ARM_ARCH__ == 6
+#define isb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c5, 4" \
+                                   : : "r" (0) : "memory")
+#define dsb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" \
+                                   : : "r" (0) : "memory")
+#define dmb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" \
+                                   : : "r" (0) : "memory")
+#elif defined(CONFIG_CPU_FA526)
+#define isb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c5, 4" \
+                                   : : "r" (0) : "memory")
+#define dsb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" \
+                                   : : "r" (0) : "memory")
+#define dmb() __asm__ __volatile__ ("" : : : "memory")
+#else
+#define isb() __asm__ __volatile__ ("" : : : "memory")
+#define dsb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" \
+                                   : : "r" (0) : "memory")
+#define dmb() __asm__ __volatile__ ("" : : : "memory")
+#endif
+
+#ifdef CONFIG_ARCH_HAS_BARRIERS
+#include <mach/barriers.h>
+#elif defined(CONFIG_ARM_DMA_MEM_BUFFERABLE) || defined(CONFIG_SMP)
+#include <asm/outercache.h>
+#define mb()           do { dsb(); outer_sync(); } while (0)
+#define rmb()          dsb()
+#define wmb()          mb()
+#else
+#include <asm/memory.h>
+#define mb()   do { if (arch_is_coherent()) dmb(); else barrier(); } while (0)
+#define rmb()  do { if (arch_is_coherent()) dmb(); else barrier(); } while (0)
+#define wmb()  do { if (arch_is_coherent()) dmb(); else barrier(); } while (0)
+#endif
+
+#ifndef CONFIG_SMP
+#define smp_mb()       barrier()
+#define smp_rmb()      barrier()
+#define smp_wmb()      barrier()
+#else
+#define smp_mb()       dmb()
+#define smp_rmb()      dmb()
+#define smp_wmb()      dmb()
+#endif
+
+#define read_barrier_depends()         do { } while(0)
+#define smp_read_barrier_depends()     do { } while(0)
+
+#define set_mb(var, value)     do { var = value; smp_mb(); } while (0)
+
+#endif /* !__ASSEMBLY__ */
+#endif /* __ASM_BARRIER_H */
index f7419ef..e691ec9 100644 (file)
@@ -24,7 +24,7 @@
 #endif
 
 #include <linux/compiler.h>
-#include <asm/system.h>
+#include <linux/irqflags.h>
 
 #define smp_mb__before_clear_bit()     smp_mb()
 #define smp_mb__after_clear_bit()      smp_mb()
index fac79dc..7af5c6c 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef _ASMARM_BUG_H
 #define _ASMARM_BUG_H
 
+#include <linux/linkage.h>
 
 #ifdef CONFIG_BUG
 
@@ -57,4 +58,33 @@ do {                                                         \
 
 #include <asm-generic/bug.h>
 
+struct pt_regs;
+void die(const char *msg, struct pt_regs *regs, int err);
+
+struct siginfo;
+void arm_notify_die(const char *str, struct pt_regs *regs, struct siginfo *info,
+               unsigned long err, unsigned long trap);
+
+#ifdef CONFIG_ARM_LPAE
+#define FAULT_CODE_ALIGNMENT   33
+#define FAULT_CODE_DEBUG       34
+#else
+#define FAULT_CODE_ALIGNMENT   1
+#define FAULT_CODE_DEBUG       2
+#endif
+
+void hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int,
+                                      struct pt_regs *),
+                    int sig, int code, const char *name);
+
+void hook_ifault_code(int nr, int (*fn)(unsigned long, unsigned int,
+                                      struct pt_regs *),
+                    int sig, int code, const char *name);
+
+extern asmlinkage void c_backtrace(unsigned long fp, int pmode);
+
+struct mm_struct;
+extern void show_pte(struct mm_struct *mm, unsigned long addr);
+extern void __show_regs(struct pt_regs *);
+
 #endif
diff --git a/arch/arm/include/asm/cmpxchg.h b/arch/arm/include/asm/cmpxchg.h
new file mode 100644 (file)
index 0000000..d41d7cb
--- /dev/null
@@ -0,0 +1,295 @@
+#ifndef __ASM_ARM_CMPXCHG_H
+#define __ASM_ARM_CMPXCHG_H
+
+#include <linux/irqflags.h>
+#include <asm/barrier.h>
+
+#if defined(CONFIG_CPU_SA1100) || defined(CONFIG_CPU_SA110)
+/*
+ * On the StrongARM, "swp" is terminally broken since it bypasses the
+ * cache totally.  This means that the cache becomes inconsistent, and,
+ * since we use normal loads/stores as well, this is really bad.
+ * Typically, this causes oopsen in filp_close, but could have other,
+ * more disastrous effects.  There are two work-arounds:
+ *  1. Disable interrupts and emulate the atomic swap
+ *  2. Clean the cache, perform atomic swap, flush the cache
+ *
+ * We choose (1) since its the "easiest" to achieve here and is not
+ * dependent on the processor type.
+ *
+ * NOTE that this solution won't work on an SMP system, so explcitly
+ * forbid it here.
+ */
+#define swp_is_buggy
+#endif
+
+static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
+{
+       extern void __bad_xchg(volatile void *, int);
+       unsigned long ret;
+#ifdef swp_is_buggy
+       unsigned long flags;
+#endif
+#if __LINUX_ARM_ARCH__ >= 6
+       unsigned int tmp;
+#endif
+
+       smp_mb();
+
+       switch (size) {
+#if __LINUX_ARM_ARCH__ >= 6
+       case 1:
+               asm volatile("@ __xchg1\n"
+               "1:     ldrexb  %0, [%3]\n"
+               "       strexb  %1, %2, [%3]\n"
+               "       teq     %1, #0\n"
+               "       bne     1b"
+                       : "=&r" (ret), "=&r" (tmp)
+                       : "r" (x), "r" (ptr)
+                       : "memory", "cc");
+               break;
+       case 4:
+               asm volatile("@ __xchg4\n"
+               "1:     ldrex   %0, [%3]\n"
+               "       strex   %1, %2, [%3]\n"
+               "       teq     %1, #0\n"
+               "       bne     1b"
+                       : "=&r" (ret), "=&r" (tmp)
+                       : "r" (x), "r" (ptr)
+                       : "memory", "cc");
+               break;
+#elif defined(swp_is_buggy)
+#ifdef CONFIG_SMP
+#error SMP is not supported on this platform
+#endif
+       case 1:
+               raw_local_irq_save(flags);
+               ret = *(volatile unsigned char *)ptr;
+               *(volatile unsigned char *)ptr = x;
+               raw_local_irq_restore(flags);
+               break;
+
+       case 4:
+               raw_local_irq_save(flags);
+               ret = *(volatile unsigned long *)ptr;
+               *(volatile unsigned long *)ptr = x;
+               raw_local_irq_restore(flags);
+               break;
+#else
+       case 1:
+               asm volatile("@ __xchg1\n"
+               "       swpb    %0, %1, [%2]"
+                       : "=&r" (ret)
+                       : "r" (x), "r" (ptr)
+                       : "memory", "cc");
+               break;
+       case 4:
+               asm volatile("@ __xchg4\n"
+               "       swp     %0, %1, [%2]"
+                       : "=&r" (ret)
+                       : "r" (x), "r" (ptr)
+                       : "memory", "cc");
+               break;
+#endif
+       default:
+               __bad_xchg(ptr, size), ret = 0;
+               break;
+       }
+       smp_mb();
+
+       return ret;
+}
+
+#define xchg(ptr,x) \
+       ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
+
+#include <asm-generic/cmpxchg-local.h>
+
+#if __LINUX_ARM_ARCH__ < 6
+/* min ARCH < ARMv6 */
+
+#ifdef CONFIG_SMP
+#error "SMP is not supported on this platform"
+#endif
+
+/*
+ * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
+ * them available.
+ */
+#define cmpxchg_local(ptr, o, n)                                              \
+       ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
+                       (unsigned long)(n), sizeof(*(ptr))))
+#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
+
+#ifndef CONFIG_SMP
+#include <asm-generic/cmpxchg.h>
+#endif
+
+#else  /* min ARCH >= ARMv6 */
+
+extern void __bad_cmpxchg(volatile void *ptr, int size);
+
+/*
+ * cmpxchg only support 32-bits operands on ARMv6.
+ */
+
+static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
+                                     unsigned long new, int size)
+{
+       unsigned long oldval, res;
+
+       switch (size) {
+#ifndef CONFIG_CPU_V6  /* min ARCH >= ARMv6K */
+       case 1:
+               do {
+                       asm volatile("@ __cmpxchg1\n"
+                       "       ldrexb  %1, [%2]\n"
+                       "       mov     %0, #0\n"
+                       "       teq     %1, %3\n"
+                       "       strexbeq %0, %4, [%2]\n"
+                               : "=&r" (res), "=&r" (oldval)
+                               : "r" (ptr), "Ir" (old), "r" (new)
+                               : "memory", "cc");
+               } while (res);
+               break;
+       case 2:
+               do {
+                       asm volatile("@ __cmpxchg1\n"
+                       "       ldrexh  %1, [%2]\n"
+                       "       mov     %0, #0\n"
+                       "       teq     %1, %3\n"
+                       "       strexheq %0, %4, [%2]\n"
+                               : "=&r" (res), "=&r" (oldval)
+                               : "r" (ptr), "Ir" (old), "r" (new)
+                               : "memory", "cc");
+               } while (res);
+               break;
+#endif
+       case 4:
+               do {
+                       asm volatile("@ __cmpxchg4\n"
+                       "       ldrex   %1, [%2]\n"
+                       "       mov     %0, #0\n"
+                       "       teq     %1, %3\n"
+                       "       strexeq %0, %4, [%2]\n"
+                               : "=&r" (res), "=&r" (oldval)
+                               : "r" (ptr), "Ir" (old), "r" (new)
+                               : "memory", "cc");
+               } while (res);
+               break;
+       default:
+               __bad_cmpxchg(ptr, size);
+               oldval = 0;
+       }
+
+       return oldval;
+}
+
+static inline unsigned long __cmpxchg_mb(volatile void *ptr, unsigned long old,
+                                        unsigned long new, int size)
+{
+       unsigned long ret;
+
+       smp_mb();
+       ret = __cmpxchg(ptr, old, new, size);
+       smp_mb();
+
+       return ret;
+}
+
+#define cmpxchg(ptr,o,n)                                               \
+       ((__typeof__(*(ptr)))__cmpxchg_mb((ptr),                        \
+                                         (unsigned long)(o),           \
+                                         (unsigned long)(n),           \
+                                         sizeof(*(ptr))))
+
+static inline unsigned long __cmpxchg_local(volatile void *ptr,
+                                           unsigned long old,
+                                           unsigned long new, int size)
+{
+       unsigned long ret;
+
+       switch (size) {
+#ifdef CONFIG_CPU_V6   /* min ARCH == ARMv6 */
+       case 1:
+       case 2:
+               ret = __cmpxchg_local_generic(ptr, old, new, size);
+               break;
+#endif
+       default:
+               ret = __cmpxchg(ptr, old, new, size);
+       }
+
+       return ret;
+}
+
+#define cmpxchg_local(ptr,o,n)                                         \
+       ((__typeof__(*(ptr)))__cmpxchg_local((ptr),                     \
+                                      (unsigned long)(o),              \
+                                      (unsigned long)(n),              \
+                                      sizeof(*(ptr))))
+
+#ifndef CONFIG_CPU_V6  /* min ARCH >= ARMv6K */
+
+/*
+ * Note : ARMv7-M (currently unsupported by Linux) does not support
+ * ldrexd/strexd. If ARMv7-M is ever supported by the Linux kernel, it should
+ * not be allowed to use __cmpxchg64.
+ */
+static inline unsigned long long __cmpxchg64(volatile void *ptr,
+                                            unsigned long long old,
+                                            unsigned long long new)
+{
+       register unsigned long long oldval asm("r0");
+       register unsigned long long __old asm("r2") = old;
+       register unsigned long long __new asm("r4") = new;
+       unsigned long res;
+
+       do {
+               asm volatile(
+               "       @ __cmpxchg8\n"
+               "       ldrexd  %1, %H1, [%2]\n"
+               "       mov     %0, #0\n"
+               "       teq     %1, %3\n"
+               "       teqeq   %H1, %H3\n"
+               "       strexdeq %0, %4, %H4, [%2]\n"
+                       : "=&r" (res), "=&r" (oldval)
+                       : "r" (ptr), "Ir" (__old), "r" (__new)
+                       : "memory", "cc");
+       } while (res);
+
+       return oldval;
+}
+
+static inline unsigned long long __cmpxchg64_mb(volatile void *ptr,
+                                               unsigned long long old,
+                                               unsigned long long new)
+{
+       unsigned long long ret;
+
+       smp_mb();
+       ret = __cmpxchg64(ptr, old, new);
+       smp_mb();
+
+       return ret;
+}
+
+#define cmpxchg64(ptr,o,n)                                             \
+       ((__typeof__(*(ptr)))__cmpxchg64_mb((ptr),                      \
+                                           (unsigned long long)(o),    \
+                                           (unsigned long long)(n)))
+
+#define cmpxchg64_local(ptr,o,n)                                       \
+       ((__typeof__(*(ptr)))__cmpxchg64((ptr),                         \
+                                        (unsigned long long)(o),       \
+                                        (unsigned long long)(n)))
+
+#else /* min ARCH = ARMv6 */
+
+#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
+
+#endif
+
+#endif /* __LINUX_ARM_ARCH__ >= 6 */
+
+#endif /* __ASM_ARM_CMPXCHG_H */
diff --git a/arch/arm/include/asm/compiler.h b/arch/arm/include/asm/compiler.h
new file mode 100644 (file)
index 0000000..8155db2
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef __ASM_ARM_COMPILER_H
+#define __ASM_ARM_COMPILER_H
+
+/*
+ * This is used to ensure the compiler did actually allocate the register we
+ * asked it for some inline assembly sequences.  Apparently we can't trust
+ * the compiler from one version to another so a bit of paranoia won't hurt.
+ * This string is meant to be concatenated with the inline asm string and
+ * will cause compilation to stop on mismatch.
+ * (for details, see gcc PR 15089)
+ */
+#define __asmeq(x, y)  ".ifnc " x "," y " ; .err ; .endif\n\t"
+
+
+#endif /* __ASM_ARM_COMPILER_H */
diff --git a/arch/arm/include/asm/cp15.h b/arch/arm/include/asm/cp15.h
new file mode 100644 (file)
index 0000000..5ef4d80
--- /dev/null
@@ -0,0 +1,87 @@
+#ifndef __ASM_ARM_CP15_H
+#define __ASM_ARM_CP15_H
+
+#include <asm/barrier.h>
+
+/*
+ * CR1 bits (CP#15 CR1)
+ */
+#define CR_M   (1 << 0)        /* MMU enable                           */
+#define CR_A   (1 << 1)        /* Alignment abort enable               */
+#define CR_C   (1 << 2)        /* Dcache enable                        */
+#define CR_W   (1 << 3)        /* Write buffer enable                  */
+#define CR_P   (1 << 4)        /* 32-bit exception handler             */
+#define CR_D   (1 << 5)        /* 32-bit data address range            */
+#define CR_L   (1 << 6)        /* Implementation defined               */
+#define CR_B   (1 << 7)        /* Big endian                           */
+#define CR_S   (1 << 8)        /* System MMU protection                */
+#define CR_R   (1 << 9)        /* ROM MMU protection                   */
+#define CR_F   (1 << 10)       /* Implementation defined               */
+#define CR_Z   (1 << 11)       /* Implementation defined               */
+#define CR_I   (1 << 12)       /* Icache enable                        */
+#define CR_V   (1 << 13)       /* Vectors relocated to 0xffff0000      */
+#define CR_RR  (1 << 14)       /* Round Robin cache replacement        */
+#define CR_L4  (1 << 15)       /* LDR pc can set T bit                 */
+#define CR_DT  (1 << 16)
+#define CR_IT  (1 << 18)
+#define CR_ST  (1 << 19)
+#define CR_FI  (1 << 21)       /* Fast interrupt (lower latency mode)  */
+#define CR_U   (1 << 22)       /* Unaligned access operation           */
+#define CR_XP  (1 << 23)       /* Extended page tables                 */
+#define CR_VE  (1 << 24)       /* Vectored interrupts                  */
+#define CR_EE  (1 << 25)       /* Exception (Big) Endian               */
+#define CR_TRE (1 << 28)       /* TEX remap enable                     */
+#define CR_AFE (1 << 29)       /* Access flag enable                   */
+#define CR_TE  (1 << 30)       /* Thumb exception enable               */
+
+#ifndef __ASSEMBLY__
+
+#if __LINUX_ARM_ARCH__ >= 4
+#define vectors_high() (cr_alignment & CR_V)
+#else
+#define vectors_high() (0)
+#endif
+
+extern unsigned long cr_no_alignment;  /* defined in entry-armv.S */
+extern unsigned long cr_alignment;     /* defined in entry-armv.S */
+
+static inline unsigned int get_cr(void)
+{
+       unsigned int val;
+       asm("mrc p15, 0, %0, c1, c0, 0  @ get CR" : "=r" (val) : : "cc");
+       return val;
+}
+
+static inline void set_cr(unsigned int val)
+{
+       asm volatile("mcr p15, 0, %0, c1, c0, 0 @ set CR"
+         : : "r" (val) : "cc");
+       isb();
+}
+
+#ifndef CONFIG_SMP
+extern void adjust_cr(unsigned long mask, unsigned long set);
+#endif
+
+#define CPACC_FULL(n)          (3 << (n * 2))
+#define CPACC_SVC(n)           (1 << (n * 2))
+#define CPACC_DISABLE(n)       (0 << (n * 2))
+
+static inline unsigned int get_copro_access(void)
+{
+       unsigned int val;
+       asm("mrc p15, 0, %0, c1, c0, 2 @ get copro access"
+         : "=r" (val) : : "cc");
+       return val;
+}
+
+static inline void set_copro_access(unsigned int val)
+{
+       asm volatile("mcr p15, 0, %0, c1, c0, 2 @ set copro access"
+         : : "r" (val) : "cc");
+       isb();
+}
+
+#endif
+
+#endif
index d3f0a9e..fe92ccf 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef __ASM_ARM_DIV64
 #define __ASM_ARM_DIV64
 
-#include <asm/system.h>
 #include <linux/types.h>
+#include <asm/compiler.h>
 
 /*
  * The semantics of do_div() are:
index 69a5b0b..5694a0d 100644 (file)
@@ -19,7 +19,6 @@
  * It should not be re-used except for that purpose.
  */
 #include <linux/spinlock.h>
-#include <asm/system.h>
 #include <asm/scatterlist.h>
 
 #include <mach/isa-dma.h>
index b5dc173..3d22204 100644 (file)
 #ifndef __ASM_PROC_DOMAIN_H
 #define __ASM_PROC_DOMAIN_H
 
+#ifndef __ASSEMBLY__
+#include <asm/barrier.h>
+#endif
+
 /*
  * Domain numbers
  *
diff --git a/arch/arm/include/asm/exec.h b/arch/arm/include/asm/exec.h
new file mode 100644 (file)
index 0000000..7c4fbef
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __ASM_ARM_EXEC_H
+#define __ASM_ARM_EXEC_H
+
+#define arch_align_stack(x) (x)
+
+#endif /* __ASM_ARM_EXEC_H */
index 077c323..2ff2c75 100644 (file)
@@ -231,6 +231,9 @@ extern int iop3xx_get_init_atu(void);
 
 
 #ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+
 void iop3xx_map_io(void);
 void iop_init_cp6_handler(void);
 void iop_init_time(unsigned long tickrate);
index 9275828..bae7eb6 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/types.h>
 #include <asm/byteorder.h>
 #include <asm/memory.h>
-#include <asm/system.h>
 #include <asm-generic/pci_iomap.h>
 
 /*
@@ -99,6 +98,7 @@ static inline void __iomem *__typesafe_io(unsigned long addr)
 
 /* IO barriers */
 #ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE
+#include <asm/barrier.h>
 #define __iormb()              rmb()
 #define __iowmb()              wmb()
 #else
index 1496565..b8e580a 100644 (file)
@@ -34,4 +34,11 @@ typedef struct {
 
 #endif
 
+/*
+ * switch_mm() may do a full cache flush over the context switch,
+ * so enable interrupts over the context switch to avoid high
+ * latency.
+ */
+#define __ARCH_WANT_INTERRUPTS_ON_CTXSW
+
 #endif
index cb8d638..f4d7f56 100644 (file)
@@ -22,7 +22,6 @@
 #include <asm/hw_breakpoint.h>
 #include <asm/ptrace.h>
 #include <asm/types.h>
-#include <asm/system.h>
 
 #ifdef __KERNEL__
 #define STACK_TOP      ((current->personality & ADDR_LIMIT_32BIT) ? \
@@ -90,6 +89,8 @@ unsigned long get_wchan(struct task_struct *p);
 #define cpu_relax()                    barrier()
 #endif
 
+void cpu_idle_wait(void);
+
 /*
  * Create a new kernel thread
  */
diff --git a/arch/arm/include/asm/switch_to.h b/arch/arm/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..fa09e6b
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef __ASM_ARM_SWITCH_TO_H
+#define __ASM_ARM_SWITCH_TO_H
+
+#include <linux/thread_info.h>
+
+/*
+ * switch_to(prev, next) should switch from task `prev' to `next'
+ * `prev' will never be the same as `next'.  schedule() itself
+ * contains the memory barrier to tell GCC not to cache `current'.
+ */
+extern struct task_struct *__switch_to(struct task_struct *, struct thread_info *, struct thread_info *);
+
+#define switch_to(prev,next,last)                                      \
+do {                                                                   \
+       last = __switch_to(prev,task_thread_info(prev), task_thread_info(next));        \
+} while (0)
+
+#endif /* __ASM_ARM_SWITCH_TO_H */
index 424aa45..74542c5 100644 (file)
@@ -1,544 +1,8 @@
-#ifndef __ASM_ARM_SYSTEM_H
-#define __ASM_ARM_SYSTEM_H
-
-#ifdef __KERNEL__
-
-#define CPU_ARCH_UNKNOWN       0
-#define CPU_ARCH_ARMv3         1
-#define CPU_ARCH_ARMv4         2
-#define CPU_ARCH_ARMv4T                3
-#define CPU_ARCH_ARMv5         4
-#define CPU_ARCH_ARMv5T                5
-#define CPU_ARCH_ARMv5TE       6
-#define CPU_ARCH_ARMv5TEJ      7
-#define CPU_ARCH_ARMv6         8
-#define CPU_ARCH_ARMv7         9
-
-/*
- * CR1 bits (CP#15 CR1)
- */
-#define CR_M   (1 << 0)        /* MMU enable                           */
-#define CR_A   (1 << 1)        /* Alignment abort enable               */
-#define CR_C   (1 << 2)        /* Dcache enable                        */
-#define CR_W   (1 << 3)        /* Write buffer enable                  */
-#define CR_P   (1 << 4)        /* 32-bit exception handler             */
-#define CR_D   (1 << 5)        /* 32-bit data address range            */
-#define CR_L   (1 << 6)        /* Implementation defined               */
-#define CR_B   (1 << 7)        /* Big endian                           */
-#define CR_S   (1 << 8)        /* System MMU protection                */
-#define CR_R   (1 << 9)        /* ROM MMU protection                   */
-#define CR_F   (1 << 10)       /* Implementation defined               */
-#define CR_Z   (1 << 11)       /* Implementation defined               */
-#define CR_I   (1 << 12)       /* Icache enable                        */
-#define CR_V   (1 << 13)       /* Vectors relocated to 0xffff0000      */
-#define CR_RR  (1 << 14)       /* Round Robin cache replacement        */
-#define CR_L4  (1 << 15)       /* LDR pc can set T bit                 */
-#define CR_DT  (1 << 16)
-#define CR_IT  (1 << 18)
-#define CR_ST  (1 << 19)
-#define CR_FI  (1 << 21)       /* Fast interrupt (lower latency mode)  */
-#define CR_U   (1 << 22)       /* Unaligned access operation           */
-#define CR_XP  (1 << 23)       /* Extended page tables                 */
-#define CR_VE  (1 << 24)       /* Vectored interrupts                  */
-#define CR_EE  (1 << 25)       /* Exception (Big) Endian               */
-#define CR_TRE (1 << 28)       /* TEX remap enable                     */
-#define CR_AFE (1 << 29)       /* Access flag enable                   */
-#define CR_TE  (1 << 30)       /* Thumb exception enable               */
-
-/*
- * This is used to ensure the compiler did actually allocate the register we
- * asked it for some inline assembly sequences.  Apparently we can't trust
- * the compiler from one version to another so a bit of paranoia won't hurt.
- * This string is meant to be concatenated with the inline asm string and
- * will cause compilation to stop on mismatch.
- * (for details, see gcc PR 15089)
- */
-#define __asmeq(x, y)  ".ifnc " x "," y " ; .err ; .endif\n\t"
-
-#ifndef __ASSEMBLY__
-
-#include <linux/compiler.h>
-#include <linux/linkage.h>
-#include <linux/irqflags.h>
-
-#include <asm/outercache.h>
-
-struct thread_info;
-struct task_struct;
-
-/* information about the system we're running on */
-extern unsigned int system_rev;
-extern unsigned int system_serial_low;
-extern unsigned int system_serial_high;
-extern unsigned int mem_fclk_21285;
-
-struct pt_regs;
-
-void die(const char *msg, struct pt_regs *regs, int err);
-
-struct siginfo;
-void arm_notify_die(const char *str, struct pt_regs *regs, struct siginfo *info,
-               unsigned long err, unsigned long trap);
-
-#ifdef CONFIG_ARM_LPAE
-#define FAULT_CODE_ALIGNMENT   33
-#define FAULT_CODE_DEBUG       34
-#else
-#define FAULT_CODE_ALIGNMENT   1
-#define FAULT_CODE_DEBUG       2
-#endif
-
-void hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int,
-                                      struct pt_regs *),
-                    int sig, int code, const char *name);
-
-void hook_ifault_code(int nr, int (*fn)(unsigned long, unsigned int,
-                                      struct pt_regs *),
-                    int sig, int code, const char *name);
-
-#define xchg(ptr,x) \
-       ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
-
-extern asmlinkage void c_backtrace(unsigned long fp, int pmode);
-
-struct mm_struct;
-extern void show_pte(struct mm_struct *mm, unsigned long addr);
-extern void __show_regs(struct pt_regs *);
-
-extern int __pure cpu_architecture(void);
-extern void cpu_init(void);
-
-void soft_restart(unsigned long);
-extern void (*arm_pm_restart)(char str, const char *cmd);
-extern void (*arm_pm_idle)(void);
-
-#define UDBG_UNDEFINED (1 << 0)
-#define UDBG_SYSCALL   (1 << 1)
-#define UDBG_BADABORT  (1 << 2)
-#define UDBG_SEGV      (1 << 3)
-#define UDBG_BUS       (1 << 4)
-
-extern unsigned int user_debug;
-
-#if __LINUX_ARM_ARCH__ >= 4
-#define vectors_high() (cr_alignment & CR_V)
-#else
-#define vectors_high() (0)
-#endif
-
-#if __LINUX_ARM_ARCH__ >= 7 ||         \
-       (__LINUX_ARM_ARCH__ == 6 && defined(CONFIG_CPU_32v6K))
-#define sev()  __asm__ __volatile__ ("sev" : : : "memory")
-#define wfe()  __asm__ __volatile__ ("wfe" : : : "memory")
-#define wfi()  __asm__ __volatile__ ("wfi" : : : "memory")
-#endif
-
-#if __LINUX_ARM_ARCH__ >= 7
-#define isb() __asm__ __volatile__ ("isb" : : : "memory")
-#define dsb() __asm__ __volatile__ ("dsb" : : : "memory")
-#define dmb() __asm__ __volatile__ ("dmb" : : : "memory")
-#elif defined(CONFIG_CPU_XSC3) || __LINUX_ARM_ARCH__ == 6
-#define isb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c5, 4" \
-                                   : : "r" (0) : "memory")
-#define dsb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" \
-                                   : : "r" (0) : "memory")
-#define dmb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" \
-                                   : : "r" (0) : "memory")
-#elif defined(CONFIG_CPU_FA526)
-#define isb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c5, 4" \
-                                   : : "r" (0) : "memory")
-#define dsb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" \
-                                   : : "r" (0) : "memory")
-#define dmb() __asm__ __volatile__ ("" : : : "memory")
-#else
-#define isb() __asm__ __volatile__ ("" : : : "memory")
-#define dsb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" \
-                                   : : "r" (0) : "memory")
-#define dmb() __asm__ __volatile__ ("" : : : "memory")
-#endif
-
-#ifdef CONFIG_ARCH_HAS_BARRIERS
-#include <mach/barriers.h>
-#elif defined(CONFIG_ARM_DMA_MEM_BUFFERABLE) || defined(CONFIG_SMP)
-#define mb()           do { dsb(); outer_sync(); } while (0)
-#define rmb()          dsb()
-#define wmb()          mb()
-#else
-#include <asm/memory.h>
-#define mb()   do { if (arch_is_coherent()) dmb(); else barrier(); } while (0)
-#define rmb()  do { if (arch_is_coherent()) dmb(); else barrier(); } while (0)
-#define wmb()  do { if (arch_is_coherent()) dmb(); else barrier(); } while (0)
-#endif
-
-#ifndef CONFIG_SMP
-#define smp_mb()       barrier()
-#define smp_rmb()      barrier()
-#define smp_wmb()      barrier()
-#else
-#define smp_mb()       dmb()
-#define smp_rmb()      dmb()
-#define smp_wmb()      dmb()
-#endif
-
-#define read_barrier_depends()         do { } while(0)
-#define smp_read_barrier_depends()     do { } while(0)
-
-#define set_mb(var, value)     do { var = value; smp_mb(); } while (0)
-#define nop() __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t");
-
-extern unsigned long cr_no_alignment;  /* defined in entry-armv.S */
-extern unsigned long cr_alignment;     /* defined in entry-armv.S */
-
-static inline unsigned int get_cr(void)
-{
-       unsigned int val;
-       asm("mrc p15, 0, %0, c1, c0, 0  @ get CR" : "=r" (val) : : "cc");
-       return val;
-}
-
-static inline void set_cr(unsigned int val)
-{
-       asm volatile("mcr p15, 0, %0, c1, c0, 0 @ set CR"
-         : : "r" (val) : "cc");
-       isb();
-}
-
-#ifndef CONFIG_SMP
-extern void adjust_cr(unsigned long mask, unsigned long set);
-#endif
-
-#define CPACC_FULL(n)          (3 << (n * 2))
-#define CPACC_SVC(n)           (1 << (n * 2))
-#define CPACC_DISABLE(n)       (0 << (n * 2))
-
-static inline unsigned int get_copro_access(void)
-{
-       unsigned int val;
-       asm("mrc p15, 0, %0, c1, c0, 2 @ get copro access"
-         : "=r" (val) : : "cc");
-       return val;
-}
-
-static inline void set_copro_access(unsigned int val)
-{
-       asm volatile("mcr p15, 0, %0, c1, c0, 2 @ set copro access"
-         : : "r" (val) : "cc");
-       isb();
-}
-
-/*
- * switch_mm() may do a full cache flush over the context switch,
- * so enable interrupts over the context switch to avoid high
- * latency.
- */
-#define __ARCH_WANT_INTERRUPTS_ON_CTXSW
-
-/*
- * switch_to(prev, next) should switch from task `prev' to `next'
- * `prev' will never be the same as `next'.  schedule() itself
- * contains the memory barrier to tell GCC not to cache `current'.
- */
-extern struct task_struct *__switch_to(struct task_struct *, struct thread_info *, struct thread_info *);
-
-#define switch_to(prev,next,last)                                      \
-do {                                                                   \
-       last = __switch_to(prev,task_thread_info(prev), task_thread_info(next));        \
-} while (0)
-
-#if defined(CONFIG_CPU_SA1100) || defined(CONFIG_CPU_SA110)
-/*
- * On the StrongARM, "swp" is terminally broken since it bypasses the
- * cache totally.  This means that the cache becomes inconsistent, and,
- * since we use normal loads/stores as well, this is really bad.
- * Typically, this causes oopsen in filp_close, but could have other,
- * more disastrous effects.  There are two work-arounds:
- *  1. Disable interrupts and emulate the atomic swap
- *  2. Clean the cache, perform atomic swap, flush the cache
- *
- * We choose (1) since its the "easiest" to achieve here and is not
- * dependent on the processor type.
- *
- * NOTE that this solution won't work on an SMP system, so explcitly
- * forbid it here.
- */
-#define swp_is_buggy
-#endif
-
-static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
-{
-       extern void __bad_xchg(volatile void *, int);
-       unsigned long ret;
-#ifdef swp_is_buggy
-       unsigned long flags;
-#endif
-#if __LINUX_ARM_ARCH__ >= 6
-       unsigned int tmp;
-#endif
-
-       smp_mb();
-
-       switch (size) {
-#if __LINUX_ARM_ARCH__ >= 6
-       case 1:
-               asm volatile("@ __xchg1\n"
-               "1:     ldrexb  %0, [%3]\n"
-               "       strexb  %1, %2, [%3]\n"
-               "       teq     %1, #0\n"
-               "       bne     1b"
-                       : "=&r" (ret), "=&r" (tmp)
-                       : "r" (x), "r" (ptr)
-                       : "memory", "cc");
-               break;
-       case 4:
-               asm volatile("@ __xchg4\n"
-               "1:     ldrex   %0, [%3]\n"
-               "       strex   %1, %2, [%3]\n"
-               "       teq     %1, #0\n"
-               "       bne     1b"
-                       : "=&r" (ret), "=&r" (tmp)
-                       : "r" (x), "r" (ptr)
-                       : "memory", "cc");
-               break;
-#elif defined(swp_is_buggy)
-#ifdef CONFIG_SMP
-#error SMP is not supported on this platform
-#endif
-       case 1:
-               raw_local_irq_save(flags);
-               ret = *(volatile unsigned char *)ptr;
-               *(volatile unsigned char *)ptr = x;
-               raw_local_irq_restore(flags);
-               break;
-
-       case 4:
-               raw_local_irq_save(flags);
-               ret = *(volatile unsigned long *)ptr;
-               *(volatile unsigned long *)ptr = x;
-               raw_local_irq_restore(flags);
-               break;
-#else
-       case 1:
-               asm volatile("@ __xchg1\n"
-               "       swpb    %0, %1, [%2]"
-                       : "=&r" (ret)
-                       : "r" (x), "r" (ptr)
-                       : "memory", "cc");
-               break;
-       case 4:
-               asm volatile("@ __xchg4\n"
-               "       swp     %0, %1, [%2]"
-                       : "=&r" (ret)
-                       : "r" (x), "r" (ptr)
-                       : "memory", "cc");
-               break;
-#endif
-       default:
-               __bad_xchg(ptr, size), ret = 0;
-               break;
-       }
-       smp_mb();
-
-       return ret;
-}
-
-extern void disable_hlt(void);
-extern void enable_hlt(void);
-
-void cpu_idle_wait(void);
-
-#include <asm-generic/cmpxchg-local.h>
-
-#if __LINUX_ARM_ARCH__ < 6
-/* min ARCH < ARMv6 */
-
-#ifdef CONFIG_SMP
-#error "SMP is not supported on this platform"
-#endif
-
-/*
- * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
- * them available.
- */
-#define cmpxchg_local(ptr, o, n)                                              \
-       ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
-                       (unsigned long)(n), sizeof(*(ptr))))
-#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
-
-#ifndef CONFIG_SMP
-#include <asm-generic/cmpxchg.h>
-#endif
-
-#else  /* min ARCH >= ARMv6 */
-
-extern void __bad_cmpxchg(volatile void *ptr, int size);
-
-/*
- * cmpxchg only support 32-bits operands on ARMv6.
- */
-
-static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
-                                     unsigned long new, int size)
-{
-       unsigned long oldval, res;
-
-       switch (size) {
-#ifndef CONFIG_CPU_V6  /* min ARCH >= ARMv6K */
-       case 1:
-               do {
-                       asm volatile("@ __cmpxchg1\n"
-                       "       ldrexb  %1, [%2]\n"
-                       "       mov     %0, #0\n"
-                       "       teq     %1, %3\n"
-                       "       strexbeq %0, %4, [%2]\n"
-                               : "=&r" (res), "=&r" (oldval)
-                               : "r" (ptr), "Ir" (old), "r" (new)
-                               : "memory", "cc");
-               } while (res);
-               break;
-       case 2:
-               do {
-                       asm volatile("@ __cmpxchg1\n"
-                       "       ldrexh  %1, [%2]\n"
-                       "       mov     %0, #0\n"
-                       "       teq     %1, %3\n"
-                       "       strexheq %0, %4, [%2]\n"
-                               : "=&r" (res), "=&r" (oldval)
-                               : "r" (ptr), "Ir" (old), "r" (new)
-                               : "memory", "cc");
-               } while (res);
-               break;
-#endif
-       case 4:
-               do {
-                       asm volatile("@ __cmpxchg4\n"
-                       "       ldrex   %1, [%2]\n"
-                       "       mov     %0, #0\n"
-                       "       teq     %1, %3\n"
-                       "       strexeq %0, %4, [%2]\n"
-                               : "=&r" (res), "=&r" (oldval)
-                               : "r" (ptr), "Ir" (old), "r" (new)
-                               : "memory", "cc");
-               } while (res);
-               break;
-       default:
-               __bad_cmpxchg(ptr, size);
-               oldval = 0;
-       }
-
-       return oldval;
-}
-
-static inline unsigned long __cmpxchg_mb(volatile void *ptr, unsigned long old,
-                                        unsigned long new, int size)
-{
-       unsigned long ret;
-
-       smp_mb();
-       ret = __cmpxchg(ptr, old, new, size);
-       smp_mb();
-
-       return ret;
-}
-
-#define cmpxchg(ptr,o,n)                                               \
-       ((__typeof__(*(ptr)))__cmpxchg_mb((ptr),                        \
-                                         (unsigned long)(o),           \
-                                         (unsigned long)(n),           \
-                                         sizeof(*(ptr))))
-
-static inline unsigned long __cmpxchg_local(volatile void *ptr,
-                                           unsigned long old,
-                                           unsigned long new, int size)
-{
-       unsigned long ret;
-
-       switch (size) {
-#ifdef CONFIG_CPU_V6   /* min ARCH == ARMv6 */
-       case 1:
-       case 2:
-               ret = __cmpxchg_local_generic(ptr, old, new, size);
-               break;
-#endif
-       default:
-               ret = __cmpxchg(ptr, old, new, size);
-       }
-
-       return ret;
-}
-
-#define cmpxchg_local(ptr,o,n)                                         \
-       ((__typeof__(*(ptr)))__cmpxchg_local((ptr),                     \
-                                      (unsigned long)(o),              \
-                                      (unsigned long)(n),              \
-                                      sizeof(*(ptr))))
-
-#ifndef CONFIG_CPU_V6  /* min ARCH >= ARMv6K */
-
-/*
- * Note : ARMv7-M (currently unsupported by Linux) does not support
- * ldrexd/strexd. If ARMv7-M is ever supported by the Linux kernel, it should
- * not be allowed to use __cmpxchg64.
- */
-static inline unsigned long long __cmpxchg64(volatile void *ptr,
-                                            unsigned long long old,
-                                            unsigned long long new)
-{
-       register unsigned long long oldval asm("r0");
-       register unsigned long long __old asm("r2") = old;
-       register unsigned long long __new asm("r4") = new;
-       unsigned long res;
-
-       do {
-               asm volatile(
-               "       @ __cmpxchg8\n"
-               "       ldrexd  %1, %H1, [%2]\n"
-               "       mov     %0, #0\n"
-               "       teq     %1, %3\n"
-               "       teqeq   %H1, %H3\n"
-               "       strexdeq %0, %4, %H4, [%2]\n"
-                       : "=&r" (res), "=&r" (oldval)
-                       : "r" (ptr), "Ir" (__old), "r" (__new)
-                       : "memory", "cc");
-       } while (res);
-
-       return oldval;
-}
-
-static inline unsigned long long __cmpxchg64_mb(volatile void *ptr,
-                                               unsigned long long old,
-                                               unsigned long long new)
-{
-       unsigned long long ret;
-
-       smp_mb();
-       ret = __cmpxchg64(ptr, old, new);
-       smp_mb();
-
-       return ret;
-}
-
-#define cmpxchg64(ptr,o,n)                                             \
-       ((__typeof__(*(ptr)))__cmpxchg64_mb((ptr),                      \
-                                           (unsigned long long)(o),    \
-                                           (unsigned long long)(n)))
-
-#define cmpxchg64_local(ptr,o,n)                                       \
-       ((__typeof__(*(ptr)))__cmpxchg64((ptr),                         \
-                                        (unsigned long long)(o),       \
-                                        (unsigned long long)(n)))
-
-#else /* min ARCH = ARMv6 */
-
-#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
-
-#endif
-
-#endif /* __LINUX_ARM_ARCH__ >= 6 */
-
-#endif /* __ASSEMBLY__ */
-
-#define arch_align_stack(x) (x)
-
-#endif /* __KERNEL__ */
-
-#endif
+/* FILE TO BE DELETED. DO NOT ADD STUFF HERE! */
+#include <asm/barrier.h>
+#include <asm/compiler.h>
+#include <asm/cmpxchg.h>
+#include <asm/exec.h>
+#include <asm/switch_to.h>
+#include <asm/system_info.h>
+#include <asm/system_misc.h>
diff --git a/arch/arm/include/asm/system_info.h b/arch/arm/include/asm/system_info.h
new file mode 100644 (file)
index 0000000..dfd386d
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef __ASM_ARM_SYSTEM_INFO_H
+#define __ASM_ARM_SYSTEM_INFO_H
+
+#define CPU_ARCH_UNKNOWN       0
+#define CPU_ARCH_ARMv3         1
+#define CPU_ARCH_ARMv4         2
+#define CPU_ARCH_ARMv4T                3
+#define CPU_ARCH_ARMv5         4
+#define CPU_ARCH_ARMv5T                5
+#define CPU_ARCH_ARMv5TE       6
+#define CPU_ARCH_ARMv5TEJ      7
+#define CPU_ARCH_ARMv6         8
+#define CPU_ARCH_ARMv7         9
+
+#ifndef __ASSEMBLY__
+
+/* information about the system we're running on */
+extern unsigned int system_rev;
+extern unsigned int system_serial_low;
+extern unsigned int system_serial_high;
+extern unsigned int mem_fclk_21285;
+
+extern int __pure cpu_architecture(void);
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* __ASM_ARM_SYSTEM_INFO_H */
diff --git a/arch/arm/include/asm/system_misc.h b/arch/arm/include/asm/system_misc.h
new file mode 100644 (file)
index 0000000..5a85f14
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef __ASM_ARM_SYSTEM_MISC_H
+#define __ASM_ARM_SYSTEM_MISC_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/compiler.h>
+#include <linux/linkage.h>
+#include <linux/irqflags.h>
+
+extern void cpu_init(void);
+
+void soft_restart(unsigned long);
+extern void (*arm_pm_restart)(char str, const char *cmd);
+extern void (*arm_pm_idle)(void);
+
+#define UDBG_UNDEFINED (1 << 0)
+#define UDBG_SYSCALL   (1 << 1)
+#define UDBG_BADABORT  (1 << 2)
+#define UDBG_SEGV      (1 << 3)
+#define UDBG_BUS       (1 << 4)
+
+extern unsigned int user_debug;
+
+extern void disable_hlt(void);
+extern void enable_hlt(void);
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* __ASM_ARM_SYSTEM_MISC_H */
index 2958976..71f6536 100644 (file)
@@ -16,8 +16,8 @@
 #include <asm/errno.h>
 #include <asm/memory.h>
 #include <asm/domain.h>
-#include <asm/system.h>
 #include <asm/unified.h>
+#include <asm/compiler.h>
 
 #define VERIFY_READ 0
 #define VERIFY_WRITE 1
index 5b0bce6..b57c75e 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/io.h>
 
 #include <asm/checksum.h>
-#include <asm/system.h>
 #include <asm/ftrace.h>
 
 /*
index ddba41d..d0d1e83 100644 (file)
@@ -3,6 +3,7 @@
 #include <linux/personality.h>
 #include <linux/binfmts.h>
 #include <linux/elf.h>
+#include <asm/system_info.h>
 
 int elf_check_arch(const struct elf32_hdr *x)
 {
index 22f0ed3..8ec5eed 100644 (file)
@@ -26,7 +26,7 @@
 #include <asm/unwind.h>
 #include <asm/unistd.h>
 #include <asm/tls.h>
-#include <asm/system.h>
+#include <asm/system_info.h>
 
 #include "entry-header.S"
 #include <asm/entry-macro-multi.S>
index 4c164ec..c32f845 100644 (file)
@@ -42,9 +42,9 @@
 #include <linux/seq_file.h>
 
 #include <asm/cacheflush.h>
+#include <asm/cp15.h>
 #include <asm/fiq.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/traps.h>
 
 static unsigned long no_fiq_insn;
index d46f259..278cfc1 100644 (file)
@@ -17,8 +17,8 @@
 #include <asm/assembler.h>
 #include <asm/ptrace.h>
 #include <asm/asm-offsets.h>
+#include <asm/cp15.h>
 #include <asm/thread_info.h>
-#include <asm/system.h>
 
 /*
  * Kernel startup entry point.
index 6d57911..a2e9694 100644 (file)
 #include <linux/init.h>
 
 #include <asm/assembler.h>
+#include <asm/cp15.h>
 #include <asm/domain.h>
 #include <asm/ptrace.h>
 #include <asm/asm-offsets.h>
 #include <asm/memory.h>
 #include <asm/thread_info.h>
-#include <asm/system.h>
 #include <asm/pgtable.h>
 
 #ifdef CONFIG_DEBUG_LL
index d6a95ef..ba386bd 100644 (file)
@@ -34,7 +34,6 @@
 #include <asm/current.h>
 #include <asm/hw_breakpoint.h>
 #include <asm/kdebug.h>
-#include <asm/system.h>
 #include <asm/traps.h>
 
 /* Breakpoint currently in use for each BRP. */
index 3efd82c..6a6a097 100644 (file)
@@ -36,7 +36,6 @@
 #include <linux/proc_fs.h>
 
 #include <asm/exception.h>
-#include <asm/system.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
index a5394fb..18a7628 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <linux/kernel.h>
 #include <linux/kprobes.h>
+#include <asm/system_info.h>
 
 #include "kprobes.h"
 
index 764bd45..5699598 100644 (file)
@@ -12,7 +12,7 @@
 #include <asm/mmu_context.h>
 #include <asm/cacheflush.h>
 #include <asm/mach-types.h>
-#include <asm/system.h>
+#include <asm/system_misc.h>
 
 extern const unsigned char relocate_new_kernel[];
 extern const unsigned int relocate_new_kernel_size;
index d3eca45..7b9cdde 100644 (file)
@@ -35,7 +35,6 @@
 #include <asm/cacheflush.h>
 #include <asm/leds.h>
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/thread_notify.h>
 #include <asm/stacktrace.h>
 #include <asm/mach/time.h>
index ede6443..45956c9 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/audit.h>
 
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/traps.h>
 
 #define REG_PC 15
index a255c39..9e0fdb3 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/sort.h>
 
 #include <asm/unified.h>
+#include <asm/cp15.h>
 #include <asm/cpu.h>
 #include <asm/cputype.h>
 #include <asm/elf.h>
 #include <asm/cacheflush.h>
 #include <asm/cachetype.h>
 #include <asm/tlbflush.h>
-#include <asm/system.h>
 
 #include <asm/prom.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
+#include <asm/system_info.h>
+#include <asm/system_misc.h>
 #include <asm/traps.h>
 #include <asm/unwind.h>
 #include <asm/memblock.h>
index 1f268bd..987dcf3 100644 (file)
@@ -4,7 +4,6 @@
 #include <asm/assembler.h>
 #include <asm/glue-cache.h>
 #include <asm/glue-proc.h>
-#include <asm/system.h>
        .text
 
 /*
index 01ec453..30ae6bb 100644 (file)
@@ -16,6 +16,7 @@
 #include <asm/cputype.h>
 #include <asm/mach/map.h>
 #include <asm/memory.h>
+#include <asm/system_info.h>
 #include "tcm.h"
 
 static struct gen_pool *tcm_pool;
index 9cb7aac..aab8997 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 
+#include <asm/system_info.h>
 #include <asm/thread_notify.h>
 
 /*
index f84dfe6..cd77743 100644 (file)
 #include <linux/atomic.h>
 #include <asm/cacheflush.h>
 #include <asm/exception.h>
-#include <asm/system.h>
 #include <asm/unistd.h>
 #include <asm/traps.h>
 #include <asm/unwind.h>
 #include <asm/tls.h>
+#include <asm/system_misc.h>
 
 #include "signal.h"
 
index e55cdcb..45db05d 100644 (file)
@@ -20,9 +20,11 @@ config HAVE_AT91_USART5
 
 config AT91_SAM9_ALT_RESET
        bool
+       default !ARCH_AT91X40
 
 config AT91_SAM9G45_RESET
        bool
+       default !ARCH_AT91X40
 
 menu "Atmel AT91 System-on-Chip"
 
@@ -45,7 +47,6 @@ config ARCH_AT91SAM9260
        select HAVE_AT91_USART4
        select HAVE_AT91_USART5
        select HAVE_NET_MACB
-       select AT91_SAM9_ALT_RESET
 
 config ARCH_AT91SAM9261
        bool "AT91SAM9261"
@@ -53,7 +54,6 @@ config ARCH_AT91SAM9261
        select GENERIC_CLOCKEVENTS
        select HAVE_FB_ATMEL
        select HAVE_AT91_DBGU0
-       select AT91_SAM9_ALT_RESET
 
 config ARCH_AT91SAM9G10
        bool "AT91SAM9G10"
@@ -61,7 +61,6 @@ config ARCH_AT91SAM9G10
        select GENERIC_CLOCKEVENTS
        select HAVE_AT91_DBGU0
        select HAVE_FB_ATMEL
-       select AT91_SAM9_ALT_RESET
 
 config ARCH_AT91SAM9263
        bool "AT91SAM9263"
@@ -70,7 +69,6 @@ config ARCH_AT91SAM9263
        select HAVE_FB_ATMEL
        select HAVE_NET_MACB
        select HAVE_AT91_DBGU1
-       select AT91_SAM9_ALT_RESET
 
 config ARCH_AT91SAM9RL
        bool "AT91SAM9RL"
@@ -79,7 +77,6 @@ config ARCH_AT91SAM9RL
        select HAVE_AT91_USART3
        select HAVE_FB_ATMEL
        select HAVE_AT91_DBGU0
-       select AT91_SAM9_ALT_RESET
 
 config ARCH_AT91SAM9G20
        bool "AT91SAM9G20"
@@ -90,7 +87,6 @@ config ARCH_AT91SAM9G20
        select HAVE_AT91_USART4
        select HAVE_AT91_USART5
        select HAVE_NET_MACB
-       select AT91_SAM9_ALT_RESET
 
 config ARCH_AT91SAM9G45
        bool "AT91SAM9G45"
@@ -100,7 +96,6 @@ config ARCH_AT91SAM9G45
        select HAVE_FB_ATMEL
        select HAVE_NET_MACB
        select HAVE_AT91_DBGU1
-       select AT91_SAM9G45_RESET
 
 config ARCH_AT91SAM9X5
        bool "AT91SAM9x5 family"
@@ -109,7 +104,6 @@ config ARCH_AT91SAM9X5
        select HAVE_FB_ATMEL
        select HAVE_NET_MACB
        select HAVE_AT91_DBGU0
-       select AT91_SAM9G45_RESET
 
 config ARCH_AT91X40
        bool "AT91x40"
index 0df1045..364c193 100644 (file)
@@ -15,6 +15,7 @@
 #include <asm/irq.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
+#include <asm/system_misc.h>
 #include <mach/at91rm9200.h>
 #include <mach/at91_pmc.h>
 #include <mach/at91_st.h>
index 14b5a9c..46f7742 100644 (file)
@@ -16,6 +16,7 @@
 #include <asm/irq.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
+#include <asm/system_misc.h>
 #include <mach/cpu.h>
 #include <mach/at91_dbgu.h>
 #include <mach/at91sam9260.h>
@@ -216,6 +217,7 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("t0_clk", "fffdc000.timer", &tc3_clk),
        CLKDEV_CON_DEV_ID("t1_clk", "fffdc000.timer", &tc4_clk),
        CLKDEV_CON_DEV_ID("t2_clk", "fffdc000.timer", &tc5_clk),
+       CLKDEV_CON_DEV_ID("hclk", "500000.ohci", &ohci_clk),
        /* fake hclk clock */
        CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
        CLKDEV_CON_ID("pioA", &pioA_clk),
index 684c5df..7de81e6 100644 (file)
@@ -16,6 +16,7 @@
 #include <asm/irq.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
+#include <asm/system_misc.h>
 #include <mach/cpu.h>
 #include <mach/at91sam9261.h>
 #include <mach/at91_pmc.h>
index 0b4fa5a..ef301be 100644 (file)
@@ -16,6 +16,7 @@
 #include <asm/irq.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
+#include <asm/system_misc.h>
 #include <mach/at91sam9263.h>
 #include <mach/at91_pmc.h>
 #include <mach/at91_rstc.h>
index 0014573..d222f83 100644 (file)
@@ -16,6 +16,7 @@
 #include <asm/irq.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
+#include <asm/system_misc.h>
 #include <mach/at91sam9g45.h>
 #include <mach/at91_pmc.h>
 #include <mach/cpu.h>
@@ -232,6 +233,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
        /* more tc lookup table for DT entries */
        CLKDEV_CON_DEV_ID("t0_clk", "fff7c000.timer", &tcb0_clk),
        CLKDEV_CON_DEV_ID("t0_clk", "fffd4000.timer", &tcb0_clk),
+       CLKDEV_CON_DEV_ID("hclk", "700000.ohci", &uhphs_clk),
+       CLKDEV_CON_DEV_ID("ehci_clk", "800000.ehci", &uhphs_clk),
        /* fake hclk clock */
        CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &uhphs_clk),
        CLKDEV_CON_ID("pioA", &pioA_clk),
index 63d9372..d9f2774 100644 (file)
@@ -15,6 +15,7 @@
 #include <asm/irq.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
+#include <asm/system_misc.h>
 #include <mach/cpu.h>
 #include <mach/at91_dbgu.h>
 #include <mach/at91sam9rl.h>
index a34d96a..b6831ee 100644 (file)
@@ -131,7 +131,7 @@ static struct clk dma1_clk = {
        .type           = CLK_TYPE_PERIPHERAL,
 };
 static struct clk uhphs_clk = {
-       .name           = "uhphs_clk",
+       .name           = "uhphs",
        .pmc_mask       = 1 << AT91SAM9X5_ID_UHPHS,
        .type           = CLK_TYPE_PERIPHERAL,
 };
@@ -230,6 +230,9 @@ static struct clk_lookup periph_clocks_lookups[] = {
        /* additional fake clock for macb_hclk */
        CLKDEV_CON_DEV_ID("hclk", "f802c000.ethernet", &macb0_clk),
        CLKDEV_CON_DEV_ID("hclk", "f8030000.ethernet", &macb1_clk),
+       CLKDEV_CON_DEV_ID("hclk", "600000.ohci", &uhphs_clk),
+       CLKDEV_CON_DEV_ID("ohci_clk", "600000.ohci", &uhphs_clk),
+       CLKDEV_CON_DEV_ID("ehci_clk", "700000.ehci", &uhphs_clk),
 };
 
 /*
@@ -299,14 +302,8 @@ static void __init at91sam9x5_map_io(void)
        at91_init_sram(0, AT91SAM9X5_SRAM_BASE, AT91SAM9X5_SRAM_SIZE);
 }
 
-static void __init at91sam9x5_ioremap_registers(void)
-{
-       at91_ioremap_ramc(0, AT91SAM9X5_BASE_DDRSDRC0, 512);
-}
-
 void __init at91sam9x5_initialize(void)
 {
-       arm_pm_restart = at91sam9g45_restart;
        at91_extern_irq = (1 << AT91SAM9X5_ID_IRQ0);
 
        /* Register GPIO subsystem (using DT) */
@@ -314,11 +311,6 @@ void __init at91sam9x5_initialize(void)
 }
 
 /* --------------------------------------------------------------------
- *  AT91SAM9x5 devices (temporary before modification of code)
- * -------------------------------------------------------------------- */
-void __init at91_add_device_nand(struct atmel_nand_data *data) {}
-
-/* --------------------------------------------------------------------
  *  Interrupt initialization
  * -------------------------------------------------------------------- */
 /*
@@ -362,7 +354,6 @@ static unsigned int at91sam9x5_default_irq_priority[NR_AIC_IRQS] __initdata = {
 struct at91_init_soc __initdata at91sam9x5_soc = {
        .map_io = at91sam9x5_map_io,
        .default_irq_priority = at91sam9x5_default_irq_priority,
-       .ioremap_registers = at91sam9x5_ioremap_registers,
        .register_clocks = at91sam9x5_register_clocks,
        .init = at91sam9x5_initialize,
 };
index 3bb4069..161efba 100644 (file)
@@ -138,6 +138,7 @@ static struct atmel_nand_data __initdata afeb9260_nand_data = {
        .rdy_pin        = AT91_PIN_PC13,
        .enable_pin     = AT91_PIN_PC14,
        .bus_width_16   = 0,
+       .ecc_mode       = NAND_ECC_SOFT,
        .parts          = afeb9260_nand_partition,
        .num_parts      = ARRAY_SIZE(afeb9260_nand_partition),
        .det_pin        = -EINVAL,
index 8510e9e..c6d44ee 100644 (file)
@@ -140,6 +140,7 @@ static struct atmel_nand_data __initdata cam60_nand_data = {
        .det_pin        = -EINVAL,
        .rdy_pin        = AT91_PIN_PA9,
        .enable_pin     = AT91_PIN_PA7,
+       .ecc_mode       = NAND_ECC_SOFT,
        .parts          = cam60_nand_partition,
        .num_parts      = ARRAY_SIZE(cam60_nand_partition),
 };
index 989e1c5..5f3680e 100644 (file)
@@ -117,6 +117,7 @@ static struct atmel_nand_data __initdata cpu9krea_nand_data = {
        .enable_pin     = AT91_PIN_PC14,
        .bus_width_16   = 0,
        .det_pin        = -EINVAL,
+       .ecc_mode       = NAND_ECC_SOFT,
 };
 
 #ifdef CONFIG_MACH_CPU9260
index 583b724..c18d4d3 100644 (file)
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 
-#include <mach/hardware.h>
 #include <mach/board.h>
-#include <mach/system_rev.h>
-#include <mach/at91sam9_smc.h>
 
 #include <asm/setup.h>
 #include <asm/irq.h>
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include "sam9_smc.h"
 #include "generic.h"
 
 
-static void __init ek_init_early(void)
-{
-       /* Initialize processor: 12.000 MHz crystal */
-       at91_initialize(12000000);
-}
-
-/* det_pin is not connected */
-static struct atmel_nand_data __initdata ek_nand_data = {
-       .ale            = 21,
-       .cle            = 22,
-       .det_pin        = -EINVAL,
-       .rdy_pin        = AT91_PIN_PC8,
-       .enable_pin     = AT91_PIN_PC14,
-};
-
-static struct sam9_smc_config __initdata ek_nand_smc_config = {
-       .ncs_read_setup         = 0,
-       .nrd_setup              = 2,
-       .ncs_write_setup        = 0,
-       .nwe_setup              = 2,
-
-       .ncs_read_pulse         = 4,
-       .nrd_pulse              = 4,
-       .ncs_write_pulse        = 4,
-       .nwe_pulse              = 4,
-
-       .read_cycle             = 7,
-       .write_cycle            = 7,
-
-       .mode                   = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE,
-       .tdf_cycles             = 3,
-};
-
-static void __init ek_add_device_nand(void)
-{
-       ek_nand_data.bus_width_16 = board_have_nand_16bit();
-       /* setup bus-width (8 or 16) */
-       if (ek_nand_data.bus_width_16)
-               ek_nand_smc_config.mode |= AT91_SMC_DBW_16;
-       else
-               ek_nand_smc_config.mode |= AT91_SMC_DBW_8;
-
-       /* configure chip-select 3 (NAND) */
-       sam9_smc_configure(0, 3, &ek_nand_smc_config);
-
-       at91_add_device_nand(&ek_nand_data);
-}
-
 static const struct of_device_id irq_of_match[] __initconst = {
 
        { .compatible = "atmel,at91rm9200-aic", .data = at91_aic_of_init },
@@ -98,9 +46,6 @@ static void __init at91_dt_init_irq(void)
 static void __init at91_dt_device_init(void)
 {
        of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-
-       /* NAND */
-       ek_add_device_nand();
 }
 
 static const char *at91_dt_board_compat[] __initdata = {
@@ -114,7 +59,7 @@ DT_MACHINE_START(at91sam_dt, "Atmel AT91SAM (Device Tree)")
        /* Maintainer: Atmel */
        .timer          = &at91sam926x_timer,
        .map_io         = at91_map_io,
-       .init_early     = ek_init_early,
+       .init_early     = at91_dt_initialize,
        .init_irq       = at91_dt_init_irq,
        .init_machine   = at91_dt_device_init,
        .dt_compat      = at91_dt_board_compat,
index bb99145..59b92aa 100644 (file)
@@ -108,6 +108,7 @@ static struct atmel_nand_data __initdata kb9202_nand_data = {
        .det_pin        = -EINVAL,
        .rdy_pin        = AT91_PIN_PC29,
        .enable_pin     = AT91_PIN_PC28,
+       .ecc_mode       = NAND_ECC_SOFT,
        .parts          = kb9202_nand_partition,
        .num_parts      = ARRAY_SIZE(kb9202_nand_partition),
 };
index 3f8617c..57d5f6a 100644 (file)
@@ -190,6 +190,7 @@ static struct atmel_nand_data __initdata neocore926_nand_data = {
        .rdy_pin                = AT91_PIN_PB19,
        .rdy_pin_active_low     = 1,
        .enable_pin             = AT91_PIN_PD15,
+       .ecc_mode               = NAND_ECC_SOFT,
        .parts                  = neocore926_nand_partition,
        .num_parts              = ARRAY_SIZE(neocore926_nand_partition),
        .det_pin                = -EINVAL,
index e029d22..b6ed5ed 100644 (file)
@@ -138,6 +138,8 @@ static struct atmel_nand_data __initdata ek_nand_data = {
        .det_pin        = -EINVAL,
        .rdy_pin        = AT91_PIN_PC13,
        .enable_pin     = AT91_PIN_PC14,
+       .ecc_mode       = NAND_ECC_SOFT,
+       .on_flash_bbt   = 1,
        .parts          = ek_nand_partition,
        .num_parts      = ARRAY_SIZE(ek_nand_partition),
 };
index 9083df0..01332aa 100644 (file)
@@ -150,6 +150,8 @@ static struct atmel_nand_data __initdata dk_nand_data = {
        .det_pin        = AT91_PIN_PB1,
        .rdy_pin        = AT91_PIN_PC2,
        .enable_pin     = -EINVAL,
+       .ecc_mode       = NAND_ECC_SOFT,
+       .on_flash_bbt   = 1,
        .parts          = dk_nand_partition,
        .num_parts      = ARRAY_SIZE(dk_nand_partition),
 };
index 84bce58..e8b116b 100644 (file)
@@ -139,6 +139,7 @@ static struct atmel_nand_data __initdata ek_nand_data = {
        .det_pin        = -EINVAL,
        .rdy_pin        = AT91_PIN_PC13,
        .enable_pin     = AT91_PIN_PC14,
+       .ecc_mode       = NAND_ECC_SOFT,
        .parts          = ek_nand_partition,
        .num_parts      = ARRAY_SIZE(ek_nand_partition),
 };
index be8233b..d5aec55 100644 (file)
@@ -181,6 +181,8 @@ static struct atmel_nand_data __initdata ek_nand_data = {
        .det_pin        = -EINVAL,
        .rdy_pin        = AT91_PIN_PC13,
        .enable_pin     = AT91_PIN_PC14,
+       .ecc_mode       = NAND_ECC_SOFT,
+       .on_flash_bbt   = 1,
        .parts          = ek_nand_partition,
        .num_parts      = ARRAY_SIZE(ek_nand_partition),
 };
index 4089507..c3f9944 100644 (file)
@@ -187,6 +187,8 @@ static struct atmel_nand_data __initdata ek_nand_data = {
        .det_pin        = -EINVAL,
        .rdy_pin        = AT91_PIN_PC15,
        .enable_pin     = AT91_PIN_PC14,
+       .ecc_mode       = NAND_ECC_SOFT,
+       .on_flash_bbt   = 1,
        .parts          = ek_nand_partition,
        .num_parts      = ARRAY_SIZE(ek_nand_partition),
 };
index 29f6605..66f0ddf 100644 (file)
@@ -187,6 +187,8 @@ static struct atmel_nand_data __initdata ek_nand_data = {
        .det_pin        = -EINVAL,
        .rdy_pin        = AT91_PIN_PA22,
        .enable_pin     = AT91_PIN_PD15,
+       .ecc_mode       = NAND_ECC_SOFT,
+       .on_flash_bbt   = 1,
        .parts          = ek_nand_partition,
        .num_parts      = ARRAY_SIZE(ek_nand_partition),
 };
index 843d628..8923ec9 100644 (file)
@@ -166,6 +166,8 @@ static struct atmel_nand_data __initdata ek_nand_data = {
        .rdy_pin        = AT91_PIN_PC13,
        .enable_pin     = AT91_PIN_PC14,
        .det_pin        = -EINVAL,
+       .ecc_mode       = NAND_ECC_SOFT,
+       .on_flash_bbt   = 1,
        .parts          = ek_nand_partition,
        .num_parts      = ARRAY_SIZE(ek_nand_partition),
 };
index 57497e2..e1bea73 100644 (file)
@@ -148,6 +148,8 @@ static struct atmel_nand_data __initdata ek_nand_data = {
        .rdy_pin        = AT91_PIN_PC8,
        .enable_pin     = AT91_PIN_PC14,
        .det_pin        = -EINVAL,
+       .ecc_mode       = NAND_ECC_SOFT,
+       .on_flash_bbt   = 1,
        .parts          = ek_nand_partition,
        .num_parts      = ARRAY_SIZE(ek_nand_partition),
 };
index c1366d0..b109ce2 100644 (file)
@@ -94,6 +94,8 @@ static struct atmel_nand_data __initdata ek_nand_data = {
        .det_pin        = -EINVAL,
        .rdy_pin        = AT91_PIN_PD17,
        .enable_pin     = AT91_PIN_PB6,
+       .ecc_mode       = NAND_ECC_SOFT,
+       .on_flash_bbt   = 1,
        .parts          = ek_nand_partition,
        .num_parts      = ARRAY_SIZE(ek_nand_partition),
 };
index 3c2e3fc..ebc9d01 100644 (file)
@@ -110,6 +110,7 @@ static struct atmel_nand_data __initdata snapper9260_nand_data = {
        .bus_width_16   = 0,
        .enable_pin     = -EINVAL,
        .det_pin        = -EINVAL,
+       .ecc_mode       = NAND_ECC_SOFT,
 };
 
 static struct sam9_smc_config __initdata snapper9260_nand_smc_config = {
index 72eb3b4..7640049 100644 (file)
@@ -86,6 +86,7 @@ static struct atmel_nand_data __initdata nand_data = {
        .enable_pin     = AT91_PIN_PC14,
        .bus_width_16   = 0,
        .det_pin        = -EINVAL,
+       .ecc_mode       = NAND_ECC_SOFT,
 };
 
 static struct sam9_smc_config __initdata nand_smc_config = {
index 26c36fc..b7483a3 100644 (file)
@@ -198,6 +198,8 @@ static struct atmel_nand_data __initdata ek_nand_data = {
        .det_pin        = -EINVAL,
        .rdy_pin        = AT91_PIN_PA22,
        .enable_pin     = AT91_PIN_PD15,
+       .ecc_mode       = NAND_ECC_SOFT,
+       .on_flash_bbt   = 1,
        .parts          = ek_nand_partition,
        .num_parts      = ARRAY_SIZE(ek_nand_partition),
 };
index 52f4607..38dd279 100644 (file)
@@ -182,6 +182,7 @@ static struct atmel_nand_data __initdata yl9200_nand_data = {
        .det_pin        = -EINVAL,
        .rdy_pin        = AT91_PIN_PC14,        /* R/!B (Sheet10) */
        .enable_pin     = AT91_PIN_PC15,        /* !CE  (Sheet10) */
+       .ecc_mode       = NAND_ECC_SOFT,
        .parts          = yl9200_nand_partition,
        .num_parts      = ARRAY_SIZE(yl9200_nand_partition),
 };
index be51ca7..a0f4d74 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/delay.h>
 #include <linux/clk.h>
 #include <linux/io.h>
+#include <linux/of_address.h>
 
 #include <mach/hardware.h>
 #include <mach/at91_pmc.h>
@@ -671,16 +672,12 @@ static void __init at91_upll_usbfs_clock_init(unsigned long main_clock)
        uhpck.rate_hz /= 1 + ((at91_pmc_read(AT91_PMC_USB) & AT91_PMC_OHCIUSBDIV) >> 8);
 }
 
-int __init at91_clock_init(unsigned long main_clock)
+static int __init at91_pmc_init(unsigned long main_clock)
 {
        unsigned tmp, freq, mckr;
        int i;
        int pll_overclock = false;
 
-       at91_pmc_base = ioremap(AT91_PMC, 256);
-       if (!at91_pmc_base)
-               panic("Impossible to ioremap AT91_PMC 0x%x\n", AT91_PMC);
-
        /*
         * When the bootloader initialized the main oscillator correctly,
         * there's no problem using the cycle counter.  But if it didn't,
@@ -802,6 +799,55 @@ int __init at91_clock_init(unsigned long main_clock)
        return 0;
 }
 
+#if defined(CONFIG_OF)
+static struct of_device_id pmc_ids[] = {
+       { .compatible = "atmel,at91rm9200-pmc" },
+       { /*sentinel*/ }
+};
+
+static struct of_device_id osc_ids[] = {
+       { .compatible = "atmel,osc" },
+       { /*sentinel*/ }
+};
+
+int __init at91_dt_clock_init(void)
+{
+       struct device_node *np;
+       u32 main_clock = 0;
+
+       np = of_find_matching_node(NULL, pmc_ids);
+       if (!np)
+               panic("unable to find compatible pmc node in dtb\n");
+
+       at91_pmc_base = of_iomap(np, 0);
+       if (!at91_pmc_base)
+               panic("unable to map pmc cpu registers\n");
+
+       of_node_put(np);
+
+       /* retrieve the freqency of fixed clocks from device tree */
+       np = of_find_matching_node(NULL, osc_ids);
+       if (np) {
+               u32 rate;
+               if (!of_property_read_u32(np, "clock-frequency", &rate))
+                       main_clock = rate;
+       }
+
+       of_node_put(np);
+
+       return at91_pmc_init(main_clock);
+}
+#endif
+
+int __init at91_clock_init(unsigned long main_clock)
+{
+       at91_pmc_base = ioremap(AT91_PMC, 256);
+       if (!at91_pmc_base)
+               panic("Impossible to ioremap AT91_PMC 0x%x\n", AT91_PMC);
+
+       return at91_pmc_init(main_clock);
+}
+
 /*
  * Several unused clocks may be active.  Turn them off.
  */
index 459f01a..dd9b346 100644 (file)
@@ -20,6 +20,7 @@ extern void __init at91_init_sram(int bank, unsigned long base,
 extern void __init at91rm9200_set_type(int type);
 extern void __init at91_initialize(unsigned long main_clock);
 extern void __init at91x40_initialize(unsigned long main_clock);
+extern void __init at91_dt_initialize(void);
 
  /* Interrupts */
 extern void __init at91_init_irq_default(void);
@@ -52,6 +53,7 @@ extern void __init at91sam9rl_set_console_clock(int id);
 extern void __init at91sam9g45_set_console_clock(int id);
 #ifdef CONFIG_AT91_PMC_UNIT
 extern int __init at91_clock_init(unsigned long main_clock);
+extern int __init at91_dt_clock_init(void);
 #else
 static int inline at91_clock_init(unsigned long main_clock) { return 0; }
 #endif
index 1d4fe82..60478ea 100644 (file)
@@ -36,9 +36,11 @@ extern void __iomem *at91_shdwc_base;
 #define                        AT91_SHDW_WKMODE0_HIGH          1
 #define                        AT91_SHDW_WKMODE0_LOW           2
 #define                        AT91_SHDW_WKMODE0_ANYLEVEL      3
-#define                AT91_SHDW_CPTWK0        (0xf << 4)              /* Counter On Wake Up 0 */
+#define                AT91_SHDW_CPTWK0_MAX    0xf                     /* Maximum Counter On Wake Up 0 */
+#define                AT91_SHDW_CPTWK0        (AT91_SHDW_CPTWK0_MAX << 4) /* Counter On Wake Up 0 */
 #define                        AT91_SHDW_CPTWK0_(x)    ((x) << 4)
 #define                AT91_SHDW_RTTWKEN       (1   << 16)             /* Real Time Timer Wake-up Enable */
+#define                AT91_SHDW_RTCWKEN       (1   << 17)             /* Real Time Clock Wake-up Enable */
 
 #define AT91_SHDW_SR           0x08                    /* Shut Down Status Register */
 #define                AT91_SHDW_WAKEUP0       (1 <<  0)               /* Wake-up 0 Status */
index a297a77..88e43d5 100644 (file)
 #define AT91SAM9X5_BASE_USART2 0xf8024000
 
 /*
- * System Peripherals
- */
-#define AT91SAM9X5_BASE_DDRSDRC0       0xffffe800
-
-/*
  * Base addresses for early serial code (uncompress.h)
  */
 #define AT91_DBGU      AT91_BASE_DBGU0
index dc8d6d4..544a5d5 100644 (file)
@@ -41,6 +41,7 @@
 #include <sound/atmel-ac97c.h>
 #include <linux/serial.h>
 #include <linux/platform_data/macb.h>
+#include <linux/platform_data/atmel.h>
 
  /* USB Device */
 struct at91_udc_data {
@@ -98,20 +99,6 @@ extern void __init at91_add_device_usbh(struct at91_usbh_data *data);
 extern void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data);
 extern void __init at91_add_device_usbh_ehci(struct at91_usbh_data *data);
 
- /* NAND / SmartMedia */
-struct atmel_nand_data {
-       int             enable_pin;     /* chip enable */
-       int             det_pin;        /* card detect */
-       int             rdy_pin;        /* ready/busy */
-       u8              rdy_pin_active_low;     /* rdy_pin value is inverted */
-       u8              ale;            /* address line number connected to ALE */
-       u8              cle;            /* address line number connected to CLE */
-       u8              bus_width_16;   /* buswidth is 16 bit */
-       u8              correction_cap; /* PMECC correction capability */
-       u16             sector_size;    /* Sector size for PMECC */
-       struct mtd_partition *parts;
-       unsigned int    num_parts;
-};
 extern void __init at91_add_device_nand(struct atmel_nand_data *data);
 
  /* I2C*/
index ec164a4..ef79a9a 100644 (file)
@@ -7,6 +7,8 @@
 #ifndef __ARCH_SYSTEM_REV_H__
 #define __ARCH_SYSTEM_REV_H__
 
+#include <asm/system_info.h>
+
 /*
  * board revision encoding
  * mach specific
index 6c9d5e6..f630250 100644 (file)
@@ -197,19 +197,6 @@ extern void at91_slow_clock(void __iomem *pmc, void __iomem *ramc0,
 extern u32 at91_slow_clock_sz;
 #endif
 
-void __iomem *at91_ramc_base[2];
-
-void __init at91_ioremap_ramc(int id, u32 addr, u32 size)
-{
-       if (id < 0 || id > 1) {
-               pr_emerg("Wrong RAM controller id (%d), cannot continue\n", id);
-               BUG();
-       }
-       at91_ramc_base[id] = ioremap(addr, size);
-       if (!at91_ramc_base[id])
-               panic("Impossible to ioremap ramc.%d 0x%x\n", id, addr);
-}
-
 static int at91_pm_enter(suspend_state_t state)
 {
        at91_gpio_suspend();
index 372396c..1083739 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/io.h>
 #include <linux/mm.h>
 #include <linux/pm.h>
+#include <linux/of_address.h>
 
 #include <asm/mach/map.h>
 
@@ -51,6 +52,19 @@ void __init at91_init_interrupts(unsigned int *priority)
        at91_gpio_irq_setup();
 }
 
+void __iomem *at91_ramc_base[2];
+
+void __init at91_ioremap_ramc(int id, u32 addr, u32 size)
+{
+       if (id < 0 || id > 1) {
+               pr_emerg("Wrong RAM controller id (%d), cannot continue\n", id);
+               BUG();
+       }
+       at91_ramc_base[id] = ioremap(addr, size);
+       if (!at91_ramc_base[id])
+               panic("Impossible to ioremap ramc.%d 0x%x\n", id, addr);
+}
+
 static struct map_desc sram_desc[2] __initdata;
 
 void __init at91_init_sram(int bank, unsigned long base, unsigned int length)
@@ -285,6 +299,150 @@ void __init at91_ioremap_matrix(u32 base_addr)
                panic("Impossible to ioremap at91_matrix_base\n");
 }
 
+#if defined(CONFIG_OF)
+static struct of_device_id rstc_ids[] = {
+       { .compatible = "atmel,at91sam9260-rstc", .data = at91sam9_alt_restart },
+       { .compatible = "atmel,at91sam9g45-rstc", .data = at91sam9g45_restart },
+       { /*sentinel*/ }
+};
+
+static void at91_dt_rstc(void)
+{
+       struct device_node *np;
+       const struct of_device_id *of_id;
+
+       np = of_find_matching_node(NULL, rstc_ids);
+       if (!np)
+               panic("unable to find compatible rstc node in dtb\n");
+
+       at91_rstc_base = of_iomap(np, 0);
+       if (!at91_rstc_base)
+               panic("unable to map rstc cpu registers\n");
+
+       of_id = of_match_node(rstc_ids, np);
+       if (!of_id)
+               panic("AT91: rtsc no restart function availlable\n");
+
+       arm_pm_restart = of_id->data;
+
+       of_node_put(np);
+}
+
+static struct of_device_id ramc_ids[] = {
+       { .compatible = "atmel,at91sam9260-sdramc" },
+       { .compatible = "atmel,at91sam9g45-ddramc" },
+       { /*sentinel*/ }
+};
+
+static void at91_dt_ramc(void)
+{
+       struct device_node *np;
+
+       np = of_find_matching_node(NULL, ramc_ids);
+       if (!np)
+               panic("unable to find compatible ram conroller node in dtb\n");
+
+       at91_ramc_base[0] = of_iomap(np, 0);
+       if (!at91_ramc_base[0])
+               panic("unable to map ramc[0] cpu registers\n");
+       /* the controller may have 2 banks */
+       at91_ramc_base[1] = of_iomap(np, 1);
+
+       of_node_put(np);
+}
+
+static struct of_device_id shdwc_ids[] = {
+       { .compatible = "atmel,at91sam9260-shdwc", },
+       { .compatible = "atmel,at91sam9rl-shdwc", },
+       { .compatible = "atmel,at91sam9x5-shdwc", },
+       { /*sentinel*/ }
+};
+
+static const char *shdwc_wakeup_modes[] = {
+       [AT91_SHDW_WKMODE0_NONE]        = "none",
+       [AT91_SHDW_WKMODE0_HIGH]        = "high",
+       [AT91_SHDW_WKMODE0_LOW]         = "low",
+       [AT91_SHDW_WKMODE0_ANYLEVEL]    = "any",
+};
+
+const int at91_dtget_shdwc_wakeup_mode(struct device_node *np)
+{
+       const char *pm;
+       int err, i;
+
+       err = of_property_read_string(np, "atmel,wakeup-mode", &pm);
+       if (err < 0)
+               return AT91_SHDW_WKMODE0_ANYLEVEL;
+
+       for (i = 0; i < ARRAY_SIZE(shdwc_wakeup_modes); i++)
+               if (!strcasecmp(pm, shdwc_wakeup_modes[i]))
+                       return i;
+
+       return -ENODEV;
+}
+
+static void at91_dt_shdwc(void)
+{
+       struct device_node *np;
+       int wakeup_mode;
+       u32 reg;
+       u32 mode = 0;
+
+       np = of_find_matching_node(NULL, shdwc_ids);
+       if (!np) {
+               pr_debug("AT91: unable to find compatible shutdown (shdwc) conroller node in dtb\n");
+               return;
+       }
+
+       at91_shdwc_base = of_iomap(np, 0);
+       if (!at91_shdwc_base)
+               panic("AT91: unable to map shdwc cpu registers\n");
+
+       wakeup_mode = at91_dtget_shdwc_wakeup_mode(np);
+       if (wakeup_mode < 0) {
+               pr_warn("AT91: shdwc unknown wakeup mode\n");
+               goto end;
+       }
+
+       if (!of_property_read_u32(np, "atmel,wakeup-counter", &reg)) {
+               if (reg > AT91_SHDW_CPTWK0_MAX) {
+                       pr_warn("AT91: shdwc wakeup conter 0x%x > 0x%x reduce it to 0x%x\n",
+                               reg, AT91_SHDW_CPTWK0_MAX, AT91_SHDW_CPTWK0_MAX);
+                       reg = AT91_SHDW_CPTWK0_MAX;
+               }
+               mode |= AT91_SHDW_CPTWK0_(reg);
+       }
+
+       if (of_property_read_bool(np, "atmel,wakeup-rtc-timer"))
+                       mode |= AT91_SHDW_RTCWKEN;
+
+       if (of_property_read_bool(np, "atmel,wakeup-rtt-timer"))
+                       mode |= AT91_SHDW_RTTWKEN;
+
+       at91_shdwc_write(AT91_SHDW_MR, wakeup_mode | mode);
+
+end:
+       pm_power_off = at91sam9_poweroff;
+
+       of_node_put(np);
+}
+
+void __init at91_dt_initialize(void)
+{
+       at91_dt_rstc();
+       at91_dt_ramc();
+       at91_dt_shdwc();
+
+       /* Init clock subsystem */
+       at91_dt_clock_init();
+
+       /* Register the processor-specific clocks */
+       at91_boot_soc.register_clocks();
+
+       at91_boot_soc.init();
+}
+#endif
+
 void __init at91_initialize(unsigned long main_clock)
 {
        at91_boot_soc.ioremap_registers();
index 8736c1a..3c5b5bb 100644 (file)
@@ -37,6 +37,7 @@
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
 #include <asm/hardware/clps7111.h>
+#include <asm/system_misc.h>
 
 /*
  * This maps the generic CLPS711x registers
index 1512144..dd9a6cd 100644 (file)
@@ -25,7 +25,6 @@
 
 #include <mach/hardware.h>
 #include <asm/leds.h>
-#include <asm/system.h>
 #include <asm/mach-types.h>
 
 #include <asm/hardware/clps7111.h>
index d508890..a70de24 100644 (file)
@@ -36,6 +36,7 @@
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
+#include <asm/system_info.h>
 
 #include <mach/cp_intc.h>
 #include <mach/da8xx.h>
index 864f676..3683306 100644 (file)
@@ -613,6 +613,113 @@ static void __init evm_init_i2c(void)
        i2c_register_board_info(1, i2c_info, ARRAY_SIZE(i2c_info));
 }
 
+#define VENC_STD_ALL   (V4L2_STD_NTSC | V4L2_STD_PAL)
+
+/* venc standard timings */
+static struct vpbe_enc_mode_info dm644xevm_enc_std_timing[] = {
+       {
+               .name           = "ntsc",
+               .timings_type   = VPBE_ENC_STD,
+               .timings        = {V4L2_STD_525_60},
+               .interlaced     = 1,
+               .xres           = 720,
+               .yres           = 480,
+               .aspect         = {11, 10},
+               .fps            = {30000, 1001},
+               .left_margin    = 0x79,
+               .upper_margin   = 0x10,
+       },
+       {
+               .name           = "pal",
+               .timings_type   = VPBE_ENC_STD,
+               .timings        = {V4L2_STD_625_50},
+               .interlaced     = 1,
+               .xres           = 720,
+               .yres           = 576,
+               .aspect         = {54, 59},
+               .fps            = {25, 1},
+               .left_margin    = 0x7e,
+               .upper_margin   = 0x16,
+       },
+};
+
+/* venc dv preset timings */
+static struct vpbe_enc_mode_info dm644xevm_enc_preset_timing[] = {
+       {
+               .name           = "480p59_94",
+               .timings_type   = VPBE_ENC_DV_PRESET,
+               .timings        = {V4L2_DV_480P59_94},
+               .interlaced     = 0,
+               .xres           = 720,
+               .yres           = 480,
+               .aspect         = {1, 1},
+               .fps            = {5994, 100},
+               .left_margin    = 0x80,
+               .upper_margin   = 0x20,
+       },
+       {
+               .name           = "576p50",
+               .timings_type   = VPBE_ENC_DV_PRESET,
+               .timings        = {V4L2_DV_576P50},
+               .interlaced     = 0,
+               .xres           = 720,
+               .yres           = 576,
+               .aspect         = {1, 1},
+               .fps            = {50, 1},
+               .left_margin    = 0x7e,
+               .upper_margin   = 0x30,
+       },
+};
+
+/*
+ * The outputs available from VPBE + encoders. Keep the order same
+ * as that of encoders. First those from venc followed by that from
+ * encoders. Index in the output refers to index on a particular encoder.
+ * Driver uses this index to pass it to encoder when it supports more
+ * than one output. Userspace applications use index of the array to
+ * set an output.
+ */
+static struct vpbe_output dm644xevm_vpbe_outputs[] = {
+       {
+               .output         = {
+                       .index          = 0,
+                       .name           = "Composite",
+                       .type           = V4L2_OUTPUT_TYPE_ANALOG,
+                       .std            = VENC_STD_ALL,
+                       .capabilities   = V4L2_OUT_CAP_STD,
+               },
+               .subdev_name    = VPBE_VENC_SUBDEV_NAME,
+               .default_mode   = "ntsc",
+               .num_modes      = ARRAY_SIZE(dm644xevm_enc_std_timing),
+               .modes          = dm644xevm_enc_std_timing,
+       },
+       {
+               .output         = {
+                       .index          = 1,
+                       .name           = "Component",
+                       .type           = V4L2_OUTPUT_TYPE_ANALOG,
+                       .capabilities   = V4L2_OUT_CAP_PRESETS,
+               },
+               .subdev_name    = VPBE_VENC_SUBDEV_NAME,
+               .default_mode   = "480p59_94",
+               .num_modes      = ARRAY_SIZE(dm644xevm_enc_preset_timing),
+               .modes          = dm644xevm_enc_preset_timing,
+       },
+};
+
+static struct vpbe_config dm644xevm_display_cfg = {
+       .module_name    = "dm644x-vpbe-display",
+       .i2c_adapter_id = 1,
+       .osd            = {
+               .module_name    = VPBE_OSD_SUBDEV_NAME,
+       },
+       .venc           = {
+               .module_name    = VPBE_VENC_SUBDEV_NAME,
+       },
+       .num_outputs    = ARRAY_SIZE(dm644xevm_vpbe_outputs),
+       .outputs        = dm644xevm_vpbe_outputs,
+};
+
 static struct platform_device *davinci_evm_devices[] __initdata = {
        &davinci_fb_device,
        &rtc_dev,
@@ -696,7 +803,7 @@ static __init void davinci_evm_init(void)
        evm_init_i2c();
 
        davinci_setup_mmc(0, &dm6446evm_mmc_config);
-       dm644x_init_video(&dm644xevm_capture_cfg);
+       dm644x_init_video(&dm644xevm_capture_cfg, &dm644xevm_display_cfg);
 
        davinci_serial_init(&uart_config);
        dm644x_init_asp(&dm644x_evm_snd_data);
index 9d70803..3e519da 100644 (file)
 
 #include <media/davinci/vpfe_capture.h>
 #include <media/davinci/vpif_types.h>
+#include <media/davinci/vpss.h>
+#include <media/davinci/vpbe_types.h>
+#include <media/davinci/vpbe_venc.h>
+#include <media/davinci/vpbe.h>
+#include <media/davinci/vpbe_osd.h>
 
 #define DAVINCI_SYSTEM_MODULE_BASE     0x01c40000
 #define SYSMOD_VIDCLKCTL               0x38
+#define SYSMOD_VPSS_CLKCTL             0x44
 #define SYSMOD_VDD3P3VPWDN             0x48
 #define SYSMOD_VSCLKDIS                        0x6c
 #define SYSMOD_PUPDCTL1                        0x7c
@@ -83,7 +89,7 @@ void dm365_set_vpfe_config(struct vpfe_config *cfg);
 /* DM644x function declarations */
 void __init dm644x_init(void);
 void __init dm644x_init_asp(struct snd_platform_data *pdata);
-int __init dm644x_init_video(struct vpfe_config *);
+int __init dm644x_init_video(struct vpfe_config *, struct vpbe_config *);
 
 /* DM646x function declarations */
 void __init dm646x_init(void);
index 23e81ca..c8b8666 100644 (file)
@@ -627,7 +627,7 @@ static struct resource dm644x_vpfe_resources[] = {
        },
 };
 
-static u64 vpfe_capture_dma_mask = DMA_BIT_MASK(32);
+static u64 dm644x_video_dma_mask = DMA_BIT_MASK(32);
 static struct resource dm644x_ccdc_resource[] = {
        /* CCDC Base address */
        {
@@ -643,7 +643,7 @@ static struct platform_device dm644x_ccdc_dev = {
        .num_resources  = ARRAY_SIZE(dm644x_ccdc_resource),
        .resource       = dm644x_ccdc_resource,
        .dev = {
-               .dma_mask               = &vpfe_capture_dma_mask,
+               .dma_mask               = &dm644x_video_dma_mask,
                .coherent_dma_mask      = DMA_BIT_MASK(32),
        },
 };
@@ -654,7 +654,134 @@ static struct platform_device dm644x_vpfe_dev = {
        .num_resources  = ARRAY_SIZE(dm644x_vpfe_resources),
        .resource       = dm644x_vpfe_resources,
        .dev = {
-               .dma_mask               = &vpfe_capture_dma_mask,
+               .dma_mask               = &dm644x_video_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       },
+};
+
+#define DM644X_OSD_BASE                0x01c72600
+
+static struct resource dm644x_osd_resources[] = {
+       {
+               .start  = DM644X_OSD_BASE,
+               .end    = DM644X_OSD_BASE + 0x1ff,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+static struct osd_platform_data dm644x_osd_data = {
+       .vpbe_type     = VPBE_VERSION_1,
+};
+
+static struct platform_device dm644x_osd_dev = {
+       .name           = VPBE_OSD_SUBDEV_NAME,
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(dm644x_osd_resources),
+       .resource       = dm644x_osd_resources,
+       .dev            = {
+               .dma_mask               = &dm644x_video_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+               .platform_data          = &dm644x_osd_data,
+       },
+};
+
+#define DM644X_VENC_BASE               0x01c72400
+
+static struct resource dm644x_venc_resources[] = {
+       {
+               .start  = DM644X_VENC_BASE,
+               .end    = DM644X_VENC_BASE + 0x17f,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+#define DM644X_VPSS_MUXSEL_PLL2_MODE          BIT(0)
+#define DM644X_VPSS_MUXSEL_VPBECLK_MODE       BIT(1)
+#define DM644X_VPSS_VENCLKEN                  BIT(3)
+#define DM644X_VPSS_DACCLKEN                  BIT(4)
+
+static int dm644x_venc_setup_clock(enum vpbe_enc_timings_type type,
+                                  unsigned int mode)
+{
+       int ret = 0;
+       u32 v = DM644X_VPSS_VENCLKEN;
+
+       switch (type) {
+       case VPBE_ENC_STD:
+               v |= DM644X_VPSS_DACCLKEN;
+               writel(v, DAVINCI_SYSMOD_VIRT(SYSMOD_VPSS_CLKCTL));
+               break;
+       case VPBE_ENC_DV_PRESET:
+               switch (mode) {
+               case V4L2_DV_480P59_94:
+               case V4L2_DV_576P50:
+                       v |= DM644X_VPSS_MUXSEL_PLL2_MODE |
+                            DM644X_VPSS_DACCLKEN;
+                       writel(v, DAVINCI_SYSMOD_VIRT(SYSMOD_VPSS_CLKCTL));
+                       break;
+               case V4L2_DV_720P60:
+               case V4L2_DV_1080I60:
+               case V4L2_DV_1080P30:
+                       /*
+                        * For HD, use external clock source since
+                        * HD requires higher clock rate
+                        */
+                       v |= DM644X_VPSS_MUXSEL_VPBECLK_MODE;
+                       writel(v, DAVINCI_SYSMOD_VIRT(SYSMOD_VPSS_CLKCTL));
+                       break;
+               default:
+                       ret = -EINVAL;
+                       break;
+               }
+               break;
+       default:
+               ret  = -EINVAL;
+       }
+
+       return ret;
+}
+
+static struct resource dm644x_v4l2_disp_resources[] = {
+       {
+               .start  = IRQ_VENCINT,
+               .end    = IRQ_VENCINT,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device dm644x_vpbe_display = {
+       .name           = "vpbe-v4l2",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(dm644x_v4l2_disp_resources),
+       .resource       = dm644x_v4l2_disp_resources,
+       .dev            = {
+               .dma_mask               = &dm644x_video_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       },
+};
+
+static struct venc_platform_data dm644x_venc_pdata = {
+       .venc_type      = VPBE_VERSION_1,
+       .setup_clock    = dm644x_venc_setup_clock,
+};
+
+static struct platform_device dm644x_venc_dev = {
+       .name           = VPBE_VENC_SUBDEV_NAME,
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(dm644x_venc_resources),
+       .resource       = dm644x_venc_resources,
+       .dev            = {
+               .dma_mask               = &dm644x_video_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+               .platform_data          = &dm644x_venc_pdata,
+       },
+};
+
+static struct platform_device dm644x_vpbe_dev = {
+       .name           = "vpbe_controller",
+       .id             = -1,
+       .dev            = {
+               .dma_mask               = &dm644x_video_dma_mask,
                .coherent_dma_mask      = DMA_BIT_MASK(32),
        },
 };
@@ -786,17 +913,30 @@ void __init dm644x_init(void)
        davinci_map_sysmod();
 }
 
-int __init dm644x_init_video(struct vpfe_config *vpfe_cfg)
+int __init dm644x_init_video(struct vpfe_config *vpfe_cfg,
+                               struct vpbe_config *vpbe_cfg)
 {
-       dm644x_vpfe_dev.dev.platform_data = vpfe_cfg;
-
-       /* Add ccdc clock aliases */
-       clk_add_alias("master", dm644x_ccdc_dev.name, "vpss_master", NULL);
-       clk_add_alias("slave", dm644x_ccdc_dev.name, "vpss_slave", NULL);
-
-       platform_device_register(&dm644x_vpss_device);
-       platform_device_register(&dm644x_ccdc_dev);
-       platform_device_register(&dm644x_vpfe_dev);
+       if (vpfe_cfg || vpbe_cfg)
+               platform_device_register(&dm644x_vpss_device);
+
+       if (vpfe_cfg) {
+               dm644x_vpfe_dev.dev.platform_data = vpfe_cfg;
+               platform_device_register(&dm644x_ccdc_dev);
+               platform_device_register(&dm644x_vpfe_dev);
+               /* Add ccdc clock aliases */
+               clk_add_alias("master", dm644x_ccdc_dev.name,
+                             "vpss_master", NULL);
+               clk_add_alias("slave", dm644x_ccdc_dev.name,
+                             "vpss_slave", NULL);
+       }
+
+       if (vpbe_cfg) {
+               dm644x_vpbe_dev.dev.platform_data = vpbe_cfg;
+               platform_device_register(&dm644x_osd_dev);
+               platform_device_register(&dm644x_venc_dev);
+               platform_device_register(&dm644x_vpbe_dev);
+               platform_device_register(&dm644x_vpbe_display);
+       }
 
        return 0;
 }
index e400d75..8c9f56a 100644 (file)
@@ -22,7 +22,7 @@
 #include <asm/mach-types.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
-#include <asm/system.h>
+#include <asm/system_misc.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/irq.h>
index d43121a..99e14e3 100644 (file)
@@ -17,7 +17,6 @@
 
 #include <mach/hardware.h>
 #include <asm/leds.h>
-#include <asm/system.h>
 #include <asm/mach-types.h>
 
 #include "core.h"
index 2bf7d6e..0491cee 100644 (file)
@@ -11,18 +11,19 @@ if ARCH_EXYNOS
 
 menu "SAMSUNG EXYNOS SoCs Support"
 
-choice
-       prompt "EXYNOS System Type"
-       default ARCH_EXYNOS4
-
 config ARCH_EXYNOS4
        bool "SAMSUNG EXYNOS4"
+       default y
        select HAVE_SMP
        select MIGHT_HAVE_CACHE_L2X0
        help
          Samsung EXYNOS4 SoCs based systems
 
-endchoice
+config ARCH_EXYNOS5
+       bool "SAMSUNG EXYNOS5"
+       select HAVE_SMP
+       help
+         Samsung EXYNOS5 (Cortex-A15) SoC based systems
 
 comment "EXYNOS SoCs"
 
@@ -56,6 +57,13 @@ config SOC_EXYNOS4412
        help
          Enable EXYNOS4412 SoC support
 
+config SOC_EXYNOS5250
+       bool "SAMSUNG EXYNOS5250"
+       default y
+       depends on ARCH_EXYNOS5
+       help
+         Enable EXYNOS5250 SoC support
+
 config EXYNOS4_MCT
        bool
        default y
@@ -356,7 +364,7 @@ config MACH_SMDK4412
          Machine support for Samsung SMDK4412
 endif
 
-comment "Flattened Device Tree based board for Exynos4 based SoC"
+comment "Flattened Device Tree based board for EXYNOS SoCs"
 
 config MACH_EXYNOS4_DT
        bool "Samsung Exynos4 Machine using device tree"
@@ -370,6 +378,15 @@ config MACH_EXYNOS4_DT
          Note: This is under development and not all peripherals can be supported
          with this machine file.
 
+config MACH_EXYNOS5_DT
+       bool "SAMSUNG EXYNOS5 Machine using device tree"
+       select SOC_EXYNOS5250
+       select USE_OF
+       select ARM_AMBA
+       help
+         Machine support for Samsung Exynos4 machine with device tree enabled.
+         Select this if a fdt blob is available for the EXYNOS4 SoC based board.
+
 if ARCH_EXYNOS4
 
 comment "Configuration for HSMMC 8-bit bus width"
index 9a4c098..8631840 100644 (file)
@@ -14,6 +14,7 @@ obj-                          :=
 
 obj-$(CONFIG_ARCH_EXYNOS)      += common.o
 obj-$(CONFIG_ARCH_EXYNOS4)     += clock-exynos4.o
+obj-$(CONFIG_ARCH_EXYNOS5)     += clock-exynos5.o
 obj-$(CONFIG_CPU_EXYNOS4210)   += clock-exynos4210.o
 obj-$(CONFIG_SOC_EXYNOS4212)   += clock-exynos4212.o
 
@@ -42,9 +43,11 @@ obj-$(CONFIG_MACH_SMDK4212)          += mach-smdk4x12.o
 obj-$(CONFIG_MACH_SMDK4412)            += mach-smdk4x12.o
 
 obj-$(CONFIG_MACH_EXYNOS4_DT)          += mach-exynos4-dt.o
+obj-$(CONFIG_MACH_EXYNOS5_DT)          += mach-exynos5-dt.o
 
 # device support
 
+obj-y                                  += dev-uart.o
 obj-$(CONFIG_ARCH_EXYNOS4)             += dev-audio.o
 obj-$(CONFIG_EXYNOS4_DEV_AHCI)         += dev-ahci.o
 obj-$(CONFIG_EXYNOS4_DEV_SYSMMU)       += dev-sysmmu.o
@@ -52,7 +55,7 @@ obj-$(CONFIG_EXYNOS4_DEV_DWMCI)               += dev-dwmci.o
 obj-$(CONFIG_EXYNOS4_DEV_DMA)          += dma.o
 obj-$(CONFIG_EXYNOS4_DEV_USB_OHCI)     += dev-ohci.o
 
-obj-$(CONFIG_ARCH_EXYNOS4)             += setup-i2c0.o
+obj-$(CONFIG_ARCH_EXYNOS)              += setup-i2c0.o
 obj-$(CONFIG_EXYNOS4_SETUP_FIMC)       += setup-fimc.o
 obj-$(CONFIG_EXYNOS4_SETUP_FIMD0)      += setup-fimd0.o
 obj-$(CONFIG_EXYNOS4_SETUP_I2C1)       += setup-i2c1.o
index 200159d..df54c2a 100644 (file)
@@ -496,11 +496,6 @@ static struct clk exynos4_init_clocks_off[] = {
                .enable         = exynos4_clk_ip_cam_ctrl,
                .ctrlbit        = (1 << 3),
        }, {
-               .name           = "fimd",
-               .devname        = "exynos4-fb.0",
-               .enable         = exynos4_clk_ip_lcd0_ctrl,
-               .ctrlbit        = (1 << 0),
-       }, {
                .name           = "hsmmc",
                .devname        = "s3c-sdhci.0",
                .parent         = &exynos4_clk_aclk_133.clk,
@@ -796,6 +791,13 @@ static struct clk exynos4_clk_mdma1 = {
        .ctrlbit        = ((1 << 8) | (1 << 5) | (1 << 2)),
 };
 
+static struct clk exynos4_clk_fimd0 = {
+       .name           = "fimd",
+       .devname        = "exynos4-fb.0",
+       .enable         = exynos4_clk_ip_lcd0_ctrl,
+       .ctrlbit        = (1 << 0),
+};
+
 struct clk *exynos4_clkset_group_list[] = {
        [0] = &clk_ext_xtal_mux,
        [1] = &clk_xusbxti,
@@ -1315,6 +1317,7 @@ static struct clk *exynos4_clk_cdev[] = {
        &exynos4_clk_pdma0,
        &exynos4_clk_pdma1,
        &exynos4_clk_mdma1,
+       &exynos4_clk_fimd0,
 };
 
 static struct clksrc_clk *exynos4_clksrc_cdev[] = {
@@ -1341,6 +1344,7 @@ static struct clk_lookup exynos4_clk_lookup[] = {
        CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &exynos4_clk_sclk_mmc1.clk),
        CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.2", &exynos4_clk_sclk_mmc2.clk),
        CLKDEV_INIT("s3c-sdhci.3", "mmc_busclk.2", &exynos4_clk_sclk_mmc3.clk),
+       CLKDEV_INIT("exynos4-fb.0", "lcd", &exynos4_clk_fimd0),
        CLKDEV_INIT("dma-pl330.0", "apb_pclk", &exynos4_clk_pdma0),
        CLKDEV_INIT("dma-pl330.1", "apb_pclk", &exynos4_clk_pdma1),
        CLKDEV_INIT("dma-pl330.2", "apb_pclk", &exynos4_clk_mdma1),
diff --git a/arch/arm/mach-exynos/clock-exynos5.c b/arch/arm/mach-exynos/clock-exynos5.c
new file mode 100644 (file)
index 0000000..d013982
--- /dev/null
@@ -0,0 +1,1247 @@
+/*
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Clock support for EXYNOS5 SoCs
+ *
+ * This program is free software; you can 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/err.h>
+#include <linux/io.h>
+#include <linux/syscore_ops.h>
+
+#include <plat/cpu-freq.h>
+#include <plat/clock.h>
+#include <plat/cpu.h>
+#include <plat/pll.h>
+#include <plat/s5p-clock.h>
+#include <plat/clock-clksrc.h>
+#include <plat/pm.h>
+
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+#include <mach/sysmmu.h>
+
+#include "common.h"
+
+#ifdef CONFIG_PM_SLEEP
+static struct sleep_save exynos5_clock_save[] = {
+       /* will be implemented */
+};
+#endif
+
+static struct clk exynos5_clk_sclk_dptxphy = {
+       .name           = "sclk_dptx",
+};
+
+static struct clk exynos5_clk_sclk_hdmi24m = {
+       .name           = "sclk_hdmi24m",
+       .rate           = 24000000,
+};
+
+static struct clk exynos5_clk_sclk_hdmi27m = {
+       .name           = "sclk_hdmi27m",
+       .rate           = 27000000,
+};
+
+static struct clk exynos5_clk_sclk_hdmiphy = {
+       .name           = "sclk_hdmiphy",
+};
+
+static struct clk exynos5_clk_sclk_usbphy = {
+       .name           = "sclk_usbphy",
+       .rate           = 48000000,
+};
+
+static int exynos5_clksrc_mask_top_ctrl(struct clk *clk, int enable)
+{
+       return s5p_gatectrl(EXYNOS5_CLKSRC_MASK_TOP, clk, enable);
+}
+
+static int exynos5_clksrc_mask_disp1_0_ctrl(struct clk *clk, int enable)
+{
+       return s5p_gatectrl(EXYNOS5_CLKSRC_MASK_DISP1_0, clk, enable);
+}
+
+static int exynos5_clksrc_mask_fsys_ctrl(struct clk *clk, int enable)
+{
+       return s5p_gatectrl(EXYNOS5_CLKSRC_MASK_FSYS, clk, enable);
+}
+
+static int exynos5_clksrc_mask_gscl_ctrl(struct clk *clk, int enable)
+{
+       return s5p_gatectrl(EXYNOS5_CLKSRC_MASK_GSCL, clk, enable);
+}
+
+static int exynos5_clksrc_mask_peric0_ctrl(struct clk *clk, int enable)
+{
+       return s5p_gatectrl(EXYNOS5_CLKSRC_MASK_PERIC0, clk, enable);
+}
+
+static int exynos5_clk_ip_core_ctrl(struct clk *clk, int enable)
+{
+       return s5p_gatectrl(EXYNOS5_CLKGATE_IP_CORE, clk, enable);
+}
+
+static int exynos5_clk_ip_disp1_ctrl(struct clk *clk, int enable)
+{
+       return s5p_gatectrl(EXYNOS5_CLKGATE_IP_DISP1, clk, enable);
+}
+
+static int exynos5_clk_ip_fsys_ctrl(struct clk *clk, int enable)
+{
+       return s5p_gatectrl(EXYNOS5_CLKGATE_IP_FSYS, clk, enable);
+}
+
+static int exynos5_clk_block_ctrl(struct clk *clk, int enable)
+{
+       return s5p_gatectrl(EXYNOS5_CLKGATE_BLOCK, clk, enable);
+}
+
+static int exynos5_clk_ip_gen_ctrl(struct clk *clk, int enable)
+{
+       return s5p_gatectrl(EXYNOS5_CLKGATE_IP_GEN, clk, enable);
+}
+
+static int exynos5_clk_ip_gps_ctrl(struct clk *clk, int enable)
+{
+       return s5p_gatectrl(EXYNOS5_CLKGATE_IP_GPS, clk, enable);
+}
+
+static int exynos5_clk_ip_mfc_ctrl(struct clk *clk, int enable)
+{
+       return s5p_gatectrl(EXYNOS5_CLKGATE_IP_MFC, clk, enable);
+}
+
+static int exynos5_clk_ip_peric_ctrl(struct clk *clk, int enable)
+{
+       return s5p_gatectrl(EXYNOS5_CLKGATE_IP_PERIC, clk, enable);
+}
+
+static int exynos5_clk_ip_peris_ctrl(struct clk *clk, int enable)
+{
+       return s5p_gatectrl(EXYNOS5_CLKGATE_IP_PERIS, clk, enable);
+}
+
+/* Core list of CMU_CPU side */
+
+static struct clksrc_clk exynos5_clk_mout_apll = {
+       .clk    = {
+               .name           = "mout_apll",
+       },
+       .sources = &clk_src_apll,
+       .reg_src = { .reg = EXYNOS5_CLKSRC_CPU, .shift = 0, .size = 1 },
+};
+
+static struct clksrc_clk exynos5_clk_sclk_apll = {
+       .clk    = {
+               .name           = "sclk_apll",
+               .parent         = &exynos5_clk_mout_apll.clk,
+       },
+       .reg_div = { .reg = EXYNOS5_CLKDIV_CPU0, .shift = 24, .size = 3 },
+};
+
+static struct clksrc_clk exynos5_clk_mout_bpll = {
+       .clk    = {
+               .name           = "mout_bpll",
+       },
+       .sources = &clk_src_bpll,
+       .reg_src = { .reg = EXYNOS5_CLKSRC_CDREX, .shift = 0, .size = 1 },
+};
+
+static struct clk *exynos5_clk_src_bpll_user_list[] = {
+       [0] = &clk_fin_mpll,
+       [1] = &exynos5_clk_mout_bpll.clk,
+};
+
+static struct clksrc_sources exynos5_clk_src_bpll_user = {
+       .sources        = exynos5_clk_src_bpll_user_list,
+       .nr_sources     = ARRAY_SIZE(exynos5_clk_src_bpll_user_list),
+};
+
+static struct clksrc_clk exynos5_clk_mout_bpll_user = {
+       .clk    = {
+               .name           = "mout_bpll_user",
+       },
+       .sources = &exynos5_clk_src_bpll_user,
+       .reg_src = { .reg = EXYNOS5_CLKSRC_TOP2, .shift = 24, .size = 1 },
+};
+
+static struct clksrc_clk exynos5_clk_mout_cpll = {
+       .clk    = {
+               .name           = "mout_cpll",
+       },
+       .sources = &clk_src_cpll,
+       .reg_src = { .reg = EXYNOS5_CLKSRC_TOP2, .shift = 8, .size = 1 },
+};
+
+static struct clksrc_clk exynos5_clk_mout_epll = {
+       .clk    = {
+               .name           = "mout_epll",
+       },
+       .sources = &clk_src_epll,
+       .reg_src = { .reg = EXYNOS5_CLKSRC_TOP2, .shift = 12, .size = 1 },
+};
+
+struct clksrc_clk exynos5_clk_mout_mpll = {
+       .clk = {
+               .name           = "mout_mpll",
+       },
+       .sources = &clk_src_mpll,
+       .reg_src = { .reg = EXYNOS5_CLKSRC_CORE1, .shift = 8, .size = 1 },
+};
+
+static struct clk *exynos_clkset_vpllsrc_list[] = {
+       [0] = &clk_fin_vpll,
+       [1] = &exynos5_clk_sclk_hdmi27m,
+};
+
+static struct clksrc_sources exynos5_clkset_vpllsrc = {
+       .sources        = exynos_clkset_vpllsrc_list,
+       .nr_sources     = ARRAY_SIZE(exynos_clkset_vpllsrc_list),
+};
+
+static struct clksrc_clk exynos5_clk_vpllsrc = {
+       .clk    = {
+               .name           = "vpll_src",
+               .enable         = exynos5_clksrc_mask_top_ctrl,
+               .ctrlbit        = (1 << 0),
+       },
+       .sources = &exynos5_clkset_vpllsrc,
+       .reg_src = { .reg = EXYNOS5_CLKSRC_TOP2, .shift = 0, .size = 1 },
+};
+
+static struct clk *exynos5_clkset_sclk_vpll_list[] = {
+       [0] = &exynos5_clk_vpllsrc.clk,
+       [1] = &clk_fout_vpll,
+};
+
+static struct clksrc_sources exynos5_clkset_sclk_vpll = {
+       .sources        = exynos5_clkset_sclk_vpll_list,
+       .nr_sources     = ARRAY_SIZE(exynos5_clkset_sclk_vpll_list),
+};
+
+static struct clksrc_clk exynos5_clk_sclk_vpll = {
+       .clk    = {
+               .name           = "sclk_vpll",
+       },
+       .sources = &exynos5_clkset_sclk_vpll,
+       .reg_src = { .reg = EXYNOS5_CLKSRC_TOP2, .shift = 16, .size = 1 },
+};
+
+static struct clksrc_clk exynos5_clk_sclk_pixel = {
+       .clk    = {
+               .name           = "sclk_pixel",
+               .parent         = &exynos5_clk_sclk_vpll.clk,
+       },
+       .reg_div = { .reg = EXYNOS5_CLKDIV_DISP1_0, .shift = 28, .size = 4 },
+};
+
+static struct clk *exynos5_clkset_sclk_hdmi_list[] = {
+       [0] = &exynos5_clk_sclk_pixel.clk,
+       [1] = &exynos5_clk_sclk_hdmiphy,
+};
+
+static struct clksrc_sources exynos5_clkset_sclk_hdmi = {
+       .sources        = exynos5_clkset_sclk_hdmi_list,
+       .nr_sources     = ARRAY_SIZE(exynos5_clkset_sclk_hdmi_list),
+};
+
+static struct clksrc_clk exynos5_clk_sclk_hdmi = {
+       .clk    = {
+               .name           = "sclk_hdmi",
+               .enable         = exynos5_clksrc_mask_disp1_0_ctrl,
+               .ctrlbit        = (1 << 20),
+       },
+       .sources = &exynos5_clkset_sclk_hdmi,
+       .reg_src = { .reg = EXYNOS5_CLKSRC_DISP1_0, .shift = 20, .size = 1 },
+};
+
+static struct clksrc_clk *exynos5_sclk_tv[] = {
+       &exynos5_clk_sclk_pixel,
+       &exynos5_clk_sclk_hdmi,
+};
+
+static struct clk *exynos5_clk_src_mpll_user_list[] = {
+       [0] = &clk_fin_mpll,
+       [1] = &exynos5_clk_mout_mpll.clk,
+};
+
+static struct clksrc_sources exynos5_clk_src_mpll_user = {
+       .sources        = exynos5_clk_src_mpll_user_list,
+       .nr_sources     = ARRAY_SIZE(exynos5_clk_src_mpll_user_list),
+};
+
+static struct clksrc_clk exynos5_clk_mout_mpll_user = {
+       .clk    = {
+               .name           = "mout_mpll_user",
+       },
+       .sources = &exynos5_clk_src_mpll_user,
+       .reg_src = { .reg = EXYNOS5_CLKSRC_TOP2, .shift = 20, .size = 1 },
+};
+
+static struct clk *exynos5_clkset_mout_cpu_list[] = {
+       [0] = &exynos5_clk_mout_apll.clk,
+       [1] = &exynos5_clk_mout_mpll.clk,
+};
+
+static struct clksrc_sources exynos5_clkset_mout_cpu = {
+       .sources        = exynos5_clkset_mout_cpu_list,
+       .nr_sources     = ARRAY_SIZE(exynos5_clkset_mout_cpu_list),
+};
+
+static struct clksrc_clk exynos5_clk_mout_cpu = {
+       .clk    = {
+               .name           = "mout_cpu",
+       },
+       .sources = &exynos5_clkset_mout_cpu,
+       .reg_src = { .reg = EXYNOS5_CLKSRC_CPU, .shift = 16, .size = 1 },
+};
+
+static struct clksrc_clk exynos5_clk_dout_armclk = {
+       .clk    = {
+               .name           = "dout_armclk",
+               .parent         = &exynos5_clk_mout_cpu.clk,
+       },
+       .reg_div = { .reg = EXYNOS5_CLKDIV_CPU0, .shift = 0, .size = 3 },
+};
+
+static struct clksrc_clk exynos5_clk_dout_arm2clk = {
+       .clk    = {
+               .name           = "dout_arm2clk",
+               .parent         = &exynos5_clk_dout_armclk.clk,
+       },
+       .reg_div = { .reg = EXYNOS5_CLKDIV_CPU0, .shift = 28, .size = 3 },
+};
+
+static struct clk exynos5_clk_armclk = {
+       .name           = "armclk",
+       .parent         = &exynos5_clk_dout_arm2clk.clk,
+};
+
+/* Core list of CMU_CDREX side */
+
+static struct clk *exynos5_clkset_cdrex_list[] = {
+       [0] = &exynos5_clk_mout_mpll.clk,
+       [1] = &exynos5_clk_mout_bpll.clk,
+};
+
+static struct clksrc_sources exynos5_clkset_cdrex = {
+       .sources        = exynos5_clkset_cdrex_list,
+       .nr_sources     = ARRAY_SIZE(exynos5_clkset_cdrex_list),
+};
+
+static struct clksrc_clk exynos5_clk_cdrex = {
+       .clk    = {
+               .name           = "clk_cdrex",
+       },
+       .sources = &exynos5_clkset_cdrex,
+       .reg_src = { .reg = EXYNOS5_CLKSRC_CDREX, .shift = 4, .size = 1 },
+       .reg_div = { .reg = EXYNOS5_CLKDIV_CDREX, .shift = 16, .size = 3 },
+};
+
+static struct clksrc_clk exynos5_clk_aclk_acp = {
+       .clk    = {
+               .name           = "aclk_acp",
+               .parent         = &exynos5_clk_mout_mpll.clk,
+       },
+       .reg_div = { .reg = EXYNOS5_CLKDIV_ACP, .shift = 0, .size = 3 },
+};
+
+static struct clksrc_clk exynos5_clk_pclk_acp = {
+       .clk    = {
+               .name           = "pclk_acp",
+               .parent         = &exynos5_clk_aclk_acp.clk,
+       },
+       .reg_div = { .reg = EXYNOS5_CLKDIV_ACP, .shift = 4, .size = 3 },
+};
+
+/* Core list of CMU_TOP side */
+
+struct clk *exynos5_clkset_aclk_top_list[] = {
+       [0] = &exynos5_clk_mout_mpll_user.clk,
+       [1] = &exynos5_clk_mout_bpll_user.clk,
+};
+
+struct clksrc_sources exynos5_clkset_aclk = {
+       .sources        = exynos5_clkset_aclk_top_list,
+       .nr_sources     = ARRAY_SIZE(exynos5_clkset_aclk_top_list),
+};
+
+static struct clksrc_clk exynos5_clk_aclk_400 = {
+       .clk    = {
+               .name           = "aclk_400",
+       },
+       .sources = &exynos5_clkset_aclk,
+       .reg_src = { .reg = EXYNOS5_CLKSRC_TOP0, .shift = 20, .size = 1 },
+       .reg_div = { .reg = EXYNOS5_CLKDIV_TOP0, .shift = 24, .size = 3 },
+};
+
+struct clk *exynos5_clkset_aclk_333_166_list[] = {
+       [0] = &exynos5_clk_mout_cpll.clk,
+       [1] = &exynos5_clk_mout_mpll_user.clk,
+};
+
+struct clksrc_sources exynos5_clkset_aclk_333_166 = {
+       .sources        = exynos5_clkset_aclk_333_166_list,
+       .nr_sources     = ARRAY_SIZE(exynos5_clkset_aclk_333_166_list),
+};
+
+static struct clksrc_clk exynos5_clk_aclk_333 = {
+       .clk    = {
+               .name           = "aclk_333",
+       },
+       .sources = &exynos5_clkset_aclk_333_166,
+       .reg_src = { .reg = EXYNOS5_CLKSRC_TOP0, .shift = 16, .size = 1 },
+       .reg_div = { .reg = EXYNOS5_CLKDIV_TOP0, .shift = 20, .size = 3 },
+};
+
+static struct clksrc_clk exynos5_clk_aclk_166 = {
+       .clk    = {
+               .name           = "aclk_166",
+       },
+       .sources = &exynos5_clkset_aclk_333_166,
+       .reg_src = { .reg = EXYNOS5_CLKSRC_TOP0, .shift = 8, .size = 1 },
+       .reg_div = { .reg = EXYNOS5_CLKDIV_TOP0, .shift = 8, .size = 3 },
+};
+
+static struct clksrc_clk exynos5_clk_aclk_266 = {
+       .clk    = {
+               .name           = "aclk_266",
+               .parent         = &exynos5_clk_mout_mpll_user.clk,
+       },
+       .reg_div = { .reg = EXYNOS5_CLKDIV_TOP0, .shift = 16, .size = 3 },
+};
+
+static struct clksrc_clk exynos5_clk_aclk_200 = {
+       .clk    = {
+               .name           = "aclk_200",
+       },
+       .sources = &exynos5_clkset_aclk,
+       .reg_src = { .reg = EXYNOS5_CLKSRC_TOP0, .shift = 12, .size = 1 },
+       .reg_div = { .reg = EXYNOS5_CLKDIV_TOP0, .shift = 12, .size = 3 },
+};
+
+static struct clksrc_clk exynos5_clk_aclk_66_pre = {
+       .clk    = {
+               .name           = "aclk_66_pre",
+               .parent         = &exynos5_clk_mout_mpll_user.clk,
+       },
+       .reg_div = { .reg = EXYNOS5_CLKDIV_TOP1, .shift = 24, .size = 3 },
+};
+
+static struct clksrc_clk exynos5_clk_aclk_66 = {
+       .clk    = {
+               .name           = "aclk_66",
+               .parent         = &exynos5_clk_aclk_66_pre.clk,
+       },
+       .reg_div = { .reg = EXYNOS5_CLKDIV_TOP0, .shift = 0, .size = 3 },
+};
+
+static struct clk exynos5_init_clocks_off[] = {
+       {
+               .name           = "timers",
+               .parent         = &exynos5_clk_aclk_66.clk,
+               .enable         = exynos5_clk_ip_peric_ctrl,
+               .ctrlbit        = (1 << 24),
+       }, {
+               .name           = "rtc",
+               .parent         = &exynos5_clk_aclk_66.clk,
+               .enable         = exynos5_clk_ip_peris_ctrl,
+               .ctrlbit        = (1 << 20),
+       }, {
+               .name           = "hsmmc",
+               .devname        = "s3c-sdhci.0",
+               .parent         = &exynos5_clk_aclk_200.clk,
+               .enable         = exynos5_clk_ip_fsys_ctrl,
+               .ctrlbit        = (1 << 12),
+       }, {
+               .name           = "hsmmc",
+               .devname        = "s3c-sdhci.1",
+               .parent         = &exynos5_clk_aclk_200.clk,
+               .enable         = exynos5_clk_ip_fsys_ctrl,
+               .ctrlbit        = (1 << 13),
+       }, {
+               .name           = "hsmmc",
+               .devname        = "s3c-sdhci.2",
+               .parent         = &exynos5_clk_aclk_200.clk,
+               .enable         = exynos5_clk_ip_fsys_ctrl,
+               .ctrlbit        = (1 << 14),
+       }, {
+               .name           = "hsmmc",
+               .devname        = "s3c-sdhci.3",
+               .parent         = &exynos5_clk_aclk_200.clk,
+               .enable         = exynos5_clk_ip_fsys_ctrl,
+               .ctrlbit        = (1 << 15),
+       }, {
+               .name           = "dwmci",
+               .parent         = &exynos5_clk_aclk_200.clk,
+               .enable         = exynos5_clk_ip_fsys_ctrl,
+               .ctrlbit        = (1 << 16),
+       }, {
+               .name           = "sata",
+               .devname        = "ahci",
+               .enable         = exynos5_clk_ip_fsys_ctrl,
+               .ctrlbit        = (1 << 6),
+       }, {
+               .name           = "sata_phy",
+               .enable         = exynos5_clk_ip_fsys_ctrl,
+               .ctrlbit        = (1 << 24),
+       }, {
+               .name           = "sata_phy_i2c",
+               .enable         = exynos5_clk_ip_fsys_ctrl,
+               .ctrlbit        = (1 << 25),
+       }, {
+               .name           = "mfc",
+               .devname        = "s5p-mfc",
+               .enable         = exynos5_clk_ip_mfc_ctrl,
+               .ctrlbit        = (1 << 0),
+       }, {
+               .name           = "hdmi",
+               .devname        = "exynos4-hdmi",
+               .enable         = exynos5_clk_ip_disp1_ctrl,
+               .ctrlbit        = (1 << 6),
+       }, {
+               .name           = "mixer",
+               .devname        = "s5p-mixer",
+               .enable         = exynos5_clk_ip_disp1_ctrl,
+               .ctrlbit        = (1 << 5),
+       }, {
+               .name           = "jpeg",
+               .enable         = exynos5_clk_ip_gen_ctrl,
+               .ctrlbit        = (1 << 2),
+       }, {
+               .name           = "dsim0",
+               .enable         = exynos5_clk_ip_disp1_ctrl,
+               .ctrlbit        = (1 << 3),
+       }, {
+               .name           = "iis",
+               .devname        = "samsung-i2s.1",
+               .enable         = exynos5_clk_ip_peric_ctrl,
+               .ctrlbit        = (1 << 20),
+       }, {
+               .name           = "iis",
+               .devname        = "samsung-i2s.2",
+               .enable         = exynos5_clk_ip_peric_ctrl,
+               .ctrlbit        = (1 << 21),
+       }, {
+               .name           = "pcm",
+               .devname        = "samsung-pcm.1",
+               .enable         = exynos5_clk_ip_peric_ctrl,
+               .ctrlbit        = (1 << 22),
+       }, {
+               .name           = "pcm",
+               .devname        = "samsung-pcm.2",
+               .enable         = exynos5_clk_ip_peric_ctrl,
+               .ctrlbit        = (1 << 23),
+       }, {
+               .name           = "spdif",
+               .devname        = "samsung-spdif",
+               .enable         = exynos5_clk_ip_peric_ctrl,
+               .ctrlbit        = (1 << 26),
+       }, {
+               .name           = "ac97",
+               .devname        = "samsung-ac97",
+               .enable         = exynos5_clk_ip_peric_ctrl,
+               .ctrlbit        = (1 << 27),
+       }, {
+               .name           = "usbhost",
+               .enable         = exynos5_clk_ip_fsys_ctrl ,
+               .ctrlbit        = (1 << 18),
+       }, {
+               .name           = "usbotg",
+               .enable         = exynos5_clk_ip_fsys_ctrl,
+               .ctrlbit        = (1 << 7),
+       }, {
+               .name           = "gps",
+               .enable         = exynos5_clk_ip_gps_ctrl,
+               .ctrlbit        = ((1 << 3) | (1 << 2) | (1 << 0)),
+       }, {
+               .name           = "nfcon",
+               .enable         = exynos5_clk_ip_fsys_ctrl,
+               .ctrlbit        = (1 << 22),
+       }, {
+               .name           = "iop",
+               .enable         = exynos5_clk_ip_fsys_ctrl,
+               .ctrlbit        = ((1 << 30) | (1 << 26) | (1 << 23)),
+       }, {
+               .name           = "core_iop",
+               .enable         = exynos5_clk_ip_core_ctrl,
+               .ctrlbit        = ((1 << 21) | (1 << 3)),
+       }, {
+               .name           = "mcu_iop",
+               .enable         = exynos5_clk_ip_fsys_ctrl,
+               .ctrlbit        = (1 << 0),
+       }, {
+               .name           = "i2c",
+               .devname        = "s3c2440-i2c.0",
+               .parent         = &exynos5_clk_aclk_66.clk,
+               .enable         = exynos5_clk_ip_peric_ctrl,
+               .ctrlbit        = (1 << 6),
+       }, {
+               .name           = "i2c",
+               .devname        = "s3c2440-i2c.1",
+               .parent         = &exynos5_clk_aclk_66.clk,
+               .enable         = exynos5_clk_ip_peric_ctrl,
+               .ctrlbit        = (1 << 7),
+       }, {
+               .name           = "i2c",
+               .devname        = "s3c2440-i2c.2",
+               .parent         = &exynos5_clk_aclk_66.clk,
+               .enable         = exynos5_clk_ip_peric_ctrl,
+               .ctrlbit        = (1 << 8),
+       }, {
+               .name           = "i2c",
+               .devname        = "s3c2440-i2c.3",
+               .parent         = &exynos5_clk_aclk_66.clk,
+               .enable         = exynos5_clk_ip_peric_ctrl,
+               .ctrlbit        = (1 << 9),
+       }, {
+               .name           = "i2c",
+               .devname        = "s3c2440-i2c.4",
+               .parent         = &exynos5_clk_aclk_66.clk,
+               .enable         = exynos5_clk_ip_peric_ctrl,
+               .ctrlbit        = (1 << 10),
+       }, {
+               .name           = "i2c",
+               .devname        = "s3c2440-i2c.5",
+               .parent         = &exynos5_clk_aclk_66.clk,
+               .enable         = exynos5_clk_ip_peric_ctrl,
+               .ctrlbit        = (1 << 11),
+       }, {
+               .name           = "i2c",
+               .devname        = "s3c2440-i2c.6",
+               .parent         = &exynos5_clk_aclk_66.clk,
+               .enable         = exynos5_clk_ip_peric_ctrl,
+               .ctrlbit        = (1 << 12),
+       }, {
+               .name           = "i2c",
+               .devname        = "s3c2440-i2c.7",
+               .parent         = &exynos5_clk_aclk_66.clk,
+               .enable         = exynos5_clk_ip_peric_ctrl,
+               .ctrlbit        = (1 << 13),
+       }, {
+               .name           = "i2c",
+               .devname        = "s3c2440-hdmiphy-i2c",
+               .parent         = &exynos5_clk_aclk_66.clk,
+               .enable         = exynos5_clk_ip_peric_ctrl,
+               .ctrlbit        = (1 << 14),
+       }
+};
+
+static struct clk exynos5_init_clocks_on[] = {
+       {
+               .name           = "uart",
+               .devname        = "s5pv210-uart.0",
+               .enable         = exynos5_clk_ip_peric_ctrl,
+               .ctrlbit        = (1 << 0),
+       }, {
+               .name           = "uart",
+               .devname        = "s5pv210-uart.1",
+               .enable         = exynos5_clk_ip_peric_ctrl,
+               .ctrlbit        = (1 << 1),
+       }, {
+               .name           = "uart",
+               .devname        = "s5pv210-uart.2",
+               .enable         = exynos5_clk_ip_peric_ctrl,
+               .ctrlbit        = (1 << 2),
+       }, {
+               .name           = "uart",
+               .devname        = "s5pv210-uart.3",
+               .enable         = exynos5_clk_ip_peric_ctrl,
+               .ctrlbit        = (1 << 3),
+       }, {
+               .name           = "uart",
+               .devname        = "s5pv210-uart.4",
+               .enable         = exynos5_clk_ip_peric_ctrl,
+               .ctrlbit        = (1 << 4),
+       }, {
+               .name           = "uart",
+               .devname        = "s5pv210-uart.5",
+               .enable         = exynos5_clk_ip_peric_ctrl,
+               .ctrlbit        = (1 << 5),
+       }
+};
+
+static struct clk exynos5_clk_pdma0 = {
+       .name           = "dma",
+       .devname        = "dma-pl330.0",
+       .enable         = exynos5_clk_ip_fsys_ctrl,
+       .ctrlbit        = (1 << 1),
+};
+
+static struct clk exynos5_clk_pdma1 = {
+       .name           = "dma",
+       .devname        = "dma-pl330.1",
+       .enable         = exynos5_clk_ip_fsys_ctrl,
+       .ctrlbit        = (1 << 1),
+};
+
+static struct clk exynos5_clk_mdma1 = {
+       .name           = "dma",
+       .devname        = "dma-pl330.2",
+       .enable         = exynos5_clk_ip_gen_ctrl,
+       .ctrlbit        = (1 << 4),
+};
+
+struct clk *exynos5_clkset_group_list[] = {
+       [0] = &clk_ext_xtal_mux,
+       [1] = NULL,
+       [2] = &exynos5_clk_sclk_hdmi24m,
+       [3] = &exynos5_clk_sclk_dptxphy,
+       [4] = &exynos5_clk_sclk_usbphy,
+       [5] = &exynos5_clk_sclk_hdmiphy,
+       [6] = &exynos5_clk_mout_mpll_user.clk,
+       [7] = &exynos5_clk_mout_epll.clk,
+       [8] = &exynos5_clk_sclk_vpll.clk,
+       [9] = &exynos5_clk_mout_cpll.clk,
+};
+
+struct clksrc_sources exynos5_clkset_group = {
+       .sources        = exynos5_clkset_group_list,
+       .nr_sources     = ARRAY_SIZE(exynos5_clkset_group_list),
+};
+
+/* Possible clock sources for aclk_266_gscl_sub Mux */
+static struct clk *clk_src_gscl_266_list[] = {
+       [0] = &clk_ext_xtal_mux,
+       [1] = &exynos5_clk_aclk_266.clk,
+};
+
+static struct clksrc_sources clk_src_gscl_266 = {
+       .sources        = clk_src_gscl_266_list,
+       .nr_sources     = ARRAY_SIZE(clk_src_gscl_266_list),
+};
+
+static struct clksrc_clk exynos5_clk_dout_mmc0 = {
+       .clk            = {
+               .name           = "dout_mmc0",
+       },
+       .sources = &exynos5_clkset_group,
+       .reg_src = { .reg = EXYNOS5_CLKSRC_FSYS, .shift = 0, .size = 4 },
+       .reg_div = { .reg = EXYNOS5_CLKDIV_FSYS1, .shift = 0, .size = 4 },
+};
+
+static struct clksrc_clk exynos5_clk_dout_mmc1 = {
+       .clk            = {
+               .name           = "dout_mmc1",
+       },
+       .sources = &exynos5_clkset_group,
+       .reg_src = { .reg = EXYNOS5_CLKSRC_FSYS, .shift = 4, .size = 4 },
+       .reg_div = { .reg = EXYNOS5_CLKDIV_FSYS1, .shift = 16, .size = 4 },
+};
+
+static struct clksrc_clk exynos5_clk_dout_mmc2 = {
+       .clk            = {
+               .name           = "dout_mmc2",
+       },
+       .sources = &exynos5_clkset_group,
+       .reg_src = { .reg = EXYNOS5_CLKSRC_FSYS, .shift = 8, .size = 4 },
+       .reg_div = { .reg = EXYNOS5_CLKDIV_FSYS2, .shift = 0, .size = 4 },
+};
+
+static struct clksrc_clk exynos5_clk_dout_mmc3 = {
+       .clk            = {
+               .name           = "dout_mmc3",
+       },
+       .sources = &exynos5_clkset_group,
+       .reg_src = { .reg = EXYNOS5_CLKSRC_FSYS, .shift = 12, .size = 4 },
+       .reg_div = { .reg = EXYNOS5_CLKDIV_FSYS2, .shift = 16, .size = 4 },
+};
+
+static struct clksrc_clk exynos5_clk_dout_mmc4 = {
+       .clk            = {
+               .name           = "dout_mmc4",
+       },
+       .sources = &exynos5_clkset_group,
+       .reg_src = { .reg = EXYNOS5_CLKSRC_FSYS, .shift = 16, .size = 4 },
+       .reg_div = { .reg = EXYNOS5_CLKDIV_FSYS3, .shift = 0, .size = 4 },
+};
+
+static struct clksrc_clk exynos5_clk_sclk_uart0 = {
+       .clk    = {
+               .name           = "uclk1",
+               .devname        = "exynos4210-uart.0",
+               .enable         = exynos5_clksrc_mask_peric0_ctrl,
+               .ctrlbit        = (1 << 0),
+       },
+       .sources = &exynos5_clkset_group,
+       .reg_src = { .reg = EXYNOS5_CLKSRC_PERIC0, .shift = 0, .size = 4 },
+       .reg_div = { .reg = EXYNOS5_CLKDIV_PERIC0, .shift = 0, .size = 4 },
+};
+
+static struct clksrc_clk exynos5_clk_sclk_uart1 = {
+       .clk    = {
+               .name           = "uclk1",
+               .devname        = "exynos4210-uart.1",
+               .enable         = exynos5_clksrc_mask_peric0_ctrl,
+               .ctrlbit        = (1 << 4),
+       },
+       .sources = &exynos5_clkset_group,
+       .reg_src = { .reg = EXYNOS5_CLKSRC_PERIC0, .shift = 4, .size = 4 },
+       .reg_div = { .reg = EXYNOS5_CLKDIV_PERIC0, .shift = 4, .size = 4 },
+};
+
+static struct clksrc_clk exynos5_clk_sclk_uart2 = {
+       .clk    = {
+               .name           = "uclk1",
+               .devname        = "exynos4210-uart.2",
+               .enable         = exynos5_clksrc_mask_peric0_ctrl,
+               .ctrlbit        = (1 << 8),
+       },
+       .sources = &exynos5_clkset_group,
+       .reg_src = { .reg = EXYNOS5_CLKSRC_PERIC0, .shift = 8, .size = 4 },
+       .reg_div = { .reg = EXYNOS5_CLKDIV_PERIC0, .shift = 8, .size = 4 },
+};
+
+static struct clksrc_clk exynos5_clk_sclk_uart3 = {
+       .clk    = {
+               .name           = "uclk1",
+               .devname        = "exynos4210-uart.3",
+               .enable         = exynos5_clksrc_mask_peric0_ctrl,
+               .ctrlbit        = (1 << 12),
+       },
+       .sources = &exynos5_clkset_group,
+       .reg_src = { .reg = EXYNOS5_CLKSRC_PERIC0, .shift = 12, .size = 4 },
+       .reg_div = { .reg = EXYNOS5_CLKDIV_PERIC0, .shift = 12, .size = 4 },
+};
+
+static struct clksrc_clk exynos5_clk_sclk_mmc0 = {
+       .clk    = {
+               .name           = "sclk_mmc",
+               .devname        = "s3c-sdhci.0",
+               .parent         = &exynos5_clk_dout_mmc0.clk,
+               .enable         = exynos5_clksrc_mask_fsys_ctrl,
+               .ctrlbit        = (1 << 0),
+       },
+       .reg_div = { .reg = EXYNOS5_CLKDIV_FSYS1, .shift = 8, .size = 8 },
+};
+
+static struct clksrc_clk exynos5_clk_sclk_mmc1 = {
+       .clk    = {
+               .name           = "sclk_mmc",
+               .devname        = "s3c-sdhci.1",
+               .parent         = &exynos5_clk_dout_mmc1.clk,
+               .enable         = exynos5_clksrc_mask_fsys_ctrl,
+               .ctrlbit        = (1 << 4),
+       },
+       .reg_div = { .reg = EXYNOS5_CLKDIV_FSYS1, .shift = 24, .size = 8 },
+};
+
+static struct clksrc_clk exynos5_clk_sclk_mmc2 = {
+       .clk    = {
+               .name           = "sclk_mmc",
+               .devname        = "s3c-sdhci.2",
+               .parent         = &exynos5_clk_dout_mmc2.clk,
+               .enable         = exynos5_clksrc_mask_fsys_ctrl,
+               .ctrlbit        = (1 << 8),
+       },
+       .reg_div = { .reg = EXYNOS5_CLKDIV_FSYS2, .shift = 8, .size = 8 },
+};
+
+static struct clksrc_clk exynos5_clk_sclk_mmc3 = {
+       .clk    = {
+               .name           = "sclk_mmc",
+               .devname        = "s3c-sdhci.3",
+               .parent         = &exynos5_clk_dout_mmc3.clk,
+               .enable         = exynos5_clksrc_mask_fsys_ctrl,
+               .ctrlbit        = (1 << 12),
+       },
+       .reg_div = { .reg = EXYNOS5_CLKDIV_FSYS2, .shift = 24, .size = 8 },
+};
+
+static struct clksrc_clk exynos5_clksrcs[] = {
+       {
+               .clk    = {
+                       .name           = "sclk_dwmci",
+                       .parent         = &exynos5_clk_dout_mmc4.clk,
+                       .enable         = exynos5_clksrc_mask_fsys_ctrl,
+                       .ctrlbit        = (1 << 16),
+               },
+               .reg_div = { .reg = EXYNOS5_CLKDIV_FSYS3, .shift = 8, .size = 8 },
+       }, {
+               .clk    = {
+                       .name           = "sclk_fimd",
+                       .devname        = "s3cfb.1",
+                       .enable         = exynos5_clksrc_mask_disp1_0_ctrl,
+                       .ctrlbit        = (1 << 0),
+               },
+               .sources = &exynos5_clkset_group,
+               .reg_src = { .reg = EXYNOS5_CLKSRC_DISP1_0, .shift = 0, .size = 4 },
+               .reg_div = { .reg = EXYNOS5_CLKDIV_DISP1_0, .shift = 0, .size = 4 },
+       }, {
+               .clk    = {
+                       .name           = "aclk_266_gscl",
+               },
+               .sources = &clk_src_gscl_266,
+               .reg_src = { .reg = EXYNOS5_CLKSRC_TOP3, .shift = 8, .size = 1 },
+       }, {
+               .clk    = {
+                       .name           = "sclk_g3d",
+                       .devname        = "mali-t604.0",
+                       .enable         = exynos5_clk_block_ctrl,
+                       .ctrlbit        = (1 << 1),
+               },
+               .sources = &exynos5_clkset_aclk,
+               .reg_src = { .reg = EXYNOS5_CLKSRC_TOP0, .shift = 20, .size = 1 },
+               .reg_div = { .reg = EXYNOS5_CLKDIV_TOP0, .shift = 24, .size = 3 },
+       }, {
+               .clk    = {
+                       .name           = "sclk_gscl_wrap",
+                       .devname        = "s5p-mipi-csis.0",
+                       .enable         = exynos5_clksrc_mask_gscl_ctrl,
+                       .ctrlbit        = (1 << 24),
+               },
+               .sources = &exynos5_clkset_group,
+               .reg_src = { .reg = EXYNOS5_CLKSRC_GSCL, .shift = 24, .size = 4 },
+               .reg_div = { .reg = EXYNOS5_CLKDIV_GSCL, .shift = 24, .size = 4 },
+       }, {
+               .clk    = {
+                       .name           = "sclk_gscl_wrap",
+                       .devname        = "s5p-mipi-csis.1",
+                       .enable         = exynos5_clksrc_mask_gscl_ctrl,
+                       .ctrlbit        = (1 << 28),
+               },
+               .sources = &exynos5_clkset_group,
+               .reg_src = { .reg = EXYNOS5_CLKSRC_GSCL, .shift = 28, .size = 4 },
+               .reg_div = { .reg = EXYNOS5_CLKDIV_GSCL, .shift = 28, .size = 4 },
+       }, {
+               .clk    = {
+                       .name           = "sclk_cam0",
+                       .enable         = exynos5_clksrc_mask_gscl_ctrl,
+                       .ctrlbit        = (1 << 16),
+               },
+               .sources = &exynos5_clkset_group,
+               .reg_src = { .reg = EXYNOS5_CLKSRC_GSCL, .shift = 16, .size = 4 },
+               .reg_div = { .reg = EXYNOS5_CLKDIV_GSCL, .shift = 16, .size = 4 },
+       }, {
+               .clk    = {
+                       .name           = "sclk_cam1",
+                       .enable         = exynos5_clksrc_mask_gscl_ctrl,
+                       .ctrlbit        = (1 << 20),
+               },
+               .sources = &exynos5_clkset_group,
+               .reg_src = { .reg = EXYNOS5_CLKSRC_GSCL, .shift = 20, .size = 4 },
+               .reg_div = { .reg = EXYNOS5_CLKDIV_GSCL, .shift = 20, .size = 4 },
+       }, {
+               .clk    = {
+                       .name           = "sclk_jpeg",
+                       .parent         = &exynos5_clk_mout_cpll.clk,
+               },
+               .reg_div = { .reg = EXYNOS5_CLKDIV_GEN, .shift = 4, .size = 3 },
+       },
+};
+
+/* Clock initialization code */
+static struct clksrc_clk *exynos5_sysclks[] = {
+       &exynos5_clk_mout_apll,
+       &exynos5_clk_sclk_apll,
+       &exynos5_clk_mout_bpll,
+       &exynos5_clk_mout_bpll_user,
+       &exynos5_clk_mout_cpll,
+       &exynos5_clk_mout_epll,
+       &exynos5_clk_mout_mpll,
+       &exynos5_clk_mout_mpll_user,
+       &exynos5_clk_vpllsrc,
+       &exynos5_clk_sclk_vpll,
+       &exynos5_clk_mout_cpu,
+       &exynos5_clk_dout_armclk,
+       &exynos5_clk_dout_arm2clk,
+       &exynos5_clk_cdrex,
+       &exynos5_clk_aclk_400,
+       &exynos5_clk_aclk_333,
+       &exynos5_clk_aclk_266,
+       &exynos5_clk_aclk_200,
+       &exynos5_clk_aclk_166,
+       &exynos5_clk_aclk_66_pre,
+       &exynos5_clk_aclk_66,
+       &exynos5_clk_dout_mmc0,
+       &exynos5_clk_dout_mmc1,
+       &exynos5_clk_dout_mmc2,
+       &exynos5_clk_dout_mmc3,
+       &exynos5_clk_dout_mmc4,
+       &exynos5_clk_aclk_acp,
+       &exynos5_clk_pclk_acp,
+};
+
+static struct clk *exynos5_clk_cdev[] = {
+       &exynos5_clk_pdma0,
+       &exynos5_clk_pdma1,
+       &exynos5_clk_mdma1,
+};
+
+static struct clksrc_clk *exynos5_clksrc_cdev[] = {
+       &exynos5_clk_sclk_uart0,
+       &exynos5_clk_sclk_uart1,
+       &exynos5_clk_sclk_uart2,
+       &exynos5_clk_sclk_uart3,
+       &exynos5_clk_sclk_mmc0,
+       &exynos5_clk_sclk_mmc1,
+       &exynos5_clk_sclk_mmc2,
+       &exynos5_clk_sclk_mmc3,
+};
+
+static struct clk_lookup exynos5_clk_lookup[] = {
+       CLKDEV_INIT("exynos4210-uart.0", "clk_uart_baud0", &exynos5_clk_sclk_uart0.clk),
+       CLKDEV_INIT("exynos4210-uart.1", "clk_uart_baud0", &exynos5_clk_sclk_uart1.clk),
+       CLKDEV_INIT("exynos4210-uart.2", "clk_uart_baud0", &exynos5_clk_sclk_uart2.clk),
+       CLKDEV_INIT("exynos4210-uart.3", "clk_uart_baud0", &exynos5_clk_sclk_uart3.clk),
+       CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.2", &exynos5_clk_sclk_mmc0.clk),
+       CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &exynos5_clk_sclk_mmc1.clk),
+       CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.2", &exynos5_clk_sclk_mmc2.clk),
+       CLKDEV_INIT("s3c-sdhci.3", "mmc_busclk.2", &exynos5_clk_sclk_mmc3.clk),
+       CLKDEV_INIT("dma-pl330.0", "apb_pclk", &exynos5_clk_pdma0),
+       CLKDEV_INIT("dma-pl330.1", "apb_pclk", &exynos5_clk_pdma1),
+       CLKDEV_INIT("dma-pl330.2", "apb_pclk", &exynos5_clk_mdma1),
+};
+
+static unsigned long exynos5_epll_get_rate(struct clk *clk)
+{
+       return clk->rate;
+}
+
+static struct clk *exynos5_clks[] __initdata = {
+       &exynos5_clk_sclk_hdmi27m,
+       &exynos5_clk_sclk_hdmiphy,
+       &clk_fout_bpll,
+       &clk_fout_cpll,
+       &exynos5_clk_armclk,
+};
+
+static u32 epll_div[][6] = {
+       { 192000000, 0, 48, 3, 1, 0 },
+       { 180000000, 0, 45, 3, 1, 0 },
+       {  73728000, 1, 73, 3, 3, 47710 },
+       {  67737600, 1, 90, 4, 3, 20762 },
+       {  49152000, 0, 49, 3, 3, 9961 },
+       {  45158400, 0, 45, 3, 3, 10381 },
+       { 180633600, 0, 45, 3, 1, 10381 },
+};
+
+static int exynos5_epll_set_rate(struct clk *clk, unsigned long rate)
+{
+       unsigned int epll_con, epll_con_k;
+       unsigned int i;
+       unsigned int tmp;
+       unsigned int epll_rate;
+       unsigned int locktime;
+       unsigned int lockcnt;
+
+       /* Return if nothing changed */
+       if (clk->rate == rate)
+               return 0;
+
+       if (clk->parent)
+               epll_rate = clk_get_rate(clk->parent);
+       else
+               epll_rate = clk_ext_xtal_mux.rate;
+
+       if (epll_rate != 24000000) {
+               pr_err("Invalid Clock : recommended clock is 24MHz.\n");
+               return -EINVAL;
+       }
+
+       epll_con = __raw_readl(EXYNOS5_EPLL_CON0);
+       epll_con &= ~(0x1 << 27 | \
+                       PLL46XX_MDIV_MASK << PLL46XX_MDIV_SHIFT |   \
+                       PLL46XX_PDIV_MASK << PLL46XX_PDIV_SHIFT | \
+                       PLL46XX_SDIV_MASK << PLL46XX_SDIV_SHIFT);
+
+       for (i = 0; i < ARRAY_SIZE(epll_div); i++) {
+               if (epll_div[i][0] == rate) {
+                       epll_con_k = epll_div[i][5] << 0;
+                       epll_con |= epll_div[i][1] << 27;
+                       epll_con |= epll_div[i][2] << PLL46XX_MDIV_SHIFT;
+                       epll_con |= epll_div[i][3] << PLL46XX_PDIV_SHIFT;
+                       epll_con |= epll_div[i][4] << PLL46XX_SDIV_SHIFT;
+                       break;
+               }
+       }
+
+       if (i == ARRAY_SIZE(epll_div)) {
+               printk(KERN_ERR "%s: Invalid Clock EPLL Frequency\n",
+                               __func__);
+               return -EINVAL;
+       }
+
+       epll_rate /= 1000000;
+
+       /* 3000 max_cycls : specification data */
+       locktime = 3000 / epll_rate * epll_div[i][3];
+       lockcnt = locktime * 10000 / (10000 / epll_rate);
+
+       __raw_writel(lockcnt, EXYNOS5_EPLL_LOCK);
+
+       __raw_writel(epll_con, EXYNOS5_EPLL_CON0);
+       __raw_writel(epll_con_k, EXYNOS5_EPLL_CON1);
+
+       do {
+               tmp = __raw_readl(EXYNOS5_EPLL_CON0);
+       } while (!(tmp & 0x1 << EXYNOS5_EPLLCON0_LOCKED_SHIFT));
+
+       clk->rate = rate;
+
+       return 0;
+}
+
+static struct clk_ops exynos5_epll_ops = {
+       .get_rate = exynos5_epll_get_rate,
+       .set_rate = exynos5_epll_set_rate,
+};
+
+static int xtal_rate;
+
+static unsigned long exynos5_fout_apll_get_rate(struct clk *clk)
+{
+       return s5p_get_pll35xx(xtal_rate, __raw_readl(EXYNOS5_APLL_CON0));
+}
+
+static struct clk_ops exynos5_fout_apll_ops = {
+       .get_rate = exynos5_fout_apll_get_rate,
+};
+
+#ifdef CONFIG_PM
+static int exynos5_clock_suspend(void)
+{
+       s3c_pm_do_save(exynos5_clock_save, ARRAY_SIZE(exynos5_clock_save));
+
+       return 0;
+}
+
+static void exynos5_clock_resume(void)
+{
+       s3c_pm_do_restore_core(exynos5_clock_save, ARRAY_SIZE(exynos5_clock_save));
+}
+#else
+#define exynos5_clock_suspend NULL
+#define exynos5_clock_resume NULL
+#endif
+
+struct syscore_ops exynos5_clock_syscore_ops = {
+       .suspend        = exynos5_clock_suspend,
+       .resume         = exynos5_clock_resume,
+};
+
+void __init_or_cpufreq exynos5_setup_clocks(void)
+{
+       struct clk *xtal_clk;
+       unsigned long apll;
+       unsigned long bpll;
+       unsigned long cpll;
+       unsigned long mpll;
+       unsigned long epll;
+       unsigned long vpll;
+       unsigned long vpllsrc;
+       unsigned long xtal;
+       unsigned long armclk;
+       unsigned long mout_cdrex;
+       unsigned long aclk_400;
+       unsigned long aclk_333;
+       unsigned long aclk_266;
+       unsigned long aclk_200;
+       unsigned long aclk_166;
+       unsigned long aclk_66;
+       unsigned int ptr;
+
+       printk(KERN_DEBUG "%s: registering clocks\n", __func__);
+
+       xtal_clk = clk_get(NULL, "xtal");
+       BUG_ON(IS_ERR(xtal_clk));
+
+       xtal = clk_get_rate(xtal_clk);
+
+       xtal_rate = xtal;
+
+       clk_put(xtal_clk);
+
+       printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal);
+
+       apll = s5p_get_pll35xx(xtal, __raw_readl(EXYNOS5_APLL_CON0));
+       bpll = s5p_get_pll35xx(xtal, __raw_readl(EXYNOS5_BPLL_CON0));
+       cpll = s5p_get_pll35xx(xtal, __raw_readl(EXYNOS5_CPLL_CON0));
+       mpll = s5p_get_pll35xx(xtal, __raw_readl(EXYNOS5_MPLL_CON0));
+       epll = s5p_get_pll36xx(xtal, __raw_readl(EXYNOS5_EPLL_CON0),
+                       __raw_readl(EXYNOS5_EPLL_CON1));
+
+       vpllsrc = clk_get_rate(&exynos5_clk_vpllsrc.clk);
+       vpll = s5p_get_pll36xx(vpllsrc, __raw_readl(EXYNOS5_VPLL_CON0),
+                       __raw_readl(EXYNOS5_VPLL_CON1));
+
+       clk_fout_apll.ops = &exynos5_fout_apll_ops;
+       clk_fout_bpll.rate = bpll;
+       clk_fout_cpll.rate = cpll;
+       clk_fout_mpll.rate = mpll;
+       clk_fout_epll.rate = epll;
+       clk_fout_vpll.rate = vpll;
+
+       printk(KERN_INFO "EXYNOS5: PLL settings, A=%ld, B=%ld, C=%ld\n"
+                       "M=%ld, E=%ld V=%ld",
+                       apll, bpll, cpll, mpll, epll, vpll);
+
+       armclk = clk_get_rate(&exynos5_clk_armclk);
+       mout_cdrex = clk_get_rate(&exynos5_clk_cdrex.clk);
+
+       aclk_400 = clk_get_rate(&exynos5_clk_aclk_400.clk);
+       aclk_333 = clk_get_rate(&exynos5_clk_aclk_333.clk);
+       aclk_266 = clk_get_rate(&exynos5_clk_aclk_266.clk);
+       aclk_200 = clk_get_rate(&exynos5_clk_aclk_200.clk);
+       aclk_166 = clk_get_rate(&exynos5_clk_aclk_166.clk);
+       aclk_66 = clk_get_rate(&exynos5_clk_aclk_66.clk);
+
+       printk(KERN_INFO "EXYNOS5: ARMCLK=%ld, CDREX=%ld, ACLK400=%ld\n"
+                       "ACLK333=%ld, ACLK266=%ld, ACLK200=%ld\n"
+                       "ACLK166=%ld, ACLK66=%ld\n",
+                       armclk, mout_cdrex, aclk_400,
+                       aclk_333, aclk_266, aclk_200,
+                       aclk_166, aclk_66);
+
+
+       clk_fout_epll.ops = &exynos5_epll_ops;
+
+       if (clk_set_parent(&exynos5_clk_mout_epll.clk, &clk_fout_epll))
+               printk(KERN_ERR "Unable to set parent %s of clock %s.\n",
+                               clk_fout_epll.name, exynos5_clk_mout_epll.clk.name);
+
+       clk_set_rate(&exynos5_clk_sclk_apll.clk, 100000000);
+       clk_set_rate(&exynos5_clk_aclk_266.clk, 300000000);
+
+       clk_set_rate(&exynos5_clk_aclk_acp.clk, 267000000);
+       clk_set_rate(&exynos5_clk_pclk_acp.clk, 134000000);
+
+       for (ptr = 0; ptr < ARRAY_SIZE(exynos5_clksrcs); ptr++)
+               s3c_set_clksrc(&exynos5_clksrcs[ptr], true);
+}
+
+void __init exynos5_register_clocks(void)
+{
+       int ptr;
+
+       s3c24xx_register_clocks(exynos5_clks, ARRAY_SIZE(exynos5_clks));
+
+       for (ptr = 0; ptr < ARRAY_SIZE(exynos5_sysclks); ptr++)
+               s3c_register_clksrc(exynos5_sysclks[ptr], 1);
+
+       for (ptr = 0; ptr < ARRAY_SIZE(exynos5_sclk_tv); ptr++)
+               s3c_register_clksrc(exynos5_sclk_tv[ptr], 1);
+
+       for (ptr = 0; ptr < ARRAY_SIZE(exynos5_clksrc_cdev); ptr++)
+               s3c_register_clksrc(exynos5_clksrc_cdev[ptr], 1);
+
+       s3c_register_clksrc(exynos5_clksrcs, ARRAY_SIZE(exynos5_clksrcs));
+       s3c_register_clocks(exynos5_init_clocks_on, ARRAY_SIZE(exynos5_init_clocks_on));
+
+       s3c24xx_register_clocks(exynos5_clk_cdev, ARRAY_SIZE(exynos5_clk_cdev));
+       for (ptr = 0; ptr < ARRAY_SIZE(exynos5_clk_cdev); ptr++)
+               s3c_disable_clocks(exynos5_clk_cdev[ptr], 1);
+
+       s3c_register_clocks(exynos5_init_clocks_off, ARRAY_SIZE(exynos5_init_clocks_off));
+       s3c_disable_clocks(exynos5_init_clocks_off, ARRAY_SIZE(exynos5_init_clocks_off));
+       clkdev_add_table(exynos5_clk_lookup, ARRAY_SIZE(exynos5_clk_lookup));
+
+       register_syscore_ops(&exynos5_clock_syscore_ops);
+       s3c_pwmclk_init();
+}
index 97ca259..e6cc50e 100644 (file)
 static const char name_exynos4210[] = "EXYNOS4210";
 static const char name_exynos4212[] = "EXYNOS4212";
 static const char name_exynos4412[] = "EXYNOS4412";
+static const char name_exynos5250[] = "EXYNOS5250";
+
+static void exynos4_map_io(void);
+static void exynos5_map_io(void);
+static void exynos4_init_clocks(int xtal);
+static void exynos5_init_clocks(int xtal);
+static void exynos_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+static int exynos_init(void);
 
 static struct cpu_table cpu_ids[] __initdata = {
        {
@@ -60,7 +68,7 @@ static struct cpu_table cpu_ids[] __initdata = {
                .idmask         = EXYNOS4_CPU_MASK,
                .map_io         = exynos4_map_io,
                .init_clocks    = exynos4_init_clocks,
-               .init_uarts     = exynos4_init_uarts,
+               .init_uarts     = exynos_init_uarts,
                .init           = exynos_init,
                .name           = name_exynos4210,
        }, {
@@ -68,7 +76,7 @@ static struct cpu_table cpu_ids[] __initdata = {
                .idmask         = EXYNOS4_CPU_MASK,
                .map_io         = exynos4_map_io,
                .init_clocks    = exynos4_init_clocks,
-               .init_uarts     = exynos4_init_uarts,
+               .init_uarts     = exynos_init_uarts,
                .init           = exynos_init,
                .name           = name_exynos4212,
        }, {
@@ -76,9 +84,17 @@ static struct cpu_table cpu_ids[] __initdata = {
                .idmask         = EXYNOS4_CPU_MASK,
                .map_io         = exynos4_map_io,
                .init_clocks    = exynos4_init_clocks,
-               .init_uarts     = exynos4_init_uarts,
+               .init_uarts     = exynos_init_uarts,
                .init           = exynos_init,
                .name           = name_exynos4412,
+       }, {
+               .idcode         = EXYNOS5250_SOC_ID,
+               .idmask         = EXYNOS5_SOC_MASK,
+               .map_io         = exynos5_map_io,
+               .init_clocks    = exynos5_init_clocks,
+               .init_uarts     = exynos_init_uarts,
+               .init           = exynos_init,
+               .name           = name_exynos5250,
        },
 };
 
@@ -87,10 +103,14 @@ static struct cpu_table cpu_ids[] __initdata = {
 static struct map_desc exynos_iodesc[] __initdata = {
        {
                .virtual        = (unsigned long)S5P_VA_CHIPID,
-               .pfn            = __phys_to_pfn(EXYNOS4_PA_CHIPID),
+               .pfn            = __phys_to_pfn(EXYNOS_PA_CHIPID),
                .length         = SZ_4K,
                .type           = MT_DEVICE,
-       }, {
+       },
+};
+
+static struct map_desc exynos4_iodesc[] __initdata = {
+       {
                .virtual        = (unsigned long)S3C_VA_SYS,
                .pfn            = __phys_to_pfn(EXYNOS4_PA_SYSCON),
                .length         = SZ_64K,
@@ -140,11 +160,7 @@ static struct map_desc exynos_iodesc[] __initdata = {
                .pfn            = __phys_to_pfn(EXYNOS4_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,
@@ -160,21 +176,6 @@ static struct map_desc exynos4_iodesc[] __initdata = {
                .length         = SZ_4K,
                .type           = MT_DEVICE,
        }, {
-               .virtual        = (unsigned long)S5P_VA_GPIO1,
-               .pfn            = __phys_to_pfn(EXYNOS4_PA_GPIO1),
-               .length         = SZ_4K,
-               .type           = MT_DEVICE,
-       }, {
-               .virtual        = (unsigned long)S5P_VA_GPIO2,
-               .pfn            = __phys_to_pfn(EXYNOS4_PA_GPIO2),
-               .length         = SZ_4K,
-               .type           = MT_DEVICE,
-       }, {
-               .virtual        = (unsigned long)S5P_VA_GPIO3,
-               .pfn            = __phys_to_pfn(EXYNOS4_PA_GPIO3),
-               .length         = SZ_256,
-               .type           = MT_DEVICE,
-       }, {
                .virtual        = (unsigned long)S5P_VA_DMC0,
                .pfn            = __phys_to_pfn(EXYNOS4_PA_DMC0),
                .length         = SZ_64K,
@@ -210,11 +211,80 @@ static struct map_desc exynos4_iodesc1[] __initdata = {
        },
 };
 
+static struct map_desc exynos5_iodesc[] __initdata = {
+       {
+               .virtual        = (unsigned long)S3C_VA_SYS,
+               .pfn            = __phys_to_pfn(EXYNOS5_PA_SYSCON),
+               .length         = SZ_64K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = (unsigned long)S3C_VA_TIMER,
+               .pfn            = __phys_to_pfn(EXYNOS5_PA_TIMER),
+               .length         = SZ_16K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = (unsigned long)S3C_VA_WATCHDOG,
+               .pfn            = __phys_to_pfn(EXYNOS5_PA_WATCHDOG),
+               .length         = SZ_4K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = (unsigned long)S5P_VA_SROMC,
+               .pfn            = __phys_to_pfn(EXYNOS5_PA_SROMC),
+               .length         = SZ_4K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = (unsigned long)S5P_VA_SYSTIMER,
+               .pfn            = __phys_to_pfn(EXYNOS5_PA_SYSTIMER),
+               .length         = SZ_4K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = (unsigned long)S5P_VA_SYSRAM,
+               .pfn            = __phys_to_pfn(EXYNOS5_PA_SYSRAM),
+               .length         = SZ_4K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = (unsigned long)S5P_VA_CMU,
+               .pfn            = __phys_to_pfn(EXYNOS5_PA_CMU),
+               .length         = 144 * SZ_1K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = (unsigned long)S5P_VA_PMU,
+               .pfn            = __phys_to_pfn(EXYNOS5_PA_PMU),
+               .length         = SZ_64K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = (unsigned long)S5P_VA_COMBINER_BASE,
+               .pfn            = __phys_to_pfn(EXYNOS5_PA_COMBINER),
+               .length         = SZ_4K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = (unsigned long)S3C_VA_UART,
+               .pfn            = __phys_to_pfn(EXYNOS5_PA_UART),
+               .length         = SZ_512K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = (unsigned long)S5P_VA_GIC_CPU,
+               .pfn            = __phys_to_pfn(EXYNOS5_PA_GIC_CPU),
+               .length         = SZ_64K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = (unsigned long)S5P_VA_GIC_DIST,
+               .pfn            = __phys_to_pfn(EXYNOS5_PA_GIC_DIST),
+               .length         = SZ_64K,
+               .type           = MT_DEVICE,
+       },
+};
+
 void exynos4_restart(char mode, const char *cmd)
 {
        __raw_writel(0x1, S5P_SWRESET);
 }
 
+void exynos5_restart(char mode, const char *cmd)
+{
+       __raw_writel(0x1, EXYNOS_SWRESET);
+}
+
 /*
  * exynos_map_io
  *
@@ -234,7 +304,7 @@ void __init exynos_init_io(struct map_desc *mach_desc, int size)
        s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids));
 }
 
-void __init exynos4_map_io(void)
+static void __init exynos4_map_io(void)
 {
        iotable_init(exynos4_iodesc, ARRAY_SIZE(exynos4_iodesc));
 
@@ -265,7 +335,22 @@ void __init exynos4_map_io(void)
        s5p_hdmi_setname("exynos4-hdmi");
 }
 
-void __init exynos4_init_clocks(int xtal)
+static void __init exynos5_map_io(void)
+{
+       iotable_init(exynos5_iodesc, ARRAY_SIZE(exynos5_iodesc));
+
+       s3c_device_i2c0.resource[0].start = EXYNOS5_PA_IIC(0);
+       s3c_device_i2c0.resource[0].end   = EXYNOS5_PA_IIC(0) + SZ_4K - 1;
+       s3c_device_i2c0.resource[1].start = EXYNOS5_IRQ_IIC;
+       s3c_device_i2c0.resource[1].end   = EXYNOS5_IRQ_IIC;
+
+       /* The I2C bus controllers are directly compatible with s3c2440 */
+       s3c_i2c0_setname("s3c2440-i2c");
+       s3c_i2c1_setname("s3c2440-i2c");
+       s3c_i2c2_setname("s3c2440-i2c");
+}
+
+static void __init exynos4_init_clocks(int xtal)
 {
        printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
 
@@ -281,6 +366,17 @@ void __init exynos4_init_clocks(int xtal)
        exynos4_setup_clocks();
 }
 
+static void __init exynos5_init_clocks(int xtal)
+{
+       printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
+
+       s3c24xx_register_baseclocks(xtal);
+       s5p_register_clocks(xtal);
+
+       exynos5_register_clocks();
+       exynos5_setup_clocks();
+}
+
 #define COMBINER_ENABLE_SET    0x0
 #define COMBINER_ENABLE_CLEAR  0x4
 #define COMBINER_INT_STATUS    0xC
@@ -354,7 +450,14 @@ static struct irq_chip combiner_chip = {
 
 static void __init combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq)
 {
-       if (combiner_nr >= MAX_COMBINER_NR)
+       unsigned int max_nr;
+
+       if (soc_is_exynos5250())
+               max_nr = EXYNOS5_MAX_COMBINER_NR;
+       else
+               max_nr = EXYNOS4_MAX_COMBINER_NR;
+
+       if (combiner_nr >= max_nr)
                BUG();
        if (irq_set_handler_data(irq, &combiner_data[combiner_nr]) != 0)
                BUG();
@@ -365,8 +468,14 @@ static void __init combiner_init(unsigned int combiner_nr, void __iomem *base,
                          unsigned int irq_start)
 {
        unsigned int i;
+       unsigned int max_nr;
 
-       if (combiner_nr >= MAX_COMBINER_NR)
+       if (soc_is_exynos5250())
+               max_nr = EXYNOS5_MAX_COMBINER_NR;
+       else
+               max_nr = EXYNOS4_MAX_COMBINER_NR;
+
+       if (combiner_nr >= max_nr)
                BUG();
 
        combiner_data[combiner_nr].base = base;
@@ -409,8 +518,28 @@ void __init exynos4_init_irq(void)
                of_irq_init(exynos4_dt_irq_match);
 #endif
 
-       for (irq = 0; irq < MAX_COMBINER_NR; irq++) {
+       for (irq = 0; irq < EXYNOS4_MAX_COMBINER_NR; irq++) {
+
+               combiner_init(irq, (void __iomem *)S5P_VA_COMBINER(irq),
+                               COMBINER_IRQ(irq, 0));
+               combiner_cascade_irq(irq, IRQ_SPI(irq));
+       }
+
+       /*
+        * The parameters of s5p_init_irq() are for VIC init.
+        * Theses parameters should be NULL and 0 because EXYNOS4
+        * uses GIC instead of VIC.
+        */
+       s5p_init_irq(NULL, 0);
+}
+
+void __init exynos5_init_irq(void)
+{
+       int irq;
+
+       gic_init(0, IRQ_PPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
 
+       for (irq = 0; irq < EXYNOS5_MAX_COMBINER_NR; irq++) {
                combiner_init(irq, (void __iomem *)S5P_VA_COMBINER(irq),
                                COMBINER_IRQ(irq, 0));
                combiner_cascade_irq(irq, IRQ_SPI(irq));
@@ -429,19 +558,34 @@ struct bus_type exynos4_subsys = {
        .dev_name       = "exynos4-core",
 };
 
+struct bus_type exynos5_subsys = {
+       .name           = "exynos5-core",
+       .dev_name       = "exynos5-core",
+};
+
 static struct device exynos4_dev = {
        .bus    = &exynos4_subsys,
 };
 
-static int __init exynos4_core_init(void)
+static struct device exynos5_dev = {
+       .bus    = &exynos5_subsys,
+};
+
+static int __init exynos_core_init(void)
 {
-       return subsys_system_register(&exynos4_subsys, NULL);
+       if (soc_is_exynos5250())
+               return subsys_system_register(&exynos5_subsys, NULL);
+       else
+               return subsys_system_register(&exynos4_subsys, NULL);
 }
-core_initcall(exynos4_core_init);
+core_initcall(exynos_core_init);
 
 #ifdef CONFIG_CACHE_L2X0
 static int __init exynos4_l2x0_cache_init(void)
 {
+       if (soc_is_exynos5250())
+               return 0;
+
        int ret;
        ret = l2x0_of_init(L2_AUX_VAL, L2_AUX_MASK);
        if (!ret) {
@@ -486,19 +630,47 @@ static int __init exynos4_l2x0_cache_init(void)
        l2x0_init(S5P_VA_L2CC, L2_AUX_VAL, L2_AUX_MASK);
        return 0;
 }
-
 early_initcall(exynos4_l2x0_cache_init);
 #endif
 
-int __init exynos_init(void)
+static int __init exynos5_l2_cache_init(void)
+{
+       unsigned int val;
+
+       if (!soc_is_exynos5250())
+               return 0;
+
+       asm volatile("mrc p15, 0, %0, c1, c0, 0\n"
+                    "bic %0, %0, #(1 << 2)\n"  /* cache disable */
+                    "mcr p15, 0, %0, c1, c0, 0\n"
+                    "mrc p15, 1, %0, c9, c0, 2\n"
+                    : "=r"(val));
+
+       val |= (1 << 9) | (1 << 5) | (2 << 6) | (2 << 0);
+
+       asm volatile("mcr p15, 1, %0, c9, c0, 2\n" : : "r"(val));
+       asm volatile("mrc p15, 0, %0, c1, c0, 0\n"
+                    "orr %0, %0, #(1 << 2)\n"  /* cache enable */
+                    "mcr p15, 0, %0, c1, c0, 0\n"
+                    : : "r"(val));
+
+       return 0;
+}
+early_initcall(exynos5_l2_cache_init);
+
+static int __init exynos_init(void)
 {
        printk(KERN_INFO "EXYNOS: Initializing architecture\n");
-       return device_register(&exynos4_dev);
+
+       if (soc_is_exynos5250())
+               return device_register(&exynos5_dev);
+       else
+               return device_register(&exynos4_dev);
 }
 
 /* uart registration process */
 
-void __init exynos4_init_uarts(struct s3c2410_uartcfg *cfg, int no)
+static void __init exynos_init_uarts(struct s3c2410_uartcfg *cfg, int no)
 {
        struct s3c2410_uartcfg *tcfg = cfg;
        u32 ucnt;
@@ -506,69 +678,138 @@ void __init exynos4_init_uarts(struct s3c2410_uartcfg *cfg, int no)
        for (ucnt = 0; ucnt < no; ucnt++, tcfg++)
                tcfg->has_fracval = 1;
 
-       s3c24xx_init_uartdevs("exynos4210-uart", s5p_uart_resources, cfg, no);
+       if (soc_is_exynos5250())
+               s3c24xx_init_uartdevs("exynos4210-uart", exynos5_uart_resources, cfg, no);
+       else
+               s3c24xx_init_uartdevs("exynos4210-uart", exynos4_uart_resources, cfg, no);
 }
 
+static void __iomem *exynos_eint_base;
+
 static DEFINE_SPINLOCK(eint_lock);
 
 static unsigned int eint0_15_data[16];
 
-static unsigned int exynos4_get_irq_nr(unsigned int number)
+static inline int exynos4_irq_to_gpio(unsigned int irq)
 {
-       u32 ret = 0;
+       if (irq < IRQ_EINT(0))
+               return -EINVAL;
 
-       switch (number) {
-       case 0 ... 3:
-               ret = (number + IRQ_EINT0);
-               break;
-       case 4 ... 7:
-               ret = (number + (IRQ_EINT4 - 4));
-               break;
-       case 8 ... 15:
-               ret = (number + (IRQ_EINT8 - 8));
-               break;
-       default:
-               printk(KERN_ERR "number available : %d\n", number);
-       }
+       irq -= IRQ_EINT(0);
+       if (irq < 8)
+               return EXYNOS4_GPX0(irq);
+
+       irq -= 8;
+       if (irq < 8)
+               return EXYNOS4_GPX1(irq);
+
+       irq -= 8;
+       if (irq < 8)
+               return EXYNOS4_GPX2(irq);
+
+       irq -= 8;
+       if (irq < 8)
+               return EXYNOS4_GPX3(irq);
+
+       return -EINVAL;
+}
 
-       return ret;
+static inline int exynos5_irq_to_gpio(unsigned int irq)
+{
+       if (irq < IRQ_EINT(0))
+               return -EINVAL;
+
+       irq -= IRQ_EINT(0);
+       if (irq < 8)
+               return EXYNOS5_GPX0(irq);
+
+       irq -= 8;
+       if (irq < 8)
+               return EXYNOS5_GPX1(irq);
+
+       irq -= 8;
+       if (irq < 8)
+               return EXYNOS5_GPX2(irq);
+
+       irq -= 8;
+       if (irq < 8)
+               return EXYNOS5_GPX3(irq);
+
+       return -EINVAL;
 }
 
-static inline void exynos4_irq_eint_mask(struct irq_data *data)
+static unsigned int exynos4_eint0_15_src_int[16] = {
+       EXYNOS4_IRQ_EINT0,
+       EXYNOS4_IRQ_EINT1,
+       EXYNOS4_IRQ_EINT2,
+       EXYNOS4_IRQ_EINT3,
+       EXYNOS4_IRQ_EINT4,
+       EXYNOS4_IRQ_EINT5,
+       EXYNOS4_IRQ_EINT6,
+       EXYNOS4_IRQ_EINT7,
+       EXYNOS4_IRQ_EINT8,
+       EXYNOS4_IRQ_EINT9,
+       EXYNOS4_IRQ_EINT10,
+       EXYNOS4_IRQ_EINT11,
+       EXYNOS4_IRQ_EINT12,
+       EXYNOS4_IRQ_EINT13,
+       EXYNOS4_IRQ_EINT14,
+       EXYNOS4_IRQ_EINT15,
+};
+
+static unsigned int exynos5_eint0_15_src_int[16] = {
+       EXYNOS5_IRQ_EINT0,
+       EXYNOS5_IRQ_EINT1,
+       EXYNOS5_IRQ_EINT2,
+       EXYNOS5_IRQ_EINT3,
+       EXYNOS5_IRQ_EINT4,
+       EXYNOS5_IRQ_EINT5,
+       EXYNOS5_IRQ_EINT6,
+       EXYNOS5_IRQ_EINT7,
+       EXYNOS5_IRQ_EINT8,
+       EXYNOS5_IRQ_EINT9,
+       EXYNOS5_IRQ_EINT10,
+       EXYNOS5_IRQ_EINT11,
+       EXYNOS5_IRQ_EINT12,
+       EXYNOS5_IRQ_EINT13,
+       EXYNOS5_IRQ_EINT14,
+       EXYNOS5_IRQ_EINT15,
+};
+static inline void exynos_irq_eint_mask(struct irq_data *data)
 {
        u32 mask;
 
        spin_lock(&eint_lock);
-       mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(data->irq)));
-       mask |= eint_irq_to_bit(data->irq);
-       __raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(data->irq)));
+       mask = __raw_readl(EINT_MASK(exynos_eint_base, data->irq));
+       mask |= EINT_OFFSET_BIT(data->irq);
+       __raw_writel(mask, EINT_MASK(exynos_eint_base, data->irq));
        spin_unlock(&eint_lock);
 }
 
-static void exynos4_irq_eint_unmask(struct irq_data *data)
+static void exynos_irq_eint_unmask(struct irq_data *data)
 {
        u32 mask;
 
        spin_lock(&eint_lock);
-       mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(data->irq)));
-       mask &= ~(eint_irq_to_bit(data->irq));
-       __raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(data->irq)));
+       mask = __raw_readl(EINT_MASK(exynos_eint_base, data->irq));
+       mask &= ~(EINT_OFFSET_BIT(data->irq));
+       __raw_writel(mask, EINT_MASK(exynos_eint_base, data->irq));
        spin_unlock(&eint_lock);
 }
 
-static inline void exynos4_irq_eint_ack(struct irq_data *data)
+static inline void exynos_irq_eint_ack(struct irq_data *data)
 {
-       __raw_writel(eint_irq_to_bit(data->irq),
-                    S5P_EINT_PEND(EINT_REG_NR(data->irq)));
+       __raw_writel(EINT_OFFSET_BIT(data->irq),
+                    EINT_PEND(exynos_eint_base, data->irq));
 }
 
-static void exynos4_irq_eint_maskack(struct irq_data *data)
+static void exynos_irq_eint_maskack(struct irq_data *data)
 {
-       exynos4_irq_eint_mask(data);
-       exynos4_irq_eint_ack(data);
+       exynos_irq_eint_mask(data);
+       exynos_irq_eint_ack(data);
 }
 
-static int exynos4_irq_eint_set_type(struct irq_data *data, unsigned int type)
+static int exynos_irq_eint_set_type(struct irq_data *data, unsigned int type)
 {
        int offs = EINT_OFFSET(data->irq);
        int shift;
@@ -605,39 +846,27 @@ static int exynos4_irq_eint_set_type(struct irq_data *data, unsigned int type)
        mask = 0x7 << shift;
 
        spin_lock(&eint_lock);
-       ctrl = __raw_readl(S5P_EINT_CON(EINT_REG_NR(data->irq)));
+       ctrl = __raw_readl(EINT_CON(exynos_eint_base, data->irq));
        ctrl &= ~mask;
        ctrl |= newvalue << shift;
-       __raw_writel(ctrl, S5P_EINT_CON(EINT_REG_NR(data->irq)));
+       __raw_writel(ctrl, EINT_CON(exynos_eint_base, data->irq));
        spin_unlock(&eint_lock);
 
-       switch (offs) {
-       case 0 ... 7:
-               s3c_gpio_cfgpin(EINT_GPIO_0(offs & 0x7), EINT_MODE);
-               break;
-       case 8 ... 15:
-               s3c_gpio_cfgpin(EINT_GPIO_1(offs & 0x7), EINT_MODE);
-               break;
-       case 16 ... 23:
-               s3c_gpio_cfgpin(EINT_GPIO_2(offs & 0x7), EINT_MODE);
-               break;
-       case 24 ... 31:
-               s3c_gpio_cfgpin(EINT_GPIO_3(offs & 0x7), EINT_MODE);
-               break;
-       default:
-               printk(KERN_ERR "No such irq number %d", offs);
-       }
+       if (soc_is_exynos5250())
+               s3c_gpio_cfgpin(exynos5_irq_to_gpio(data->irq), S3C_GPIO_SFN(0xf));
+       else
+               s3c_gpio_cfgpin(exynos4_irq_to_gpio(data->irq), S3C_GPIO_SFN(0xf));
 
        return 0;
 }
 
-static struct irq_chip exynos4_irq_eint = {
-       .name           = "exynos4-eint",
-       .irq_mask       = exynos4_irq_eint_mask,
-       .irq_unmask     = exynos4_irq_eint_unmask,
-       .irq_mask_ack   = exynos4_irq_eint_maskack,
-       .irq_ack        = exynos4_irq_eint_ack,
-       .irq_set_type   = exynos4_irq_eint_set_type,
+static struct irq_chip exynos_irq_eint = {
+       .name           = "exynos-eint",
+       .irq_mask       = exynos_irq_eint_mask,
+       .irq_unmask     = exynos_irq_eint_unmask,
+       .irq_mask_ack   = exynos_irq_eint_maskack,
+       .irq_ack        = exynos_irq_eint_ack,
+       .irq_set_type   = exynos_irq_eint_set_type,
 #ifdef CONFIG_PM
        .irq_set_wake   = s3c_irqext_wake,
 #endif
@@ -652,12 +881,12 @@ static struct irq_chip exynos4_irq_eint = {
  *
  * Each EINT pend/mask registers handle eight of them.
  */
-static inline void exynos4_irq_demux_eint(unsigned int start)
+static inline void exynos_irq_demux_eint(unsigned int start)
 {
        unsigned int irq;
 
-       u32 status = __raw_readl(S5P_EINT_PEND(EINT_REG_NR(start)));
-       u32 mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(start)));
+       u32 status = __raw_readl(EINT_PEND(exynos_eint_base, start));
+       u32 mask = __raw_readl(EINT_MASK(exynos_eint_base, start));
 
        status &= ~mask;
        status &= 0xff;
@@ -669,16 +898,16 @@ static inline void exynos4_irq_demux_eint(unsigned int start)
        }
 }
 
-static void exynos4_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc)
+static void exynos_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc)
 {
        struct irq_chip *chip = irq_get_chip(irq);
        chained_irq_enter(chip, desc);
-       exynos4_irq_demux_eint(IRQ_EINT(16));
-       exynos4_irq_demux_eint(IRQ_EINT(24));
+       exynos_irq_demux_eint(IRQ_EINT(16));
+       exynos_irq_demux_eint(IRQ_EINT(24));
        chained_irq_exit(chip, desc);
 }
 
-static void exynos4_irq_eint0_15(unsigned int irq, struct irq_desc *desc)
+static void exynos_irq_eint0_15(unsigned int irq, struct irq_desc *desc)
 {
        u32 *irq_data = irq_get_handler_data(irq);
        struct irq_chip *chip = irq_get_chip(irq);
@@ -695,27 +924,44 @@ static void exynos4_irq_eint0_15(unsigned int irq, struct irq_desc *desc)
        chained_irq_exit(chip, desc);
 }
 
-static int __init exynos4_init_irq_eint(void)
+static int __init exynos_init_irq_eint(void)
 {
        int irq;
 
+       if (soc_is_exynos5250())
+               exynos_eint_base = ioremap(EXYNOS5_PA_GPIO1, SZ_4K);
+       else
+               exynos_eint_base = ioremap(EXYNOS4_PA_GPIO2, SZ_4K);
+
+       if (exynos_eint_base == NULL) {
+               pr_err("unable to ioremap for EINT base address\n");
+               return -ENOMEM;
+       }
+
        for (irq = 0 ; irq <= 31 ; irq++) {
-               irq_set_chip_and_handler(IRQ_EINT(irq), &exynos4_irq_eint,
+               irq_set_chip_and_handler(IRQ_EINT(irq), &exynos_irq_eint,
                                         handle_level_irq);
                set_irq_flags(IRQ_EINT(irq), IRQF_VALID);
        }
 
-       irq_set_chained_handler(IRQ_EINT16_31, exynos4_irq_demux_eint16_31);
+       irq_set_chained_handler(EXYNOS_IRQ_EINT16_31, exynos_irq_demux_eint16_31);
 
        for (irq = 0 ; irq <= 15 ; irq++) {
                eint0_15_data[irq] = IRQ_EINT(irq);
 
-               irq_set_handler_data(exynos4_get_irq_nr(irq),
-                                    &eint0_15_data[irq]);
-               irq_set_chained_handler(exynos4_get_irq_nr(irq),
-                                       exynos4_irq_eint0_15);
+               if (soc_is_exynos5250()) {
+                       irq_set_handler_data(exynos5_eint0_15_src_int[irq],
+                                            &eint0_15_data[irq]);
+                       irq_set_chained_handler(exynos5_eint0_15_src_int[irq],
+                                               exynos_irq_eint0_15);
+               } else {
+                       irq_set_handler_data(exynos4_eint0_15_src_int[irq],
+                                            &eint0_15_data[irq]);
+                       irq_set_chained_handler(exynos4_eint0_15_src_int[irq],
+                                               exynos_irq_eint0_15);
+               }
        }
 
        return 0;
 }
-arch_initcall(exynos4_init_irq_eint);
+arch_initcall(exynos_init_irq_eint);
index 8c1efe6..677b546 100644 (file)
 #ifndef __ARCH_ARM_MACH_EXYNOS_COMMON_H
 #define __ARCH_ARM_MACH_EXYNOS_COMMON_H
 
+extern struct sys_timer exynos4_timer;
+
 void exynos_init_io(struct map_desc *mach_desc, int size);
 void exynos4_init_irq(void);
+void exynos5_init_irq(void);
+void exynos4_restart(char mode, const char *cmd);
+void exynos5_restart(char mode, const char *cmd);
 
 #ifdef CONFIG_ARCH_EXYNOS4
 void exynos4_register_clocks(void);
 void exynos4_setup_clocks(void);
 
-void exynos4210_register_clocks(void);
-void exynos4212_register_clocks(void);
-
 #else
 #define exynos4_register_clocks()
 #define exynos4_setup_clocks()
+#endif
 
-#define exynos4210_register_clocks()
-#define exynos4212_register_clocks()
+#ifdef CONFIG_ARCH_EXYNOS5
+void exynos5_register_clocks(void);
+void exynos5_setup_clocks(void);
+
+#else
+#define exynos5_register_clocks()
+#define exynos5_setup_clocks()
 #endif
 
-void exynos4_restart(char mode, const char *cmd);
+#ifdef CONFIG_CPU_EXYNOS4210
+void exynos4210_register_clocks(void);
 
-extern struct sys_timer exynos4_timer;
+#else
+#define exynos4210_register_clocks()
+#endif
 
-#ifdef CONFIG_ARCH_EXYNOS
-extern  int exynos_init(void);
-extern void exynos4_map_io(void);
-extern void exynos4_init_clocks(int xtal);
-extern void exynos4_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+#ifdef CONFIG_SOC_EXYNOS4212
+void exynos4212_register_clocks(void);
 
 #else
-#define exynos4_init_clocks NULL
-#define exynos4_init_uarts NULL
-#define exynos4_map_io NULL
-#define exynos_init NULL
+#define exynos4212_register_clocks()
 #endif
 
 #endif /* __ARCH_ARM_MACH_EXYNOS_COMMON_H */
index f57a3de..50ce5b0 100644 (file)
@@ -242,8 +242,8 @@ static struct resource exynos4_ahci_resource[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = IRQ_SATA,
-               .end    = IRQ_SATA,
+               .start  = EXYNOS4_IRQ_SATA,
+               .end    = EXYNOS4_IRQ_SATA,
                .flags  = IORESOURCE_IRQ,
        },
 };
index 5a9f9c2..7199e1a 100644 (file)
@@ -304,8 +304,8 @@ static struct resource exynos4_ac97_resource[] = {
                .flags  = IORESOURCE_DMA,
        },
        [4] = {
-               .start  = IRQ_AC97,
-               .end    = IRQ_AC97,
+               .start  = EXYNOS4_IRQ_AC97,
+               .end    = EXYNOS4_IRQ_AC97,
                .flags  = IORESOURCE_IRQ,
        },
 };
diff --git a/arch/arm/mach-exynos/dev-uart.c b/arch/arm/mach-exynos/dev-uart.c
new file mode 100644 (file)
index 0000000..2e85c02
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Base EXYNOS UART 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/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/irq.h>
+#include <mach/hardware.h>
+#include <mach/map.h>
+
+#include <plat/devs.h>
+
+#define EXYNOS_UART_RESOURCE(_series, _nr)     \
+static struct resource exynos##_series##_uart##_nr##_resource[] = {    \
+       [0] = DEFINE_RES_MEM(EXYNOS##_series##_PA_UART##_nr, EXYNOS##_series##_SZ_UART),        \
+       [1] = DEFINE_RES_IRQ(EXYNOS##_series##_IRQ_UART##_nr),  \
+};
+
+EXYNOS_UART_RESOURCE(4, 0)
+EXYNOS_UART_RESOURCE(4, 1)
+EXYNOS_UART_RESOURCE(4, 2)
+EXYNOS_UART_RESOURCE(4, 3)
+
+struct s3c24xx_uart_resources exynos4_uart_resources[] __initdata = {
+       [0] = {
+               .resources      = exynos4_uart0_resource,
+               .nr_resources   = ARRAY_SIZE(exynos4_uart0_resource),
+       },
+       [1] = {
+               .resources      = exynos4_uart1_resource,
+               .nr_resources   = ARRAY_SIZE(exynos4_uart1_resource),
+       },
+       [2] = {
+               .resources      = exynos4_uart2_resource,
+               .nr_resources   = ARRAY_SIZE(exynos4_uart2_resource),
+       },
+       [3] = {
+               .resources      = exynos4_uart3_resource,
+               .nr_resources   = ARRAY_SIZE(exynos4_uart3_resource),
+       },
+};
+
+EXYNOS_UART_RESOURCE(5, 0)
+EXYNOS_UART_RESOURCE(5, 1)
+EXYNOS_UART_RESOURCE(5, 2)
+EXYNOS_UART_RESOURCE(5, 3)
+
+struct s3c24xx_uart_resources exynos5_uart_resources[] __initdata = {
+       [0] = {
+               .resources      = exynos5_uart0_resource,
+               .nr_resources   = ARRAY_SIZE(exynos5_uart0_resource),
+       },
+       [1] = {
+               .resources      = exynos5_uart1_resource,
+               .nr_resources   = ARRAY_SIZE(exynos5_uart0_resource),
+       },
+       [2] = {
+               .resources      = exynos5_uart2_resource,
+               .nr_resources   = ARRAY_SIZE(exynos5_uart2_resource),
+       },
+       [3] = {
+               .resources      = exynos5_uart3_resource,
+               .nr_resources   = ARRAY_SIZE(exynos5_uart3_resource),
+       },
+};
index 13607c4..3983abe 100644 (file)
@@ -108,7 +108,7 @@ static u8 exynos4212_pdma0_peri[] = {
 struct dma_pl330_platdata exynos4_pdma0_pdata;
 
 static AMBA_AHB_DEVICE(exynos4_pdma0, "dma-pl330.0", 0x00041330,
-       EXYNOS4_PA_PDMA0, {IRQ_PDMA0}, &exynos4_pdma0_pdata);
+       EXYNOS4_PA_PDMA0, {EXYNOS4_IRQ_PDMA0}, &exynos4_pdma0_pdata);
 
 static u8 exynos4210_pdma1_peri[] = {
        DMACH_PCM0_RX,
@@ -174,7 +174,7 @@ static u8 exynos4212_pdma1_peri[] = {
 static struct dma_pl330_platdata exynos4_pdma1_pdata;
 
 static AMBA_AHB_DEVICE(exynos4_pdma1,  "dma-pl330.1", 0x00041330,
-       EXYNOS4_PA_PDMA1, {IRQ_PDMA1}, &exynos4_pdma1_pdata);
+       EXYNOS4_PA_PDMA1, {EXYNOS4_IRQ_PDMA1}, &exynos4_pdma1_pdata);
 
 static u8 mdma_peri[] = {
        DMACH_MTOM_0,
@@ -193,7 +193,7 @@ static struct dma_pl330_platdata exynos4_mdma1_pdata = {
 };
 
 static AMBA_AHB_DEVICE(exynos4_mdma1,  "dma-pl330.2", 0x00041330,
-       EXYNOS4_PA_MDMA1, {IRQ_MDMA1}, &exynos4_mdma1_pdata);
+       EXYNOS4_PA_MDMA1, {EXYNOS4_IRQ_MDMA1}, &exynos4_mdma1_pdata);
 
 static int __init exynos4_dma_init(void)
 {
index dd1ad55..9c17a0a 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/io.h>
 
 #include <asm/cacheflush.h>
+#include <asm/cp15.h>
 #include <asm/smp_plat.h>
 
 #include <mach/regs-pmu.h>
index 6cacf16..6c857ff 100644 (file)
         */
 
        .macro addruart, rp, rv, tmp
-               ldr     \rp, = S3C_PA_UART
-               ldr     \rv, = S3C_VA_UART
+               mov     \rp, #0x10000000
+               ldr     \rp, [\rp, #0x0]
+               and     \rp, \rp, #0xf00000
+               teq     \rp, #0x500000          @@ EXYNOS5
+               ldreq   \rp, =EXYNOS5_PA_UART
+               movne   \rp, #EXYNOS4_PA_UART   @@ EXYNOS4
+               ldr     \rv, =S3C_VA_UART
 #if CONFIG_DEBUG_S3C_UART != 0
                add     \rp, \rp, #(0x10000 * CONFIG_DEBUG_S3C_UART)
                add     \rv, \rv, #(0x10000 * CONFIG_DEBUG_S3C_UART)
index 80523ca..d7498af 100644 (file)
@@ -1,9 +1,8 @@
-/* linux/arch/arm/mach-exynos4/include/mach/gpio.h
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+/*
+ * Copyright (c) 2010-2012 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com
  *
- * EXYNOS4 - GPIO lib support
+ * EXYNOS - GPIO lib 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
 #ifndef __ASM_ARCH_GPIO_H
 #define __ASM_ARCH_GPIO_H __FILE__
 
-/* Practically, GPIO banks up to GPZ are the configurable gpio banks */
+/* Macro for EXYNOS GPIO numbering */
+
+#define EXYNOS_GPIO_NEXT(__gpio) \
+       ((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 1)
+
+/* EXYNOS4 GPIO bank sizes */
 
-/* GPIO bank sizes */
 #define EXYNOS4_GPIO_A0_NR     (8)
 #define EXYNOS4_GPIO_A1_NR     (6)
 #define EXYNOS4_GPIO_B_NR      (8)
 #define EXYNOS4_GPIO_Y6_NR     (8)
 #define EXYNOS4_GPIO_Z_NR      (7)
 
-/* GPIO bank numbers */
-
-#define EXYNOS4_GPIO_NEXT(__gpio) \
-       ((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 1)
+/* EXYNOS4 GPIO bank numbers */
 
-enum s5p_gpio_number {
+enum exynos4_gpio_number {
        EXYNOS4_GPIO_A0_START   = 0,
-       EXYNOS4_GPIO_A1_START   = EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_A0),
-       EXYNOS4_GPIO_B_START    = EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_A1),
-       EXYNOS4_GPIO_C0_START   = EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_B),
-       EXYNOS4_GPIO_C1_START   = EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_C0),
-       EXYNOS4_GPIO_D0_START   = EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_C1),
-       EXYNOS4_GPIO_D1_START   = EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_D0),
-       EXYNOS4_GPIO_E0_START   = EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_D1),
-       EXYNOS4_GPIO_E1_START   = EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_E0),
-       EXYNOS4_GPIO_E2_START   = EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_E1),
-       EXYNOS4_GPIO_E3_START   = EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_E2),
-       EXYNOS4_GPIO_E4_START   = EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_E3),
-       EXYNOS4_GPIO_F0_START   = EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_E4),
-       EXYNOS4_GPIO_F1_START   = EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_F0),
-       EXYNOS4_GPIO_F2_START   = EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_F1),
-       EXYNOS4_GPIO_F3_START   = EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_F2),
-       EXYNOS4_GPIO_J0_START   = EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_F3),
-       EXYNOS4_GPIO_J1_START   = EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_J0),
-       EXYNOS4_GPIO_K0_START   = EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_J1),
-       EXYNOS4_GPIO_K1_START   = EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_K0),
-       EXYNOS4_GPIO_K2_START   = EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_K1),
-       EXYNOS4_GPIO_K3_START   = EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_K2),
-       EXYNOS4_GPIO_L0_START   = EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_K3),
-       EXYNOS4_GPIO_L1_START   = EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_L0),
-       EXYNOS4_GPIO_L2_START   = EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_L1),
-       EXYNOS4_GPIO_X0_START   = EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_L2),
-       EXYNOS4_GPIO_X1_START   = EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_X0),
-       EXYNOS4_GPIO_X2_START   = EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_X1),
-       EXYNOS4_GPIO_X3_START   = EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_X2),
-       EXYNOS4_GPIO_Y0_START   = EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_X3),
-       EXYNOS4_GPIO_Y1_START   = EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_Y0),
-       EXYNOS4_GPIO_Y2_START   = EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_Y1),
-       EXYNOS4_GPIO_Y3_START   = EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_Y2),
-       EXYNOS4_GPIO_Y4_START   = EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_Y3),
-       EXYNOS4_GPIO_Y5_START   = EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_Y4),
-       EXYNOS4_GPIO_Y6_START   = EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_Y5),
-       EXYNOS4_GPIO_Z_START    = EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_Y6),
+       EXYNOS4_GPIO_A1_START   = EXYNOS_GPIO_NEXT(EXYNOS4_GPIO_A0),
+       EXYNOS4_GPIO_B_START    = EXYNOS_GPIO_NEXT(EXYNOS4_GPIO_A1),
+       EXYNOS4_GPIO_C0_START   = EXYNOS_GPIO_NEXT(EXYNOS4_GPIO_B),
+       EXYNOS4_GPIO_C1_START   = EXYNOS_GPIO_NEXT(EXYNOS4_GPIO_C0),
+       EXYNOS4_GPIO_D0_START   = EXYNOS_GPIO_NEXT(EXYNOS4_GPIO_C1),
+       EXYNOS4_GPIO_D1_START   = EXYNOS_GPIO_NEXT(EXYNOS4_GPIO_D0),
+       EXYNOS4_GPIO_E0_START   = EXYNOS_GPIO_NEXT(EXYNOS4_GPIO_D1),
+       EXYNOS4_GPIO_E1_START   = EXYNOS_GPIO_NEXT(EXYNOS4_GPIO_E0),
+       EXYNOS4_GPIO_E2_START   = EXYNOS_GPIO_NEXT(EXYNOS4_GPIO_E1),
+       EXYNOS4_GPIO_E3_START   = EXYNOS_GPIO_NEXT(EXYNOS4_GPIO_E2),
+       EXYNOS4_GPIO_E4_START   = EXYNOS_GPIO_NEXT(EXYNOS4_GPIO_E3),
+       EXYNOS4_GPIO_F0_START   = EXYNOS_GPIO_NEXT(EXYNOS4_GPIO_E4),
+       EXYNOS4_GPIO_F1_START   = EXYNOS_GPIO_NEXT(EXYNOS4_GPIO_F0),
+       EXYNOS4_GPIO_F2_START   = EXYNOS_GPIO_NEXT(EXYNOS4_GPIO_F1),
+       EXYNOS4_GPIO_F3_START   = EXYNOS_GPIO_NEXT(EXYNOS4_GPIO_F2),
+       EXYNOS4_GPIO_J0_START   = EXYNOS_GPIO_NEXT(EXYNOS4_GPIO_F3),
+       EXYNOS4_GPIO_J1_START   = EXYNOS_GPIO_NEXT(EXYNOS4_GPIO_J0),
+       EXYNOS4_GPIO_K0_START   = EXYNOS_GPIO_NEXT(EXYNOS4_GPIO_J1),
+       EXYNOS4_GPIO_K1_START   = EXYNOS_GPIO_NEXT(EXYNOS4_GPIO_K0),
+       EXYNOS4_GPIO_K2_START   = EXYNOS_GPIO_NEXT(EXYNOS4_GPIO_K1),
+       EXYNOS4_GPIO_K3_START   = EXYNOS_GPIO_NEXT(EXYNOS4_GPIO_K2),
+       EXYNOS4_GPIO_L0_START   = EXYNOS_GPIO_NEXT(EXYNOS4_GPIO_K3),
+       EXYNOS4_GPIO_L1_START   = EXYNOS_GPIO_NEXT(EXYNOS4_GPIO_L0),
+       EXYNOS4_GPIO_L2_START   = EXYNOS_GPIO_NEXT(EXYNOS4_GPIO_L1),
+       EXYNOS4_GPIO_X0_START   = EXYNOS_GPIO_NEXT(EXYNOS4_GPIO_L2),
+       EXYNOS4_GPIO_X1_START   = EXYNOS_GPIO_NEXT(EXYNOS4_GPIO_X0),
+       EXYNOS4_GPIO_X2_START   = EXYNOS_GPIO_NEXT(EXYNOS4_GPIO_X1),
+       EXYNOS4_GPIO_X3_START   = EXYNOS_GPIO_NEXT(EXYNOS4_GPIO_X2),
+       EXYNOS4_GPIO_Y0_START   = EXYNOS_GPIO_NEXT(EXYNOS4_GPIO_X3),
+       EXYNOS4_GPIO_Y1_START   = EXYNOS_GPIO_NEXT(EXYNOS4_GPIO_Y0),
+       EXYNOS4_GPIO_Y2_START   = EXYNOS_GPIO_NEXT(EXYNOS4_GPIO_Y1),
+       EXYNOS4_GPIO_Y3_START   = EXYNOS_GPIO_NEXT(EXYNOS4_GPIO_Y2),
+       EXYNOS4_GPIO_Y4_START   = EXYNOS_GPIO_NEXT(EXYNOS4_GPIO_Y3),
+       EXYNOS4_GPIO_Y5_START   = EXYNOS_GPIO_NEXT(EXYNOS4_GPIO_Y4),
+       EXYNOS4_GPIO_Y6_START   = EXYNOS_GPIO_NEXT(EXYNOS4_GPIO_Y5),
+       EXYNOS4_GPIO_Z_START    = EXYNOS_GPIO_NEXT(EXYNOS4_GPIO_Y6),
 };
 
 /* EXYNOS4 GPIO number definitions */
+
 #define EXYNOS4_GPA0(_nr)      (EXYNOS4_GPIO_A0_START + (_nr))
 #define EXYNOS4_GPA1(_nr)      (EXYNOS4_GPIO_A1_START + (_nr))
 #define EXYNOS4_GPB(_nr)       (EXYNOS4_GPIO_B_START + (_nr))
@@ -139,11 +140,147 @@ enum s5p_gpio_number {
 #define EXYNOS4_GPZ(_nr)       (EXYNOS4_GPIO_Z_START + (_nr))
 
 /* the end of the EXYNOS4 specific gpios */
+
 #define EXYNOS4_GPIO_END       (EXYNOS4_GPZ(EXYNOS4_GPIO_Z_NR) + 1)
-#define S3C_GPIO_END           EXYNOS4_GPIO_END
 
-/* define the number of gpios we need to the one after the GPZ() range */
-#define ARCH_NR_GPIOS          (EXYNOS4_GPZ(EXYNOS4_GPIO_Z_NR) +       \
-                                CONFIG_SAMSUNG_GPIO_EXTRA + 1)
+/* EXYNOS5 GPIO bank sizes */
+
+#define EXYNOS5_GPIO_A0_NR     (8)
+#define EXYNOS5_GPIO_A1_NR     (6)
+#define EXYNOS5_GPIO_A2_NR     (8)
+#define EXYNOS5_GPIO_B0_NR     (5)
+#define EXYNOS5_GPIO_B1_NR     (5)
+#define EXYNOS5_GPIO_B2_NR     (4)
+#define EXYNOS5_GPIO_B3_NR     (4)
+#define EXYNOS5_GPIO_C0_NR     (7)
+#define EXYNOS5_GPIO_C1_NR     (7)
+#define EXYNOS5_GPIO_C2_NR     (7)
+#define EXYNOS5_GPIO_C3_NR     (7)
+#define EXYNOS5_GPIO_D0_NR     (8)
+#define EXYNOS5_GPIO_D1_NR     (8)
+#define EXYNOS5_GPIO_Y0_NR     (6)
+#define EXYNOS5_GPIO_Y1_NR     (4)
+#define EXYNOS5_GPIO_Y2_NR     (6)
+#define EXYNOS5_GPIO_Y3_NR     (8)
+#define EXYNOS5_GPIO_Y4_NR     (8)
+#define EXYNOS5_GPIO_Y5_NR     (8)
+#define EXYNOS5_GPIO_Y6_NR     (8)
+#define EXYNOS5_GPIO_X0_NR     (8)
+#define EXYNOS5_GPIO_X1_NR     (8)
+#define EXYNOS5_GPIO_X2_NR     (8)
+#define EXYNOS5_GPIO_X3_NR     (8)
+#define EXYNOS5_GPIO_E0_NR     (8)
+#define EXYNOS5_GPIO_E1_NR     (2)
+#define EXYNOS5_GPIO_F0_NR     (4)
+#define EXYNOS5_GPIO_F1_NR     (4)
+#define EXYNOS5_GPIO_G0_NR     (8)
+#define EXYNOS5_GPIO_G1_NR     (8)
+#define EXYNOS5_GPIO_G2_NR     (2)
+#define EXYNOS5_GPIO_H0_NR     (4)
+#define EXYNOS5_GPIO_H1_NR     (8)
+#define EXYNOS5_GPIO_V0_NR     (8)
+#define EXYNOS5_GPIO_V1_NR     (8)
+#define EXYNOS5_GPIO_V2_NR     (8)
+#define EXYNOS5_GPIO_V3_NR     (8)
+#define EXYNOS5_GPIO_V4_NR     (2)
+#define EXYNOS5_GPIO_Z_NR      (7)
+
+/* EXYNOS5 GPIO bank numbers */
+
+enum exynos5_gpio_number {
+       EXYNOS5_GPIO_A0_START           = 0,
+       EXYNOS5_GPIO_A1_START           = EXYNOS_GPIO_NEXT(EXYNOS5_GPIO_A0),
+       EXYNOS5_GPIO_A2_START           = EXYNOS_GPIO_NEXT(EXYNOS5_GPIO_A1),
+       EXYNOS5_GPIO_B0_START           = EXYNOS_GPIO_NEXT(EXYNOS5_GPIO_A2),
+       EXYNOS5_GPIO_B1_START           = EXYNOS_GPIO_NEXT(EXYNOS5_GPIO_B0),
+       EXYNOS5_GPIO_B2_START           = EXYNOS_GPIO_NEXT(EXYNOS5_GPIO_B1),
+       EXYNOS5_GPIO_B3_START           = EXYNOS_GPIO_NEXT(EXYNOS5_GPIO_B2),
+       EXYNOS5_GPIO_C0_START           = EXYNOS_GPIO_NEXT(EXYNOS5_GPIO_B3),
+       EXYNOS5_GPIO_C1_START           = EXYNOS_GPIO_NEXT(EXYNOS5_GPIO_C0),
+       EXYNOS5_GPIO_C2_START           = EXYNOS_GPIO_NEXT(EXYNOS5_GPIO_C1),
+       EXYNOS5_GPIO_C3_START           = EXYNOS_GPIO_NEXT(EXYNOS5_GPIO_C2),
+       EXYNOS5_GPIO_D0_START           = EXYNOS_GPIO_NEXT(EXYNOS5_GPIO_C3),
+       EXYNOS5_GPIO_D1_START           = EXYNOS_GPIO_NEXT(EXYNOS5_GPIO_D0),
+       EXYNOS5_GPIO_Y0_START           = EXYNOS_GPIO_NEXT(EXYNOS5_GPIO_D1),
+       EXYNOS5_GPIO_Y1_START           = EXYNOS_GPIO_NEXT(EXYNOS5_GPIO_Y0),
+       EXYNOS5_GPIO_Y2_START           = EXYNOS_GPIO_NEXT(EXYNOS5_GPIO_Y1),
+       EXYNOS5_GPIO_Y3_START           = EXYNOS_GPIO_NEXT(EXYNOS5_GPIO_Y2),
+       EXYNOS5_GPIO_Y4_START           = EXYNOS_GPIO_NEXT(EXYNOS5_GPIO_Y3),
+       EXYNOS5_GPIO_Y5_START           = EXYNOS_GPIO_NEXT(EXYNOS5_GPIO_Y4),
+       EXYNOS5_GPIO_Y6_START           = EXYNOS_GPIO_NEXT(EXYNOS5_GPIO_Y5),
+       EXYNOS5_GPIO_X0_START           = EXYNOS_GPIO_NEXT(EXYNOS5_GPIO_Y6),
+       EXYNOS5_GPIO_X1_START           = EXYNOS_GPIO_NEXT(EXYNOS5_GPIO_X0),
+       EXYNOS5_GPIO_X2_START           = EXYNOS_GPIO_NEXT(EXYNOS5_GPIO_X1),
+       EXYNOS5_GPIO_X3_START           = EXYNOS_GPIO_NEXT(EXYNOS5_GPIO_X2),
+       EXYNOS5_GPIO_E0_START           = EXYNOS_GPIO_NEXT(EXYNOS5_GPIO_X3),
+       EXYNOS5_GPIO_E1_START           = EXYNOS_GPIO_NEXT(EXYNOS5_GPIO_E0),
+       EXYNOS5_GPIO_F0_START           = EXYNOS_GPIO_NEXT(EXYNOS5_GPIO_E1),
+       EXYNOS5_GPIO_F1_START           = EXYNOS_GPIO_NEXT(EXYNOS5_GPIO_F0),
+       EXYNOS5_GPIO_G0_START           = EXYNOS_GPIO_NEXT(EXYNOS5_GPIO_F1),
+       EXYNOS5_GPIO_G1_START           = EXYNOS_GPIO_NEXT(EXYNOS5_GPIO_G0),
+       EXYNOS5_GPIO_G2_START           = EXYNOS_GPIO_NEXT(EXYNOS5_GPIO_G1),
+       EXYNOS5_GPIO_H0_START           = EXYNOS_GPIO_NEXT(EXYNOS5_GPIO_G2),
+       EXYNOS5_GPIO_H1_START           = EXYNOS_GPIO_NEXT(EXYNOS5_GPIO_H0),
+       EXYNOS5_GPIO_V0_START           = EXYNOS_GPIO_NEXT(EXYNOS5_GPIO_H1),
+       EXYNOS5_GPIO_V1_START           = EXYNOS_GPIO_NEXT(EXYNOS5_GPIO_V0),
+       EXYNOS5_GPIO_V2_START           = EXYNOS_GPIO_NEXT(EXYNOS5_GPIO_V1),
+       EXYNOS5_GPIO_V3_START           = EXYNOS_GPIO_NEXT(EXYNOS5_GPIO_V2),
+       EXYNOS5_GPIO_V4_START           = EXYNOS_GPIO_NEXT(EXYNOS5_GPIO_V3),
+       EXYNOS5_GPIO_Z_START            = EXYNOS_GPIO_NEXT(EXYNOS5_GPIO_V4),
+};
+
+/* EXYNOS5 GPIO number definitions */
+
+#define EXYNOS5_GPA0(_nr)      (EXYNOS5_GPIO_A0_START + (_nr))
+#define EXYNOS5_GPA1(_nr)      (EXYNOS5_GPIO_A1_START + (_nr))
+#define EXYNOS5_GPA2(_nr)      (EXYNOS5_GPIO_A2_START + (_nr))
+#define EXYNOS5_GPB0(_nr)      (EXYNOS5_GPIO_B0_START + (_nr))
+#define EXYNOS5_GPB1(_nr)      (EXYNOS5_GPIO_B1_START + (_nr))
+#define EXYNOS5_GPB2(_nr)      (EXYNOS5_GPIO_B2_START + (_nr))
+#define EXYNOS5_GPB3(_nr)      (EXYNOS5_GPIO_B3_START + (_nr))
+#define EXYNOS5_GPC0(_nr)      (EXYNOS5_GPIO_C0_START + (_nr))
+#define EXYNOS5_GPC1(_nr)      (EXYNOS5_GPIO_C1_START + (_nr))
+#define EXYNOS5_GPC2(_nr)      (EXYNOS5_GPIO_C2_START + (_nr))
+#define EXYNOS5_GPC3(_nr)      (EXYNOS5_GPIO_C3_START + (_nr))
+#define EXYNOS5_GPD0(_nr)      (EXYNOS5_GPIO_D0_START + (_nr))
+#define EXYNOS5_GPD1(_nr)      (EXYNOS5_GPIO_D1_START + (_nr))
+#define EXYNOS5_GPY0(_nr)      (EXYNOS5_GPIO_Y0_START + (_nr))
+#define EXYNOS5_GPY1(_nr)      (EXYNOS5_GPIO_Y1_START + (_nr))
+#define EXYNOS5_GPY2(_nr)      (EXYNOS5_GPIO_Y2_START + (_nr))
+#define EXYNOS5_GPY3(_nr)      (EXYNOS5_GPIO_Y3_START + (_nr))
+#define EXYNOS5_GPY4(_nr)      (EXYNOS5_GPIO_Y4_START + (_nr))
+#define EXYNOS5_GPY5(_nr)      (EXYNOS5_GPIO_Y5_START + (_nr))
+#define EXYNOS5_GPY6(_nr)      (EXYNOS5_GPIO_Y6_START + (_nr))
+#define EXYNOS5_GPX0(_nr)      (EXYNOS5_GPIO_X0_START + (_nr))
+#define EXYNOS5_GPX1(_nr)      (EXYNOS5_GPIO_X1_START + (_nr))
+#define EXYNOS5_GPX2(_nr)      (EXYNOS5_GPIO_X2_START + (_nr))
+#define EXYNOS5_GPX3(_nr)      (EXYNOS5_GPIO_X3_START + (_nr))
+#define EXYNOS5_GPE0(_nr)      (EXYNOS5_GPIO_E0_START + (_nr))
+#define EXYNOS5_GPE1(_nr)      (EXYNOS5_GPIO_E1_START + (_nr))
+#define EXYNOS5_GPF0(_nr)      (EXYNOS5_GPIO_F0_START + (_nr))
+#define EXYNOS5_GPF1(_nr)      (EXYNOS5_GPIO_F1_START + (_nr))
+#define EXYNOS5_GPG0(_nr)      (EXYNOS5_GPIO_G0_START + (_nr))
+#define EXYNOS5_GPG1(_nr)      (EXYNOS5_GPIO_G1_START + (_nr))
+#define EXYNOS5_GPG2(_nr)      (EXYNOS5_GPIO_G2_START + (_nr))
+#define EXYNOS5_GPH0(_nr)      (EXYNOS5_GPIO_H0_START + (_nr))
+#define EXYNOS5_GPH1(_nr)      (EXYNOS5_GPIO_H1_START + (_nr))
+#define EXYNOS5_GPV0(_nr)      (EXYNOS5_GPIO_V0_START + (_nr))
+#define EXYNOS5_GPV1(_nr)      (EXYNOS5_GPIO_V1_START + (_nr))
+#define EXYNOS5_GPV2(_nr)      (EXYNOS5_GPIO_V2_START + (_nr))
+#define EXYNOS5_GPV3(_nr)      (EXYNOS5_GPIO_V3_START + (_nr))
+#define EXYNOS5_GPV4(_nr)      (EXYNOS5_GPIO_V4_START + (_nr))
+#define EXYNOS5_GPZ(_nr)       (EXYNOS5_GPIO_Z_START + (_nr))
+
+/* the end of the EXYNOS5 specific gpios */
+
+#define EXYNOS5_GPIO_END       (EXYNOS5_GPZ(EXYNOS5_GPIO_Z_NR) + 1)
+
+/* actually, EXYNOS5_GPIO_END is bigger than EXYNOS4 */
+
+#define S3C_GPIO_END           (EXYNOS5_GPIO_END)
+
+/* define the number of gpios */
+
+#define ARCH_NR_GPIOS          (CONFIG_SAMSUNG_GPIO_EXTRA + S3C_GPIO_END)
 
 #endif /* __ASM_ARCH_GPIO_H */
index 1d401c9..9bee853 100644 (file)
@@ -1,9 +1,8 @@
-/* linux/arch/arm/mach-exynos4/include/mach/irqs.h
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+/*
+ * Copyright (c) 2010-2012 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com
  *
- * EXYNOS4 - IRQ definitions
+ * EXYNOS - IRQ 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
 
 /* PPI: Private Peripheral Interrupt */
 
-#define IRQ_PPI(x)             (x+16)
-
-#define IRQ_MCT_LOCALTIMER     IRQ_PPI(12)
+#define IRQ_PPI(x)                     (x + 16)
 
 /* SPI: Shared Peripheral Interrupt */
 
-#define IRQ_SPI(x)             (x+32)
-
-#define IRQ_EINT0              IRQ_SPI(16)
-#define IRQ_EINT1              IRQ_SPI(17)
-#define IRQ_EINT2              IRQ_SPI(18)
-#define IRQ_EINT3              IRQ_SPI(19)
-#define IRQ_EINT4              IRQ_SPI(20)
-#define IRQ_EINT5              IRQ_SPI(21)
-#define IRQ_EINT6              IRQ_SPI(22)
-#define IRQ_EINT7              IRQ_SPI(23)
-#define IRQ_EINT8              IRQ_SPI(24)
-#define IRQ_EINT9              IRQ_SPI(25)
-#define IRQ_EINT10             IRQ_SPI(26)
-#define IRQ_EINT11             IRQ_SPI(27)
-#define IRQ_EINT12             IRQ_SPI(28)
-#define IRQ_EINT13             IRQ_SPI(29)
-#define IRQ_EINT14             IRQ_SPI(30)
-#define IRQ_EINT15             IRQ_SPI(31)
-#define IRQ_EINT16_31          IRQ_SPI(32)
-
-#define IRQ_MDMA0              IRQ_SPI(33)
-#define IRQ_MDMA1              IRQ_SPI(34)
-#define IRQ_PDMA0              IRQ_SPI(35)
-#define IRQ_PDMA1              IRQ_SPI(36)
-#define IRQ_TIMER0_VIC         IRQ_SPI(37)
-#define IRQ_TIMER1_VIC         IRQ_SPI(38)
-#define IRQ_TIMER2_VIC         IRQ_SPI(39)
-#define IRQ_TIMER3_VIC         IRQ_SPI(40)
-#define IRQ_TIMER4_VIC         IRQ_SPI(41)
-#define IRQ_MCT_L0             IRQ_SPI(42)
-#define IRQ_WDT                        IRQ_SPI(43)
-#define IRQ_RTC_ALARM          IRQ_SPI(44)
-#define IRQ_RTC_TIC            IRQ_SPI(45)
-#define IRQ_GPIO_XB            IRQ_SPI(46)
-#define IRQ_GPIO_XA            IRQ_SPI(47)
-#define IRQ_MCT_L1             IRQ_SPI(48)
-
-#define IRQ_UART0              IRQ_SPI(52)
-#define IRQ_UART1              IRQ_SPI(53)
-#define IRQ_UART2              IRQ_SPI(54)
-#define IRQ_UART3              IRQ_SPI(55)
-#define IRQ_UART4              IRQ_SPI(56)
-#define IRQ_MCT_G0             IRQ_SPI(57)
-#define IRQ_IIC                        IRQ_SPI(58)
-#define IRQ_IIC1               IRQ_SPI(59)
-#define IRQ_IIC2               IRQ_SPI(60)
-#define IRQ_IIC3               IRQ_SPI(61)
-#define IRQ_IIC4               IRQ_SPI(62)
-#define IRQ_IIC5               IRQ_SPI(63)
-#define IRQ_IIC6               IRQ_SPI(64)
-#define IRQ_IIC7               IRQ_SPI(65)
-#define IRQ_SPI0               IRQ_SPI(66)
-#define IRQ_SPI1               IRQ_SPI(67)
-#define IRQ_SPI2               IRQ_SPI(68)
-
-#define IRQ_USB_HOST           IRQ_SPI(70)
-#define IRQ_USB_HSOTG          IRQ_SPI(71)
-#define IRQ_MODEM_IF           IRQ_SPI(72)
-#define IRQ_HSMMC0             IRQ_SPI(73)
-#define IRQ_HSMMC1             IRQ_SPI(74)
-#define IRQ_HSMMC2             IRQ_SPI(75)
-#define IRQ_HSMMC3             IRQ_SPI(76)
-#define IRQ_DWMCI              IRQ_SPI(77)
-
-#define IRQ_MIPI_CSIS0         IRQ_SPI(78)
-#define IRQ_MIPI_CSIS1         IRQ_SPI(80)
-
-#define IRQ_ONENAND_AUDI       IRQ_SPI(82)
-#define IRQ_ROTATOR            IRQ_SPI(83)
-#define IRQ_FIMC0              IRQ_SPI(84)
-#define IRQ_FIMC1              IRQ_SPI(85)
-#define IRQ_FIMC2              IRQ_SPI(86)
-#define IRQ_FIMC3              IRQ_SPI(87)
-#define IRQ_JPEG               IRQ_SPI(88)
-#define IRQ_2D                 IRQ_SPI(89)
-#define IRQ_PCIE               IRQ_SPI(90)
-
-#define IRQ_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)
-#define IRQ_I2S1               IRQ_SPI(98)
-#define IRQ_I2S2               IRQ_SPI(99)
-#define IRQ_AC97               IRQ_SPI(100)
-
-#define IRQ_SPDIF              IRQ_SPI(104)
-#define IRQ_ADC0               IRQ_SPI(105)
-#define IRQ_PEN0               IRQ_SPI(106)
-#define IRQ_ADC1               IRQ_SPI(107)
-#define IRQ_PEN1               IRQ_SPI(108)
-#define IRQ_KEYPAD             IRQ_SPI(109)
-#define IRQ_PMU                        IRQ_SPI(110)
-#define IRQ_GPS                        IRQ_SPI(111)
-#define IRQ_INTFEEDCTRL_SSS    IRQ_SPI(112)
-#define IRQ_SLIMBUS            IRQ_SPI(113)
-
-#define IRQ_TSI                        IRQ_SPI(115)
-#define IRQ_SATA               IRQ_SPI(116)
-
-#define MAX_IRQ_IN_COMBINER    8
-#define COMBINER_GROUP(x)      ((x) * MAX_IRQ_IN_COMBINER + IRQ_SPI(128))
-#define COMBINER_IRQ(x, y)     (COMBINER_GROUP(x) + y)
-
-#define IRQ_SYSMMU_MDMA0_0     COMBINER_IRQ(4, 0)
-#define IRQ_SYSMMU_SSS_0       COMBINER_IRQ(4, 1)
-#define IRQ_SYSMMU_FIMC0_0     COMBINER_IRQ(4, 2)
-#define IRQ_SYSMMU_FIMC1_0     COMBINER_IRQ(4, 3)
-#define IRQ_SYSMMU_FIMC2_0     COMBINER_IRQ(4, 4)
-#define IRQ_SYSMMU_FIMC3_0     COMBINER_IRQ(4, 5)
-#define IRQ_SYSMMU_JPEG_0      COMBINER_IRQ(4, 6)
-#define IRQ_SYSMMU_2D_0                COMBINER_IRQ(4, 7)
-
-#define IRQ_SYSMMU_ROTATOR_0   COMBINER_IRQ(5, 0)
-#define IRQ_SYSMMU_MDMA1_0     COMBINER_IRQ(5, 1)
-#define IRQ_SYSMMU_LCD0_M0_0   COMBINER_IRQ(5, 2)
-#define IRQ_SYSMMU_LCD1_M1_0   COMBINER_IRQ(5, 3)
-#define IRQ_SYSMMU_TV_M0_0     COMBINER_IRQ(5, 4)
-#define IRQ_SYSMMU_MFC_M0_0    COMBINER_IRQ(5, 5)
-#define IRQ_SYSMMU_MFC_M1_0    COMBINER_IRQ(5, 6)
-#define IRQ_SYSMMU_PCIE_0      COMBINER_IRQ(5, 7)
-
-#define IRQ_FIMD0_FIFO         COMBINER_IRQ(11, 0)
-#define IRQ_FIMD0_VSYNC                COMBINER_IRQ(11, 1)
-#define IRQ_FIMD0_SYSTEM       COMBINER_IRQ(11, 2)
-
-#define MAX_COMBINER_NR                16
-
-#define IRQ_ADC                        IRQ_ADC0
-#define IRQ_TC                 IRQ_PEN0
-
-#define S5P_IRQ_EINT_BASE      COMBINER_IRQ(MAX_COMBINER_NR, 0)
-
-#define S5P_EINT_BASE1         (S5P_IRQ_EINT_BASE + 0)
-#define S5P_EINT_BASE2         (S5P_IRQ_EINT_BASE + 16)
-
-/* optional GPIO interrupts */
-#define S5P_GPIOINT_BASE       (S5P_IRQ_EINT_BASE + 32)
-#define IRQ_GPIO1_NR_GROUPS    16
-#define IRQ_GPIO2_NR_GROUPS    9
-#define IRQ_GPIO_END           (S5P_GPIOINT_BASE + S5P_GPIOINT_COUNT)
-
-#define IRQ_TIMER_BASE         (IRQ_GPIO_END + 64)
+#define IRQ_SPI(x)                     (x + 32)
+
+/* COMBINER */
+
+#define MAX_IRQ_IN_COMBINER            8
+#define COMBINER_GROUP(x)              ((x) * MAX_IRQ_IN_COMBINER + IRQ_SPI(128))
+#define COMBINER_IRQ(x, y)             (COMBINER_GROUP(x) + y)
+
+/* For EXYNOS4 and EXYNOS5 */
+
+#define EXYNOS_IRQ_MCT_LOCALTIMER      IRQ_PPI(12)
+
+#define EXYNOS_IRQ_EINT16_31           IRQ_SPI(32)
+
+/* For EXYNOS4 SoCs */
+
+#define EXYNOS4_IRQ_EINT0              IRQ_SPI(16)
+#define EXYNOS4_IRQ_EINT1              IRQ_SPI(17)
+#define EXYNOS4_IRQ_EINT2              IRQ_SPI(18)
+#define EXYNOS4_IRQ_EINT3              IRQ_SPI(19)
+#define EXYNOS4_IRQ_EINT4              IRQ_SPI(20)
+#define EXYNOS4_IRQ_EINT5              IRQ_SPI(21)
+#define EXYNOS4_IRQ_EINT6              IRQ_SPI(22)
+#define EXYNOS4_IRQ_EINT7              IRQ_SPI(23)
+#define EXYNOS4_IRQ_EINT8              IRQ_SPI(24)
+#define EXYNOS4_IRQ_EINT9              IRQ_SPI(25)
+#define EXYNOS4_IRQ_EINT10             IRQ_SPI(26)
+#define EXYNOS4_IRQ_EINT11             IRQ_SPI(27)
+#define EXYNOS4_IRQ_EINT12             IRQ_SPI(28)
+#define EXYNOS4_IRQ_EINT13             IRQ_SPI(29)
+#define EXYNOS4_IRQ_EINT14             IRQ_SPI(30)
+#define EXYNOS4_IRQ_EINT15             IRQ_SPI(31)
+
+#define EXYNOS4_IRQ_MDMA0              IRQ_SPI(33)
+#define EXYNOS4_IRQ_MDMA1              IRQ_SPI(34)
+#define EXYNOS4_IRQ_PDMA0              IRQ_SPI(35)
+#define EXYNOS4_IRQ_PDMA1              IRQ_SPI(36)
+#define EXYNOS4_IRQ_TIMER0_VIC         IRQ_SPI(37)
+#define EXYNOS4_IRQ_TIMER1_VIC         IRQ_SPI(38)
+#define EXYNOS4_IRQ_TIMER2_VIC         IRQ_SPI(39)
+#define EXYNOS4_IRQ_TIMER3_VIC         IRQ_SPI(40)
+#define EXYNOS4_IRQ_TIMER4_VIC         IRQ_SPI(41)
+#define EXYNOS4_IRQ_MCT_L0             IRQ_SPI(42)
+#define EXYNOS4_IRQ_WDT                        IRQ_SPI(43)
+#define EXYNOS4_IRQ_RTC_ALARM          IRQ_SPI(44)
+#define EXYNOS4_IRQ_RTC_TIC            IRQ_SPI(45)
+#define EXYNOS4_IRQ_GPIO_XB            IRQ_SPI(46)
+#define EXYNOS4_IRQ_GPIO_XA            IRQ_SPI(47)
+#define EXYNOS4_IRQ_MCT_L1             IRQ_SPI(48)
+
+#define EXYNOS4_IRQ_UART0              IRQ_SPI(52)
+#define EXYNOS4_IRQ_UART1              IRQ_SPI(53)
+#define EXYNOS4_IRQ_UART2              IRQ_SPI(54)
+#define EXYNOS4_IRQ_UART3              IRQ_SPI(55)
+#define EXYNOS4_IRQ_UART4              IRQ_SPI(56)
+#define EXYNOS4_IRQ_MCT_G0             IRQ_SPI(57)
+#define EXYNOS4_IRQ_IIC                        IRQ_SPI(58)
+#define EXYNOS4_IRQ_IIC1               IRQ_SPI(59)
+#define EXYNOS4_IRQ_IIC2               IRQ_SPI(60)
+#define EXYNOS4_IRQ_IIC3               IRQ_SPI(61)
+#define EXYNOS4_IRQ_IIC4               IRQ_SPI(62)
+#define EXYNOS4_IRQ_IIC5               IRQ_SPI(63)
+#define EXYNOS4_IRQ_IIC6               IRQ_SPI(64)
+#define EXYNOS4_IRQ_IIC7               IRQ_SPI(65)
+#define EXYNOS4_IRQ_SPI0               IRQ_SPI(66)
+#define EXYNOS4_IRQ_SPI1               IRQ_SPI(67)
+#define EXYNOS4_IRQ_SPI2               IRQ_SPI(68)
+
+#define EXYNOS4_IRQ_USB_HOST           IRQ_SPI(70)
+#define EXYNOS4_IRQ_USB_HSOTG          IRQ_SPI(71)
+#define EXYNOS4_IRQ_MODEM_IF           IRQ_SPI(72)
+#define EXYNOS4_IRQ_HSMMC0             IRQ_SPI(73)
+#define EXYNOS4_IRQ_HSMMC1             IRQ_SPI(74)
+#define EXYNOS4_IRQ_HSMMC2             IRQ_SPI(75)
+#define EXYNOS4_IRQ_HSMMC3             IRQ_SPI(76)
+#define EXYNOS4_IRQ_DWMCI              IRQ_SPI(77)
+
+#define EXYNOS4_IRQ_MIPI_CSIS0         IRQ_SPI(78)
+#define EXYNOS4_IRQ_MIPI_CSIS1         IRQ_SPI(80)
+
+#define EXYNOS4_IRQ_ONENAND_AUDI       IRQ_SPI(82)
+#define EXYNOS4_IRQ_ROTATOR            IRQ_SPI(83)
+#define EXYNOS4_IRQ_FIMC0              IRQ_SPI(84)
+#define EXYNOS4_IRQ_FIMC1              IRQ_SPI(85)
+#define EXYNOS4_IRQ_FIMC2              IRQ_SPI(86)
+#define EXYNOS4_IRQ_FIMC3              IRQ_SPI(87)
+#define EXYNOS4_IRQ_JPEG               IRQ_SPI(88)
+#define EXYNOS4_IRQ_2D                 IRQ_SPI(89)
+#define EXYNOS4_IRQ_PCIE               IRQ_SPI(90)
+
+#define EXYNOS4_IRQ_MIXER              IRQ_SPI(91)
+#define EXYNOS4_IRQ_HDMI               IRQ_SPI(92)
+#define EXYNOS4_IRQ_IIC_HDMIPHY                IRQ_SPI(93)
+#define EXYNOS4_IRQ_MFC                        IRQ_SPI(94)
+#define EXYNOS4_IRQ_SDO                        IRQ_SPI(95)
+
+#define EXYNOS4_IRQ_AUDIO_SS           IRQ_SPI(96)
+#define EXYNOS4_IRQ_I2S0               IRQ_SPI(97)
+#define EXYNOS4_IRQ_I2S1               IRQ_SPI(98)
+#define EXYNOS4_IRQ_I2S2               IRQ_SPI(99)
+#define EXYNOS4_IRQ_AC97               IRQ_SPI(100)
+
+#define EXYNOS4_IRQ_SPDIF              IRQ_SPI(104)
+#define EXYNOS4_IRQ_ADC0               IRQ_SPI(105)
+#define EXYNOS4_IRQ_PEN0               IRQ_SPI(106)
+#define EXYNOS4_IRQ_ADC1               IRQ_SPI(107)
+#define EXYNOS4_IRQ_PEN1               IRQ_SPI(108)
+#define EXYNOS4_IRQ_KEYPAD             IRQ_SPI(109)
+#define EXYNOS4_IRQ_PMU                        IRQ_SPI(110)
+#define EXYNOS4_IRQ_GPS                        IRQ_SPI(111)
+#define EXYNOS4_IRQ_INTFEEDCTRL_SSS    IRQ_SPI(112)
+#define EXYNOS4_IRQ_SLIMBUS            IRQ_SPI(113)
+
+#define EXYNOS4_IRQ_TSI                        IRQ_SPI(115)
+#define EXYNOS4_IRQ_SATA               IRQ_SPI(116)
+
+#define EXYNOS4_IRQ_SYSMMU_MDMA0_0     COMBINER_IRQ(4, 0)
+#define EXYNOS4_IRQ_SYSMMU_SSS_0       COMBINER_IRQ(4, 1)
+#define EXYNOS4_IRQ_SYSMMU_FIMC0_0     COMBINER_IRQ(4, 2)
+#define EXYNOS4_IRQ_SYSMMU_FIMC1_0     COMBINER_IRQ(4, 3)
+#define EXYNOS4_IRQ_SYSMMU_FIMC2_0     COMBINER_IRQ(4, 4)
+#define EXYNOS4_IRQ_SYSMMU_FIMC3_0     COMBINER_IRQ(4, 5)
+#define EXYNOS4_IRQ_SYSMMU_JPEG_0      COMBINER_IRQ(4, 6)
+#define EXYNOS4_IRQ_SYSMMU_2D_0                COMBINER_IRQ(4, 7)
+
+#define EXYNOS4_IRQ_SYSMMU_ROTATOR_0   COMBINER_IRQ(5, 0)
+#define EXYNOS4_IRQ_SYSMMU_MDMA1_0     COMBINER_IRQ(5, 1)
+#define EXYNOS4_IRQ_SYSMMU_LCD0_M0_0   COMBINER_IRQ(5, 2)
+#define EXYNOS4_IRQ_SYSMMU_LCD1_M1_0   COMBINER_IRQ(5, 3)
+#define EXYNOS4_IRQ_SYSMMU_TV_M0_0     COMBINER_IRQ(5, 4)
+#define EXYNOS4_IRQ_SYSMMU_MFC_M0_0    COMBINER_IRQ(5, 5)
+#define EXYNOS4_IRQ_SYSMMU_MFC_M1_0    COMBINER_IRQ(5, 6)
+#define EXYNOS4_IRQ_SYSMMU_PCIE_0      COMBINER_IRQ(5, 7)
+
+#define EXYNOS4_IRQ_FIMD0_FIFO         COMBINER_IRQ(11, 0)
+#define EXYNOS4_IRQ_FIMD0_VSYNC                COMBINER_IRQ(11, 1)
+#define EXYNOS4_IRQ_FIMD0_SYSTEM       COMBINER_IRQ(11, 2)
+
+#define EXYNOS4_MAX_COMBINER_NR                16
+
+#define EXYNOS4_IRQ_GPIO1_NR_GROUPS    16
+#define EXYNOS4_IRQ_GPIO2_NR_GROUPS    9
+
+/*
+ * For Compatibility:
+ * the default is for EXYNOS4, and
+ * for exynos5, should be re-mapped at function
+ */
+
+#define IRQ_TIMER0_VIC                 EXYNOS4_IRQ_TIMER0_VIC
+#define IRQ_TIMER1_VIC                 EXYNOS4_IRQ_TIMER1_VIC
+#define IRQ_TIMER2_VIC                 EXYNOS4_IRQ_TIMER2_VIC
+#define IRQ_TIMER3_VIC                 EXYNOS4_IRQ_TIMER3_VIC
+#define IRQ_TIMER4_VIC                 EXYNOS4_IRQ_TIMER4_VIC
+
+#define IRQ_WDT                                EXYNOS4_IRQ_WDT
+#define IRQ_RTC_ALARM                  EXYNOS4_IRQ_RTC_ALARM
+#define IRQ_RTC_TIC                    EXYNOS4_IRQ_RTC_TIC
+#define IRQ_GPIO_XB                    EXYNOS4_IRQ_GPIO_XB
+#define IRQ_GPIO_XA                    EXYNOS4_IRQ_GPIO_XA
+
+#define IRQ_IIC                                EXYNOS4_IRQ_IIC
+#define IRQ_IIC1                       EXYNOS4_IRQ_IIC1
+#define IRQ_IIC3                       EXYNOS4_IRQ_IIC3
+#define IRQ_IIC5                       EXYNOS4_IRQ_IIC5
+#define IRQ_IIC6                       EXYNOS4_IRQ_IIC6
+#define IRQ_IIC7                       EXYNOS4_IRQ_IIC7
+
+#define IRQ_USB_HOST                   EXYNOS4_IRQ_USB_HOST
+
+#define IRQ_HSMMC0                     EXYNOS4_IRQ_HSMMC0
+#define IRQ_HSMMC1                     EXYNOS4_IRQ_HSMMC1
+#define IRQ_HSMMC2                     EXYNOS4_IRQ_HSMMC2
+#define IRQ_HSMMC3                     EXYNOS4_IRQ_HSMMC3
+
+#define IRQ_MIPI_CSIS0                 EXYNOS4_IRQ_MIPI_CSIS0
+
+#define IRQ_ONENAND_AUDI               EXYNOS4_IRQ_ONENAND_AUDI
+
+#define IRQ_FIMC0                      EXYNOS4_IRQ_FIMC0
+#define IRQ_FIMC1                      EXYNOS4_IRQ_FIMC1
+#define IRQ_FIMC2                      EXYNOS4_IRQ_FIMC2
+#define IRQ_FIMC3                      EXYNOS4_IRQ_FIMC3
+#define IRQ_JPEG                       EXYNOS4_IRQ_JPEG
+#define IRQ_2D                         EXYNOS4_IRQ_2D
+
+#define IRQ_MIXER                      EXYNOS4_IRQ_MIXER
+#define IRQ_HDMI                       EXYNOS4_IRQ_HDMI
+#define IRQ_IIC_HDMIPHY                        EXYNOS4_IRQ_IIC_HDMIPHY
+#define IRQ_MFC                                EXYNOS4_IRQ_MFC
+#define IRQ_SDO                                EXYNOS4_IRQ_SDO
+
+#define IRQ_ADC                                EXYNOS4_IRQ_ADC0
+#define IRQ_TC                         EXYNOS4_IRQ_PEN0
+
+#define IRQ_KEYPAD                     EXYNOS4_IRQ_KEYPAD
+#define IRQ_PMU                                EXYNOS4_IRQ_PMU
+
+#define IRQ_SYSMMU_MDMA0_0             EXYNOS4_IRQ_SYSMMU_MDMA0_0
+#define IRQ_SYSMMU_SSS_0                EXYNOS4_IRQ_SYSMMU_SSS_0
+#define IRQ_SYSMMU_FIMC0_0              EXYNOS4_IRQ_SYSMMU_FIMC0_0
+#define IRQ_SYSMMU_FIMC1_0              EXYNOS4_IRQ_SYSMMU_FIMC1_0
+#define IRQ_SYSMMU_FIMC2_0              EXYNOS4_IRQ_SYSMMU_FIMC2_0
+#define IRQ_SYSMMU_FIMC3_0              EXYNOS4_IRQ_SYSMMU_FIMC3_0
+#define IRQ_SYSMMU_JPEG_0               EXYNOS4_IRQ_SYSMMU_JPEG_0
+#define IRQ_SYSMMU_2D_0                 EXYNOS4_IRQ_SYSMMU_2D_0
+
+#define IRQ_SYSMMU_ROTATOR_0            EXYNOS4_IRQ_SYSMMU_ROTATOR_0
+#define IRQ_SYSMMU_MDMA1_0              EXYNOS4_IRQ_SYSMMU_MDMA1_0
+#define IRQ_SYSMMU_LCD0_M0_0            EXYNOS4_IRQ_SYSMMU_LCD0_M0_0
+#define IRQ_SYSMMU_LCD1_M1_0            EXYNOS4_IRQ_SYSMMU_LCD1_M1_0
+#define IRQ_SYSMMU_TV_M0_0              EXYNOS4_IRQ_SYSMMU_TV_M0_0
+#define IRQ_SYSMMU_MFC_M0_0             EXYNOS4_IRQ_SYSMMU_MFC_M0_0
+#define IRQ_SYSMMU_MFC_M1_0             EXYNOS4_IRQ_SYSMMU_MFC_M1_0
+#define IRQ_SYSMMU_PCIE_0               EXYNOS4_IRQ_SYSMMU_PCIE_0
+
+#define IRQ_FIMD0_FIFO                 EXYNOS4_IRQ_FIMD0_FIFO
+#define IRQ_FIMD0_VSYNC                        EXYNOS4_IRQ_FIMD0_VSYNC
+#define IRQ_FIMD0_SYSTEM               EXYNOS4_IRQ_FIMD0_SYSTEM
+
+#define IRQ_GPIO1_NR_GROUPS            EXYNOS4_IRQ_GPIO1_NR_GROUPS
+#define IRQ_GPIO2_NR_GROUPS            EXYNOS4_IRQ_GPIO2_NR_GROUPS
+
+/* For EXYNOS5 SoCs */
+
+#define EXYNOS5_IRQ_MDMA0              IRQ_SPI(33)
+#define EXYNOS5_IRQ_PDMA0              IRQ_SPI(34)
+#define EXYNOS5_IRQ_PDMA1              IRQ_SPI(35)
+#define EXYNOS5_IRQ_TIMER0_VIC         IRQ_SPI(36)
+#define EXYNOS5_IRQ_TIMER1_VIC         IRQ_SPI(37)
+#define EXYNOS5_IRQ_TIMER2_VIC         IRQ_SPI(38)
+#define EXYNOS5_IRQ_TIMER3_VIC         IRQ_SPI(39)
+#define EXYNOS5_IRQ_TIMER4_VIC         IRQ_SPI(40)
+#define EXYNOS5_IRQ_RTIC               IRQ_SPI(41)
+#define EXYNOS5_IRQ_WDT                        IRQ_SPI(42)
+#define EXYNOS5_IRQ_RTC_ALARM          IRQ_SPI(43)
+#define EXYNOS5_IRQ_RTC_TIC            IRQ_SPI(44)
+#define EXYNOS5_IRQ_GPIO_XB            IRQ_SPI(45)
+#define EXYNOS5_IRQ_GPIO_XA            IRQ_SPI(46)
+#define EXYNOS5_IRQ_GPIO               IRQ_SPI(47)
+#define EXYNOS5_IRQ_IEM_IEC            IRQ_SPI(48)
+#define EXYNOS5_IRQ_IEM_APC            IRQ_SPI(49)
+#define EXYNOS5_IRQ_GPIO_C2C           IRQ_SPI(50)
+#define EXYNOS5_IRQ_UART0              IRQ_SPI(51)
+#define EXYNOS5_IRQ_UART1              IRQ_SPI(52)
+#define EXYNOS5_IRQ_UART2              IRQ_SPI(53)
+#define EXYNOS5_IRQ_UART3              IRQ_SPI(54)
+#define EXYNOS5_IRQ_UART4              IRQ_SPI(55)
+#define EXYNOS5_IRQ_IIC                        IRQ_SPI(56)
+#define EXYNOS5_IRQ_IIC1               IRQ_SPI(57)
+#define EXYNOS5_IRQ_IIC2               IRQ_SPI(58)
+#define EXYNOS5_IRQ_IIC3               IRQ_SPI(59)
+#define EXYNOS5_IRQ_IIC4               IRQ_SPI(60)
+#define EXYNOS5_IRQ_IIC5               IRQ_SPI(61)
+#define EXYNOS5_IRQ_IIC6               IRQ_SPI(62)
+#define EXYNOS5_IRQ_IIC7               IRQ_SPI(63)
+#define EXYNOS5_IRQ_IIC_HDMIPHY                IRQ_SPI(64)
+#define EXYNOS5_IRQ_TMU                        IRQ_SPI(65)
+#define EXYNOS5_IRQ_FIQ_0              IRQ_SPI(66)
+#define EXYNOS5_IRQ_FIQ_1              IRQ_SPI(67)
+#define EXYNOS5_IRQ_SPI0               IRQ_SPI(68)
+#define EXYNOS5_IRQ_SPI1               IRQ_SPI(69)
+#define EXYNOS5_IRQ_SPI2               IRQ_SPI(70)
+#define EXYNOS5_IRQ_USB_HOST           IRQ_SPI(71)
+#define EXYNOS5_IRQ_USB3_DRD           IRQ_SPI(72)
+#define EXYNOS5_IRQ_MIPI_HSI           IRQ_SPI(73)
+#define EXYNOS5_IRQ_USB_HSOTG          IRQ_SPI(74)
+#define EXYNOS5_IRQ_HSMMC0             IRQ_SPI(75)
+#define EXYNOS5_IRQ_HSMMC1             IRQ_SPI(76)
+#define EXYNOS5_IRQ_HSMMC2             IRQ_SPI(77)
+#define EXYNOS5_IRQ_HSMMC3             IRQ_SPI(78)
+#define EXYNOS5_IRQ_MIPICSI0           IRQ_SPI(79)
+#define EXYNOS5_IRQ_MIPICSI1           IRQ_SPI(80)
+#define EXYNOS5_IRQ_EFNFCON_DMA_ABORT  IRQ_SPI(81)
+#define EXYNOS5_IRQ_MIPIDSI0           IRQ_SPI(82)
+#define EXYNOS5_IRQ_ROTATOR            IRQ_SPI(84)
+#define EXYNOS5_IRQ_GSC0               IRQ_SPI(85)
+#define EXYNOS5_IRQ_GSC1               IRQ_SPI(86)
+#define EXYNOS5_IRQ_GSC2               IRQ_SPI(87)
+#define EXYNOS5_IRQ_GSC3               IRQ_SPI(88)
+#define EXYNOS5_IRQ_JPEG               IRQ_SPI(89)
+#define EXYNOS5_IRQ_EFNFCON_DMA                IRQ_SPI(90)
+#define EXYNOS5_IRQ_2D                 IRQ_SPI(91)
+#define EXYNOS5_IRQ_SFMC0              IRQ_SPI(92)
+#define EXYNOS5_IRQ_SFMC1              IRQ_SPI(93)
+#define EXYNOS5_IRQ_MIXER              IRQ_SPI(94)
+#define EXYNOS5_IRQ_HDMI               IRQ_SPI(95)
+#define EXYNOS5_IRQ_MFC                        IRQ_SPI(96)
+#define EXYNOS5_IRQ_AUDIO_SS           IRQ_SPI(97)
+#define EXYNOS5_IRQ_I2S0               IRQ_SPI(98)
+#define EXYNOS5_IRQ_I2S1               IRQ_SPI(99)
+#define EXYNOS5_IRQ_I2S2               IRQ_SPI(100)
+#define EXYNOS5_IRQ_AC97               IRQ_SPI(101)
+#define EXYNOS5_IRQ_PCM0               IRQ_SPI(102)
+#define EXYNOS5_IRQ_PCM1               IRQ_SPI(103)
+#define EXYNOS5_IRQ_PCM2               IRQ_SPI(104)
+#define EXYNOS5_IRQ_SPDIF              IRQ_SPI(105)
+#define EXYNOS5_IRQ_ADC0               IRQ_SPI(106)
+
+#define EXYNOS5_IRQ_SATA_PHY           IRQ_SPI(108)
+#define EXYNOS5_IRQ_SATA_PMEMREQ       IRQ_SPI(109)
+#define EXYNOS5_IRQ_CAM_C              IRQ_SPI(110)
+#define EXYNOS5_IRQ_EAGLE_PMU          IRQ_SPI(111)
+#define EXYNOS5_IRQ_INTFEEDCTRL_SSS    IRQ_SPI(112)
+#define EXYNOS5_IRQ_DP1_INTP1          IRQ_SPI(113)
+#define EXYNOS5_IRQ_CEC                        IRQ_SPI(114)
+#define EXYNOS5_IRQ_SATA               IRQ_SPI(115)
+#define EXYNOS5_IRQ_NFCON              IRQ_SPI(116)
+
+#define EXYNOS5_IRQ_MMC44              IRQ_SPI(123)
+#define EXYNOS5_IRQ_MDMA1              IRQ_SPI(124)
+#define EXYNOS5_IRQ_FIMC_LITE0         IRQ_SPI(125)
+#define EXYNOS5_IRQ_FIMC_LITE1         IRQ_SPI(126)
+#define EXYNOS5_IRQ_RP_TIMER           IRQ_SPI(127)
+
+#define EXYNOS5_IRQ_PMU                        COMBINER_IRQ(1, 2)
+#define EXYNOS5_IRQ_PMU_CPU1           COMBINER_IRQ(1, 6)
+
+#define EXYNOS5_IRQ_SYSMMU_GSC0_0      COMBINER_IRQ(2, 0)
+#define EXYNOS5_IRQ_SYSMMU_GSC0_1      COMBINER_IRQ(2, 1)
+#define EXYNOS5_IRQ_SYSMMU_GSC1_0      COMBINER_IRQ(2, 2)
+#define EXYNOS5_IRQ_SYSMMU_GSC1_1      COMBINER_IRQ(2, 3)
+#define EXYNOS5_IRQ_SYSMMU_GSC2_0      COMBINER_IRQ(2, 4)
+#define EXYNOS5_IRQ_SYSMMU_GSC2_1      COMBINER_IRQ(2, 5)
+#define EXYNOS5_IRQ_SYSMMU_GSC3_0      COMBINER_IRQ(2, 6)
+#define EXYNOS5_IRQ_SYSMMU_GSC3_1      COMBINER_IRQ(2, 7)
+
+#define EXYNOS5_IRQ_SYSMMU_FIMD1_0     COMBINER_IRQ(3, 2)
+#define EXYNOS5_IRQ_SYSMMU_FIMD1_1     COMBINER_IRQ(3, 3)
+#define EXYNOS5_IRQ_SYSMMU_LITE0_0     COMBINER_IRQ(3, 4)
+#define EXYNOS5_IRQ_SYSMMU_LITE0_1     COMBINER_IRQ(3, 5)
+#define EXYNOS5_IRQ_SYSMMU_SCALERPISP_0        COMBINER_IRQ(3, 6)
+#define EXYNOS5_IRQ_SYSMMU_SCALERPISP_1        COMBINER_IRQ(3, 7)
+
+#define EXYNOS5_IRQ_SYSMMU_ROTATOR_0   COMBINER_IRQ(4, 0)
+#define EXYNOS5_IRQ_SYSMMU_ROTATOR_1   COMBINER_IRQ(4, 1)
+#define EXYNOS5_IRQ_SYSMMU_JPEG_0      COMBINER_IRQ(4, 2)
+#define EXYNOS5_IRQ_SYSMMU_JPEG_1      COMBINER_IRQ(4, 3)
+
+#define EXYNOS5_IRQ_SYSMMU_FD_0                COMBINER_IRQ(5, 0)
+#define EXYNOS5_IRQ_SYSMMU_FD_1                COMBINER_IRQ(5, 1)
+#define EXYNOS5_IRQ_SYSMMU_SCALERCISP_0        COMBINER_IRQ(5, 2)
+#define EXYNOS5_IRQ_SYSMMU_SCALERCISP_1        COMBINER_IRQ(5, 3)
+#define EXYNOS5_IRQ_SYSMMU_MCUISP_0    COMBINER_IRQ(5, 4)
+#define EXYNOS5_IRQ_SYSMMU_MCUISP_1    COMBINER_IRQ(5, 5)
+#define EXYNOS5_IRQ_SYSMMU_3DNR_0      COMBINER_IRQ(5, 6)
+#define EXYNOS5_IRQ_SYSMMU_3DNR_1      COMBINER_IRQ(5, 7)
+
+#define EXYNOS5_IRQ_SYSMMU_ARM_0       COMBINER_IRQ(6, 0)
+#define EXYNOS5_IRQ_SYSMMU_ARM_1       COMBINER_IRQ(6, 1)
+#define EXYNOS5_IRQ_SYSMMU_MFC_L_0     COMBINER_IRQ(6, 2)
+#define EXYNOS5_IRQ_SYSMMU_MFC_L_1     COMBINER_IRQ(6, 3)
+#define EXYNOS5_IRQ_SYSMMU_RTIC_0      COMBINER_IRQ(6, 4)
+#define EXYNOS5_IRQ_SYSMMU_RTIC_1      COMBINER_IRQ(6, 5)
+#define EXYNOS5_IRQ_SYSMMU_SSS_0       COMBINER_IRQ(6, 6)
+#define EXYNOS5_IRQ_SYSMMU_SSS_1       COMBINER_IRQ(6, 7)
+
+#define EXYNOS5_IRQ_SYSMMU_MDMA0_0     COMBINER_IRQ(7, 0)
+#define EXYNOS5_IRQ_SYSMMU_MDMA0_1     COMBINER_IRQ(7, 1)
+#define EXYNOS5_IRQ_SYSMMU_MDMA1_0     COMBINER_IRQ(7, 2)
+#define EXYNOS5_IRQ_SYSMMU_MDMA1_1     COMBINER_IRQ(7, 3)
+#define EXYNOS5_IRQ_SYSMMU_TV_0                COMBINER_IRQ(7, 4)
+#define EXYNOS5_IRQ_SYSMMU_TV_1                COMBINER_IRQ(7, 5)
+#define EXYNOS5_IRQ_SYSMMU_GPSX_0      COMBINER_IRQ(7, 6)
+#define EXYNOS5_IRQ_SYSMMU_GPSX_1      COMBINER_IRQ(7, 7)
+
+#define EXYNOS5_IRQ_SYSMMU_MFC_R_0     COMBINER_IRQ(8, 5)
+#define EXYNOS5_IRQ_SYSMMU_MFC_R_1     COMBINER_IRQ(8, 6)
+
+#define EXYNOS5_IRQ_SYSMMU_DIS1_0      COMBINER_IRQ(9, 4)
+#define EXYNOS5_IRQ_SYSMMU_DIS1_1      COMBINER_IRQ(9, 5)
+
+#define EXYNOS5_IRQ_DP                 COMBINER_IRQ(10, 3)
+#define EXYNOS5_IRQ_SYSMMU_DIS0_0      COMBINER_IRQ(10, 4)
+#define EXYNOS5_IRQ_SYSMMU_DIS0_1      COMBINER_IRQ(10, 5)
+#define EXYNOS5_IRQ_SYSMMU_ISP_0       COMBINER_IRQ(10, 6)
+#define EXYNOS5_IRQ_SYSMMU_ISP_1       COMBINER_IRQ(10, 7)
+
+#define EXYNOS5_IRQ_SYSMMU_ODC_0       COMBINER_IRQ(11, 0)
+#define EXYNOS5_IRQ_SYSMMU_ODC_1       COMBINER_IRQ(11, 1)
+#define EXYNOS5_IRQ_SYSMMU_DRC_0       COMBINER_IRQ(11, 6)
+#define EXYNOS5_IRQ_SYSMMU_DRC_1       COMBINER_IRQ(11, 7)
+
+#define EXYNOS5_IRQ_FIMD1_FIFO         COMBINER_IRQ(18, 4)
+#define EXYNOS5_IRQ_FIMD1_VSYNC                COMBINER_IRQ(18, 5)
+#define EXYNOS5_IRQ_FIMD1_SYSTEM       COMBINER_IRQ(18, 6)
+
+#define EXYNOS5_IRQ_EINT0              COMBINER_IRQ(23, 0)
+#define EXYNOS5_IRQ_MCT_L0             COMBINER_IRQ(23, 1)
+#define EXYNOS5_IRQ_MCT_L1             COMBINER_IRQ(23, 2)
+#define EXYNOS5_IRQ_MCT_G0             COMBINER_IRQ(23, 3)
+#define EXYNOS5_IRQ_MCT_G1             COMBINER_IRQ(23, 4)
+#define EXYNOS5_IRQ_MCT_G2             COMBINER_IRQ(23, 5)
+#define EXYNOS5_IRQ_MCT_G3             COMBINER_IRQ(23, 6)
+
+#define EXYNOS5_IRQ_EINT1              COMBINER_IRQ(24, 0)
+#define EXYNOS5_IRQ_SYSMMU_LITE1_0     COMBINER_IRQ(24, 1)
+#define EXYNOS5_IRQ_SYSMMU_LITE1_1     COMBINER_IRQ(24, 2)
+#define EXYNOS5_IRQ_SYSMMU_2D_0                COMBINER_IRQ(24, 5)
+#define EXYNOS5_IRQ_SYSMMU_2D_1                COMBINER_IRQ(24, 6)
+
+#define EXYNOS5_IRQ_EINT2              COMBINER_IRQ(25, 0)
+#define EXYNOS5_IRQ_EINT3              COMBINER_IRQ(25, 1)
+
+#define EXYNOS5_IRQ_EINT4              COMBINER_IRQ(26, 0)
+#define EXYNOS5_IRQ_EINT5              COMBINER_IRQ(26, 1)
+
+#define EXYNOS5_IRQ_EINT6              COMBINER_IRQ(27, 0)
+#define EXYNOS5_IRQ_EINT7              COMBINER_IRQ(27, 1)
+
+#define EXYNOS5_IRQ_EINT8              COMBINER_IRQ(28, 0)
+#define EXYNOS5_IRQ_EINT9              COMBINER_IRQ(28, 1)
+
+#define EXYNOS5_IRQ_EINT10             COMBINER_IRQ(29, 0)
+#define EXYNOS5_IRQ_EINT11             COMBINER_IRQ(29, 1)
+
+#define EXYNOS5_IRQ_EINT12             COMBINER_IRQ(30, 0)
+#define EXYNOS5_IRQ_EINT13             COMBINER_IRQ(30, 1)
+
+#define EXYNOS5_IRQ_EINT14             COMBINER_IRQ(31, 0)
+#define EXYNOS5_IRQ_EINT15             COMBINER_IRQ(31, 1)
+
+#define EXYNOS5_MAX_COMBINER_NR                32
+
+#define EXYNOS5_IRQ_GPIO1_NR_GROUPS    13
+#define EXYNOS5_IRQ_GPIO2_NR_GROUPS    9
+#define EXYNOS5_IRQ_GPIO3_NR_GROUPS    5
+#define EXYNOS5_IRQ_GPIO4_NR_GROUPS    1
+
+#define MAX_COMBINER_NR                        (EXYNOS4_MAX_COMBINER_NR > EXYNOS5_MAX_COMBINER_NR ? \
+                                       EXYNOS4_MAX_COMBINER_NR : EXYNOS5_MAX_COMBINER_NR)
+
+#define S5P_EINT_BASE1                 COMBINER_IRQ(MAX_COMBINER_NR, 0)
+#define S5P_EINT_BASE2                 (S5P_EINT_BASE1 + 16)
+#define S5P_GPIOINT_BASE               (S5P_EINT_BASE1 + 32)
+#define IRQ_GPIO_END                   (S5P_GPIOINT_BASE + S5P_GPIOINT_COUNT)
+#define IRQ_TIMER_BASE                 (IRQ_GPIO_END + 64)
 
 /* Set the default NR_IRQS */
-#define NR_IRQS                        (IRQ_TIMER_BASE + IRQ_TIMER_COUNT)
+
+#define NR_IRQS                                (IRQ_TIMER_BASE + IRQ_TIMER_COUNT)
 
 #endif /* __ASM_ARCH_IRQS_H */
index 609127d..024d38f 100644 (file)
@@ -25,6 +25,7 @@
 
 #define EXYNOS4_PA_SYSRAM0             0x02025000
 #define EXYNOS4_PA_SYSRAM1             0x02020000
+#define EXYNOS5_PA_SYSRAM              0x02020000
 
 #define EXYNOS4_PA_FIMC0               0x11800000
 #define EXYNOS4_PA_FIMC1               0x11810000
 #define EXYNOS4_PA_ONENAND             0x0C000000
 #define EXYNOS4_PA_ONENAND_DMA         0x0C600000
 
-#define EXYNOS4_PA_CHIPID              0x10000000
+#define EXYNOS_PA_CHIPID               0x10000000
 
 #define EXYNOS4_PA_SYSCON              0x10010000
+#define EXYNOS5_PA_SYSCON              0x10050100
+
 #define EXYNOS4_PA_PMU                 0x10020000
+#define EXYNOS5_PA_PMU                 0x10040000
+
 #define EXYNOS4_PA_CMU                 0x10030000
+#define EXYNOS5_PA_CMU                 0x10010000
 
 #define EXYNOS4_PA_SYSTIMER            0x10050000
+#define EXYNOS5_PA_SYSTIMER            0x101C0000
+
 #define EXYNOS4_PA_WATCHDOG            0x10060000
+#define EXYNOS5_PA_WATCHDOG            0x101D0000
+
 #define EXYNOS4_PA_RTC                 0x10070000
 
 #define EXYNOS4_PA_KEYPAD              0x100A0000
 #define EXYNOS4_PA_DMC1                        0x10410000
 
 #define EXYNOS4_PA_COMBINER            0x10440000
+#define EXYNOS5_PA_COMBINER            0x10440000
 
 #define EXYNOS4_PA_GIC_CPU             0x10480000
 #define EXYNOS4_PA_GIC_DIST            0x10490000
+#define EXYNOS5_PA_GIC_CPU             0x10480000
+#define EXYNOS5_PA_GIC_DIST            0x10490000
 
 #define EXYNOS4_PA_COREPERI            0x10500000
 #define EXYNOS4_PA_TWD                 0x10500600
 #define EXYNOS4_PA_SPI1                        0x13930000
 #define EXYNOS4_PA_SPI2                        0x13940000
 
-
 #define EXYNOS4_PA_GPIO1               0x11400000
 #define EXYNOS4_PA_GPIO2               0x11000000
 #define EXYNOS4_PA_GPIO3               0x03860000
+#define EXYNOS5_PA_GPIO1               0x11400000
+#define EXYNOS5_PA_GPIO2               0x13400000
+#define EXYNOS5_PA_GPIO3               0x10D10000
+#define EXYNOS5_PA_GPIO4               0x03860000
 
 #define EXYNOS4_PA_MIPI_CSIS0          0x11880000
 #define EXYNOS4_PA_MIPI_CSIS1          0x11890000
 #define EXYNOS4_PA_SATAPHY_CTRL                0x126B0000
 
 #define EXYNOS4_PA_SROMC               0x12570000
+#define EXYNOS5_PA_SROMC               0x12250000
 
 #define EXYNOS4_PA_EHCI                        0x12580000
 #define EXYNOS4_PA_OHCI                        0x12590000
 #define EXYNOS4_PA_MFC                 0x13400000
 
 #define EXYNOS4_PA_UART                        0x13800000
+#define EXYNOS5_PA_UART                        0x12C00000
 
 #define EXYNOS4_PA_VP                  0x12C00000
 #define EXYNOS4_PA_MIXER               0x12C10000
 #define EXYNOS4_PA_IIC_HDMIPHY         0x138E0000
 
 #define EXYNOS4_PA_IIC(x)              (0x13860000 + ((x) * 0x10000))
+#define EXYNOS5_PA_IIC(x)              (0x12C60000 + ((x) * 0x10000))
 
 #define EXYNOS4_PA_ADC                 0x13910000
 #define EXYNOS4_PA_ADC1                        0x13911000
 #define EXYNOS4_PA_SPDIF               0x139B0000
 
 #define EXYNOS4_PA_TIMER               0x139D0000
+#define EXYNOS5_PA_TIMER               0x12DD0000
 
 #define EXYNOS4_PA_SDRAM               0x40000000
+#define EXYNOS5_PA_SDRAM               0x40000000
 
 /* Compatibiltiy Defines */
 
 #define S3C_PA_IIC7                    EXYNOS4_PA_IIC(7)
 #define S3C_PA_RTC                     EXYNOS4_PA_RTC
 #define S3C_PA_WDT                     EXYNOS4_PA_WATCHDOG
-#define S3C_PA_UART                    EXYNOS4_PA_UART
 #define S3C_PA_SPI0                    EXYNOS4_PA_SPI0
 #define S3C_PA_SPI1                    EXYNOS4_PA_SPI1
 #define S3C_PA_SPI2                    EXYNOS4_PA_SPI2
 
 /* Compatibility UART */
 
-#define S3C_VA_UARTx(x)                        (S3C_VA_UART + ((x) * S3C_UART_OFFSET))
+#define EXYNOS4_PA_UART0               0x13800000
+#define EXYNOS4_PA_UART1               0x13810000
+#define EXYNOS4_PA_UART2               0x13820000
+#define EXYNOS4_PA_UART3               0x13830000
+#define EXYNOS4_SZ_UART                        SZ_256
 
-#define S5P_PA_UART(x)                 (EXYNOS4_PA_UART + ((x) * S3C_UART_OFFSET))
-#define S5P_PA_UART0                   S5P_PA_UART(0)
-#define S5P_PA_UART1                   S5P_PA_UART(1)
-#define S5P_PA_UART2                   S5P_PA_UART(2)
-#define S5P_PA_UART3                   S5P_PA_UART(3)
-#define S5P_PA_UART4                   S5P_PA_UART(4)
+#define EXYNOS5_PA_UART0               0x12C00000
+#define EXYNOS5_PA_UART1               0x12C10000
+#define EXYNOS5_PA_UART2               0x12C20000
+#define EXYNOS5_PA_UART3               0x12C30000
+#define EXYNOS5_SZ_UART                        SZ_256
 
-#define S5P_SZ_UART                    SZ_256
+#define S3C_VA_UARTx(x)                        (S3C_VA_UART + ((x) * S3C_UART_OFFSET))
 
 #endif /* __ASM_ARCH_MAP_H */
index 1e4abd6..e141c1f 100644 (file)
 #define EXYNOS4_CLKDIV_CAM1_JPEG_SHIFT         (0)
 #define EXYNOS4_CLKDIV_CAM1_JPEG_MASK          (0xf << EXYNOS4_CLKDIV_CAM1_JPEG_SHIFT)
 
+/* For EXYNOS5250 */
+
+#define EXYNOS5_APLL_CON0                      EXYNOS_CLKREG(0x00100)
+#define EXYNOS5_CLKSRC_CPU                     EXYNOS_CLKREG(0x00200)
+#define EXYNOS5_CLKDIV_CPU0                    EXYNOS_CLKREG(0x00500)
+#define EXYNOS5_MPLL_CON0                      EXYNOS_CLKREG(0x04100)
+#define EXYNOS5_CLKSRC_CORE1                   EXYNOS_CLKREG(0x04204)
+
+#define EXYNOS5_CLKGATE_IP_CORE                        EXYNOS_CLKREG(0x04900)
+
+#define EXYNOS5_CLKDIV_ACP                     EXYNOS_CLKREG(0x08500)
+
+#define EXYNOS5_CLKSRC_TOP2                    EXYNOS_CLKREG(0x10218)
+#define EXYNOS5_EPLL_CON0                      EXYNOS_CLKREG(0x10130)
+#define EXYNOS5_EPLL_CON1                      EXYNOS_CLKREG(0x10134)
+#define EXYNOS5_VPLL_CON0                      EXYNOS_CLKREG(0x10140)
+#define EXYNOS5_VPLL_CON1                      EXYNOS_CLKREG(0x10144)
+#define EXYNOS5_CPLL_CON0                      EXYNOS_CLKREG(0x10120)
+
+#define EXYNOS5_CLKSRC_TOP0                    EXYNOS_CLKREG(0x10210)
+#define EXYNOS5_CLKSRC_TOP3                    EXYNOS_CLKREG(0x1021C)
+#define EXYNOS5_CLKSRC_GSCL                    EXYNOS_CLKREG(0x10220)
+#define EXYNOS5_CLKSRC_DISP1_0                 EXYNOS_CLKREG(0x1022C)
+#define EXYNOS5_CLKSRC_FSYS                    EXYNOS_CLKREG(0x10244)
+#define EXYNOS5_CLKSRC_PERIC0                  EXYNOS_CLKREG(0x10250)
+
+#define EXYNOS5_CLKSRC_MASK_TOP                        EXYNOS_CLKREG(0x10310)
+#define EXYNOS5_CLKSRC_MASK_GSCL               EXYNOS_CLKREG(0x10320)
+#define EXYNOS5_CLKSRC_MASK_DISP1_0            EXYNOS_CLKREG(0x1032C)
+#define EXYNOS5_CLKSRC_MASK_FSYS               EXYNOS_CLKREG(0x10340)
+#define EXYNOS5_CLKSRC_MASK_PERIC0             EXYNOS_CLKREG(0x10350)
+
+#define EXYNOS5_CLKDIV_TOP0                    EXYNOS_CLKREG(0x10510)
+#define EXYNOS5_CLKDIV_TOP1                    EXYNOS_CLKREG(0x10514)
+#define EXYNOS5_CLKDIV_GSCL                    EXYNOS_CLKREG(0x10520)
+#define EXYNOS5_CLKDIV_DISP1_0                 EXYNOS_CLKREG(0x1052C)
+#define EXYNOS5_CLKDIV_GEN                     EXYNOS_CLKREG(0x1053C)
+#define EXYNOS5_CLKDIV_FSYS0                   EXYNOS_CLKREG(0x10548)
+#define EXYNOS5_CLKDIV_FSYS1                   EXYNOS_CLKREG(0x1054C)
+#define EXYNOS5_CLKDIV_FSYS2                   EXYNOS_CLKREG(0x10550)
+#define EXYNOS5_CLKDIV_FSYS3                   EXYNOS_CLKREG(0x10554)
+#define EXYNOS5_CLKDIV_PERIC0                  EXYNOS_CLKREG(0x10558)
+
+#define EXYNOS5_CLKGATE_IP_ACP                 EXYNOS_CLKREG(0x08800)
+#define EXYNOS5_CLKGATE_IP_GSCL                        EXYNOS_CLKREG(0x10920)
+#define EXYNOS5_CLKGATE_IP_DISP1               EXYNOS_CLKREG(0x10928)
+#define EXYNOS5_CLKGATE_IP_MFC                 EXYNOS_CLKREG(0x1092C)
+#define EXYNOS5_CLKGATE_IP_GEN                 EXYNOS_CLKREG(0x10934)
+#define EXYNOS5_CLKGATE_IP_FSYS                        EXYNOS_CLKREG(0x10944)
+#define EXYNOS5_CLKGATE_IP_GPS                 EXYNOS_CLKREG(0x1094C)
+#define EXYNOS5_CLKGATE_IP_PERIC               EXYNOS_CLKREG(0x10950)
+#define EXYNOS5_CLKGATE_IP_PERIS               EXYNOS_CLKREG(0x10960)
+#define EXYNOS5_CLKGATE_BLOCK                  EXYNOS_CLKREG(0x10980)
+
+#define EXYNOS5_BPLL_CON0                      EXYNOS_CLKREG(0x20110)
+#define EXYNOS5_CLKSRC_CDREX                   EXYNOS_CLKREG(0x20200)
+#define EXYNOS5_CLKDIV_CDREX                   EXYNOS_CLKREG(0x20500)
+
+#define EXYNOS5_EPLL_LOCK                      EXYNOS_CLKREG(0x10030)
+
+#define EXYNOS5_EPLLCON0_LOCKED_SHIFT          (29)
+
 /* Compatibility defines and inclusion */
 
 #include <mach/regs-pmu.h>
index 1401b21..e4b5b60 100644 (file)
 #include <mach/map.h>
 #include <mach/irqs.h>
 
+#define EINT_REG_NR(x)                 (EINT_OFFSET(x) >> 3)
+#define EINT_CON(b, x)                 (b + 0xE00 + (EINT_REG_NR(x) * 4))
+#define EINT_FLTCON(b, x)              (b + 0xE80 + (EINT_REG_NR(x) * 4))
+#define EINT_MASK(b, x)                        (b + 0xF00 + (EINT_REG_NR(x) * 4))
+#define EINT_PEND(b, x)                        (b + 0xF40 + (EINT_REG_NR(x) * 4))
+
+#define EINT_OFFSET_BIT(x)             (1 << (EINT_OFFSET(x) & 0x7))
+
+/* compatibility for plat-s5p/irq-pm.c */
 #define EXYNOS4_EINT40CON              (S5P_VA_GPIO2 + 0xE00)
 #define S5P_EINT_CON(x)                        (EXYNOS4_EINT40CON + ((x) * 0x4))
 
 #define EXYNOS4_EINT40PEND             (S5P_VA_GPIO2 + 0xF40)
 #define S5P_EINT_PEND(x)               (EXYNOS4_EINT40PEND + ((x) * 0x4))
 
-#define EINT_REG_NR(x)                 (EINT_OFFSET(x) >> 3)
-
-#define eint_irq_to_bit(irq)           (1 << (EINT_OFFSET(irq) & 0x7))
-
-#define EINT_MODE                      S3C_GPIO_SFN(0xf)
-
-#define EINT_GPIO_0(x)                 EXYNOS4_GPX0(x)
-#define EINT_GPIO_1(x)                 EXYNOS4_GPX1(x)
-#define EINT_GPIO_2(x)                 EXYNOS4_GPX2(x)
-#define EINT_GPIO_3(x)                 EXYNOS4_GPX3(x)
-
 #endif /* __ASM_ARCH_REGS_GPIO_H */
index 4fff8e9..4c53f38 100644 (file)
@@ -31,6 +31,7 @@
 #define S5P_USE_STANDBYWFE_ISP_ARM             (1 << 26)
 
 #define S5P_SWRESET                            S5P_PMUREG(0x0400)
+#define EXYNOS_SWRESET                         S5P_PMUREG(0x0400)
 
 #define S5P_WAKEUP_STAT                                S5P_PMUREG(0x0600)
 #define S5P_EINT_WAKEUP_MASK                   S5P_PMUREG(0x0604)
index 21d97bc..493f4f3 100644 (file)
@@ -1,9 +1,8 @@
-/* linux/arch/arm/mach-exynos4/include/mach/uncompress.h
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+/*
+ * Copyright (c) 2010-2012 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com
  *
- * EXYNOS4 - uncompress code
+ * EXYNOS - uncompress 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
 #ifndef __ASM_ARCH_UNCOMPRESS_H
 #define __ASM_ARCH_UNCOMPRESS_H __FILE__
 
+#include <asm/mach-types.h>
+
 #include <mach/map.h>
+
+volatile u8 *uart_base;
+
 #include <plat/uncompress.h>
 
 static void arch_detect_cpu(void)
 {
-       /* we do not need to do any cpu detection here at the moment. */
+       if (machine_is_smdk5250())
+               uart_base = (volatile u8 *)EXYNOS5_PA_UART + (S3C_UART_OFFSET * CONFIG_S3C_LOWLEVEL_UART_PORT);
+       else
+               uart_base = (volatile u8 *)EXYNOS4_PA_UART + (S3C_UART_OFFSET * CONFIG_S3C_LOWLEVEL_UART_PORT);
 
        /*
         * For preventing FIFO overrun or infinite loop of UART console,
index e6b02fd..8245f1c 100644 (file)
  * data from the device tree.
  */
 static const struct of_dev_auxdata exynos4210_auxdata_lookup[] __initconst = {
-       OF_DEV_AUXDATA("samsung,exynos4210-uart", S5P_PA_UART0,
+       OF_DEV_AUXDATA("samsung,exynos4210-uart", EXYNOS4_PA_UART0,
                                "exynos4210-uart.0", NULL),
-       OF_DEV_AUXDATA("samsung,exynos4210-uart", S5P_PA_UART1,
+       OF_DEV_AUXDATA("samsung,exynos4210-uart", EXYNOS4_PA_UART1,
                                "exynos4210-uart.1", NULL),
-       OF_DEV_AUXDATA("samsung,exynos4210-uart", S5P_PA_UART2,
+       OF_DEV_AUXDATA("samsung,exynos4210-uart", EXYNOS4_PA_UART2,
                                "exynos4210-uart.2", NULL),
-       OF_DEV_AUXDATA("samsung,exynos4210-uart", S5P_PA_UART3,
+       OF_DEV_AUXDATA("samsung,exynos4210-uart", EXYNOS4_PA_UART3,
                                "exynos4210-uart.3", NULL),
        OF_DEV_AUXDATA("samsung,exynos4210-sdhci", EXYNOS4_PA_HSMMC(0),
                                "exynos4-sdhci.0", NULL),
diff --git a/arch/arm/mach-exynos/mach-exynos5-dt.c b/arch/arm/mach-exynos/mach-exynos5-dt.c
new file mode 100644 (file)
index 0000000..0d26f50
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * SAMSUNG EXYNOS5250 Flattened Device Tree enabled machine
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/of_platform.h>
+#include <linux/serial_core.h>
+
+#include <asm/mach/arch.h>
+#include <asm/hardware/gic.h>
+#include <mach/map.h>
+
+#include <plat/cpu.h>
+#include <plat/regs-serial.h>
+
+#include "common.h"
+
+/*
+ * The following lookup table is used to override device names when devices
+ * are registered from device tree. This is temporarily added to enable
+ * device tree support addition for the EXYNOS5 architecture.
+ *
+ * For drivers that require platform data to be provided from the machine
+ * file, a platform data pointer can also be supplied along with the
+ * devices names. Usually, the platform data elements that cannot be parsed
+ * from the device tree by the drivers (example: function pointers) are
+ * supplied. But it should be noted that this is a temporary mechanism and
+ * at some point, the drivers should be capable of parsing all the platform
+ * data from the device tree.
+ */
+static const struct of_dev_auxdata exynos5250_auxdata_lookup[] __initconst = {
+       OF_DEV_AUXDATA("samsung,exynos4210-uart", EXYNOS5_PA_UART0,
+                               "exynos4210-uart.0", NULL),
+       OF_DEV_AUXDATA("samsung,exynos4210-uart", EXYNOS5_PA_UART1,
+                               "exynos4210-uart.1", NULL),
+       OF_DEV_AUXDATA("samsung,exynos4210-uart", EXYNOS5_PA_UART2,
+                               "exynos4210-uart.2", NULL),
+       OF_DEV_AUXDATA("samsung,exynos4210-uart", EXYNOS5_PA_UART3,
+                               "exynos4210-uart.3", NULL),
+       OF_DEV_AUXDATA("arm,pl330", EXYNOS5_PA_PDMA0, "dma-pl330.0", NULL),
+       OF_DEV_AUXDATA("arm,pl330", EXYNOS5_PA_PDMA1, "dma-pl330.1", NULL),
+       OF_DEV_AUXDATA("arm,pl330", EXYNOS5_PA_PDMA1, "dma-pl330.2", NULL),
+       {},
+};
+
+static void __init exynos5250_dt_map_io(void)
+{
+       exynos_init_io(NULL, 0);
+       s3c24xx_init_clocks(24000000);
+}
+
+static void __init exynos5250_dt_machine_init(void)
+{
+       of_platform_populate(NULL, of_default_bus_match_table,
+                               exynos5250_auxdata_lookup, NULL);
+}
+
+static char const *exynos5250_dt_compat[] __initdata = {
+       "samsung,exynos5250",
+       NULL
+};
+
+DT_MACHINE_START(EXYNOS5_DT, "SAMSUNG EXYNOS5 (Flattened Device Tree)")
+       /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
+       .init_irq       = exynos5_init_irq,
+       .map_io         = exynos5250_dt_map_io,
+       .handle_irq     = gic_handle_irq,
+       .init_machine   = exynos5250_dt_machine_init,
+       .timer          = &exynos4_timer,
+       .dt_compat      = exynos5250_dt_compat,
+       .restart        = exynos5_restart,
+MACHINE_END
index e8a1caa..897d9a9 100644 (file)
@@ -261,7 +261,10 @@ static void exynos4_clockevent_init(void)
        mct_comp_device.cpumask = cpumask_of(0);
        clockevents_register_device(&mct_comp_device);
 
-       setup_irq(IRQ_MCT_G0, &mct_comp_event_irq);
+       if (soc_is_exynos5250())
+               setup_irq(EXYNOS5_IRQ_MCT_G0, &mct_comp_event_irq);
+       else
+               setup_irq(EXYNOS4_IRQ_MCT_G0, &mct_comp_event_irq);
 }
 
 #ifdef CONFIG_LOCAL_TIMERS
@@ -412,16 +415,16 @@ static int __cpuinit exynos4_local_timer_setup(struct clock_event_device *evt)
        if (mct_int_type == MCT_INT_SPI) {
                if (cpu == 0) {
                        mct_tick0_event_irq.dev_id = mevt;
-                       evt->irq = IRQ_MCT_L0;
-                       setup_irq(IRQ_MCT_L0, &mct_tick0_event_irq);
+                       evt->irq = EXYNOS4_IRQ_MCT_L0;
+                       setup_irq(EXYNOS4_IRQ_MCT_L0, &mct_tick0_event_irq);
                } else {
                        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));
+                       evt->irq = EXYNOS4_IRQ_MCT_L1;
+                       setup_irq(EXYNOS4_IRQ_MCT_L1, &mct_tick1_event_irq);
+                       irq_set_affinity(EXYNOS4_IRQ_MCT_L1, cpumask_of(1));
                }
        } else {
-               enable_percpu_irq(IRQ_MCT_LOCALTIMER, 0);
+               enable_percpu_irq(EXYNOS_IRQ_MCT_LOCALTIMER, 0);
        }
 
        return 0;
@@ -437,7 +440,7 @@ static void exynos4_local_timer_stop(struct clock_event_device *evt)
                else
                        remove_irq(evt->irq, &mct_tick1_event_irq);
        else
-               disable_percpu_irq(IRQ_MCT_LOCALTIMER);
+               disable_percpu_irq(EXYNOS_IRQ_MCT_LOCALTIMER);
 }
 
 static struct local_timer_ops exynos4_mct_tick_ops __cpuinitdata = {
@@ -457,11 +460,11 @@ static void __init exynos4_timer_resources(void)
        if (mct_int_type == MCT_INT_PPI) {
                int err;
 
-               err = request_percpu_irq(IRQ_MCT_LOCALTIMER,
+               err = request_percpu_irq(EXYNOS_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);
+                    EXYNOS_IRQ_MCT_LOCALTIMER, err);
        }
 
        local_timer_register(&exynos4_mct_tick_ops);
index 0f2035a..36c3984 100644 (file)
@@ -166,7 +166,10 @@ void __init smp_init_cpus(void)
        void __iomem *scu_base = scu_base_addr();
        unsigned int i, ncores;
 
-       ncores = scu_base ? scu_get_core_count(scu_base) : 1;
+       if (soc_is_exynos5250())
+               ncores = 2;
+       else
+               ncores = scu_base ? scu_get_core_count(scu_base) : 1;
 
        /* sanity check */
        if (ncores > nr_cpu_ids) {
@@ -183,8 +186,8 @@ void __init smp_init_cpus(void)
 
 void __init platform_smp_prepare_cpus(unsigned int max_cpus)
 {
-
-       scu_enable(scu_base_addr());
+       if (!soc_is_exynos5250())
+               scu_enable(scu_base_addr());
 
        /*
         * Write the address of secondary startup into the
index 0b04af2..13b3068 100644 (file)
@@ -183,6 +183,12 @@ static __init int exynos4_pm_init_power_domain(void)
 #ifdef CONFIG_S5P_DEV_CSIS1
        exynos_pm_add_dev_to_genpd(&s5p_device_mipi_csis1, &exynos4_pd_cam);
 #endif
+#ifdef CONFIG_S5P_DEV_G2D
+       exynos_pm_add_dev_to_genpd(&s5p_device_g2d, &exynos4_pd_lcd0);
+#endif
+#ifdef CONFIG_S5P_DEV_JPEG
+       exynos_pm_add_dev_to_genpd(&s5p_device_jpeg, &exynos4_pd_cam);
+#endif
        return 0;
 }
 arch_initcall(exynos4_pm_init_power_domain);
index d395bd1..b90d94c 100644 (file)
@@ -1,7 +1,5 @@
 /*
- * linux/arch/arm/mach-exynos4/setup-i2c0.c
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2009-2012 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com/
  *
  * I2C0 GPIO configuration.
@@ -18,9 +16,14 @@ struct platform_device; /* don't need the contents */
 #include <linux/gpio.h>
 #include <plat/iic.h>
 #include <plat/gpio-cfg.h>
+#include <plat/cpu.h>
 
 void s3c_i2c0_cfg_gpio(struct platform_device *dev)
 {
+       if (soc_is_exynos5250())
+               /* will be implemented with gpio function */
+               return;
+
        s3c_gpio_cfgall_range(EXYNOS4_GPD1(0), 2,
                              S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
 }
index 41978ee..3e6aaa6 100644 (file)
@@ -21,6 +21,7 @@
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 #include <asm/setup.h>
+#include <asm/system_misc.h>
 #include <asm/hardware/dec21285.h>
 
 #include <asm/mach/irq.h>
index 121ad1d..3b54196 100644 (file)
@@ -14,6 +14,7 @@
 
 #include <asm/hardware/dec21285.h>
 #include <asm/mach/time.h>
+#include <asm/system_info.h>
 
 #include "common.h"
 
index 3194d3f..e17e11d 100644 (file)
@@ -21,7 +21,6 @@
 #include <video/vga.h>
 
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/mach/pci.h>
 #include <asm/hardware/dec21285.h>
 
index 4e10090..5bd2667 100644 (file)
@@ -24,7 +24,6 @@
 #include <mach/hardware.h>
 #include <asm/leds.h>
 #include <asm/mach-types.h>
-#include <asm/system.h>
 
 #define LED_STATE_ENABLED      1
 #define LED_STATE_CLAIMED      2
index 80a1c5c..cac9f67 100644 (file)
@@ -17,6 +17,7 @@
 #include <asm/leds.h>
 #include <asm/mach-types.h>
 #include <asm/setup.h>
+#include <asm/system_misc.h>
 
 #include <asm/mach/arch.h>
 
index e57102e..5a2bd89 100644 (file)
@@ -24,7 +24,6 @@
 #include <mach/hardware.h>
 #include <asm/leds.h>
 #include <asm/mach-types.h>
-#include <asm/system.h>
 
 #define LED_STATE_ENABLED      1
 #define LED_STATE_CLAIMED      2
index 42afc29..3189a60 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/scatterlist.h>
 #include <linux/io.h>
 
-#include <asm/system.h>
 #include <asm/irq.h>
 #include <mach/hardware.h>
 #include <mach/dma-v1.h>
index 7696dfa..da6c1d9 100644 (file)
@@ -26,6 +26,7 @@
 #include <asm/hardware/gic.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
+#include <asm/system_misc.h>
 #include <mach/common.h>
 #include <mach/hardware.h>
 
index 3a5ed2d..586e9f8 100644 (file)
@@ -33,6 +33,7 @@
 #include <mach/iomux-mx51.h>
 
 #include <asm/setup.h>
+#include <asm/system_info.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
index ea5f65b..24aded9 100644 (file)
@@ -36,6 +36,7 @@
 #include <mach/iomux-mx51.h>
 
 #include <asm/setup.h>
+#include <asm/system_info.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
index 15b87f2..1a65d77 100644 (file)
@@ -27,7 +27,6 @@
 #include <mach/platform.h>
 #include <asm/irq.h>
 #include <mach/cm.h>
-#include <asm/system.h>
 #include <asm/leds.h>
 #include <asm/mach-types.h>
 #include <asm/mach/time.h>
index 28be186..466defa 100644 (file)
@@ -29,7 +29,6 @@
 #include <mach/hardware.h>
 #include <mach/platform.h>
 #include <asm/leds.h>
-#include <asm/system.h>
 #include <asm/mach-types.h>
 #include <mach/cm.h>
 
index 520b6bf..36068f4 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/init.h>
 
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/mach/pci.h>
 #include <asm/mach-types.h>
 
index 015be77..4be172c 100644 (file)
@@ -32,7 +32,6 @@
 #include <mach/platform.h>
 #include <asm/irq.h>
 #include <asm/signal.h>
-#include <asm/system.h>
 #include <asm/mach/pci.h>
 #include <asm/irq_regs.h>
 
index cdae24e..bbf54d7 100644 (file)
@@ -22,7 +22,6 @@
 #include <asm/page.h>
 #include <asm/mach/map.h>
 #include <asm/setup.h>
-#include <asm/system.h>
 #include <asm/memory.h>
 #include <mach/hardware.h>
 #include <asm/hardware/iop3xx.h>
index 81c4537..f214cdf 100644 (file)
@@ -32,7 +32,6 @@
 #include <asm/memory.h>
 #include <mach/hardware.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/tlbflush.h>
 #include <asm/pgtable.h>
 
index e872d23..4867f40 100644 (file)
@@ -36,7 +36,6 @@
 #include <asm/irq.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
-#include <asm/system.h>
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 
index d519944..915ad49 100644 (file)
@@ -29,7 +29,6 @@
 #include <asm/irq.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
-#include <asm/system.h>
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 
index b415feb..a9f1819 100644 (file)
@@ -29,7 +29,6 @@
 #include <asm/irq.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
-#include <asm/system.h>
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 
index dd98382..421e38d 100644 (file)
@@ -30,7 +30,6 @@
 #include <asm/irq.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
-#include <asm/system.h>
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 
index 7632bea..5196c39 100644 (file)
@@ -34,7 +34,6 @@
 #include <asm/irq.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
-#include <asm/system.h>
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 
index 49c36f3..9c02de9 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/io.h>
 
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <mach/hardware.h>
 
 #include <asm/mach/pci.h>
index 7c1495e..d2c2dc3 100644 (file)
@@ -34,7 +34,6 @@
 #include <asm/memory.h>
 #include <mach/hardware.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/tlbflush.h>
 #include <asm/pgtable.h>
 
index 8f2487e..d142d45 100644 (file)
@@ -32,7 +32,6 @@
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/tlbflush.h>
 #include <asm/pgtable.h>
 
index 5d5dd3e..b0e07db 100644 (file)
@@ -36,7 +36,6 @@
 #include <asm/memory.h>
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
-#include <asm/system.h>
 #include <asm/tlbflush.h>
 #include <asm/pgtable.h>
 
index 3cbbd32..911f5a5 100644 (file)
@@ -28,7 +28,6 @@
 
 #include <asm/irq.h>
 #include <asm/sizes.h>
-#include <asm/system.h>
 #include <asm/mach/pci.h>
 #include <mach/hardware.h>
 
index 377283f..eaaa3fa 100644 (file)
@@ -36,7 +36,6 @@
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/tlbflush.h>
 #include <asm/pgtable.h>
 
index 8508882..d5719eb 100644 (file)
@@ -32,7 +32,6 @@
 #include <asm/cputype.h>
 #include <asm/irq.h>
 #include <asm/sizes.h>
-#include <asm/system.h>
 #include <asm/mach/pci.h>
 #include <mach/hardware.h>
 
index c0e3d69..78ae12c 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/pci.h>
 #include <linux/serial_8250.h>
 #include <asm/mach-types.h>
-#include <asm/system.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
 #include <asm/mach/pci.h>
index acbc5e1..e299a95 100644 (file)
@@ -21,3 +21,4 @@ obj-$(CONFIG_MACH_T5325)              += t5325-setup.o
 
 obj-$(CONFIG_CPU_IDLE)                 += cpuidle.o
 obj-$(CONFIG_ARCH_KIRKWOOD_DT)         += board-dt.o
+obj-$(CONFIG_MACH_DREAMPLUG_DT)                += board-dreamplug.o
diff --git a/arch/arm/mach-kirkwood/board-dreamplug.c b/arch/arm/mach-kirkwood/board-dreamplug.c
new file mode 100644 (file)
index 0000000..9854539
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2012 (C), Jason Cooper <jason@lakedaemon.net>
+ *
+ * arch/arm/mach-kirkwood/board-dreamplug.c
+ *
+ * Marvell DreamPlug Reference Board Init for drivers not converted to
+ * flattened device tree yet.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/partitions.h>
+#include <linux/ata_platform.h>
+#include <linux/mv643xx_eth.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_fdt.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <linux/mtd/physmap.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/orion_spi.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <mach/kirkwood.h>
+#include <mach/bridge-regs.h>
+#include <plat/mvsdio.h>
+#include "common.h"
+#include "mpp.h"
+
+struct mtd_partition dreamplug_partitions[] = {
+       {
+               .name   = "u-boot",
+               .size   = SZ_512K,
+               .offset = 0,
+       },
+       {
+               .name   = "u-boot env",
+               .size   = SZ_64K,
+               .offset = SZ_512K + SZ_512K,
+       },
+       {
+               .name   = "dtb",
+               .size   = SZ_64K,
+               .offset = SZ_512K + SZ_512K + SZ_512K,
+       },
+};
+
+static const struct flash_platform_data dreamplug_spi_slave_data = {
+       .type           = "mx25l1606e",
+       .name           = "spi_flash",
+       .parts          = dreamplug_partitions,
+       .nr_parts       = ARRAY_SIZE(dreamplug_partitions),
+};
+
+static struct spi_board_info __initdata dreamplug_spi_slave_info[] = {
+       {
+               .modalias       = "m25p80",
+               .platform_data  = &dreamplug_spi_slave_data,
+               .irq            = -1,
+               .max_speed_hz   = 50000000,
+               .bus_num        = 0,
+               .chip_select    = 0,
+       },
+};
+
+static struct mv643xx_eth_platform_data dreamplug_ge00_data = {
+       .phy_addr       = MV643XX_ETH_PHY_ADDR(0),
+};
+
+static struct mv643xx_eth_platform_data dreamplug_ge01_data = {
+       .phy_addr       = MV643XX_ETH_PHY_ADDR(1),
+};
+
+static struct mv_sata_platform_data dreamplug_sata_data = {
+       .n_ports        = 1,
+};
+
+static struct mvsdio_platform_data dreamplug_mvsdio_data = {
+       /* unfortunately the CD signal has not been connected */
+};
+
+static struct gpio_led dreamplug_led_pins[] = {
+       {
+               .name                   = "dreamplug:blue:bluetooth",
+               .gpio                   = 47,
+               .active_low             = 1,
+       },
+       {
+               .name                   = "dreamplug:green:wifi",
+               .gpio                   = 48,
+               .active_low             = 1,
+       },
+       {
+               .name                   = "dreamplug:green:wifi_ap",
+               .gpio                   = 49,
+               .active_low             = 1,
+       },
+};
+
+static struct gpio_led_platform_data dreamplug_led_data = {
+       .leds           = dreamplug_led_pins,
+       .num_leds       = ARRAY_SIZE(dreamplug_led_pins),
+};
+
+static struct platform_device dreamplug_leds = {
+       .name   = "leds-gpio",
+       .id     = -1,
+       .dev    = {
+               .platform_data  = &dreamplug_led_data,
+       }
+};
+
+static unsigned int dreamplug_mpp_config[] __initdata = {
+       MPP0_SPI_SCn,
+       MPP1_SPI_MOSI,
+       MPP2_SPI_SCK,
+       MPP3_SPI_MISO,
+       MPP47_GPIO,     /* Bluetooth LED */
+       MPP48_GPIO,     /* Wifi LED */
+       MPP49_GPIO,     /* Wifi AP LED */
+       0
+};
+
+void __init dreamplug_init(void)
+{
+       /*
+        * Basic setup. Needs to be called early.
+        */
+       kirkwood_mpp_conf(dreamplug_mpp_config);
+
+       spi_register_board_info(dreamplug_spi_slave_info,
+                               ARRAY_SIZE(dreamplug_spi_slave_info));
+       kirkwood_spi_init();
+
+       kirkwood_ehci_init();
+       kirkwood_ge00_init(&dreamplug_ge00_data);
+       kirkwood_ge01_init(&dreamplug_ge01_data);
+       kirkwood_sata_init(&dreamplug_sata_data);
+       kirkwood_sdio_init(&dreamplug_mvsdio_data);
+
+       platform_device_register(&dreamplug_leds);
+}
index fbe6405..1c672d9 100644 (file)
@@ -3,7 +3,7 @@
  *
  * arch/arm/mach-kirkwood/board-dt.c
  *
- * Marvell DreamPlug Reference Board Setup
+ * Flattened Device Tree board initialization
  *
  * This file is licensed under the terms of the GNU General Public
  * License version 2.  This program is licensed "as is" without any
 
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/mtd/partitions.h>
-#include <linux/ata_platform.h>
-#include <linux/mv643xx_eth.h>
 #include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_fdt.h>
-#include <linux/of_irq.h>
 #include <linux/of_platform.h>
-#include <linux/gpio.h>
-#include <linux/leds.h>
-#include <linux/mtd/physmap.h>
-#include <linux/spi/flash.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/orion_spi.h>
-#include <asm/mach-types.h>
 #include <asm/mach/arch.h>
-#include <mach/kirkwood.h>
-#include <plat/mvsdio.h>
+#include <asm/mach/map.h>
+#include <mach/bridge-regs.h>
 #include "common.h"
-#include "mpp.h"
 
 static struct of_device_id kirkwood_dt_match_table[] __initdata = {
        { .compatible = "simple-bus", },
        { }
 };
 
-struct mtd_partition dreamplug_partitions[] = {
-       {
-               .name   = "u-boot",
-               .size   = SZ_512K,
-               .offset = 0,
-       },
-       {
-               .name   = "u-boot env",
-               .size   = SZ_64K,
-               .offset = SZ_512K + SZ_512K,
-       },
-       {
-               .name   = "dtb",
-               .size   = SZ_64K,
-               .offset = SZ_512K + SZ_512K + SZ_512K,
-       },
-};
-
-static const struct flash_platform_data dreamplug_spi_slave_data = {
-       .type           = "mx25l1606e",
-       .name           = "spi_flash",
-       .parts          = dreamplug_partitions,
-       .nr_parts       = ARRAY_SIZE(dreamplug_partitions),
-};
-
-static struct spi_board_info __initdata dreamplug_spi_slave_info[] = {
-       {
-               .modalias       = "m25p80",
-               .platform_data  = &dreamplug_spi_slave_data,
-               .irq            = -1,
-               .max_speed_hz   = 50000000,
-               .bus_num        = 0,
-               .chip_select    = 0,
-       },
-};
-
-static struct mv643xx_eth_platform_data dreamplug_ge00_data = {
-       .phy_addr       = MV643XX_ETH_PHY_ADDR(0),
-};
-
-static struct mv643xx_eth_platform_data dreamplug_ge01_data = {
-       .phy_addr       = MV643XX_ETH_PHY_ADDR(1),
-};
-
-static struct mv_sata_platform_data dreamplug_sata_data = {
-       .n_ports        = 1,
-};
-
-static struct mvsdio_platform_data dreamplug_mvsdio_data = {
-       /* unfortunately the CD signal has not been connected */
-};
-
-static struct gpio_led dreamplug_led_pins[] = {
-       {
-               .name                   = "dreamplug:blue:bluetooth",
-               .gpio                   = 47,
-               .active_low             = 1,
-       },
-       {
-               .name                   = "dreamplug:green:wifi",
-               .gpio                   = 48,
-               .active_low             = 1,
-       },
-       {
-               .name                   = "dreamplug:green:wifi_ap",
-               .gpio                   = 49,
-               .active_low             = 1,
-       },
-};
-
-static struct gpio_led_platform_data dreamplug_led_data = {
-       .leds           = dreamplug_led_pins,
-       .num_leds       = ARRAY_SIZE(dreamplug_led_pins),
-};
-
-static struct platform_device dreamplug_leds = {
-       .name   = "leds-gpio",
-       .id     = -1,
-       .dev    = {
-               .platform_data  = &dreamplug_led_data,
-       }
-};
-
-static unsigned int dreamplug_mpp_config[] __initdata = {
-       MPP0_SPI_SCn,
-       MPP1_SPI_MOSI,
-       MPP2_SPI_SCK,
-       MPP3_SPI_MISO,
-       MPP47_GPIO,     /* Bluetooth LED */
-       MPP48_GPIO,     /* Wifi LED */
-       MPP49_GPIO,     /* Wifi AP LED */
-       0
-};
-
-static void __init dreamplug_init(void)
+static void __init kirkwood_dt_init(void)
 {
+       pr_info("Kirkwood: %s, TCLK=%d.\n", kirkwood_id(), kirkwood_tclk);
+
        /*
-        * Basic setup. Needs to be called early.
+        * Disable propagation of mbus errors to the CPU local bus,
+        * as this causes mbus errors (which can occur for example
+        * for PCI aborts) to throw CPU aborts, which we're not set
+        * up to deal with.
         */
-       kirkwood_mpp_conf(dreamplug_mpp_config);
+       writel(readl(CPU_CONFIG) & ~CPU_CONFIG_ERROR_PROP, CPU_CONFIG);
 
-       spi_register_board_info(dreamplug_spi_slave_info,
-                               ARRAY_SIZE(dreamplug_spi_slave_info));
-       kirkwood_spi_init();
+       kirkwood_setup_cpu_mbus();
 
-       kirkwood_ehci_init();
-       kirkwood_ge00_init(&dreamplug_ge00_data);
-       kirkwood_ge01_init(&dreamplug_ge01_data);
-       kirkwood_sata_init(&dreamplug_sata_data);
-       kirkwood_sdio_init(&dreamplug_mvsdio_data);
+#ifdef CONFIG_CACHE_FEROCEON_L2
+       kirkwood_l2_init();
+#endif
 
-       platform_device_register(&dreamplug_leds);
-}
+       /* internal devices that every board has */
+       kirkwood_wdt_init();
+       kirkwood_xor0_init();
+       kirkwood_xor1_init();
+       kirkwood_crypto_init();
 
-static void __init kirkwood_dt_init(void)
-{
-       kirkwood_init();
+#ifdef CONFIG_KEXEC
+       kexec_reinit = kirkwood_enable_pcie;
+#endif
 
        if (of_machine_is_compatible("globalscale,dreamplug"))
                dreamplug_init();
index 77d4852..a02cae8 100644 (file)
@@ -279,7 +279,7 @@ void __init kirkwood_crypto_init(void)
 /*****************************************************************************
  * XOR0
  ****************************************************************************/
-static void __init kirkwood_xor0_init(void)
+void __init kirkwood_xor0_init(void)
 {
        kirkwood_clk_ctrl |= CGC_XOR0;
 
@@ -291,7 +291,7 @@ static void __init kirkwood_xor0_init(void)
 /*****************************************************************************
  * XOR1
  ****************************************************************************/
-static void __init kirkwood_xor1_init(void)
+void __init kirkwood_xor1_init(void)
 {
        kirkwood_clk_ctrl |= CGC_XOR1;
 
@@ -303,7 +303,7 @@ static void __init kirkwood_xor1_init(void)
 /*****************************************************************************
  * Watchdog
  ****************************************************************************/
-static void __init kirkwood_wdt_init(void)
+void __init kirkwood_wdt_init(void)
 {
        orion_wdt_init(kirkwood_tclk);
 }
@@ -392,7 +392,7 @@ void __init kirkwood_audio_init(void)
 /*
  * Identify device ID and revision.
  */
-static char * __init kirkwood_id(void)
+char * __init kirkwood_id(void)
 {
        u32 dev, rev;
 
@@ -435,7 +435,7 @@ static char * __init kirkwood_id(void)
        }
 }
 
-static void __init kirkwood_l2_init(void)
+void __init kirkwood_l2_init(void)
 {
 #ifdef CONFIG_CACHE_FEROCEON_L2_WRITETHROUGH
        writel(readl(L2_CONFIG_REG) | L2_WRITETHROUGH, L2_CONFIG_REG);
@@ -450,7 +450,6 @@ void __init kirkwood_init(void)
 {
        printk(KERN_INFO "Kirkwood: %s, TCLK=%d.\n",
                kirkwood_id(), kirkwood_tclk);
-       kirkwood_i2s_data.tclk = kirkwood_tclk;
 
        /*
         * Disable propagation of mbus errors to the CPU local bus,
index 9071a39..fa8e768 100644 (file)
@@ -51,6 +51,21 @@ void kirkwood_nand_init_rnb(struct mtd_partition *parts, int nr_parts, int (*dev
 void kirkwood_audio_init(void);
 void kirkwood_restart(char, const char *);
 
+/* board init functions for boards not fully converted to fdt */
+#ifdef CONFIG_MACH_DREAMPLUG_DT
+void dreamplug_init(void);
+#else
+static inline void dreamplug_init(void) {};
+#endif
+
+/* early init functions not converted to fdt yet */
+char *kirkwood_id(void);
+void kirkwood_l2_init(void);
+void kirkwood_wdt_init(void);
+void kirkwood_xor0_init(void);
+void kirkwood_xor1_init(void);
+void kirkwood_crypto_init(void);
+
 extern int kirkwood_tclk;
 extern struct sys_timer kirkwood_timer;
 
index 37dfcd5..ec783a3 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/io.h>
 
 #include <asm/mach/time.h>
+#include <asm/system_misc.h>
 
 #include <mach/regs-timer.h>
 #include <mach/regs-irq.h>
index fde6635..75946ac 100644 (file)
@@ -29,5 +29,30 @@ config ARCH_LPC32XX_UART6_SELECT
 
 endmenu
 
+menu "LPC32XX chip components"
+
+config ARCH_LPC32XX_IRAM_FOR_NET
+       bool "Use IRAM for network buffers"
+       default y
+       help
+         Say Y here to use the LPC internal fast IRAM (i.e. 256KB SRAM) as
+         network buffer.  If the total combined required buffer sizes is
+         larger than the size of IRAM, then SDRAM will be used instead.
+
+         This can be enabled safely if the IRAM is not intended for other
+         uses.
+
+config ARCH_LPC32XX_MII_SUPPORT
+       bool "Check to enable MII support or leave disabled for RMII support"
+       help
+         Say Y here to enable MII support, or N for RMII support. Regardless of
+         which support is selected, the ethernet interface driver needs to be
+         selected in the device driver networking section.
+
+         The PHY3250 reference board uses RMII, so users of this board should
+         say N.
+
+endmenu
+
 endif
 
index f55c772..b7ef511 100644 (file)
@@ -87,6 +87,7 @@
 #include <linux/list.h>
 #include <linux/errno.h>
 #include <linux/device.h>
+#include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/amba/bus.h>
 
 static DEFINE_SPINLOCK(global_clkregs_lock);
 
+static int usb_pll_enable, usb_pll_valid;
+
 static struct clk clk_armpll;
 static struct clk clk_usbpll;
 
@@ -384,30 +387,62 @@ static u32 local_clk_usbpll_setup(struct clk_pll_setup *pHCLKPllSetup)
 static int local_usbpll_enable(struct clk *clk, int enable)
 {
        u32 reg;
-       int ret = -ENODEV;
-       unsigned long timeout = jiffies + msecs_to_jiffies(10);
+       int ret = 0;
+       unsigned long timeout = jiffies + msecs_to_jiffies(20);
 
        reg = __raw_readl(LPC32XX_CLKPWR_USB_CTRL);
 
-       if (enable == 0) {
-               reg &= ~(LPC32XX_CLKPWR_USBCTRL_CLK_EN1 |
-                       LPC32XX_CLKPWR_USBCTRL_CLK_EN2);
-               __raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL);
-       } else if (reg & LPC32XX_CLKPWR_USBCTRL_PLL_PWRUP) {
+       __raw_writel(reg & ~(LPC32XX_CLKPWR_USBCTRL_CLK_EN2 |
+               LPC32XX_CLKPWR_USBCTRL_PLL_PWRUP),
+               LPC32XX_CLKPWR_USB_CTRL);
+       __raw_writel(reg & ~LPC32XX_CLKPWR_USBCTRL_CLK_EN1,
+               LPC32XX_CLKPWR_USB_CTRL);
+
+       if (enable && usb_pll_valid && usb_pll_enable) {
+               ret = -ENODEV;
+               /*
+                * If the PLL rate has been previously set, then the rate
+                * in the PLL register is valid and can be enabled here.
+                * Otherwise, it needs to be enabled as part of setrate.
+                */
+
+               /*
+                * Gate clock into PLL
+                */
                reg |= LPC32XX_CLKPWR_USBCTRL_CLK_EN1;
                __raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL);
 
-               /* Wait for PLL lock */
+               /*
+                * Enable PLL
+                */
+               reg |= LPC32XX_CLKPWR_USBCTRL_PLL_PWRUP;
+               __raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL);
+
+               /*
+                * Wait for PLL to lock
+                */
                while (time_before(jiffies, timeout) && (ret == -ENODEV)) {
                        reg = __raw_readl(LPC32XX_CLKPWR_USB_CTRL);
                        if (reg & LPC32XX_CLKPWR_USBCTRL_PLL_STS)
                                ret = 0;
+                       else
+                               udelay(10);
                }
 
+               /*
+                * Gate clock from PLL if PLL is locked
+                */
                if (ret == 0) {
-                       reg |= LPC32XX_CLKPWR_USBCTRL_CLK_EN2;
-                       __raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL);
+                       __raw_writel(reg | LPC32XX_CLKPWR_USBCTRL_CLK_EN2,
+                               LPC32XX_CLKPWR_USB_CTRL);
+               } else {
+                       __raw_writel(reg & ~(LPC32XX_CLKPWR_USBCTRL_CLK_EN1 |
+                               LPC32XX_CLKPWR_USBCTRL_PLL_PWRUP),
+                               LPC32XX_CLKPWR_USB_CTRL);
                }
+       } else if ((enable == 0) && usb_pll_valid  && usb_pll_enable) {
+               usb_pll_valid = 0;
+               usb_pll_enable = 0;
        }
 
        return ret;
@@ -425,7 +460,7 @@ static unsigned long local_usbpll_round_rate(struct clk *clk,
         */
        rate = rate * 1000;
 
-       clkin = clk->parent->rate;
+       clkin = clk->get_rate(clk);
        usbdiv = (__raw_readl(LPC32XX_CLKPWR_USBCLK_PDIV) &
                LPC32XX_CLKPWR_USBPDIV_PLL_MASK) + 1;
        clkin = clkin / usbdiv;
@@ -439,7 +474,8 @@ static unsigned long local_usbpll_round_rate(struct clk *clk,
 
 static int local_usbpll_set_rate(struct clk *clk, unsigned long rate)
 {
-       u32 clkin, reg, usbdiv;
+       int ret = -ENODEV;
+       u32 clkin, usbdiv;
        struct clk_pll_setup pllsetup;
 
        /*
@@ -448,7 +484,7 @@ static int local_usbpll_set_rate(struct clk *clk, unsigned long rate)
         */
        rate = rate * 1000;
 
-       clkin = clk->get_rate(clk);
+       clkin = clk->get_rate(clk->parent);
        usbdiv = (__raw_readl(LPC32XX_CLKPWR_USBCLK_PDIV) &
                LPC32XX_CLKPWR_USBPDIV_PLL_MASK) + 1;
        clkin = clkin / usbdiv;
@@ -457,22 +493,25 @@ static int local_usbpll_set_rate(struct clk *clk, unsigned long rate)
        if (local_clk_find_pll_cfg(clkin, rate, &pllsetup) == 0)
                return -EINVAL;
 
+       /*
+        * Disable PLL clocks during PLL change
+        */
        local_usbpll_enable(clk, 0);
-
-       reg = __raw_readl(LPC32XX_CLKPWR_USB_CTRL);
-       reg |= LPC32XX_CLKPWR_USBCTRL_CLK_EN1;
-       __raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL);
-
-       pllsetup.analog_on = 1;
+       pllsetup.analog_on = 0;
        local_clk_usbpll_setup(&pllsetup);
 
-       clk->rate = clk_check_pll_setup(clkin, &pllsetup);
+       /*
+        * Start USB PLL and check PLL status
+        */
+
+       usb_pll_valid = 1;
+       usb_pll_enable = 1;
 
-       reg = __raw_readl(LPC32XX_CLKPWR_USB_CTRL);
-       reg |= LPC32XX_CLKPWR_USBCTRL_CLK_EN2;
-       __raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL);
+       ret = local_usbpll_enable(clk, 1);
+       if (ret >= 0)
+               clk->rate = clk_check_pll_setup(clkin, &pllsetup);
 
-       return 0;
+       return ret;
 }
 
 static struct clk clk_usbpll = {
index 6c76bb3..bbbf063 100644 (file)
@@ -160,6 +160,53 @@ struct platform_device lpc32xx_adc_device = {
 };
 
 /*
+ * USB support
+ */
+/* The dmamask must be set for OHCI to work */
+static u64 ohci_dmamask = ~(u32) 0;
+static struct resource ohci_resources[] = {
+       {
+               .start = IO_ADDRESS(LPC32XX_USB_BASE),
+               .end = IO_ADDRESS(LPC32XX_USB_BASE + 0x100 - 1),
+               .flags = IORESOURCE_MEM,
+       }, {
+               .start = IRQ_LPC32XX_USB_HOST,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+struct platform_device lpc32xx_ohci_device = {
+       .name = "usb-ohci",
+       .id = -1,
+       .dev = {
+               .dma_mask = &ohci_dmamask,
+               .coherent_dma_mask = 0xFFFFFFFF,
+       },
+       .num_resources = ARRAY_SIZE(ohci_resources),
+       .resource = ohci_resources,
+};
+
+/*
+ * Network Support
+ */
+static struct resource net_resources[] = {
+       [0] = DEFINE_RES_MEM(LPC32XX_ETHERNET_BASE, SZ_4K),
+       [1] = DEFINE_RES_MEM(LPC32XX_IRAM_BASE, SZ_128K),
+       [2] = DEFINE_RES_IRQ(IRQ_LPC32XX_ETHERNET),
+};
+
+static u64 lpc32xx_mac_dma_mask = 0xffffffffUL;
+struct platform_device lpc32xx_net_device = {
+       .name = "lpc-eth",
+       .id = 0,
+       .dev = {
+               .dma_mask = &lpc32xx_mac_dma_mask,
+               .coherent_dma_mask = 0xffffffffUL,
+       },
+       .num_resources = ARRAY_SIZE(net_resources),
+       .resource = net_resources,
+};
+
+/*
  * Returns the unique ID for the device
  */
 void lpc32xx_get_uid(u32 devid[4])
index 68f2e46..68e45e8 100644 (file)
@@ -19,6 +19,7 @@
 #ifndef __LPC32XX_COMMON_H
 #define __LPC32XX_COMMON_H
 
+#include <mach/board.h>
 #include <linux/platform_device.h>
 
 /*
@@ -31,6 +32,8 @@ extern struct platform_device lpc32xx_i2c2_device;
 extern struct platform_device lpc32xx_tsc_device;
 extern struct platform_device lpc32xx_adc_device;
 extern struct platform_device lpc32xx_rtc_device;
+extern struct platform_device lpc32xx_ohci_device;
+extern struct platform_device lpc32xx_net_device;
 
 /*
  * Other arch specific structures and functions
@@ -67,7 +70,6 @@ extern u32 clk_get_pclk_div(void);
 extern void lpc32xx_get_uid(u32 devid[4]);
 
 extern u32 lpc32xx_return_iram_size(void);
-
 /*
  * Pointers used for sizing and copying suspend function data
  */
diff --git a/arch/arm/mach-lpc32xx/include/mach/board.h b/arch/arm/mach-lpc32xx/include/mach/board.h
new file mode 100644 (file)
index 0000000..52531ca
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * arm/arch/mach-lpc32xx/include/mach/board.h
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ASM_ARCH_BOARD_H
+#define __ASM_ARCH_BOARD_H
+
+extern u32 lpc32xx_return_iram_size(void);
+
+#endif  /* __ASM_ARCH_BOARD_H */
index c74de01..d080cb1 100644 (file)
@@ -150,6 +150,10 @@ static const struct lpc32xx_event_info lpc32xx_events[NR_IRQS] = {
                .event_group = &lpc32xx_event_int_regs,
                .mask = LPC32XX_CLKPWR_INTSRC_KEY_BIT,
        },
+       [IRQ_LPC32XX_ETHERNET] = {
+               .event_group = &lpc32xx_event_int_regs,
+               .mask = LPC32XX_CLKPWR_INTSRC_MAC_BIT,
+       },
        [IRQ_LPC32XX_USB_OTG_ATX] = {
                .event_group = &lpc32xx_event_int_regs,
                .mask = LPC32XX_CLKPWR_INTSRC_USBATXINT_BIT,
index 0d79a3f..7f7401e 100644 (file)
@@ -37,6 +37,7 @@
 
 #include <mach/hardware.h>
 #include <mach/platform.h>
+#include <mach/board.h>
 #include <mach/gpio-lpc32xx.h>
 #include "common.h"
 
@@ -255,6 +256,8 @@ static struct platform_device *phy3250_devs[] __initdata = {
        &lpc32xx_watchdog_device,
        &lpc32xx_gpio_led_device,
        &lpc32xx_adc_device,
+       &lpc32xx_ohci_device,
+       &lpc32xx_net_device,
 };
 
 static struct amba_device *amba_devs[] __initdata = {
index 062b5b9..9292b79 100644 (file)
@@ -14,6 +14,7 @@
 
 #include <asm/page.h>
 #include <asm/mach/map.h>
+#include <asm/system_misc.h>
 #include <mach/addr-map.h>
 #include <mach/cputype.h>
 
index f7d59c0..b24d2c3 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/platform_device.h>
 
 #include <asm/mach/time.h>
+#include <asm/system_misc.h>
 #include <mach/addr-map.h>
 #include <mach/cputype.h>
 #include <mach/regs-apbc.h>
index 97b8191..4a8ea0d 100644 (file)
@@ -27,7 +27,6 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/flash.h>
-#include <asm/system.h>
 #include <mach/system.h>
 #include <mach/vreg.h>
 #include <mach/board.h>
index 7aa5ac5..80ac1fc 100644 (file)
@@ -25,7 +25,7 @@
 #include <linux/module.h>
 
 #include <asm/proc-fns.h>
-#include <asm/system.h>
+#include <asm/system_misc.h>
 
 #include <mach/mxs.h>
 #include <mach/common.h>
index f24c1e2..2b28e1d 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <asm/system_info.h>
 
 #include <plat/cpu.h>
 
index 4b818eb..f6b14a1 100644 (file)
@@ -17,7 +17,6 @@
 
 #include <mach/hardware.h>
 #include <asm/leds.h>
-#include <asm/system.h>
 #include <asm/mach-types.h>
 
 #include <plat/fpga.h>
index 9b99c28..3a066ee 100644 (file)
@@ -5,7 +5,6 @@
 
 #include <mach/hardware.h>
 #include <asm/leds.h>
-#include <asm/system.h>
 
 #include "leds.h"
 
index da09f43..936ed42 100644 (file)
@@ -8,7 +8,6 @@
 
 #include <mach/hardware.h>
 #include <asm/leds.h>
-#include <asm/system.h>
 
 #include "leds.h"
 
index 5fdef7a..087dba0 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/io.h>
 #include <linux/spinlock.h>
 
-#include <asm/system.h>
 
 #include <plat/mux.h>
 
index 2fae6a2..4d8dd9a 100644 (file)
@@ -44,7 +44,6 @@
 #include <linux/clockchips.h>
 #include <linux/io.h>
 
-#include <asm/system.h>
 #include <asm/leds.h>
 #include <asm/irq.h>
 #include <asm/sched_clock.h>
index a2e6d07..325b9a0 100644 (file)
@@ -46,7 +46,6 @@
 #include <linux/clockchips.h>
 #include <linux/io.h>
 
-#include <asm/system.h>
 #include <asm/leds.h>
 #include <asm/irq.h>
 #include <asm/mach/irq.h>
index 30768c2..37dcb1b 100644 (file)
@@ -490,21 +490,22 @@ static struct platform_device omap_vwlan_device = {
 
 static int omap4_twl6030_hsmmc_late_init(struct device *dev)
 {
-       int ret = 0;
+       int irq = 0;
        struct platform_device *pdev = container_of(dev,
                                struct platform_device, dev);
        struct omap_mmc_platform_data *pdata = dev->platform_data;
 
        /* Setting MMC1 Card detect Irq */
        if (pdev->id == 0) {
-               ret = twl6030_mmc_card_detect_config();
-               if (ret)
+               irq = twl6030_mmc_card_detect_config();
+               if (irq < 0) {
                        pr_err("Failed configuring MMC1 card detect\n");
-               pdata->slots[0].card_detect_irq = TWL6030_IRQ_BASE +
-                                               MMCDETECT_INTR_OFFSET;
+                       return irq;
+               }
+               pdata->slots[0].card_detect_irq = irq;
                pdata->slots[0].card_detect = twl6030_mmc_card_detect;
        }
-       return ret;
+       return 0;
 }
 
 static __init void omap4_twl6030_hsmmc_set_late_init(struct device *dev)
index 8842e04..ae2251f 100644 (file)
@@ -42,6 +42,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/flash.h>
+#include <asm/system_info.h>
 
 #include <plat/board.h>
 #include "common.h"
index e9071a5..8bf8e99 100644 (file)
@@ -238,7 +238,7 @@ struct wl12xx_platform_data omap_panda_wlan_data  __initdata = {
 
 static int omap4_twl6030_hsmmc_late_init(struct device *dev)
 {
-       int ret = 0;
+       int irq = 0;
        struct platform_device *pdev = container_of(dev,
                                struct platform_device, dev);
        struct omap_mmc_platform_data *pdata = dev->platform_data;
@@ -249,14 +249,15 @@ static int omap4_twl6030_hsmmc_late_init(struct device *dev)
        }
        /* Setting MMC1 Card detect Irq */
        if (pdev->id == 0) {
-               ret = twl6030_mmc_card_detect_config();
-                if (ret)
+               irq = twl6030_mmc_card_detect_config();
+               if (irq < 0) {
                        dev_err(dev, "%s: Error card detect config(%d)\n",
-                               __func__, ret);
-                else
-                       pdata->slots[0].card_detect = twl6030_mmc_card_detect;
+                               __func__, irq);
+                       return irq;
+               }
+               pdata->slots[0].card_detect = twl6030_mmc_card_detect;
        }
-       return ret;
+       return 0;
 }
 
 static __init void omap4_twl6030_hsmmc_set_late_init(struct device *dev)
index 16aebfb..f120997 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/gpio_keys.h>
 #include <linux/mmc/host.h>
 #include <linux/power/isp1704_charger.h>
+#include <asm/system_info.h>
 
 #include <plat/mcspi.h>
 #include <plat/board.h>
index f26b2fa..65c3391 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 
-#include <asm/system.h>
 
 #include <plat/omap_hwmod.h>
 
index 63ab686..13670aa 100644 (file)
@@ -46,7 +46,6 @@
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 #include <asm/smp_scu.h>
-#include <asm/system.h>
 #include <asm/pgalloc.h>
 #include <asm/suspend.h>
 #include <asm/hardware/cache-l2x0.h>
index 5ca45ca..95442b6 100644 (file)
@@ -33,6 +33,7 @@
 #include <asm/mach/time.h>
 #include <asm/mach/irq.h>
 #include <asm/mach-types.h>
+#include <asm/system_misc.h>
 
 #include <plat/clock.h>
 #include <plat/sram.h>
index 027a537..238defc 100644 (file)
@@ -31,6 +31,7 @@
 #include <trace/events/power.h>
 
 #include <asm/suspend.h>
+#include <asm/system_misc.h>
 
 #include <plat/sram.h>
 #include "clockdomain.h"
index 91e0b1c..9ccaadc 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/list.h>
 #include <linux/err.h>
 #include <linux/slab.h>
+#include <asm/system_misc.h>
 
 #include "common.h"
 #include "clockdomain.h"
index abd2834..9f6b83d 100644 (file)
@@ -10,7 +10,6 @@
  */
 
 #include <linux/linkage.h>
-#include <asm/system.h>
 #include <asm/smp_scu.h>
 #include <asm/memory.h>
 #include <asm/hardware/cache-l2x0.h>
index 5dad38e..2448166 100644 (file)
@@ -21,6 +21,7 @@
 #include <net/dsa.h>
 #include <asm/page.h>
 #include <asm/setup.h>
+#include <asm/system_misc.h>
 #include <asm/timex.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
index 91b0f47..c3ed15b 100644 (file)
@@ -32,6 +32,7 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/pci.h>
+#include <asm/system_info.h>
 #include <mach/orion5x.h>
 #include "common.h"
 #include "mpp.h"
index 5272131..0c9e413 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/gpio.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
-#include <asm/system.h>
 #include <mach/orion5x.h>
 #include "common.h"
 #include "mpp.h"
index 9a8697b..c1b5d8a 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/gpio.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
-#include <asm/system.h>
 #include <mach/orion5x.h>
 #include "common.h"
 #include "mpp.h"
index 09c7365..949eaa8 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/gpio.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
-#include <asm/system.h>
 #include <mach/orion5x.h>
 #include "common.h"
 #include "mpp.h"
index 4cfb40b..be4c928 100644 (file)
@@ -32,7 +32,7 @@
 #include <asm/mach-types.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
-#include <asm/system.h>
+#include <asm/system_misc.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
index 7fa4bf2..a4739e9 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/io.h>
 #include <linux/gfp.h>
 
-#include <asm/system.h>
 #include <mach/hardware.h>
 #include <mach/dma.h>
 #include <asm/dma-mapping.h>
index 7608c7a..41e4201 100644 (file)
@@ -28,7 +28,6 @@
 #include <asm/setup.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
-#include <asm/system.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/irq.h>
 #include <asm/mach/map.h>
index 0c8aad4..0cfe8af 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 
-#include <asm/system.h>
 #include <mach/hardware.h>
 #include <asm/leds.h>
 #include <asm/mach/time.h>
index 4b981b8..895ee8c 100644 (file)
@@ -44,6 +44,7 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/setup.h>
+#include <asm/system_info.h>
 
 #include <mach/pxa300.h>
 #include <mach/pxa27x-udc.h>
index 2b8ca0d..68cc75f 100644 (file)
@@ -18,6 +18,7 @@
 #include <asm/mach-types.h>
 #include <mach/hardware.h>
 #include <asm/sizes.h>
+#include <asm/system_info.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/irq.h>
 #include <mach/pxa3xx-regs.h>
index 11f1e73..de9d45e 100644 (file)
@@ -40,7 +40,6 @@
 #include <asm/mach-types.h>
 #include <mach/hardware.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
index 5432ecb..4225417 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/init.h>
 
 #include <mach/hardware.h>
-#include <asm/system.h>
 #include <asm/mach/map.h>
 #include <asm/mach-types.h>
 
index 8b9c171..06b0600 100644 (file)
@@ -16,7 +16,6 @@
 
 #include <mach/hardware.h>
 #include <asm/leds.h>
-#include <asm/system.h>
 
 #include <mach/pxa25x.h>
 #include <mach/idp.h>
index e26d5ef..0bd85c8 100644 (file)
@@ -15,7 +15,6 @@
 
 #include <mach/hardware.h>
 #include <asm/leds.h>
-#include <asm/system.h>
 #include <mach/pxa25x.h>
 #include <mach/lubbock.h>
 
index db4af5e..4058ab3 100644 (file)
@@ -14,7 +14,6 @@
 
 #include <mach/hardware.h>
 #include <asm/leds.h>
-#include <asm/system.h>
 
 #include <mach/pxa27x.h>
 #include <mach/mainstone.h>
index 5e26f3e..6f4785b 100644 (file)
@@ -34,6 +34,7 @@
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
+#include <asm/system_info.h>
 
 #include <mach/pxa27x.h>
 #include <mach/magician.h>
index 744baee..89d98c8 100644 (file)
@@ -34,7 +34,6 @@
 #include <asm/mach-types.h>
 #include <asm/irq.h>
 #include <asm/setup.h>
-#include <asm/system.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
index c8497b0..b452889 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/gpio.h>
 #include <linux/io.h>
 #include <asm/proc-fns.h>
+#include <asm/system_misc.h>
 
 #include <mach/regs-ost.h>
 #include <mach/reset.h>
index 023d6ca..7a3d342 100644 (file)
@@ -57,6 +57,7 @@
 #include <asm/mach-types.h>
 #include <asm/irq.h>
 #include <asm/sizes.h>
+#include <asm/system_info.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
index a4dd1c3..af3d4f7 100644 (file)
@@ -32,6 +32,7 @@
 
 #include <asm/mach-types.h>
 #include <asm/suspend.h>
+#include <asm/system_info.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
index acd329a..45868bb 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/clkdev.h>
 #include <linux/mtd/physmap.h>
 
-#include <asm/system.h>
 #include <mach/hardware.h>
 #include <asm/irq.h>
 #include <asm/leds.h>
index eb55f05..57d9efb 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/smp.h>
 
 #include <asm/cacheflush.h>
+#include <asm/cp15.h>
 #include <asm/smp_plat.h>
 
 extern volatile int pen_release;
index 731552d..f3fa259 100644 (file)
@@ -28,6 +28,7 @@
 #include <asm/page.h>
 #include <asm/domain.h>
 #include <asm/setup.h>
+#include <asm/system_misc.h>
 
 #include <asm/mach/map.h>
 #include <asm/mach/arch.h>
index 061b6bb..a3c5cb0 100644 (file)
@@ -30,6 +30,7 @@
 
 #include <mach/hardware.h>
 #include <asm/irq.h>
+#include <asm/system_misc.h>
 
 #include <plat/cpu-freq.h>
 
index c6eac98..d4bc7f9 100644 (file)
@@ -31,6 +31,7 @@
 #include <mach/hardware.h>
 #include <asm/proc-fns.h>
 #include <asm/irq.h>
+#include <asm/system_misc.h>
 
 #include <plat/cpu-freq.h>
 
index 0e9a71c..7743fad 100644 (file)
@@ -43,6 +43,7 @@
 #include <mach/hardware.h>
 #include <asm/proc-fns.h>
 #include <asm/irq.h>
+#include <asm/system_misc.h>
 
 #include <mach/regs-s3c2443-clock.h>
 
index b7778a9..ab648ad 100644 (file)
@@ -29,6 +29,7 @@
 
 #include <mach/hardware.h>
 #include <asm/irq.h>
+#include <asm/system_misc.h>
 
 #include <mach/regs-s3c2443-clock.h>
 
index d15852f..6f74118 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 
+#include <asm/system_misc.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
index bee7dcd..b313380 100644 (file)
@@ -29,6 +29,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/hardware/vic.h>
+#include <asm/system_misc.h>
 
 #include <mach/map.h>
 #include <mach/hardware.h>
index b6a6772..0ace108 100644 (file)
@@ -17,6 +17,8 @@
 #include <linux/mfd/wm831x/gpio.h>
 #include <linux/mfd/wm8994/pdata.h>
 
+#include <linux/regulator/machine.h>
+
 #include <sound/wm5100.h>
 #include <sound/wm8996.h>
 #include <sound/wm8962.h>
@@ -153,6 +155,14 @@ static const struct i2c_board_info wm1259_devs[] = {
        },
 };
 
+static struct regulator_init_data wm8994_ldo1 = {
+       .supply_regulator = "WALLVDD",
+};
+
+static struct regulator_init_data wm8994_ldo2 = {
+       .supply_regulator = "WALLVDD",
+};
+
 static struct wm8994_pdata wm8994_pdata = {
        .gpio_base = CODEC_GPIO_BASE,
        .gpio_defaults = {
@@ -160,8 +170,8 @@ static struct wm8994_pdata wm8994_pdata = {
        },
        .irq_base = CODEC_IRQ_BASE,
        .ldo = {
-               { .supply = "WALLVDD" },
-               { .supply = "WALLVDD" },
+                { .init_data = &wm8994_ldo1, },
+                { .init_data = &wm8994_ldo2, },
        },
 };
 
index 9143f8b..6e6a0a9 100644 (file)
@@ -27,6 +27,7 @@
 
 #include <asm/irq.h>
 #include <asm/proc-fns.h>
+#include <asm/system_misc.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
index ff71e2d..6219086 100644 (file)
@@ -27,6 +27,7 @@
 
 #include <asm/irq.h>
 #include <asm/proc-fns.h>
+#include <asm/system_misc.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
index 1d0f71b..7c524b4 100644 (file)
 #include <video/sa1100fb.h>
 
 #include <asm/div64.h>
-#include <asm/system.h>
 #include <asm/mach/map.h>
 #include <asm/mach/flash.h>
 #include <asm/irq.h>
+#include <asm/system_misc.h>
 
 #include <mach/hardware.h>
 #include <mach/irqs.h>
index 64e9b4b..3699176 100644 (file)
@@ -13,7 +13,6 @@
 
 #include <mach/hardware.h>
 #include <asm/leds.h>
-#include <asm/system.h>
 #include <mach/assabet.h>
 
 #include "leds.h"
index cf1e384..f99fac3 100644 (file)
@@ -14,7 +14,6 @@
 
 #include <mach/hardware.h>
 #include <asm/leds.h>
-#include <asm/system.h>
 
 #include "leds.h"
 
index 259b48e..040540f 100644 (file)
@@ -7,7 +7,6 @@
 
 #include <mach/hardware.h>
 #include <asm/leds.h>
-#include <asm/system.h>
 
 #include "leds.h"
 
index 2bce137..6a23524 100644 (file)
@@ -13,7 +13,6 @@
 
 #include <mach/hardware.h>
 #include <asm/leds.h>
-#include <asm/system.h>
 
 #include "leds.h"
 
index 0505a1f..a51830c 100644 (file)
@@ -13,7 +13,6 @@
 
 #include <mach/hardware.h>
 #include <asm/leds.h>
-#include <asm/system.h>
 
 #include "leds.h"
 
index bf85b8b..2fa499e 100644 (file)
@@ -30,7 +30,6 @@
 #include <mach/hardware.h>
 #include <asm/memory.h>
 #include <asm/suspend.h>
-#include <asm/system.h>
 #include <asm/mach/time.h>
 
 extern int sa1100_finish_suspend(unsigned long);
index ccd4918..2560907 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/io.h>
 
 #include <asm/leds.h>
-#include <asm/system.h>
 
 #define LED_STATE_ENABLED      1
 #define LED_STATE_CLAIMED      2
index 262f8de..b56dde2 100644 (file)
@@ -1186,6 +1186,7 @@ static struct i2c_board_info i2c1_devices[] = {
        },
 };
 
+
 #define GPIO_PORT9CR   0xE6051009
 #define GPIO_PORT10CR  0xE605100A
 #define USCCR1         0xE6058144
index bd4253b..ca60950 100644 (file)
@@ -1327,15 +1327,6 @@ static struct i2c_board_info i2c1_devices[] = {
        },
 };
 
-static void __init mackerel_map_io(void)
-{
-       sh7372_map_io();
-       /* DMA memory at 0xff200000 - 0xffdfffff. The default 2MB size isn't
-        * enough to allocate the frame buffer memory.
-        */
-       init_consistent_dma_size(12 << 20);
-}
-
 #define GPIO_PORT9CR   0xE6051009
 #define GPIO_PORT10CR  0xE605100A
 #define GPIO_PORT167CR 0xE60520A7
@@ -1555,7 +1546,7 @@ static void __init mackerel_init(void)
 }
 
 MACHINE_START(MACKEREL, "mackerel")
-       .map_io         = mackerel_map_io,
+       .map_io         = sh7372_map_io,
        .init_early     = sh7372_add_early_devices,
        .init_irq       = sh7372_init_irq,
        .handle_irq     = shmobile_handle_irq_intc,
index 1b23342..21b09b6 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/suspend.h>
 #include <linux/module.h>
 #include <linux/err.h>
-#include <asm/system.h>
 #include <asm/io.h>
 
 static void shmobile_enter_wfi(void)
index 3bbcb3f..540eaff 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef __ASM_ARCH_SYSTEM_H
 #define __ASM_ARCH_SYSTEM_H
 
+#include <asm/system_misc.h>
+
 static inline void arch_reset(char mode, const char *cmd)
 {
        soft_restart(0);
index c38ba7b..a18a4ae 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/console.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <mach/common.h>
 #include <mach/r8a7779.h>
index fcf8b17..a3bdb12 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/irq.h>
 #include <linux/bitrev.h>
 #include <linux/console.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/tlbflush.h>
 #include <asm/suspend.h>
index 5375325..4e818b7 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/sh_intc.h>
 #include <linux/sh_timer.h>
 #include <linux/pm_domain.h>
+#include <linux/dma-mapping.h>
 #include <mach/hardware.h>
 #include <mach/sh7372.h>
 #include <mach/common.h>
@@ -54,6 +55,12 @@ static struct map_desc sh7372_io_desc[] __initdata = {
 void __init sh7372_map_io(void)
 {
        iotable_init(sh7372_io_desc, ARRAY_SIZE(sh7372_io_desc));
+
+       /*
+        * DMA memory at 0xff200000 - 0xffdfffff. The default 2MB size isn't
+        * enough to allocate the frame buffer memory.
+        */
+       init_consistent_dma_size(12 << 20);
 }
 
 /* SCIFA0 */
index c1febe1..4d1b86a 100644 (file)
@@ -12,8 +12,8 @@
 #include <linux/suspend.h>
 #include <linux/module.h>
 #include <linux/err.h>
-#include <asm/system.h>
 #include <asm/io.h>
+#include <asm/system_misc.h>
 
 static int shmobile_suspend_default_enter(suspend_state_t suspend_state)
 {
index ff4ae5b..fbe298b 100644 (file)
@@ -5,11 +5,12 @@
 if ARCH_SPEAR6XX
 
 menu "SPEAr6xx Implementations"
-config BOARD_SPEAR600_EVB
-       bool "SPEAr600 Evaluation Board"
+config BOARD_SPEAR600_DT
+       bool "SPEAr600 generic board configured via device-tree"
        select MACH_SPEAR600
+       select USE_OF
        help
-         Supports ST SPEAr600 Evaluation Board
+         Supports ST SPEAr600 boards configured via the device-tree
 
 endmenu
 
index cc1a4d8..76e5750 100644 (file)
@@ -4,9 +4,3 @@
 
 # common files
 obj-y  += clock.o spear6xx.o
-
-# spear600 specific files
-obj-$(CONFIG_MACH_SPEAR600) += spear600.o
-
-# spear600 boards files
-obj-$(CONFIG_BOARD_SPEAR600_EVB) += spear600_evb.o
index ac70e0d..358f280 100644 (file)
@@ -641,8 +641,8 @@ static struct clk_lookup spear_clk_lookups[] = {
        { .con_id = "gpt0_synth_clk",   .clk = &gpt0_synth_clk},
        { .con_id = "gpt2_synth_clk",   .clk = &gpt2_synth_clk},
        { .con_id = "gpt3_synth_clk",   .clk = &gpt3_synth_clk},
-       { .dev_id = "uart0",            .clk = &uart0_clk},
-       { .dev_id = "uart1",            .clk = &uart1_clk},
+       { .dev_id = "d0000000.serial",  .clk = &uart0_clk},
+       { .dev_id = "d0080000.serial",  .clk = &uart1_clk},
        { .dev_id = "firda",            .clk = &firda_clk},
        { .dev_id = "clcd",             .clk = &clcd_clk},
        { .dev_id = "gpt0",             .clk = &gpt0_clk},
@@ -655,20 +655,20 @@ static struct clk_lookup spear_clk_lookups[] = {
        { .con_id = "usbh.1_clk",       .clk = &usbh1_clk},
        /* clock derived from ahb clk */
        { .con_id = "apb_clk",          .clk = &apb_clk},
-       { .dev_id = "i2c_designware.0", .clk = &i2c_clk},
+       { .dev_id = "d0200000.i2c",     .clk = &i2c_clk},
        { .dev_id = "dma",              .clk = &dma_clk},
        { .dev_id = "jpeg",             .clk = &jpeg_clk},
        { .dev_id = "gmac",             .clk = &gmac_clk},
        { .dev_id = "smi",              .clk = &smi_clk},
-       { .con_id = "fsmc",             .clk = &fsmc_clk},
+       { .dev_id = "fsmc-nand",        .clk = &fsmc_clk},
        /* clock derived from apb clk */
        { .dev_id = "adc",              .clk = &adc_clk},
        { .dev_id = "ssp-pl022.0",      .clk = &ssp0_clk},
        { .dev_id = "ssp-pl022.1",      .clk = &ssp1_clk},
        { .dev_id = "ssp-pl022.2",      .clk = &ssp2_clk},
-       { .dev_id = "gpio0",            .clk = &gpio0_clk},
-       { .dev_id = "gpio1",            .clk = &gpio1_clk},
-       { .dev_id = "gpio2",            .clk = &gpio2_clk},
+       { .dev_id = "f0100000.gpio",    .clk = &gpio0_clk},
+       { .dev_id = "fc980000.gpio",    .clk = &gpio1_clk},
+       { .dev_id = "d8100000.gpio",    .clk = &gpio2_clk},
 };
 
 void __init spear6xx_clk_init(void)
diff --git a/arch/arm/mach-spear6xx/spear600.c b/arch/arm/mach-spear6xx/spear600.c
deleted file mode 100644 (file)
index d0e6eea..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * arch/arm/mach-spear6xx/spear600.c
- *
- * SPEAr600 machine source file
- *
- * Copyright (C) 2009 ST Microelectronics
- * Rajeev Kumar<rajeev-dlh.kumar@st.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/ptrace.h>
-#include <asm/irq.h>
-#include <mach/generic.h>
-#include <mach/hardware.h>
-
-/* Add spear600 specific devices here */
-
-void __init spear600_init(void)
-{
-       /* call spear6xx family common init function */
-       spear6xx_init();
-}
diff --git a/arch/arm/mach-spear6xx/spear600_evb.c b/arch/arm/mach-spear6xx/spear600_evb.c
deleted file mode 100644 (file)
index c6e4254..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * arch/arm/mach-spear6xx/spear600_evb.c
- *
- * SPEAr600 evaluation board source file
- *
- * Copyright (C) 2009 ST Microelectronics
- * Viresh Kumar<viresh.kumar@st.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <asm/hardware/vic.h>
-#include <asm/mach/arch.h>
-#include <asm/mach-types.h>
-#include <mach/generic.h>
-#include <mach/hardware.h>
-
-static struct amba_device *amba_devs[] __initdata = {
-       &gpio_device[0],
-       &gpio_device[1],
-       &gpio_device[2],
-       &uart_device[0],
-       &uart_device[1],
-};
-
-static struct platform_device *plat_devs[] __initdata = {
-};
-
-static void __init spear600_evb_init(void)
-{
-       unsigned int i;
-
-       /* call spear600 machine init function */
-       spear600_init();
-
-       /* Add Platform Devices */
-       platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs));
-
-       /* Add Amba Devices */
-       for (i = 0; i < ARRAY_SIZE(amba_devs); i++)
-               amba_device_register(amba_devs[i], &iomem_resource);
-}
-
-MACHINE_START(SPEAR600, "ST-SPEAR600-EVB")
-       .atag_offset    =       0x100,
-       .map_io         =       spear6xx_map_io,
-       .init_irq       =       spear6xx_init_irq,
-       .handle_irq     =       vic_handle_irq,
-       .timer          =       &spear6xx_timer,
-       .init_machine   =       spear600_evb_init,
-       .restart        =       spear_restart,
-MACHINE_END
index b997b1b..2ed8b14 100644 (file)
  * Copyright (C) 2009 ST Microelectronics
  * Rajeev Kumar<rajeev-dlh.kumar@st.com>
  *
+ * Copyright 2012 Stefan Roese <sr@denx.de>
+ *
  * 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/types.h>
-#include <linux/amba/pl061.h>
-#include <linux/ptrace.h>
-#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
 #include <asm/hardware/vic.h>
-#include <asm/irq.h>
 #include <asm/mach/arch.h>
 #include <mach/generic.h>
 #include <mach/hardware.h>
-#include <mach/irqs.h>
-
-/* Add spear6xx machines common devices here */
-/* uart device registration */
-struct amba_device uart_device[] = {
-       {
-               .dev = {
-                       .init_name = "uart0",
-               },
-               .res = {
-                       .start = SPEAR6XX_ICM1_UART0_BASE,
-                       .end = SPEAR6XX_ICM1_UART0_BASE + SZ_4K - 1,
-                       .flags = IORESOURCE_MEM,
-               },
-               .irq = {IRQ_UART_0},
-       }, {
-               .dev = {
-                       .init_name = "uart1",
-               },
-               .res = {
-                       .start = SPEAR6XX_ICM1_UART1_BASE,
-                       .end = SPEAR6XX_ICM1_UART1_BASE + SZ_4K - 1,
-                       .flags = IORESOURCE_MEM,
-               },
-               .irq = {IRQ_UART_1},
-       }
-};
-
-/* gpio device registration */
-static struct pl061_platform_data gpio_plat_data[] = {
-       {
-               .gpio_base      = 0,
-               .irq_base       = SPEAR_GPIO0_INT_BASE,
-       }, {
-               .gpio_base      = 8,
-               .irq_base       = SPEAR_GPIO1_INT_BASE,
-       }, {
-               .gpio_base      = 16,
-               .irq_base       = SPEAR_GPIO2_INT_BASE,
-       },
-};
-
-struct amba_device gpio_device[] = {
-       {
-               .dev = {
-                       .init_name = "gpio0",
-                       .platform_data = &gpio_plat_data[0],
-               },
-               .res = {
-                       .start = SPEAR6XX_CPU_GPIO_BASE,
-                       .end = SPEAR6XX_CPU_GPIO_BASE + SZ_4K - 1,
-                       .flags = IORESOURCE_MEM,
-               },
-               .irq = {IRQ_LOCAL_GPIO},
-       }, {
-               .dev = {
-                       .init_name = "gpio1",
-                       .platform_data = &gpio_plat_data[1],
-               },
-               .res = {
-                       .start = SPEAR6XX_ICM3_GPIO_BASE,
-                       .end = SPEAR6XX_ICM3_GPIO_BASE + SZ_4K - 1,
-                       .flags = IORESOURCE_MEM,
-               },
-               .irq = {IRQ_BASIC_GPIO},
-       }, {
-               .dev = {
-                       .init_name = "gpio2",
-                       .platform_data = &gpio_plat_data[2],
-               },
-               .res = {
-                       .start = SPEAR6XX_ICM2_GPIO_BASE,
-                       .end = SPEAR6XX_ICM2_GPIO_BASE + SZ_4K - 1,
-                       .flags = IORESOURCE_MEM,
-               },
-               .irq = {IRQ_APPL_GPIO},
-       }
-};
-
-/* This will add devices, and do machine specific tasks */
-void __init spear6xx_init(void)
-{
-       /* nothing to do for now */
-}
-
-/* This will initialize vic */
-void __init spear6xx_init_irq(void)
-{
-       vic_init((void __iomem *)VA_SPEAR6XX_CPU_VIC_PRI_BASE, 0, ~0, 0);
-       vic_init((void __iomem *)VA_SPEAR6XX_CPU_VIC_SEC_BASE, 32, ~0, 0);
-}
 
 /* Following will create static virtual/physical mappings */
 static struct map_desc spear6xx_io_desc[] __initdata = {
@@ -181,3 +91,33 @@ static void __init spear6xx_timer_init(void)
 struct sys_timer spear6xx_timer = {
        .init = spear6xx_timer_init,
 };
+
+static void __init spear600_dt_init(void)
+{
+       of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+static const char *spear600_dt_board_compat[] = {
+       "st,spear600",
+       NULL
+};
+
+static const struct of_device_id vic_of_match[] __initconst = {
+       { .compatible = "arm,pl190-vic", .data = vic_of_init, },
+       { /* Sentinel */ }
+};
+
+static void __init spear6xx_dt_init_irq(void)
+{
+       of_irq_init(vic_of_match);
+}
+
+DT_MACHINE_START(SPEAR600_DT, "ST SPEAr600 (Flattened Device Tree)")
+       .map_io         =       spear6xx_map_io,
+       .init_irq       =       spear6xx_dt_init_irq,
+       .handle_irq     =       vic_handle_irq,
+       .timer          =       &spear6xx_timer,
+       .init_machine   =       spear600_dt_init,
+       .restart        =       spear_restart,
+       .dt_compat      =       spear600_dt_board_compat,
+MACHINE_END
index 1dd2726..d87d968 100644 (file)
@@ -8,6 +8,7 @@ obj-y                                   += timer.o
 obj-y                                   += pinmux.o
 obj-y                                  += fuse.o
 obj-y                                  += pmc.o
+obj-y                                  += flowctrl.o
 obj-$(CONFIG_CPU_IDLE)                 += cpuidle.o
 obj-$(CONFIG_CPU_IDLE)                 += sleep.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)                += powergate.o
@@ -18,6 +19,7 @@ obj-$(CONFIG_ARCH_TEGRA_3x_SOC)               += pinmux-tegra30-tables.o
 obj-$(CONFIG_ARCH_TEGRA_3x_SOC)                += board-dt-tegra30.o
 obj-$(CONFIG_ARCH_TEGRA_3x_SOC)                += tegra30_clocks.o
 obj-$(CONFIG_SMP)                      += platsmp.o headsmp.o
+obj-$(CONFIG_SMP)                       += reset.o
 obj-$(CONFIG_HOTPLUG_CPU)               += hotplug.o
 obj-$(CONFIG_TEGRA_SYSTEM_DMA)         += dma.o apbio.o
 obj-$(CONFIG_CPU_FREQ)                  += cpu-tegra.o
index 96f6c0d..5f7c03e 100644 (file)
@@ -56,7 +56,7 @@ struct of_dev_auxdata tegra30_auxdata_lookup[] __initdata = {
 
 static __initdata struct tegra_clk_init_table tegra_dt_clk_init_table[] = {
        /* name         parent          rate            enabled */
-       { "uartd",      "pll_p",        408000000,      true },
+       { "uarta",      "pll_p",        408000000,      true },
        { NULL,         NULL,           0,              0},
 };
 
index 2f86fcc..22df10f 100644 (file)
@@ -27,6 +27,7 @@
 #include <asm/hardware/gic.h>
 
 #include <mach/iomap.h>
+#include <mach/powergate.h>
 
 #include "board.h"
 #include "clock.h"
@@ -118,13 +119,16 @@ void __init tegra20_init_early(void)
        tegra_clk_init_from_table(tegra20_clk_init_table);
        tegra_init_cache(0x331, 0x441);
        tegra_pmc_init();
+       tegra_powergate_init();
 }
 #endif
 #ifdef CONFIG_ARCH_TEGRA_3x_SOC
 void __init tegra30_init_early(void)
 {
+       tegra_init_fuse();
        tegra30_init_clocks();
        tegra_init_cache(0x441, 0x551);
        tegra_pmc_init();
+       tegra_powergate_init();
 }
 #endif
index bb5ce39..7a065f0 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/io.h>
 #include <linux/suspend.h>
 
-#include <asm/system.h>
 
 #include <mach/clk.h>
 
diff --git a/arch/arm/mach-tegra/flowctrl.c b/arch/arm/mach-tegra/flowctrl.c
new file mode 100644 (file)
index 0000000..fef66a7
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * arch/arm/mach-tegra/flowctrl.c
+ *
+ * functions and macros to control the flowcontroller
+ *
+ * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+
+#include <mach/iomap.h>
+
+#include "flowctrl.h"
+
+u8 flowctrl_offset_halt_cpu[] = {
+       FLOW_CTRL_HALT_CPU0_EVENTS,
+       FLOW_CTRL_HALT_CPU1_EVENTS,
+       FLOW_CTRL_HALT_CPU1_EVENTS + 8,
+       FLOW_CTRL_HALT_CPU1_EVENTS + 16,
+};
+
+u8 flowctrl_offset_cpu_csr[] = {
+       FLOW_CTRL_CPU0_CSR,
+       FLOW_CTRL_CPU1_CSR,
+       FLOW_CTRL_CPU1_CSR + 8,
+       FLOW_CTRL_CPU1_CSR + 16,
+};
+
+static void flowctrl_update(u8 offset, u32 value)
+{
+       void __iomem *addr = IO_ADDRESS(TEGRA_FLOW_CTRL_BASE) + offset;
+
+       writel(value, addr);
+
+       /* ensure the update has reached the flow controller */
+       wmb();
+       readl_relaxed(addr);
+}
+
+void flowctrl_write_cpu_csr(unsigned int cpuid, u32 value)
+{
+       return flowctrl_update(flowctrl_offset_halt_cpu[cpuid], value);
+}
+
+void flowctrl_write_cpu_halt(unsigned int cpuid, u32 value)
+{
+       return flowctrl_update(flowctrl_offset_cpu_csr[cpuid], value);
+}
index 74c6efb..1942817 100644 (file)
@@ -34,4 +34,9 @@
 #define FLOW_CTRL_HALT_CPU1_EVENTS     0x14
 #define FLOW_CTRL_CPU1_CSR             0x18
 
+#ifndef __ASSEMBLY__
+void flowctrl_write_cpu_csr(unsigned int cpuid, u32 value);
+void flowctrl_write_cpu_halt(unsigned int cpuid, u32 value);
+#endif
+
 #endif
index c1afb27..f946d12 100644 (file)
@@ -34,6 +34,7 @@
 int tegra_sku_id;
 int tegra_cpu_process_id;
 int tegra_core_process_id;
+int tegra_chip_id;
 enum tegra_revision tegra_revision;
 
 /* The BCT to use at boot is specified by board straps that can be read
@@ -66,12 +67,9 @@ static inline bool get_spare_fuse(int bit)
        return tegra_fuse_readl(FUSE_SPARE_BIT + bit * 4);
 }
 
-static enum tegra_revision tegra_get_revision(void)
+static enum tegra_revision tegra_get_revision(u32 id)
 {
-       void __iomem *chip_id = IO_ADDRESS(TEGRA_APB_MISC_BASE) + 0x804;
-       u32 id = readl(chip_id);
        u32 minor_rev = (id >> 16) & 0xf;
-       u32 chipid = (id >> 8) & 0xff;
 
        switch (minor_rev) {
        case 1:
@@ -79,7 +77,8 @@ static enum tegra_revision tegra_get_revision(void)
        case 2:
                return TEGRA_REVISION_A02;
        case 3:
-               if (chipid == 0x20 && (get_spare_fuse(18) || get_spare_fuse(19)))
+               if (tegra_chip_id == TEGRA20 &&
+                       (get_spare_fuse(18) || get_spare_fuse(19)))
                        return TEGRA_REVISION_A03p;
                else
                        return TEGRA_REVISION_A03;
@@ -92,6 +91,8 @@ static enum tegra_revision tegra_get_revision(void)
 
 void tegra_init_fuse(void)
 {
+       u32 id;
+
        u32 reg = readl(IO_TO_VIRT(TEGRA_CLK_RESET_BASE + 0x48));
        reg |= 1 << 28;
        writel(reg, IO_TO_VIRT(TEGRA_CLK_RESET_BASE + 0x48));
@@ -108,10 +109,13 @@ void tegra_init_fuse(void)
        reg = tegra_apb_readl(TEGRA_APB_MISC_BASE + STRAP_OPT);
        tegra_bct_strapping = (reg & RAM_ID_MASK) >> RAM_CODE_SHIFT;
 
-       tegra_revision = tegra_get_revision();
+       id = readl_relaxed(IO_ADDRESS(TEGRA_APB_MISC_BASE) + 0x804);
+       tegra_chip_id = (id >> 8) & 0xff;
+
+       tegra_revision = tegra_get_revision(id);
 
        pr_info("Tegra Revision: %s SKU: %d CPU Process: %d Core Process: %d\n",
-               tegra_revision_name[tegra_get_revision()],
+               tegra_revision_name[tegra_revision],
                tegra_sku_id, tegra_cpu_process_id,
                tegra_core_process_id);
 }
index d65d2ab..d2107b2 100644 (file)
@@ -35,9 +35,13 @@ enum tegra_revision {
 #define SKU_ID_AP25E   27
 #define SKU_ID_T25E    28
 
+#define TEGRA20                0x20
+#define TEGRA30                0x30
+
 extern int tegra_sku_id;
 extern int tegra_cpu_process_id;
 extern int tegra_core_process_id;
+extern int tegra_chip_id;
 extern enum tegra_revision tegra_revision;
 
 extern int tegra_bct_strapping;
index b5349b2..fef9c2c 100644 (file)
@@ -1,6 +1,23 @@
 #include <linux/linkage.h>
 #include <linux/init.h>
 
+#include <asm/cache.h>
+
+#include <mach/iomap.h>
+
+#include "flowctrl.h"
+#include "reset.h"
+
+#define APB_MISC_GP_HIDREV     0x804
+#define PMC_SCRATCH41  0x140
+
+#define RESET_DATA(x)  ((TEGRA_RESET_##x)*4)
+
+       .macro mov32, reg, val
+       movw    \reg, #:lower16:\val
+       movt    \reg, #:upper16:\val
+       .endm
+
         .section ".text.head", "ax"
        __CPUINIT
 
@@ -47,15 +64,149 @@ ENTRY(v7_invalidate_l1)
         mov     pc, lr
 ENDPROC(v7_invalidate_l1)
 
+
 ENTRY(tegra_secondary_startup)
-       msr     cpsr_fsxc, #0xd3
         bl      v7_invalidate_l1
-       mrc     p15, 0, r0, c0, c0, 5
-        and    r0, r0, #15
-        ldr     r1, =0x6000f100
-        str     r0, [r1]
-1:      ldr     r2, [r1]
-        cmp     r0, r2
-        beq     1b
+       /* Enable coresight */
+       mov32   r0, 0xC5ACCE55
+       mcr     p14, 0, r0, c7, c12, 6
         b       secondary_startup
 ENDPROC(tegra_secondary_startup)
+
+       .align L1_CACHE_SHIFT
+ENTRY(__tegra_cpu_reset_handler_start)
+
+/*
+ * __tegra_cpu_reset_handler:
+ *
+ * Common handler for all CPU reset events.
+ *
+ * Register usage within the reset handler:
+ *
+ *      R7  = CPU present (to the OS) mask
+ *      R8  = CPU in LP1 state mask
+ *      R9  = CPU in LP2 state mask
+ *      R10 = CPU number
+ *      R11 = CPU mask
+ *      R12 = pointer to reset handler data
+ *
+ * NOTE: This code is copied to IRAM. All code and data accesses
+ *       must be position-independent.
+ */
+
+       .align L1_CACHE_SHIFT
+ENTRY(__tegra_cpu_reset_handler)
+
+       cpsid   aif, 0x13                       @ SVC mode, interrupts disabled
+       mrc     p15, 0, r10, c0, c0, 5          @ MPIDR
+       and     r10, r10, #0x3                  @ R10 = CPU number
+       mov     r11, #1
+       mov     r11, r11, lsl r10               @ R11 = CPU mask
+       adr     r12, __tegra_cpu_reset_handler_data
+
+#ifdef CONFIG_SMP
+       /* Does the OS know about this CPU? */
+       ldr     r7, [r12, #RESET_DATA(MASK_PRESENT)]
+       tst     r7, r11                         @ if !present
+       bleq    __die                           @ CPU not present (to OS)
+#endif
+
+#ifdef CONFIG_ARCH_TEGRA_2x_SOC
+       /* Are we on Tegra20? */
+       mov32   r6, TEGRA_APB_MISC_BASE
+       ldr     r0, [r6, #APB_MISC_GP_HIDREV]
+       and     r0, r0, #0xff00
+       cmp     r0, #(0x20 << 8)
+       bne     1f
+       /* If not CPU0, don't let CPU0 reset CPU1 now that CPU1 is coming up. */
+       mov32   r6, TEGRA_PMC_BASE
+       mov     r0, #0
+       cmp     r10, #0
+       strne   r0, [r6, #PMC_SCRATCH41]
+1:
+#endif
+
+#ifdef CONFIG_SMP
+       /*
+        * Can only be secondary boot (initial or hotplug) but CPU 0
+        * cannot be here.
+        */
+       cmp     r10, #0
+       bleq    __die                           @ CPU0 cannot be here
+       ldr     lr, [r12, #RESET_DATA(STARTUP_SECONDARY)]
+       cmp     lr, #0
+       bleq    __die                           @ no secondary startup handler
+       bx      lr
+#endif
+
+/*
+ * We don't know why the CPU reset. Just kill it.
+ * The LR register will contain the address we died at + 4.
+ */
+
+__die:
+       sub     lr, lr, #4
+       mov32   r7, TEGRA_PMC_BASE
+       str     lr, [r7, #PMC_SCRATCH41]
+
+       mov32   r7, TEGRA_CLK_RESET_BASE
+
+       /* Are we on Tegra20? */
+       mov32   r6, TEGRA_APB_MISC_BASE
+       ldr     r0, [r6, #APB_MISC_GP_HIDREV]
+       and     r0, r0, #0xff00
+       cmp     r0, #(0x20 << 8)
+       bne     1f
+
+#ifdef CONFIG_ARCH_TEGRA_2x_SOC
+       mov32   r0, 0x1111
+       mov     r1, r0, lsl r10
+       str     r1, [r7, #0x340]                @ CLK_RST_CPU_CMPLX_SET
+#endif
+1:
+#ifdef CONFIG_ARCH_TEGRA_3x_SOC
+       mov32   r6, TEGRA_FLOW_CTRL_BASE
+
+       cmp     r10, #0
+       moveq   r1, #FLOW_CTRL_HALT_CPU0_EVENTS
+       moveq   r2, #FLOW_CTRL_CPU0_CSR
+       movne   r1, r10, lsl #3
+       addne   r2, r1, #(FLOW_CTRL_CPU1_CSR-8)
+       addne   r1, r1, #(FLOW_CTRL_HALT_CPU1_EVENTS-8)
+
+       /* Clear CPU "event" and "interrupt" flags and power gate
+          it when halting but not before it is in the "WFI" state. */
+       ldr     r0, [r6, +r2]
+       orr     r0, r0, #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG
+       orr     r0, r0, #FLOW_CTRL_CSR_ENABLE
+       str     r0, [r6, +r2]
+
+       /* Unconditionally halt this CPU */
+       mov     r0, #FLOW_CTRL_WAITEVENT
+       str     r0, [r6, +r1]
+       ldr     r0, [r6, +r1]                   @ memory barrier
+
+       dsb
+       isb
+       wfi                                     @ CPU should be power gated here
+
+       /* If the CPU didn't power gate above just kill it's clock. */
+
+       mov     r0, r11, lsl #8
+       str     r0, [r7, #348]                  @ CLK_CPU_CMPLX_SET
+#endif
+
+       /* If the CPU still isn't dead, just spin here. */
+       b       .
+ENDPROC(__tegra_cpu_reset_handler)
+
+       .align L1_CACHE_SHIFT
+       .type   __tegra_cpu_reset_handler_data, %object
+       .globl  __tegra_cpu_reset_handler_data
+__tegra_cpu_reset_handler_data:
+       .rept   TEGRA_RESET_DATA_SIZE
+       .long   0
+       .endr
+       .align L1_CACHE_SHIFT
+
+ENTRY(__tegra_cpu_reset_handler_end)
index f329404..d8dc9dd 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/smp.h>
 
 #include <asm/cacheflush.h>
+#include <asm/cp15.h>
 
 static inline void cpu_enter_lowpower(void)
 {
index 67644c9..cff672a 100644 (file)
 #define TEGRA_AHB_GIZMO_BASE           0x6000C004
 #define TEGRA_AHB_GIZMO_SIZE           0x10C
 
+#define TEGRA_SB_BASE                  0x6000C200
+#define TEGRA_SB_SIZE                  256
+
 #define TEGRA_STATMON_BASE             0x6000C400
 #define TEGRA_STATMON_SIZE             SZ_1K
 
index 39c396d..4752b1a 100644 (file)
 #define TEGRA_POWERGATE_VDEC   4
 #define TEGRA_POWERGATE_L2     5
 #define TEGRA_POWERGATE_MPE    6
-#define TEGRA_NUM_POWERGATE    7
+#define TEGRA_POWERGATE_HEG    7
+#define TEGRA_POWERGATE_SATA   8
+#define TEGRA_POWERGATE_CPU1   9
+#define TEGRA_POWERGATE_CPU2   10
+#define TEGRA_POWERGATE_CPU3   11
+#define TEGRA_POWERGATE_CELP   12
+#define TEGRA_POWERGATE_3D1    13
 
+#define TEGRA_POWERGATE_CPU0   TEGRA_POWERGATE_CPU
+#define TEGRA_POWERGATE_3D0    TEGRA_POWERGATE_3D
+
+int  __init tegra_powergate_init(void);
+
+int tegra_cpu_powergate_id(int cpuid);
+int tegra_powergate_is_powered(int id);
 int tegra_powergate_power_on(int id);
 int tegra_powergate_power_off(int id);
 int tegra_powergate_remove_clamping(int id);
index 7d2b5d0..1a208db 100644 (file)
 #include <asm/mach-types.h>
 #include <asm/smp_scu.h>
 
+#include <mach/clk.h>
 #include <mach/iomap.h>
+#include <mach/powergate.h>
+
+#include "fuse.h"
+#include "flowctrl.h"
+#include "reset.h"
 
 extern void tegra_secondary_startup(void);
 
-static DEFINE_SPINLOCK(boot_lock);
 static void __iomem *scu_base = IO_ADDRESS(TEGRA_ARM_PERIF_BASE);
 
 #define EVP_CPU_RESET_VECTOR \
        (IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE) + 0x100)
 #define CLK_RST_CONTROLLER_CLK_CPU_CMPLX \
        (IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x4c)
+#define CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET \
+       (IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x340)
 #define CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR \
        (IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x344)
+#define CLK_RST_CONTROLLER_CLK_CPU_CMPLX_CLR \
+       (IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x34c)
+
+#define CPU_CLOCK(cpu) (0x1<<(8+cpu))
+#define CPU_RESET(cpu) (0x1111ul<<(cpu))
 
 void __cpuinit platform_secondary_init(unsigned int cpu)
 {
@@ -47,63 +59,106 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
         */
        gic_secondary_init(0);
 
-       /*
-        * Synchronise with the boot thread.
-        */
-       spin_lock(&boot_lock);
-       spin_unlock(&boot_lock);
 }
 
-int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
+static int tegra20_power_up_cpu(unsigned int cpu)
 {
-       unsigned long old_boot_vector;
-       unsigned long boot_vector;
-       unsigned long timeout;
        u32 reg;
 
-       /*
-        * set synchronisation state between this boot processor
-        * and the secondary one
-        */
-       spin_lock(&boot_lock);
+       /* Enable the CPU clock. */
+       reg = readl(CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
+       writel(reg & ~CPU_CLOCK(cpu), CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
+       barrier();
+       reg = readl(CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
 
+       /* Clear flow controller CSR. */
+       flowctrl_write_cpu_csr(cpu, 0);
 
-       /* set the reset vector to point to the secondary_startup routine */
+       return 0;
+}
 
-       boot_vector = virt_to_phys(tegra_secondary_startup);
-       old_boot_vector = readl(EVP_CPU_RESET_VECTOR);
-       writel(boot_vector, EVP_CPU_RESET_VECTOR);
+static int tegra30_power_up_cpu(unsigned int cpu)
+{
+       u32 reg;
+       int ret, pwrgateid;
+       unsigned long timeout;
 
-       /* enable cpu clock on cpu1 */
-       reg = readl(CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
-       writel(reg & ~(1<<9), CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
+       pwrgateid = tegra_cpu_powergate_id(cpu);
+       if (pwrgateid < 0)
+               return pwrgateid;
+
+       /* If this is the first boot, toggle powergates directly. */
+       if (!tegra_powergate_is_powered(pwrgateid)) {
+               ret = tegra_powergate_power_on(pwrgateid);
+               if (ret)
+                       return ret;
+
+               /* Wait for the power to come up. */
+               timeout = jiffies + 10*HZ;
+               while (tegra_powergate_is_powered(pwrgateid)) {
+                       if (time_after(jiffies, timeout))
+                               return -ETIMEDOUT;
+                       udelay(10);
+               }
+       }
 
-       reg = (1<<13) | (1<<9) | (1<<5) | (1<<1);
-       writel(reg, CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR);
+       /* CPU partition is powered. Enable the CPU clock. */
+       writel(CPU_CLOCK(cpu), CLK_RST_CONTROLLER_CLK_CPU_CMPLX_CLR);
+       reg = readl(CLK_RST_CONTROLLER_CLK_CPU_CMPLX_CLR);
+       udelay(10);
 
-       smp_wmb();
-       flush_cache_all();
+       /* Remove I/O clamps. */
+       ret = tegra_powergate_remove_clamping(pwrgateid);
+       udelay(10);
 
-       /* unhalt the cpu */
-       writel(0, IO_ADDRESS(TEGRA_FLOW_CTRL_BASE) + 0x14);
+       /* Clear flow controller CSR. */
+       flowctrl_write_cpu_csr(cpu, 0);
 
-       timeout = jiffies + (1 * HZ);
-       while (time_before(jiffies, timeout)) {
-               if (readl(EVP_CPU_RESET_VECTOR) != boot_vector)
-                       break;
-               udelay(10);
-       }
+       return 0;
+}
+
+int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+       int status;
 
-       /* put the old boot vector back */
-       writel(old_boot_vector, EVP_CPU_RESET_VECTOR);
+       /*
+        * Force the CPU into reset. The CPU must remain in reset when the
+        * flow controller state is cleared (which will cause the flow
+        * controller to stop driving reset if the CPU has been power-gated
+        * via the flow controller). This will have no effect on first boot
+        * of the CPU since it should already be in reset.
+        */
+       writel(CPU_RESET(cpu), CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET);
+       dmb();
 
        /*
-        * now the secondary core is starting up let it run its
-        * calibrations, then wait for it to finish
+        * Unhalt the CPU. If the flow controller was used to power-gate the
+        * CPU this will cause the flow controller to stop driving reset.
+        * The CPU will remain in reset because the clock and reset block
+        * is now driving reset.
         */
-       spin_unlock(&boot_lock);
+       flowctrl_write_cpu_halt(cpu, 0);
+
+       switch (tegra_chip_id) {
+       case TEGRA20:
+               status = tegra20_power_up_cpu(cpu);
+               break;
+       case TEGRA30:
+               status = tegra30_power_up_cpu(cpu);
+               break;
+       default:
+               status = -EINVAL;
+               break;
+       }
 
-       return 0;
+       if (status)
+               goto done;
+
+       /* Take the CPU out of reset. */
+       writel(CPU_RESET(cpu), CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR);
+       wmb();
+done:
+       return status;
 }
 
 /*
@@ -128,6 +183,6 @@ void __init smp_init_cpus(void)
 
 void __init platform_smp_prepare_cpus(unsigned int max_cpus)
 {
-
+       tegra_cpu_reset_handler_init();
        scu_enable(scu_base);
 }
index 9483064..c238699 100644 (file)
@@ -31,6 +31,8 @@
 #include <mach/iomap.h>
 #include <mach/powergate.h>
 
+#include "fuse.h"
+
 #define PWRGATE_TOGGLE         0x30
 #define  PWRGATE_TOGGLE_START  (1 << 8)
 
 
 #define PWRGATE_STATUS         0x38
 
+static int tegra_num_powerdomains;
+static int tegra_num_cpu_domains;
+static u8 *tegra_cpu_domains;
+static u8 tegra30_cpu_domains[] = {
+       TEGRA_POWERGATE_CPU0,
+       TEGRA_POWERGATE_CPU1,
+       TEGRA_POWERGATE_CPU2,
+       TEGRA_POWERGATE_CPU3,
+};
+
 static DEFINE_SPINLOCK(tegra_powergate_lock);
 
 static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);
@@ -75,7 +87,7 @@ static int tegra_powergate_set(int id, bool new_state)
 
 int tegra_powergate_power_on(int id)
 {
-       if (id < 0 || id >= TEGRA_NUM_POWERGATE)
+       if (id < 0 || id >= tegra_num_powerdomains)
                return -EINVAL;
 
        return tegra_powergate_set(id, true);
@@ -83,17 +95,18 @@ int tegra_powergate_power_on(int id)
 
 int tegra_powergate_power_off(int id)
 {
-       if (id < 0 || id >= TEGRA_NUM_POWERGATE)
+       if (id < 0 || id >= tegra_num_powerdomains)
                return -EINVAL;
 
        return tegra_powergate_set(id, false);
 }
 
-static bool tegra_powergate_is_powered(int id)
+int tegra_powergate_is_powered(int id)
 {
        u32 status;
 
-       WARN_ON(id < 0 || id >= TEGRA_NUM_POWERGATE);
+       if (id < 0 || id >= tegra_num_powerdomains)
+               return -EINVAL;
 
        status = pmc_read(PWRGATE_STATUS) & (1 << id);
        return !!status;
@@ -103,7 +116,7 @@ int tegra_powergate_remove_clamping(int id)
 {
        u32 mask;
 
-       if (id < 0 || id >= TEGRA_NUM_POWERGATE)
+       if (id < 0 || id >= tegra_num_powerdomains)
                return -EINVAL;
 
        /*
@@ -156,6 +169,34 @@ err_power:
        return ret;
 }
 
+int tegra_cpu_powergate_id(int cpuid)
+{
+       if (cpuid > 0 && cpuid < tegra_num_cpu_domains)
+               return tegra_cpu_domains[cpuid];
+
+       return -EINVAL;
+}
+
+int __init tegra_powergate_init(void)
+{
+       switch (tegra_chip_id) {
+       case TEGRA20:
+               tegra_num_powerdomains = 7;
+               break;
+       case TEGRA30:
+               tegra_num_powerdomains = 14;
+               tegra_num_cpu_domains = 4;
+               tegra_cpu_domains = tegra30_cpu_domains;
+               break;
+       default:
+               /* Unknown Tegra variant. Disable powergating */
+               tegra_num_powerdomains = 0;
+               break;
+       }
+
+       return 0;
+}
+
 #ifdef CONFIG_DEBUG_FS
 
 static const char * const powergate_name[] = {
@@ -175,7 +216,7 @@ static int powergate_show(struct seq_file *s, void *data)
        seq_printf(s, " powergate powered\n");
        seq_printf(s, "------------------\n");
 
-       for (i = 0; i < TEGRA_NUM_POWERGATE; i++)
+       for (i = 0; i < tegra_num_powerdomains; i++)
                seq_printf(s, " %9s %7s\n", powergate_name[i],
                        tegra_powergate_is_powered(i) ? "yes" : "no");
        return 0;
diff --git a/arch/arm/mach-tegra/reset.c b/arch/arm/mach-tegra/reset.c
new file mode 100644 (file)
index 0000000..4d6a2ee
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * arch/arm/mach-tegra/reset.c
+ *
+ * Copyright (C) 2011,2012 NVIDIA Corporation.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/cpumask.h>
+#include <linux/bitops.h>
+
+#include <asm/cacheflush.h>
+#include <asm/hardware/cache-l2x0.h>
+
+#include <mach/iomap.h>
+#include <mach/irammap.h>
+
+#include "reset.h"
+#include "fuse.h"
+
+#define TEGRA_IRAM_RESET_BASE (TEGRA_IRAM_BASE + \
+                               TEGRA_IRAM_RESET_HANDLER_OFFSET)
+
+static bool is_enabled;
+
+static void tegra_cpu_reset_handler_enable(void)
+{
+       void __iomem *iram_base = IO_ADDRESS(TEGRA_IRAM_RESET_BASE);
+       void __iomem *evp_cpu_reset =
+               IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE + 0x100);
+       void __iomem *sb_ctrl = IO_ADDRESS(TEGRA_SB_BASE);
+       u32 reg;
+
+       BUG_ON(is_enabled);
+       BUG_ON(tegra_cpu_reset_handler_size > TEGRA_IRAM_RESET_HANDLER_SIZE);
+
+       memcpy(iram_base, (void *)__tegra_cpu_reset_handler_start,
+                       tegra_cpu_reset_handler_size);
+
+       /*
+        * NOTE: This must be the one and only write to the EVP CPU reset
+        *       vector in the entire system.
+        */
+       writel(TEGRA_IRAM_RESET_BASE + tegra_cpu_reset_handler_offset,
+                       evp_cpu_reset);
+       wmb();
+       reg = readl(evp_cpu_reset);
+
+       /*
+        * Prevent further modifications to the physical reset vector.
+        *  NOTE: Has no effect on chips prior to Tegra30.
+        */
+       if (tegra_chip_id != TEGRA20) {
+               reg = readl(sb_ctrl);
+               reg |= 2;
+               writel(reg, sb_ctrl);
+               wmb();
+       }
+
+       is_enabled = true;
+}
+
+void __init tegra_cpu_reset_handler_init(void)
+{
+
+#ifdef CONFIG_SMP
+       __tegra_cpu_reset_handler_data[TEGRA_RESET_MASK_PRESENT] =
+               *((u32 *)cpu_present_mask);
+       __tegra_cpu_reset_handler_data[TEGRA_RESET_STARTUP_SECONDARY] =
+               virt_to_phys((void *)tegra_secondary_startup);
+#endif
+
+       tegra_cpu_reset_handler_enable();
+}
diff --git a/arch/arm/mach-tegra/reset.h b/arch/arm/mach-tegra/reset.h
new file mode 100644 (file)
index 0000000..de88bf8
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * arch/arm/mach-tegra/reset.h
+ *
+ * CPU reset dispatcher.
+ *
+ * Copyright (c) 2011, NVIDIA Corporation.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __MACH_TEGRA_RESET_H
+#define __MACH_TEGRA_RESET_H
+
+#define TEGRA_RESET_MASK_PRESENT       0
+#define TEGRA_RESET_MASK_LP1           1
+#define TEGRA_RESET_MASK_LP2           2
+#define TEGRA_RESET_STARTUP_SECONDARY  3
+#define TEGRA_RESET_STARTUP_LP2                4
+#define TEGRA_RESET_STARTUP_LP1                5
+#define TEGRA_RESET_DATA_SIZE          6
+
+#ifndef __ASSEMBLY__
+
+extern unsigned long __tegra_cpu_reset_handler_data[TEGRA_RESET_DATA_SIZE];
+
+void __tegra_cpu_reset_handler_start(void);
+void __tegra_cpu_reset_handler(void);
+void __tegra_cpu_reset_handler_end(void);
+void tegra_secondary_startup(void);
+
+#define tegra_cpu_reset_handler_offset \
+               ((u32)__tegra_cpu_reset_handler - \
+                (u32)__tegra_cpu_reset_handler_start)
+
+#define tegra_cpu_reset_handler_size \
+               (__tegra_cpu_reset_handler_end - \
+                __tegra_cpu_reset_handler_start)
+
+void __init tegra_cpu_reset_handler_init(void);
+
+#endif
+#endif
index 9ec6358..880d02e 100644 (file)
@@ -27,6 +27,7 @@ config MACH_MOP500
        select UX500_SOC_DB8500
        select I2C
        select I2C_NOMADIK
+       select SOC_BUS
        help
          Include support for the MOP500 development platform.
 
@@ -57,6 +58,12 @@ config UX500_AUTO_PLATFORM
          At least one platform needs to be selected in order to build
          a working kernel. If everything else is disabled, this
          automatically enables MACH_MOP500.
+
+config MACH_UX500_DT
+       bool "Generic U8500 support using device tree"
+       depends on MACH_MOP500
+       select USE_OF
+
 endmenu
 
 config UX500_DEBUG_UART
index ff0a4b5..dd5cd00 100644 (file)
@@ -2,3 +2,4 @@
 params_phys-y  := 0x00000100
 initrd_phys-y  := 0x00800000
 
+dtb-$(CONFIG_MACH_SNOWBALL) += snowball.dtb
index 1daead3..920251c 100644 (file)
@@ -99,7 +99,7 @@ static struct mmci_platform_data mop500_sdi0_data = {
 #endif
 };
 
-static void sdi0_configure(void)
+static void sdi0_configure(struct device *parent)
 {
        int ret;
 
@@ -118,15 +118,15 @@ static void sdi0_configure(void)
        gpio_direction_output(sdi0_en, 1);
 
        /* Add the device, force v2 to subrevision 1 */
-       db8500_add_sdi0(&mop500_sdi0_data, U8500_SDI_V2_PERIPHID);
+       db8500_add_sdi0(parent, &mop500_sdi0_data, U8500_SDI_V2_PERIPHID);
 }
 
-void mop500_sdi_tc35892_init(void)
+void mop500_sdi_tc35892_init(struct device *parent)
 {
        mop500_sdi0_data.gpio_cd = GPIO_SDMMC_CD;
        sdi0_en = GPIO_SDMMC_EN;
        sdi0_vsel = GPIO_SDMMC_1V8_3V_SEL;
-       sdi0_configure();
+       sdi0_configure(parent);
 }
 
 /*
@@ -241,12 +241,13 @@ static struct mmci_platform_data mop500_sdi4_data = {
 #endif
 };
 
-void __init mop500_sdi_init(void)
+void __init mop500_sdi_init(struct device *parent)
 {
        /* PoP:ed eMMC */
-       db8500_add_sdi2(&mop500_sdi2_data, U8500_SDI_V2_PERIPHID);
+       db8500_add_sdi2(parent, &mop500_sdi2_data, U8500_SDI_V2_PERIPHID);
        /* On-board eMMC */
-       db8500_add_sdi4(&mop500_sdi4_data, U8500_SDI_V2_PERIPHID);
+       db8500_add_sdi4(parent, &mop500_sdi4_data, U8500_SDI_V2_PERIPHID);
+
        /*
         * On boards with the TC35892 GPIO expander, sdi0 will finally
         * be added when the TC35892 initializes and calls
@@ -254,31 +255,31 @@ void __init mop500_sdi_init(void)
         */
 }
 
-void __init snowball_sdi_init(void)
+void __init snowball_sdi_init(struct device *parent)
 {
        /* On Snowball MMC_CAP_SD_HIGHSPEED isn't supported (Hardware issue?) */
        mop500_sdi0_data.capabilities &= ~MMC_CAP_SD_HIGHSPEED;
        /* On-board eMMC */
-       db8500_add_sdi4(&mop500_sdi4_data, U8500_SDI_V2_PERIPHID);
+       db8500_add_sdi4(parent, &mop500_sdi4_data, U8500_SDI_V2_PERIPHID);
        /* External Micro SD slot */
        mop500_sdi0_data.gpio_cd = SNOWBALL_SDMMC_CD_GPIO;
        mop500_sdi0_data.cd_invert = true;
        sdi0_en = SNOWBALL_SDMMC_EN_GPIO;
        sdi0_vsel = SNOWBALL_SDMMC_1V8_3V_GPIO;
-       sdi0_configure();
+       sdi0_configure(parent);
 }
 
-void __init hrefv60_sdi_init(void)
+void __init hrefv60_sdi_init(struct device *parent)
 {
        /* PoP:ed eMMC */
-       db8500_add_sdi2(&mop500_sdi2_data, U8500_SDI_V2_PERIPHID);
+       db8500_add_sdi2(parent, &mop500_sdi2_data, U8500_SDI_V2_PERIPHID);
        /* On-board eMMC */
-       db8500_add_sdi4(&mop500_sdi4_data, U8500_SDI_V2_PERIPHID);
+       db8500_add_sdi4(parent, &mop500_sdi4_data, U8500_SDI_V2_PERIPHID);
        /* External Micro SD slot */
        mop500_sdi0_data.gpio_cd = HREFV60_SDMMC_CD_GPIO;
        sdi0_en = HREFV60_SDMMC_EN_GPIO;
        sdi0_vsel = HREFV60_SDMMC_1V8_3V_GPIO;
-       sdi0_configure();
+       sdi0_configure(parent);
        /* WLAN SDIO channel */
-       db8500_add_sdi1(&mop500_sdi1_data, U8500_SDI_V2_PERIPHID);
+       db8500_add_sdi1(parent, &mop500_sdi1_data, U8500_SDI_V2_PERIPHID);
 }
index 6d672a5..77d03c1 100644 (file)
@@ -30,6 +30,9 @@
 #include <linux/gpio_keys.h>
 #include <linux/delay.h>
 
+#include <linux/of.h>
+#include <linux/of_platform.h>
+
 #include <linux/leds.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -226,7 +229,12 @@ static struct tps6105x_platform_data mop500_tps61052_data = {
 
 static void mop500_tc35892_init(struct tc3589x *tc3589x, unsigned int base)
 {
-       mop500_sdi_tc35892_init();
+       struct device *parent = NULL;
+#if 0
+       /* FIXME: Is the sdi actually part of tc3589x? */
+       parent = tc3589x->dev;
+#endif
+       mop500_sdi_tc35892_init(parent);
 }
 
 static struct tc3589x_gpio_platform_data mop500_tc35892_gpio_data = {
@@ -353,12 +361,12 @@ U8500_I2C_CONTROLLER(1, 0xe, 1, 8, 100000, 200, I2C_FREQ_MODE_FAST);
 U8500_I2C_CONTROLLER(2,        0xe, 1, 8, 100000, 200, I2C_FREQ_MODE_FAST);
 U8500_I2C_CONTROLLER(3,        0xe, 1, 8, 100000, 200, I2C_FREQ_MODE_FAST);
 
-static void __init mop500_i2c_init(void)
+static void __init mop500_i2c_init(struct device *parent)
 {
-       db8500_add_i2c0(&u8500_i2c0_data);
-       db8500_add_i2c1(&u8500_i2c1_data);
-       db8500_add_i2c2(&u8500_i2c2_data);
-       db8500_add_i2c3(&u8500_i2c3_data);
+       db8500_add_i2c0(parent, &u8500_i2c0_data);
+       db8500_add_i2c1(parent, &u8500_i2c1_data);
+       db8500_add_i2c2(parent, &u8500_i2c2_data);
+       db8500_add_i2c3(parent, &u8500_i2c3_data);
 }
 
 static struct gpio_keys_button mop500_gpio_keys[] = {
@@ -435,7 +443,7 @@ static struct stedma40_chan_cfg ssp0_dma_cfg_tx = {
 };
 #endif
 
-static struct pl022_ssp_controller ssp0_platform_data = {
+static struct pl022_ssp_controller ssp0_plat = {
        .bus_id = 0,
 #ifdef CONFIG_STE_DMA40
        .enable_dma = 1,
@@ -451,9 +459,9 @@ static struct pl022_ssp_controller ssp0_platform_data = {
        .num_chipselect = 5,
 };
 
-static void __init mop500_spi_init(void)
+static void __init mop500_spi_init(struct device *parent)
 {
-       db8500_add_ssp0(&ssp0_platform_data);
+       db8500_add_ssp0(parent, &ssp0_plat);
 }
 
 #ifdef CONFIG_STE_DMA40
@@ -587,11 +595,11 @@ static struct amba_pl011_data uart2_plat = {
 #endif
 };
 
-static void __init mop500_uart_init(void)
+static void __init mop500_uart_init(struct device *parent)
 {
-       db8500_add_uart0(&uart0_plat);
-       db8500_add_uart1(&uart1_plat);
-       db8500_add_uart2(&uart2_plat);
+       db8500_add_uart0(parent, &uart0_plat);
+       db8500_add_uart1(parent, &uart1_plat);
+       db8500_add_uart2(parent, &uart2_plat);
 }
 
 static struct platform_device *snowball_platform_devs[] __initdata = {
@@ -603,21 +611,27 @@ static struct platform_device *snowball_platform_devs[] __initdata = {
 
 static void __init mop500_init_machine(void)
 {
+       struct device *parent = NULL;
        int i2c0_devs;
+       int i;
 
        mop500_gpio_keys[0].gpio = GPIO_PROX_SENSOR;
 
-       u8500_init_devices();
+       parent = u8500_init_devices();
 
        mop500_pins_init();
 
+       /* FIXME: parent of ab8500 should be prcmu */
+       for (i = 0; i < ARRAY_SIZE(mop500_platform_devs); i++)
+               mop500_platform_devs[i]->dev.parent = parent;
+
        platform_add_devices(mop500_platform_devs,
                        ARRAY_SIZE(mop500_platform_devs));
 
-       mop500_i2c_init();
-       mop500_sdi_init();
-       mop500_spi_init();
-       mop500_uart_init();
+       mop500_i2c_init(parent);
+       mop500_sdi_init(parent);
+       mop500_spi_init(parent);
+       mop500_uart_init(parent);
 
        i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices);
 
@@ -631,19 +645,24 @@ static void __init mop500_init_machine(void)
 
 static void __init snowball_init_machine(void)
 {
+       struct device *parent = NULL;
        int i2c0_devs;
+       int i;
 
-       u8500_init_devices();
+       parent = u8500_init_devices();
 
        snowball_pins_init();
 
+       for (i = 0; i < ARRAY_SIZE(snowball_platform_devs); i++)
+               snowball_platform_devs[i]->dev.parent = parent;
+
        platform_add_devices(snowball_platform_devs,
                        ARRAY_SIZE(snowball_platform_devs));
 
-       mop500_i2c_init();
-       snowball_sdi_init();
-       mop500_spi_init();
-       mop500_uart_init();
+       mop500_i2c_init(parent);
+       snowball_sdi_init(parent);
+       mop500_spi_init(parent);
+       mop500_uart_init(parent);
 
        i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices);
        i2c_register_board_info(0, mop500_i2c0_devices, i2c0_devs);
@@ -656,7 +675,9 @@ static void __init snowball_init_machine(void)
 
 static void __init hrefv60_init_machine(void)
 {
+       struct device *parent = NULL;
        int i2c0_devs;
+       int i;
 
        /*
         * The HREFv60 board removed a GPIO expander and routed
@@ -665,17 +686,20 @@ static void __init hrefv60_init_machine(void)
         */
        mop500_gpio_keys[0].gpio = HREFV60_PROX_SENSE_GPIO;
 
-       u8500_init_devices();
+       parent = u8500_init_devices();
 
        hrefv60_pins_init();
 
+       for (i = 0; i < ARRAY_SIZE(mop500_platform_devs); i++)
+               mop500_platform_devs[i]->dev.parent = parent;
+
        platform_add_devices(mop500_platform_devs,
                        ARRAY_SIZE(mop500_platform_devs));
 
-       mop500_i2c_init();
-       hrefv60_sdi_init();
-       mop500_spi_init();
-       mop500_uart_init();
+       mop500_i2c_init(parent);
+       hrefv60_sdi_init(parent);
+       mop500_spi_init(parent);
+       mop500_uart_init(parent);
 
        i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices);
 
@@ -718,3 +742,94 @@ MACHINE_START(SNOWBALL, "Calao Systems Snowball platform")
        .handle_irq     = gic_handle_irq,
        .init_machine   = snowball_init_machine,
 MACHINE_END
+
+#ifdef CONFIG_MACH_UX500_DT
+
+struct of_dev_auxdata u8500_auxdata_lookup[] __initdata = {
+       OF_DEV_AUXDATA("arm,pl011", 0x80120000, "uart0", &uart0_plat),
+       OF_DEV_AUXDATA("arm,pl011", 0x80121000, "uart1", &uart1_plat),
+       OF_DEV_AUXDATA("arm,pl011", 0x80007000, "uart2", &uart2_plat),
+       OF_DEV_AUXDATA("arm,pl022", 0x80002000, "ssp0",  &ssp0_plat),
+       {},
+};
+
+static const struct of_device_id u8500_soc_node[] = {
+       /* only create devices below soc node */
+       { .compatible = "stericsson,db8500", },
+       { },
+};
+
+static void __init u8500_init_machine(void)
+{
+       struct device *parent = NULL;
+       int i2c0_devs;
+       int i;
+
+       parent = u8500_init_devices();
+       i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices);
+
+       for (i = 0; i < ARRAY_SIZE(mop500_platform_devs); i++)
+               mop500_platform_devs[i]->dev.parent = parent;
+       for (i = 0; i < ARRAY_SIZE(snowball_platform_devs); i++)
+               snowball_platform_devs[i]->dev.parent = parent;
+
+       /* automatically probe child nodes of db8500 device */
+       of_platform_populate(NULL, u8500_soc_node, u8500_auxdata_lookup, parent);
+
+       if (of_machine_is_compatible("st-ericsson,mop500")) {
+               mop500_gpio_keys[0].gpio = GPIO_PROX_SENSOR;
+               mop500_pins_init();
+
+               platform_add_devices(mop500_platform_devs,
+                               ARRAY_SIZE(mop500_platform_devs));
+
+               mop500_sdi_init(parent);
+       } else if (of_machine_is_compatible("calaosystems,snowball-a9500")) {
+               snowball_pins_init();
+               platform_add_devices(snowball_platform_devs,
+                               ARRAY_SIZE(snowball_platform_devs));
+
+               snowball_sdi_init(parent);
+       } else if (of_machine_is_compatible("st-ericsson,hrefv60+")) {
+               /*
+                * The HREFv60 board removed a GPIO expander and routed
+                * all these GPIO pins to the internal GPIO controller
+                * instead.
+                */
+               mop500_gpio_keys[0].gpio = HREFV60_PROX_SENSE_GPIO;
+               i2c0_devs -= NUM_PRE_V60_I2C0_DEVICES;
+               hrefv60_pins_init();
+               platform_add_devices(mop500_platform_devs,
+                               ARRAY_SIZE(mop500_platform_devs));
+
+               hrefv60_sdi_init(parent);
+       }
+       mop500_i2c_init(parent);
+
+       i2c_register_board_info(0, mop500_i2c0_devices, i2c0_devs);
+       i2c_register_board_info(2, mop500_i2c2_devices,
+                               ARRAY_SIZE(mop500_i2c2_devices));
+
+       /* This board has full regulator constraints */
+       regulator_has_full_constraints();
+}
+
+static const char * u8500_dt_board_compat[] = {
+       "calaosystems,snowball-a9500",
+       "st-ericsson,hrefv60+",
+       "st-ericsson,u8500",
+       "st-ericsson,mop500",
+       NULL,
+};
+
+
+DT_MACHINE_START(U8500_DT, "ST-Ericsson U8500 platform (Device Tree Support)")
+       .map_io         = u8500_map_io,
+       .init_irq       = ux500_init_irq,
+       /* we re-use nomadik timer here */
+       .timer          = &ux500_timer,
+       .handle_irq     = gic_handle_irq,
+       .init_machine   = u8500_init_machine,
+       .dt_compat      = u8500_dt_board_compat,
+MACHINE_END
+#endif
index 7ff6cbf..fdcfa87 100644 (file)
 
 struct i2c_board_info;
 
-extern void mop500_sdi_init(void);
-extern void snowball_sdi_init(void);
-extern void hrefv60_sdi_init(void);
-extern void mop500_sdi_tc35892_init(void);
+extern void mop500_sdi_init(struct device *parent);
+extern void snowball_sdi_init(struct device *parent);
+extern void hrefv60_sdi_init(struct device *parent);
+extern void mop500_sdi_tc35892_init(struct device *parent);
 void __init mop500_u8500uib_init(void);
 void __init mop500_stuib_init(void);
 void __init mop500_pins_init(void);
index 63c3f80..836112e 100644 (file)
@@ -66,9 +66,9 @@ static struct mmci_platform_data u5500_sdi0_data = {
 #endif
 };
 
-void __init u5500_sdi_init(void)
+void __init u5500_sdi_init(struct device *parent)
 {
        nmk_config_pins(u5500_sdi_pins, ARRAY_SIZE(u5500_sdi_pins));
 
-       db5500_add_sdi0(&u5500_sdi0_data);
+       db5500_add_sdi0(parent, &u5500_sdi0_data);
 }
index 9de9e9c..0ff4be7 100644 (file)
@@ -97,9 +97,9 @@ static struct i2c_board_info __initdata u5500_i2c2_devices[] = {
        },
 };
 
-static void __init u5500_i2c_init(void)
+static void __init u5500_i2c_init(struct device *parent)
 {
-       db5500_add_i2c2(&u5500_i2c2_data);
+       db5500_add_i2c2(parent, &u5500_i2c2_data);
        i2c_register_board_info(2, ARRAY_AND_SIZE(u5500_i2c2_devices));
 }
 
@@ -126,20 +126,27 @@ static struct platform_device *u5500_platform_devices[] __initdata = {
        &ab5500_device,
 };
 
-static void __init u5500_uart_init(void)
+static void __init u5500_uart_init(struct device *parent)
 {
-       db5500_add_uart0(NULL);
-       db5500_add_uart1(NULL);
-       db5500_add_uart2(NULL);
+       db5500_add_uart0(parent, NULL);
+       db5500_add_uart1(parent, NULL);
+       db5500_add_uart2(parent, NULL);
 }
 
 static void __init u5500_init_machine(void)
 {
-       u5500_init_devices();
+       struct device *parent = NULL;
+       int i;
+
+       parent = u5500_init_devices();
        nmk_config_pins(u5500_pins, ARRAY_SIZE(u5500_pins));
-       u5500_i2c_init();
-       u5500_sdi_init();
-       u5500_uart_init();
+
+       u5500_i2c_init(parent);
+       u5500_sdi_init(parent);
+       u5500_uart_init(parent);
+
+       for (i = 0; i < ARRAY_SIZE(u5500_platform_devices); i++)
+               u5500_platform_devices[i]->dev.parent = parent;
 
        platform_add_devices(u5500_platform_devices,
                ARRAY_SIZE(u5500_platform_devices));
index da5569d..77a75ed 100644 (file)
@@ -5,6 +5,8 @@
  */
 
 #include <linux/io.h>
+#include <linux/of.h>
+
 #include <asm/cacheflush.h>
 #include <asm/hardware/cache-l2x0.h>
 #include <mach/hardware.h>
@@ -45,7 +47,10 @@ static int __init ux500_l2x0_init(void)
        ux500_l2x0_unlock();
 
        /* 64KB way size, 8 way associativity, force WA */
-       l2x0_init(l2x0_base, 0x3e060000, 0xc0000fff);
+       if (of_have_populated_dt())
+               l2x0_of_init(0x3e060000, 0xc0000fff);
+       else
+               l2x0_init(l2x0_base, 0x3e060000, 0xc0000fff);
 
        /*
         * We can't disable l2 as we are in non secure mode, currently
index 18aa5c0..bca47f3 100644 (file)
@@ -147,13 +147,13 @@ static resource_size_t __initdata db5500_gpio_base[] = {
        U5500_GPIOBANK7_BASE,
 };
 
-static void __init db5500_add_gpios(void)
+static void __init db5500_add_gpios(struct device *parent)
 {
        struct nmk_gpio_platform_data pdata = {
                /* No custom data yet */
        };
 
-       dbx500_add_gpios(ARRAY_AND_SIZE(db5500_gpio_base),
+       dbx500_add_gpios(parent, ARRAY_AND_SIZE(db5500_gpio_base),
                         IRQ_DB5500_GPIO0, &pdata);
 }
 
@@ -212,14 +212,36 @@ static int usb_db5500_tx_dma_cfg[] = {
        DB5500_DMA_DEV38_USB_OTG_OEP_8
 };
 
-void __init u5500_init_devices(void)
+static const char *db5500_read_soc_id(void)
 {
-       db5500_add_gpios();
+       return kasprintf(GFP_KERNEL, "u5500 currently unsupported\n");
+}
+
+static struct device * __init db5500_soc_device_init(void)
+{
+       const char *soc_id = db5500_read_soc_id();
+
+       return ux500_soc_device_init(soc_id);
+}
+
+struct device * __init u5500_init_devices(void)
+{
+       struct device *parent;
+       int i;
+
+       parent = db5500_soc_device_init();
+
+       db5500_add_gpios(parent);
        db5500_pmu_init();
-       db5500_dma_init();
-       db5500_add_rtc();
-       db5500_add_usb(usb_db5500_rx_dma_cfg, usb_db5500_tx_dma_cfg);
+       db5500_dma_init(parent);
+       db5500_add_rtc(parent);
+       db5500_add_usb(parent, usb_db5500_rx_dma_cfg, usb_db5500_tx_dma_cfg);
+
+       for (i = 0; i < ARRAY_SIZE(db5500_platform_devs); i++)
+               db5500_platform_devs[i]->dev.parent = parent;
 
        platform_add_devices(db5500_platform_devs,
                             ARRAY_SIZE(db5500_platform_devs));
+
+       return parent;
 }
index 7176ee7..9bd8163 100644 (file)
@@ -24,6 +24,7 @@
 #include <mach/setup.h>
 #include <mach/devices.h>
 #include <mach/usb.h>
+#include <mach/db8500-regs.h>
 
 #include "devices-db8500.h"
 #include "ste-dma40-db8500.h"
@@ -132,13 +133,13 @@ static resource_size_t __initdata db8500_gpio_base[] = {
        U8500_GPIOBANK8_BASE,
 };
 
-static void __init db8500_add_gpios(void)
+static void __init db8500_add_gpios(struct device *parent)
 {
        struct nmk_gpio_platform_data pdata = {
                .supports_sleepmode = true,
        };
 
-       dbx500_add_gpios(ARRAY_AND_SIZE(db8500_gpio_base),
+       dbx500_add_gpios(parent, ARRAY_AND_SIZE(db8500_gpio_base),
                         IRQ_DB8500_GPIO0, &pdata);
 }
 
@@ -164,17 +165,44 @@ static int usb_db8500_tx_dma_cfg[] = {
        DB8500_DMA_DEV39_USB_OTG_OEP_8
 };
 
+static const char *db8500_read_soc_id(void)
+{
+       void __iomem *uid = __io_address(U8500_BB_UID_BASE);
+
+       return kasprintf(GFP_KERNEL, "%08x%08x%08x%08x%08x",
+                        readl((u32 *)uid+1),
+                        readl((u32 *)uid+1), readl((u32 *)uid+2),
+                        readl((u32 *)uid+3), readl((u32 *)uid+4));
+}
+
+static struct device * __init db8500_soc_device_init(void)
+{
+       const char *soc_id = db8500_read_soc_id();
+
+       return ux500_soc_device_init(soc_id);
+}
+
 /*
  * This function is called from the board init
  */
-void __init u8500_init_devices(void)
+struct device * __init u8500_init_devices(void)
 {
-       db8500_add_rtc();
-       db8500_add_gpios();
-       db8500_add_usb(usb_db8500_rx_dma_cfg, usb_db8500_tx_dma_cfg);
+       struct device *parent;
+       int i;
+
+       parent = db8500_soc_device_init();
+
+       db8500_add_rtc(parent);
+       db8500_add_gpios(parent);
+       db8500_add_usb(parent, usb_db8500_rx_dma_cfg, usb_db8500_tx_dma_cfg);
+
+       platform_device_register_data(parent,
+               "cpufreq-u8500", -1, NULL, 0);
+
+       for (i = 0; i < ARRAY_SIZE(platform_devs); i++)
+               platform_devs[i]->dev.parent = parent;
 
-       platform_device_register_simple("cpufreq-u8500", -1, NULL, 0);
        platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs));
 
-       return ;
+       return parent;
 }
index 851308b..d11f389 100644 (file)
@@ -2,6 +2,7 @@
  * Copyright (C) ST-Ericsson SA 2010
  *
  * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
+ * Author: Lee Jones <lee.jones@linaro.org> for ST-Ericsson
  * License terms: GNU General Public License (GPL) version 2
  */
 
 #include <linux/mfd/db8500-prcmu.h>
 #include <linux/mfd/db5500-prcmu.h>
 #include <linux/clksrc-dbx500-prcmu.h>
+#include <linux/sys_soc.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/stat.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
 
 #include <asm/hardware/gic.h>
 #include <asm/mach/map.h>
 
 void __iomem *_PRCMU_BASE;
 
+static const struct of_device_id ux500_dt_irq_match[] = {
+       { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
+       {},
+};
+
 void __init ux500_init_irq(void)
 {
        void __iomem *dist_base;
@@ -37,7 +49,12 @@ void __init ux500_init_irq(void)
        } else
                ux500_unknown_soc();
 
-       gic_init(0, 29, dist_base, cpu_base);
+#ifdef CONFIG_OF
+       if (of_have_populated_dt())
+               of_irq_init(ux500_dt_irq_match);
+       else
+#endif
+               gic_init(0, 29, dist_base, cpu_base);
 
        /*
         * Init clocks here so that they are available for system timer
@@ -49,3 +66,73 @@ void __init ux500_init_irq(void)
                db8500_prcmu_early_init();
        clk_init();
 }
+
+static const char * __init ux500_get_machine(void)
+{
+       return kasprintf(GFP_KERNEL, "DB%4x", dbx500_partnumber());
+}
+
+static const char * __init ux500_get_family(void)
+{
+       return kasprintf(GFP_KERNEL, "ux500");
+}
+
+static const char * __init ux500_get_revision(void)
+{
+       unsigned int rev = dbx500_revision();
+
+       if (rev == 0x01)
+               return kasprintf(GFP_KERNEL, "%s", "ED");
+       else if (rev >= 0xA0)
+               return kasprintf(GFP_KERNEL, "%d.%d",
+                                (rev >> 4) - 0xA + 1, rev & 0xf);
+
+       return kasprintf(GFP_KERNEL, "%s", "Unknown");
+}
+
+static ssize_t ux500_get_process(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       if (dbx500_id.process == 0x00)
+               return sprintf(buf, "Standard\n");
+
+       return sprintf(buf, "%02xnm\n", dbx500_id.process);
+}
+
+static void __init soc_info_populate(struct soc_device_attribute *soc_dev_attr,
+                                    const char *soc_id)
+{
+       soc_dev_attr->soc_id   = soc_id;
+       soc_dev_attr->machine  = ux500_get_machine();
+       soc_dev_attr->family   = ux500_get_family();
+       soc_dev_attr->revision = ux500_get_revision();
+}
+
+struct device_attribute ux500_soc_attr =
+       __ATTR(process,  S_IRUGO, ux500_get_process,  NULL);
+
+struct device * __init ux500_soc_device_init(const char *soc_id)
+{
+       struct device *parent;
+       struct soc_device *soc_dev;
+       struct soc_device_attribute *soc_dev_attr;
+
+       soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
+       if (!soc_dev_attr)
+               return ERR_PTR(-ENOMEM);
+
+       soc_info_populate(soc_dev_attr, soc_id);
+
+       soc_dev = soc_device_register(soc_dev_attr);
+       if (IS_ERR_OR_NULL(soc_dev)) {
+               kfree(soc_dev_attr);
+               return NULL;
+       }
+
+       parent = soc_device_to_device(soc_dev);
+       if (!IS_ERR_OR_NULL(parent))
+               device_create_file(parent, &ux500_soc_attr);
+
+       return parent;
+}
index 898a645..c5312a4 100644 (file)
@@ -20,8 +20,9 @@
 #include "devices-common.h"
 
 struct amba_device *
-dbx500_add_amba_device(const char *name, resource_size_t base,
-                      int irq, void *pdata, unsigned int periphid)
+dbx500_add_amba_device(struct device *parent, const char *name,
+                      resource_size_t base, int irq, void *pdata,
+                      unsigned int periphid)
 {
        struct amba_device *dev;
        int ret;
@@ -39,6 +40,8 @@ dbx500_add_amba_device(const char *name, resource_size_t base,
 
        dev->dev.platform_data = pdata;
 
+       dev->dev.parent = parent;
+
        ret = amba_device_add(dev, &iomem_resource);
        if (ret) {
                amba_device_put(dev);
@@ -49,60 +52,7 @@ dbx500_add_amba_device(const char *name, resource_size_t base,
 }
 
 static struct platform_device *
-dbx500_add_platform_device(const char *name, int id, void *pdata,
-                          struct resource *res, int resnum)
-{
-       struct platform_device *dev;
-       int ret;
-
-       dev = platform_device_alloc(name, id);
-       if (!dev)
-               return ERR_PTR(-ENOMEM);
-
-       dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
-       dev->dev.dma_mask = &dev->dev.coherent_dma_mask;
-
-       ret = platform_device_add_resources(dev, res, resnum);
-       if (ret)
-               goto out_free;
-
-       dev->dev.platform_data = pdata;
-
-       ret = platform_device_add(dev);
-       if (ret)
-               goto out_free;
-
-       return dev;
-
-out_free:
-       platform_device_put(dev);
-       return ERR_PTR(ret);
-}
-
-struct platform_device *
-dbx500_add_platform_device_4k1irq(const char *name, int id,
-                                 resource_size_t base,
-                                 int irq, void *pdata)
-{
-       struct resource resources[] = {
-               [0] = {
-                       .start  = base,
-                       .end    = base + SZ_4K - 1,
-                       .flags  = IORESOURCE_MEM,
-               },
-               [1] = {
-                       .start  = irq,
-                       .end    = irq,
-                       .flags  = IORESOURCE_IRQ,
-               }
-       };
-
-       return dbx500_add_platform_device(name, id, pdata, resources,
-                                         ARRAY_SIZE(resources));
-}
-
-static struct platform_device *
-dbx500_add_gpio(int id, resource_size_t addr, int irq,
+dbx500_add_gpio(struct device *parent, int id, resource_size_t addr, int irq,
                struct nmk_gpio_platform_data *pdata)
 {
        struct resource resources[] = {
@@ -118,13 +68,18 @@ dbx500_add_gpio(int id, resource_size_t addr, int irq,
                }
        };
 
-       return platform_device_register_resndata(NULL, "gpio", id,
-                               resources, ARRAY_SIZE(resources),
-                               pdata, sizeof(*pdata));
+       return platform_device_register_resndata(
+               parent,
+               "gpio",
+               id,
+               resources,
+               ARRAY_SIZE(resources),
+               pdata,
+               sizeof(*pdata));
 }
 
-void dbx500_add_gpios(resource_size_t *base, int num, int irq,
-                     struct nmk_gpio_platform_data *pdata)
+void dbx500_add_gpios(struct device *parent, resource_size_t *base, int num,
+                     int irq, struct nmk_gpio_platform_data *pdata)
 {
        int first = 0;
        int i;
@@ -134,6 +89,6 @@ void dbx500_add_gpios(resource_size_t *base, int num, int irq,
                pdata->first_irq = NOMADIK_GPIO_TO_IRQ(first);
                pdata->num_gpio = 32;
 
-               dbx500_add_gpio(i, base[i], irq, pdata);
+               dbx500_add_gpio(parent, i, base[i], irq, pdata);
        }
 }
index 7825705..39c74ec 100644 (file)
@@ -8,80 +8,89 @@
 #ifndef __DEVICES_COMMON_H
 #define __DEVICES_COMMON_H
 
-extern struct amba_device *
-dbx500_add_amba_device(const char *name, resource_size_t base,
-                      int irq, void *pdata, unsigned int periphid);
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/sys_soc.h>
+#include <plat/i2c.h>
 
-extern struct platform_device *
-dbx500_add_platform_device_4k1irq(const char *name, int id,
-                                 resource_size_t base,
-                                 int irq, void *pdata);
+extern struct amba_device *
+dbx500_add_amba_device(struct device *parent, const char *name,
+                      resource_size_t base, int irq, void *pdata,
+                      unsigned int periphid);
 
 struct spi_master_cntlr;
 
 static inline struct amba_device *
-dbx500_add_msp_spi(const char *name, resource_size_t base, int irq,
+dbx500_add_msp_spi(struct device *parent, const char *name,
+                  resource_size_t base, int irq,
                   struct spi_master_cntlr *pdata)
 {
-       return dbx500_add_amba_device(name, base, irq, pdata, 0);
+       return dbx500_add_amba_device(parent, name, base, irq,
+                                     pdata, 0);
 }
 
 static inline struct amba_device *
-dbx500_add_spi(const char *name, resource_size_t base, int irq,
-              struct spi_master_cntlr *pdata,
+dbx500_add_spi(struct device *parent, const char *name, resource_size_t base,
+              int irq, struct spi_master_cntlr *pdata,
               u32 periphid)
 {
-       return dbx500_add_amba_device(name, base, irq, pdata, periphid);
+       return dbx500_add_amba_device(parent, name, base, irq,
+                                     pdata, periphid);
 }
 
 struct mmci_platform_data;
 
 static inline struct amba_device *
-dbx500_add_sdi(const char *name, resource_size_t base, int irq,
-              struct mmci_platform_data *pdata,
-              u32 periphid)
+dbx500_add_sdi(struct device *parent, const char *name, resource_size_t base,
+              int irq, struct mmci_platform_data *pdata, u32 periphid)
 {
-       return dbx500_add_amba_device(name, base, irq, pdata, periphid);
+       return dbx500_add_amba_device(parent, name, base, irq,
+                                     pdata, periphid);
 }
 
 struct amba_pl011_data;
 
 static inline struct amba_device *
-dbx500_add_uart(const char *name, resource_size_t base, int irq,
-               struct amba_pl011_data *pdata)
+dbx500_add_uart(struct device *parent, const char *name, resource_size_t base,
+               int irq, struct amba_pl011_data *pdata)
 {
-       return dbx500_add_amba_device(name, base, irq, pdata, 0);
+       return dbx500_add_amba_device(parent, name, base, irq, pdata, 0);
 }
 
 struct nmk_i2c_controller;
 
 static inline struct platform_device *
-dbx500_add_i2c(int id, resource_size_t base, int irq,
-              struct nmk_i2c_controller *pdata)
-{
-       return dbx500_add_platform_device_4k1irq("nmk-i2c", id, base, irq,
-                                                pdata);
-}
-
-struct msp_i2s_platform_data;
-
-static inline struct platform_device *
-dbx500_add_msp_i2s(int id, resource_size_t base, int irq,
-                  struct msp_i2s_platform_data *pdata)
+dbx500_add_i2c(struct device *parent, int id, resource_size_t base, int irq,
+              struct nmk_i2c_controller *data)
 {
-       return dbx500_add_platform_device_4k1irq("MSP_I2S", id, base, irq,
-                                                pdata);
+       struct resource res[] = {
+               DEFINE_RES_MEM(base, SZ_4K),
+               DEFINE_RES_IRQ(irq),
+       };
+
+       struct platform_device_info pdevinfo = {
+               .parent = parent,
+               .name = "nmk-i2c",
+               .id = id,
+               .res = res,
+               .num_res = ARRAY_SIZE(res),
+               .data = data,
+               .size_data = sizeof(*data),
+               .dma_mask = DMA_BIT_MASK(32),
+       };
+
+       return platform_device_register_full(&pdevinfo);
 }
 
 static inline struct amba_device *
-dbx500_add_rtc(resource_size_t base, int irq)
+dbx500_add_rtc(struct device *parent, resource_size_t base, int irq)
 {
-       return dbx500_add_amba_device("rtc-pl031", base, irq, NULL, 0);
+       return dbx500_add_amba_device(parent, "rtc-pl031", base, irq, NULL, 0);
 }
 
 struct nmk_gpio_platform_data;
 
-void dbx500_add_gpios(resource_size_t *base, int num, int irq,
-                     struct nmk_gpio_platform_data *pdata);
+void dbx500_add_gpios(struct device *parent, resource_size_t *base, int num,
+                     int irq, struct nmk_gpio_platform_data *pdata);
 
 #endif
index 0c4bccd..e709555 100644 (file)
 
 #include "devices-common.h"
 
-#define db5500_add_i2c1(pdata) \
-       dbx500_add_i2c(1, U5500_I2C1_BASE, IRQ_DB5500_I2C1, pdata)
-#define db5500_add_i2c2(pdata) \
-       dbx500_add_i2c(2, U5500_I2C2_BASE, IRQ_DB5500_I2C2, pdata)
-#define db5500_add_i2c3(pdata) \
-       dbx500_add_i2c(3, U5500_I2C3_BASE, IRQ_DB5500_I2C3, pdata)
+#define db5500_add_i2c1(parent, pdata) \
+       dbx500_add_i2c(parent, 1, U5500_I2C1_BASE, IRQ_DB5500_I2C1, pdata)
+#define db5500_add_i2c2(parent, pdata) \
+       dbx500_add_i2c(parent, 2, U5500_I2C2_BASE, IRQ_DB5500_I2C2, pdata)
+#define db5500_add_i2c3(parent, pdata) \
+       dbx500_add_i2c(parent, 3, U5500_I2C3_BASE, IRQ_DB5500_I2C3, pdata)
 
-#define db5500_add_msp0_i2s(pdata) \
-       dbx500_add_msp_i2s(0, U5500_MSP0_BASE, IRQ_DB5500_MSP0, pdata)
-#define db5500_add_msp1_i2s(pdata) \
-       dbx500_add_msp_i2s(1, U5500_MSP1_BASE, IRQ_DB5500_MSP1, pdata)
-#define db5500_add_msp2_i2s(pdata) \
-       dbx500_add_msp_i2s(2, U5500_MSP2_BASE, IRQ_DB5500_MSP2, pdata)
+#define db5500_add_msp0_spi(parent, pdata) \
+       dbx500_add_msp_spi(parent, "msp0", U5500_MSP0_BASE, \
+                          IRQ_DB5500_MSP0, pdata)
+#define db5500_add_msp1_spi(parent, pdata) \
+       dbx500_add_msp_spi(parent, "msp1", U5500_MSP1_BASE, \
+                          IRQ_DB5500_MSP1, pdata)
+#define db5500_add_msp2_spi(parent, pdata) \
+       dbx500_add_msp_spi(parent, "msp2", U5500_MSP2_BASE, \
+                          IRQ_DB5500_MSP2, pdata)
 
-#define db5500_add_msp0_spi(pdata) \
-       dbx500_add_msp_spi("msp0", U5500_MSP0_BASE, IRQ_DB5500_MSP0, pdata)
-#define db5500_add_msp1_spi(pdata) \
-       dbx500_add_msp_spi("msp1", U5500_MSP1_BASE, IRQ_DB5500_MSP1, pdata)
-#define db5500_add_msp2_spi(pdata) \
-       dbx500_add_msp_spi("msp2", U5500_MSP2_BASE, IRQ_DB5500_MSP2, pdata)
+#define db5500_add_msp0_spi(parent, pdata) \
+       dbx500_add_msp_spi(parent, "msp0", U5500_MSP0_BASE, \
+                         IRQ_DB5500_MSP0, pdata)
+#define db5500_add_msp1_spi(parent, pdata) \
+       dbx500_add_msp_spi(parent, "msp1", U5500_MSP1_BASE, \
+                         IRQ_DB5500_MSP1, pdata)
+#define db5500_add_msp2_spi(parent, pdata) \
+       dbx500_add_msp_spi(parent, "msp2", U5500_MSP2_BASE, \
+                         IRQ_DB5500_MSP2, pdata)
 
-#define db5500_add_rtc() \
-       dbx500_add_rtc(U5500_RTC_BASE, IRQ_DB5500_RTC);
+#define db5500_add_rtc(parent) \
+       dbx500_add_rtc(parent, U5500_RTC_BASE, IRQ_DB5500_RTC);
 
-#define db5500_add_usb(rx_cfg, tx_cfg) \
-       ux500_add_usb(U5500_USBOTG_BASE, IRQ_DB5500_USBOTG, rx_cfg, tx_cfg)
+#define db5500_add_usb(parent, rx_cfg, tx_cfg) \
+       ux500_add_usb(parent, U5500_USBOTG_BASE, \
+                     IRQ_DB5500_USBOTG, rx_cfg, tx_cfg)
 
-#define db5500_add_sdi0(pdata) \
-       dbx500_add_sdi("sdi0", U5500_SDI0_BASE, IRQ_DB5500_SDMMC0, pdata, \
+#define db5500_add_sdi0(parent, pdata) \
+       dbx500_add_sdi(parent, "sdi0", U5500_SDI0_BASE, \
+                      IRQ_DB5500_SDMMC0, pdata,        \
                       0x10480180)
-#define db5500_add_sdi1(pdata) \
-       dbx500_add_sdi("sdi1", U5500_SDI1_BASE, IRQ_DB5500_SDMMC1, pdata, \
+#define db5500_add_sdi1(parent, pdata) \
+       dbx500_add_sdi(parent, "sdi1", U5500_SDI1_BASE, \
+                      IRQ_DB5500_SDMMC1, pdata,        \
                       0x10480180)
-#define db5500_add_sdi2(pdata) \
-       dbx500_add_sdi("sdi2", U5500_SDI2_BASE, IRQ_DB5500_SDMMC2, pdata \
+#define db5500_add_sdi2(parent, pdata) \
+       dbx500_add_sdi(parent, "sdi2", U5500_SDI2_BASE, \
+                      IRQ_DB5500_SDMMC2, pdata         \
                       0x10480180)
-#define db5500_add_sdi3(pdata) \
-       dbx500_add_sdi("sdi3", U5500_SDI3_BASE, IRQ_DB5500_SDMMC3, pdata \
+#define db5500_add_sdi3(parent, pdata) \
+       dbx500_add_sdi(parent, "sdi3", U5500_SDI3_BASE, \
+                      IRQ_DB5500_SDMMC3, pdata         \
                       0x10480180)
-#define db5500_add_sdi4(pdata) \
-       dbx500_add_sdi("sdi4", U5500_SDI4_BASE, IRQ_DB5500_SDMMC4, pdata \
+#define db5500_add_sdi4(parent, pdata) \
+       dbx500_add_sdi(parent, "sdi4", U5500_SDI4_BASE, \
+                      IRQ_DB5500_SDMMC4, pdata         \
                       0x10480180)
 
 /* This one has a bad peripheral ID in the U5500 silicon */
-#define db5500_add_spi0(pdata) \
-       dbx500_add_spi("spi0", U5500_SPI0_BASE, IRQ_DB5500_SPI0, pdata, \
+#define db5500_add_spi0(parent, pdata) \
+       dbx500_add_spi(parent, "spi0", U5500_SPI0_BASE, \
+                      IRQ_DB5500_SPI0, pdata,          \
                       0x10080023)
-#define db5500_add_spi1(pdata) \
-       dbx500_add_spi("spi1", U5500_SPI1_BASE, IRQ_DB5500_SPI1, pdata, \
+#define db5500_add_spi1(parent, pdata) \
+       dbx500_add_spi(parent, "spi1", U5500_SPI1_BASE, \
+                      IRQ_DB5500_SPI1, pdata,          \
                       0x10080023)
-#define db5500_add_spi2(pdata) \
-       dbx500_add_spi("spi2", U5500_SPI2_BASE, IRQ_DB5500_SPI2, pdata \
+#define db5500_add_spi2(parent, pdata) \
+       dbx500_add_spi(parent, "spi2", U5500_SPI2_BASE, \
+                      IRQ_DB5500_SPI2, pdata           \
                       0x10080023)
-#define db5500_add_spi3(pdata) \
-       dbx500_add_spi("spi3", U5500_SPI3_BASE, IRQ_DB5500_SPI3, pdata \
+#define db5500_add_spi3(parent, pdata) \
+       dbx500_add_spi(parent, "spi3", U5500_SPI3_BASE, \
+                      IRQ_DB5500_SPI3, pdata           \
                       0x10080023)
 
-#define db5500_add_uart0(plat) \
-       dbx500_add_uart("uart0", U5500_UART0_BASE, IRQ_DB5500_UART0, plat)
-#define db5500_add_uart1(plat) \
-       dbx500_add_uart("uart1", U5500_UART1_BASE, IRQ_DB5500_UART1, plat)
-#define db5500_add_uart2(plat) \
-       dbx500_add_uart("uart2", U5500_UART2_BASE, IRQ_DB5500_UART2, plat)
-#define db5500_add_uart3(plat) \
-       dbx500_add_uart("uart3", U5500_UART3_BASE, IRQ_DB5500_UART3, plat)
+#define db5500_add_uart0(parent, plat) \
+       dbx500_add_uart(parent, "uart0", U5500_UART0_BASE, \
+                       IRQ_DB5500_UART0, plat)
+#define db5500_add_uart1(parent, plat) \
+       dbx500_add_uart(parent, "uart1", U5500_UART1_BASE, \
+                       IRQ_DB5500_UART1, plat)
+#define db5500_add_uart2(parent, plat) \
+       dbx500_add_uart(parent, "uart2", U5500_UART2_BASE, \
+                       IRQ_DB5500_UART2, plat)
+#define db5500_add_uart3(parent, plat) \
+       dbx500_add_uart(parent, "uart3", U5500_UART3_BASE, \
+                       IRQ_DB5500_UART3, plat)
 
 #endif
index cbd4a9a..9fd93e9 100644 (file)
@@ -14,88 +14,114 @@ struct ske_keypad_platform_data;
 struct pl022_ssp_controller;
 
 static inline struct platform_device *
-db8500_add_ske_keypad(struct ske_keypad_platform_data *pdata)
+db8500_add_ske_keypad(struct device *parent,
+                     struct ske_keypad_platform_data *pdata,
+                     size_t size)
 {
-       return dbx500_add_platform_device_4k1irq("nmk-ske-keypad", -1,
-                                                U8500_SKE_BASE,
-                                                IRQ_DB8500_KB, pdata);
+       struct resource resources[] = {
+               DEFINE_RES_MEM(U8500_SKE_BASE, SZ_4K),
+               DEFINE_RES_IRQ(IRQ_DB8500_KB),
+       };
+
+       return platform_device_register_resndata(parent, "nmk-ske-keypad", -1,
+                                                resources, 2, pdata, size);
 }
 
 static inline struct amba_device *
-db8500_add_ssp(const char *name, resource_size_t base, int irq,
-              struct pl022_ssp_controller *pdata)
+db8500_add_ssp(struct device *parent, const char *name, resource_size_t base,
+              int irq, struct pl022_ssp_controller *pdata)
 {
-       return dbx500_add_amba_device(name, base, irq, pdata, 0);
+       return dbx500_add_amba_device(parent, name, base, irq, pdata, 0);
 }
 
 
-#define db8500_add_i2c0(pdata) \
-       dbx500_add_i2c(0, U8500_I2C0_BASE, IRQ_DB8500_I2C0, pdata)
-#define db8500_add_i2c1(pdata) \
-       dbx500_add_i2c(1, U8500_I2C1_BASE, IRQ_DB8500_I2C1, pdata)
-#define db8500_add_i2c2(pdata) \
-       dbx500_add_i2c(2, U8500_I2C2_BASE, IRQ_DB8500_I2C2, pdata)
-#define db8500_add_i2c3(pdata) \
-       dbx500_add_i2c(3, U8500_I2C3_BASE, IRQ_DB8500_I2C3, pdata)
-#define db8500_add_i2c4(pdata) \
-       dbx500_add_i2c(4, U8500_I2C4_BASE, IRQ_DB8500_I2C4, pdata)
-
-#define db8500_add_msp0_i2s(pdata) \
-       dbx500_add_msp_i2s(0, U8500_MSP0_BASE, IRQ_DB8500_MSP0, pdata)
-#define db8500_add_msp1_i2s(pdata) \
-       dbx500_add_msp_i2s(1, U8500_MSP1_BASE, IRQ_DB8500_MSP1, pdata)
-#define db8500_add_msp2_i2s(pdata) \
-       dbx500_add_msp_i2s(2, U8500_MSP2_BASE, IRQ_DB8500_MSP2, pdata)
-#define db8500_add_msp3_i2s(pdata) \
-       dbx500_add_msp_i2s(3, U8500_MSP3_BASE, IRQ_DB8500_MSP1, pdata)
-
-#define db8500_add_msp0_spi(pdata) \
-       dbx500_add_msp_spi("msp0", U8500_MSP0_BASE, IRQ_DB8500_MSP0, pdata)
-#define db8500_add_msp1_spi(pdata) \
-       dbx500_add_msp_spi("msp1", U8500_MSP1_BASE, IRQ_DB8500_MSP1, pdata)
-#define db8500_add_msp2_spi(pdata) \
-       dbx500_add_msp_spi("msp2", U8500_MSP2_BASE, IRQ_DB8500_MSP2, pdata)
-#define db8500_add_msp3_spi(pdata) \
-       dbx500_add_msp_spi("msp3", U8500_MSP3_BASE, IRQ_DB8500_MSP1, pdata)
-
-#define db8500_add_rtc() \
-       dbx500_add_rtc(U8500_RTC_BASE, IRQ_DB8500_RTC);
-
-#define db8500_add_usb(rx_cfg, tx_cfg) \
-       ux500_add_usb(U8500_USBOTG_BASE, IRQ_DB8500_USBOTG, rx_cfg, tx_cfg)
-
-#define db8500_add_sdi0(pdata, pid) \
-       dbx500_add_sdi("sdi0", U8500_SDI0_BASE, IRQ_DB8500_SDMMC0, pdata, pid)
-#define db8500_add_sdi1(pdata, pid) \
-       dbx500_add_sdi("sdi1", U8500_SDI1_BASE, IRQ_DB8500_SDMMC1, pdata, pid)
-#define db8500_add_sdi2(pdata, pid) \
-       dbx500_add_sdi("sdi2", U8500_SDI2_BASE, IRQ_DB8500_SDMMC2, pdata, pid)
-#define db8500_add_sdi3(pdata, pid) \
-       dbx500_add_sdi("sdi3", U8500_SDI3_BASE, IRQ_DB8500_SDMMC3, pdata, pid)
-#define db8500_add_sdi4(pdata, pid) \
-       dbx500_add_sdi("sdi4", U8500_SDI4_BASE, IRQ_DB8500_SDMMC4, pdata, pid)
-#define db8500_add_sdi5(pdata, pid) \
-       dbx500_add_sdi("sdi5", U8500_SDI5_BASE, IRQ_DB8500_SDMMC5, pdata, pid)
-
-#define db8500_add_ssp0(pdata) \
-       db8500_add_ssp("ssp0", U8500_SSP0_BASE, IRQ_DB8500_SSP0, pdata)
-#define db8500_add_ssp1(pdata) \
-       db8500_add_ssp("ssp1", U8500_SSP1_BASE, IRQ_DB8500_SSP1, pdata)
-
-#define db8500_add_spi0(pdata) \
-       dbx500_add_spi("spi0", U8500_SPI0_BASE, IRQ_DB8500_SPI0, pdata, 0)
-#define db8500_add_spi1(pdata) \
-       dbx500_add_spi("spi1", U8500_SPI1_BASE, IRQ_DB8500_SPI1, pdata, 0)
-#define db8500_add_spi2(pdata) \
-       dbx500_add_spi("spi2", U8500_SPI2_BASE, IRQ_DB8500_SPI2, pdata, 0)
-#define db8500_add_spi3(pdata) \
-       dbx500_add_spi("spi3", U8500_SPI3_BASE, IRQ_DB8500_SPI3, pdata, 0)
-
-#define db8500_add_uart0(pdata) \
-       dbx500_add_uart("uart0", U8500_UART0_BASE, IRQ_DB8500_UART0, pdata)
-#define db8500_add_uart1(pdata) \
-       dbx500_add_uart("uart1", U8500_UART1_BASE, IRQ_DB8500_UART1, pdata)
-#define db8500_add_uart2(pdata) \
-       dbx500_add_uart("uart2", U8500_UART2_BASE, IRQ_DB8500_UART2, pdata)
+#define db8500_add_i2c0(parent, pdata) \
+       dbx500_add_i2c(parent, 0, U8500_I2C0_BASE, IRQ_DB8500_I2C0, pdata)
+#define db8500_add_i2c1(parent, pdata) \
+       dbx500_add_i2c(parent, 1, U8500_I2C1_BASE, IRQ_DB8500_I2C1, pdata)
+#define db8500_add_i2c2(parent, pdata) \
+       dbx500_add_i2c(parent, 2, U8500_I2C2_BASE, IRQ_DB8500_I2C2, pdata)
+#define db8500_add_i2c3(parent, pdata) \
+       dbx500_add_i2c(parent, 3, U8500_I2C3_BASE, IRQ_DB8500_I2C3, pdata)
+#define db8500_add_i2c4(parent, pdata) \
+       dbx500_add_i2c(parent, 4, U8500_I2C4_BASE, IRQ_DB8500_I2C4, pdata)
+
+#define db8500_add_msp0_i2s(parent, pdata) \
+       dbx500_add_msp_i2s(parent, 0, U8500_MSP0_BASE, IRQ_DB8500_MSP0, pdata)
+#define db8500_add_msp1_i2s(parent, pdata) \
+       dbx500_add_msp_i2s(parent, 1, U8500_MSP1_BASE, IRQ_DB8500_MSP1, pdata)
+#define db8500_add_msp2_i2s(parent, pdata) \
+       dbx500_add_msp_i2s(parent, 2, U8500_MSP2_BASE, IRQ_DB8500_MSP2, pdata)
+#define db8500_add_msp3_i2s(parent, pdata) \
+       dbx500_add_msp_i2s(parent, 3, U8500_MSP3_BASE, IRQ_DB8500_MSP1, pdata)
+
+#define db8500_add_msp0_spi(parent, pdata) \
+       dbx500_add_msp_spi(parent, "msp0", U8500_MSP0_BASE, \
+                          IRQ_DB8500_MSP0, pdata)
+#define db8500_add_msp1_spi(parent, pdata) \
+       dbx500_add_msp_spi(parent, "msp1", U8500_MSP1_BASE, \
+                          IRQ_DB8500_MSP1, pdata)
+#define db8500_add_msp2_spi(parent, pdata) \
+       dbx500_add_msp_spi(parent, "msp2", U8500_MSP2_BASE, \
+                          IRQ_DB8500_MSP2, pdata)
+#define db8500_add_msp3_spi(parent, pdata) \
+       dbx500_add_msp_spi(parent, "msp3", U8500_MSP3_BASE, \
+                          IRQ_DB8500_MSP1, pdata)
+
+#define db8500_add_rtc(parent) \
+       dbx500_add_rtc(parent, U8500_RTC_BASE, IRQ_DB8500_RTC);
+
+#define db8500_add_usb(parent, rx_cfg, tx_cfg) \
+       ux500_add_usb(parent, U8500_USBOTG_BASE, \
+                     IRQ_DB8500_USBOTG, rx_cfg, tx_cfg)
+
+#define db8500_add_sdi0(parent, pdata, pid) \
+       dbx500_add_sdi(parent, "sdi0", U8500_SDI0_BASE, \
+                      IRQ_DB8500_SDMMC0, pdata, pid)
+#define db8500_add_sdi1(parent, pdata, pid) \
+       dbx500_add_sdi(parent, "sdi1", U8500_SDI1_BASE, \
+                      IRQ_DB8500_SDMMC1, pdata, pid)
+#define db8500_add_sdi2(parent, pdata, pid) \
+       dbx500_add_sdi(parent, "sdi2", U8500_SDI2_BASE, \
+                      IRQ_DB8500_SDMMC2, pdata, pid)
+#define db8500_add_sdi3(parent, pdata, pid) \
+       dbx500_add_sdi(parent, "sdi3", U8500_SDI3_BASE, \
+                      IRQ_DB8500_SDMMC3, pdata, pid)
+#define db8500_add_sdi4(parent, pdata, pid) \
+       dbx500_add_sdi(parent, "sdi4", U8500_SDI4_BASE, \
+                      IRQ_DB8500_SDMMC4, pdata, pid)
+#define db8500_add_sdi5(parent, pdata, pid) \
+       dbx500_add_sdi(parent, "sdi5", U8500_SDI5_BASE, \
+                      IRQ_DB8500_SDMMC5, pdata, pid)
+
+#define db8500_add_ssp0(parent, pdata) \
+       db8500_add_ssp(parent, "ssp0", U8500_SSP0_BASE, \
+                      IRQ_DB8500_SSP0, pdata)
+#define db8500_add_ssp1(parent, pdata) \
+       db8500_add_ssp(parent, "ssp1", U8500_SSP1_BASE, \
+                      IRQ_DB8500_SSP1, pdata)
+
+#define db8500_add_spi0(parent, pdata) \
+       dbx500_add_spi(parent, "spi0", U8500_SPI0_BASE, \
+                      IRQ_DB8500_SPI0, pdata, 0)
+#define db8500_add_spi1(parent, pdata) \
+       dbx500_add_spi(parent, "spi1", U8500_SPI1_BASE, \
+                      IRQ_DB8500_SPI1, pdata, 0)
+#define db8500_add_spi2(parent, pdata) \
+       dbx500_add_spi(parent, "spi2", U8500_SPI2_BASE, \
+                      IRQ_DB8500_SPI2, pdata, 0)
+#define db8500_add_spi3(parent, pdata) \
+       dbx500_add_spi(parent, "spi3", U8500_SPI3_BASE, \
+                      IRQ_DB8500_SPI3, pdata, 0)
+
+#define db8500_add_uart0(parent, pdata) \
+       dbx500_add_uart(parent, "uart0", U8500_UART0_BASE, \
+                       IRQ_DB8500_UART0, pdata)
+#define db8500_add_uart1(parent, pdata) \
+       dbx500_add_uart(parent, "uart1", U8500_UART1_BASE, \
+                       IRQ_DB8500_UART1, pdata)
+#define db8500_add_uart2(parent, pdata) \
+       dbx500_add_uart(parent, "uart2", U8500_UART2_BASE, \
+                       IRQ_DB8500_UART2, pdata)
 
 #endif
index 1cfab68..41e9470 100644 (file)
@@ -125,10 +125,11 @@ static struct platform_device dma40_device = {
        .resource       = dma40_resources
 };
 
-void __init db5500_dma_init(void)
+void __init db5500_dma_init(struct device *parent)
 {
        int ret;
 
+       dma40_device.dev.parent = parent;
        ret = platform_device_register(&dma40_device);
        if (ret)
                dev_err(&dma40_device.dev, "unable to register device: %d\n", ret);
index 80e10f5..9ec20b9 100644 (file)
 #define U8500_MODEM_BASE       0xe000000
 #define U8500_APE_BASE         0x6000000
 
+/* SoC identification number information */
+#define U8500_BB_UID_BASE      (U8500_BACKUPRAM1_BASE + 0xFC0)
+
 #endif
index d2d4131..7d34c52 100644 (file)
@@ -13,7 +13,7 @@
 
 #define MOP500_AB8500_IRQ_BASE         IRQ_BOARD_START
 #define MOP500_AB8500_IRQ_END          (MOP500_AB8500_IRQ_BASE \
-                                        + AB8500_NR_IRQS)
+                                        + AB8500_MAX_NR_IRQS)
 
 /* TC35892 */
 #define TC35892_NR_INTERNAL_IRQS       8
index 93d4039..3dc00ff 100644 (file)
@@ -18,14 +18,16 @@ void __init ux500_map_io(void);
 extern void __init u5500_map_io(void);
 extern void __init u8500_map_io(void);
 
-extern void __init u5500_init_devices(void);
-extern void __init u8500_init_devices(void);
+extern struct device * __init u5500_init_devices(void);
+extern struct device * __init u8500_init_devices(void);
 
 extern void __init ux500_init_irq(void);
 
-extern void __init u5500_sdi_init(void);
+extern void __init u5500_sdi_init(struct device *parent);
 
-extern void __init db5500_dma_init(void);
+extern void __init db5500_dma_init(struct device *parent);
+
+extern struct device *ux500_soc_device_init(const char *soc_id);
 
 struct amba_device;
 extern void __init amba_add_devices(struct amba_device *devs[], int num);
index d3739d4..4c1cc50 100644 (file)
@@ -20,6 +20,6 @@ struct ux500_musb_board_data {
        bool (*dma_filter)(struct dma_chan *chan, void *filter_param);
 };
 
-void ux500_add_usb(resource_size_t base, int irq, int *dma_rx_cfg,
-       int *dma_tx_cfg);
+void ux500_add_usb(struct device *parent, resource_size_t base,
+                  int irq, int *dma_rx_cfg, int *dma_tx_cfg);
 #endif
index e9d5807..d37df98 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/io.h>
 #include <linux/errno.h>
 #include <linux/clksrc-dbx500-prcmu.h>
+#include <linux/of.h>
 
 #include <asm/smp_twd.h>
 
@@ -30,9 +31,13 @@ static void __init ux500_twd_init(void)
        twd_local_timer = cpu_is_u5500() ? &u5500_twd_local_timer :
                                           &u8500_twd_local_timer;
 
-       err = twd_local_timer_register(twd_local_timer);
-       if (err)
-               pr_err("twd_local_timer_register failed %d\n", err);
+       if (of_have_populated_dt())
+               twd_local_timer_of_register();
+       else {
+               err = twd_local_timer_register(twd_local_timer);
+               if (err)
+                       pr_err("twd_local_timer_register failed %d\n", err);
+       }
 }
 #else
 #define ux500_twd_init()       do { } while(0)
index 9f9e1c2..a74af38 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/platform_device.h>
 #include <linux/usb/musb.h>
 #include <linux/dma-mapping.h>
+
 #include <plat/ste_dma40.h>
 #include <mach/hardware.h>
 #include <mach/usb.h>
@@ -140,8 +141,8 @@ static inline void ux500_usb_dma_update_tx_ch_config(int *dst_dev_type)
                musb_dma_tx_ch[idx].dst_dev_type = dst_dev_type[idx];
 }
 
-void ux500_add_usb(resource_size_t base, int irq, int *dma_rx_cfg,
-       int *dma_tx_cfg)
+void ux500_add_usb(struct device *parent, resource_size_t base, int irq,
+                  int *dma_rx_cfg, int *dma_tx_cfg)
 {
        ux500_musb_device.resource[0].start = base;
        ux500_musb_device.resource[0].end = base + SZ_64K - 1;
@@ -151,5 +152,7 @@ void ux500_add_usb(resource_size_t base, int irq, int *dma_rx_cfg,
        ux500_usb_dma_update_rx_ch_config(dma_rx_cfg);
        ux500_usb_dma_update_tx_ch_config(dma_tx_cfg);
 
+       ux500_musb_device.dev.parent = parent;
+
        platform_device_register(&ux500_musb_device);
 }
index 0968772..6bbd74e 100644 (file)
@@ -36,7 +36,6 @@
 #include <linux/clkdev.h>
 #include <linux/mtd/physmap.h>
 
-#include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/leds.h>
 #include <asm/hardware/arm_timer.h>
index 51733b0..a6e23f4 100644 (file)
@@ -24,7 +24,6 @@
 
 #include <mach/hardware.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/mach/pci.h>
 
 /*
index 3034a4d..c504a72 100644 (file)
@@ -14,7 +14,7 @@
 
 #include <asm/cacheflush.h>
 #include <asm/smp_plat.h>
-#include <asm/system.h>
+#include <asm/cp15.h>
 
 extern volatile int pen_release;
 
index 9a06619..9e4dd8b 100644 (file)
@@ -28,6 +28,7 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 #include <asm/irq.h>
+#include <asm/system_misc.h>
 
 #include <mach/hardware.h>
 #include <mach/regs-serial.h>
index caf14dc..9107231 100644 (file)
@@ -22,7 +22,8 @@
 #include <linux/sched.h>
 #include <linux/uaccess.h>
 
-#include <asm/system.h>
+#include <asm/cp15.h>
+#include <asm/system_info.h>
 #include <asm/unaligned.h>
 
 #include "fault.h"
index e0b0e7a..dd3d591 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/init.h>
 #include <linux/highmem.h>
 #include <asm/cacheflush.h>
+#include <asm/cp15.h>
 #include <plat/cache-feroceon-l2.h>
 
 /*
index 5086865..1fbca05 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <linux/init.h>
 #include <asm/cacheflush.h>
+#include <asm/cp15.h>
 #include <asm/hardware/cache-tauros2.h>
 
 
index 5a32020..6c3edeb 100644 (file)
@@ -18,7 +18,7 @@
  */
 #include <linux/init.h>
 #include <linux/highmem.h>
-#include <asm/system.h>
+#include <asm/cp15.h>
 #include <asm/cputype.h>
 #include <asm/cacheflush.h>
 
index bb7eac3..5bdff5c 100644 (file)
@@ -21,8 +21,9 @@
 #include <linux/perf_event.h>
 
 #include <asm/exception.h>
-#include <asm/system.h>
 #include <asm/pgtable.h>
+#include <asm/system_misc.h>
+#include <asm/system_info.h>
 #include <asm/tlbflush.h>
 
 #include "fault.h"
index 1a8d4aa..062d61a 100644 (file)
@@ -16,7 +16,6 @@
 #include <asm/cachetype.h>
 #include <asm/highmem.h>
 #include <asm/smp_plat.h>
-#include <asm/system.h>
 #include <asm/tlbflush.h>
 
 #include "mm.h"
index feacf4c..ab88ed4 100644 (file)
@@ -5,6 +5,7 @@
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
 #include <asm/sections.h>
+#include <asm/system_info.h>
 
 pgd_t *idmap_pgd;
 
index 80632e8..6780b49 100644 (file)
 #include <linux/vmalloc.h>
 #include <linux/io.h>
 
+#include <asm/cp15.h>
 #include <asm/cputype.h>
 #include <asm/cacheflush.h>
 #include <asm/mmu_context.h>
 #include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
 #include <asm/sizes.h>
+#include <asm/system_info.h>
 
 #include <asm/mach/map.h>
 #include "mm.h"
index 94c5a0c..cd439c1 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/fs.h>
 #include <linux/vmalloc.h>
 
+#include <asm/cp15.h>
 #include <asm/cputype.h>
 #include <asm/sections.h>
 #include <asm/cachetype.h>
@@ -25,6 +26,7 @@
 #include <asm/smp_plat.h>
 #include <asm/tlb.h>
 #include <asm/highmem.h>
+#include <asm/system_info.h>
 #include <asm/traps.h>
 
 #include <asm/mach/arch.h>
index a3e78cc..0acb089 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/highmem.h>
 #include <linux/slab.h>
 
+#include <asm/cp15.h>
 #include <asm/pgalloc.h>
 #include <asm/page.h>
 #include <asm/tlbflush.h>
index 272558a..d217e97 100644 (file)
@@ -22,7 +22,6 @@
 #include <asm/pgtable.h>
 #include <asm/page.h>
 #include <asm/ptrace.h>
-#include <asm/system.h>
 
 #include "proc-macros.S"
 
index cc60acd..2782ebc 100644 (file)
@@ -28,7 +28,6 @@
 
 #include <linux/compiler.h>
 #include <linux/string.h>
-#include <asm/system.h>
 
 /* Reset the FPA11 chip.  Called to initialize and reset the emulator. */
 static void resetFPA11(void)
index 4efe392..88215ad 100644 (file)
@@ -23,7 +23,6 @@
 #include <asm/page.h>
 #include <asm/mach/map.h>
 #include <asm/setup.h>
-#include <asm/system.h>
 #include <asm/memory.h>
 #include <mach/hardware.h>
 #include <asm/hardware/iop3xx.h>
index 7276835..0da4205 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/io.h>
 #include <asm/irq.h>
 #include <asm/signal.h>
-#include <asm/system.h>
 #include <mach/hardware.h>
 #include <asm/mach/pci.h>
 #include <asm/hardware/iop3xx.h>
index 6a85a0c..33fa699 100644 (file)
@@ -8,6 +8,7 @@
  * published by the Free Software Foundation.
  */
 #include <asm/hardware/iop3xx.h>
+#include <asm/system_misc.h>
 #include <mach/hardware.h>
 
 void iop3xx_restart(char mode, const char *cmd)
index f30dcac..1996c3e 100644 (file)
@@ -25,8 +25,8 @@
 
 #include <mach/hardware.h>
 #include <mach/common.h>
+#include <asm/system_misc.h>
 #include <asm/proc-fns.h>
-#include <asm/system.h>
 #include <asm/mach-types.h>
 
 void __iomem *(*imx_ioremap)(unsigned long, size_t, unsigned int) = NULL;
index 61a1ec2..39407cb 100644 (file)
@@ -15,7 +15,6 @@
 
 #include <mach/hardware.h>
 #include <asm/leds.h>
-#include <asm/system.h>
 #include <asm/mach-types.h>
 
 #include <plat/fpga.h>
index 74300ae..ecdb3da 100644 (file)
@@ -36,7 +36,6 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 
-#include <asm/system.h>
 #include <mach/hardware.h>
 #include <plat/dma.h>
 
index cb75b65..b8a96c6 100644 (file)
@@ -218,30 +218,14 @@ extern void omap_set_gpio_debounce(int gpio, int enable);
 extern void omap_set_gpio_debounce_time(int gpio, int enable);
 /*-------------------------------------------------------------------------*/
 
-/* Wrappers for "new style" GPIO calls, using the new infrastructure
+/*
+ * Wrappers for "new style" GPIO calls, using the new infrastructure
  * which lets us plug in FPGA, I2C, and other implementations.
- * *
+ *
  * The original OMAP-specific calls should eventually be removed.
  */
 
 #include <linux/errno.h>
 #include <asm-generic/gpio.h>
 
-static inline int irq_to_gpio(unsigned irq)
-{
-       int tmp;
-
-       /* omap1 SOC mpuio */
-       if (cpu_class_is_omap1() && (irq < (IH_MPUIO_BASE + 16)))
-               return (irq - IH_MPUIO_BASE) + OMAP_MAX_GPIO_LINES;
-
-       /* SOC gpio */
-       tmp = irq - IH_GPIO_BASE;
-       if (tmp < OMAP_MAX_GPIO_LINES)
-               return tmp;
-
-       /* we don't supply reverse mappings for non-SOC gpios */
-       return -EIO;
-}
-
 #endif
index 089899a..74daf5e 100644 (file)
@@ -21,6 +21,7 @@
 #include <plat/orion_wdt.h>
 #include <plat/mv_xor.h>
 #include <plat/ehci-orion.h>
+#include <mach/bridge-regs.h>
 
 /* Fill in the resources structure and link it into the platform
    device structure. There is always a memory region, and nearly
@@ -568,13 +569,17 @@ void __init orion_spi_1_init(unsigned long mapbase,
  ****************************************************************************/
 static struct orion_wdt_platform_data orion_wdt_data;
 
+static struct resource orion_wdt_resource =
+               DEFINE_RES_MEM(TIMER_VIRT_BASE, 0x28);
+
 static struct platform_device orion_wdt_device = {
        .name           = "orion_wdt",
        .id             = -1,
        .dev            = {
                .platform_data  = &orion_wdt_data,
        },
-       .num_resources  = 0,
+       .resource       = &orion_wdt_resource,
+       .num_resources  = 1,
 };
 
 void __init orion_wdt_init(unsigned long tclk)
index 885f8ab..d6a55bd 100644 (file)
@@ -2,7 +2,6 @@
 #define __PLAT_AUDIO_H
 
 struct kirkwood_asoc_platform_data {
-       u32 tclk;
        int burst;
 };
 #endif
index 2d3c19d..79ef102 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/errno.h>
 #include <linux/dma-mapping.h>
 
-#include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/memory.h>
 #include <mach/hardware.h>
index 32a0993..0db73ae 100644 (file)
@@ -35,6 +35,7 @@
 #include <mach/regs-clock.h>
 #include <asm/irq.h>
 #include <asm/cacheflush.h>
+#include <asm/system_info.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
index 2bab4c9..28f898f 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/errno.h>
 #include <linux/io.h>
 
-#include <asm/system.h>
 #include <asm/irq.h>
 #include <mach/hardware.h>
 #include <mach/dma.h>
index 7a30869..96bea32 100644 (file)
@@ -9,8 +9,8 @@ config PLAT_S5P
        bool
        depends on (ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS)
        default y
-       select ARM_VIC if !ARCH_EXYNOS4
-       select ARM_GIC if ARCH_EXYNOS4
+       select ARM_VIC if !ARCH_EXYNOS
+       select ARM_GIC if ARCH_EXYNOS
        select GIC_NON_BANKED if ARCH_EXYNOS4
        select NO_IOPORT
        select ARCH_REQUIRE_GPIOLIB
@@ -40,6 +40,10 @@ config S5P_HRT
        help
          Use the High Resolution timer support
 
+config S5P_DEV_UART
+       def_bool y
+       depends on (ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210)
+
 config S5P_PM
        bool
        help
index 30d8c30..4bd8241 100644 (file)
@@ -12,7 +12,6 @@ obj-                          :=
 
 # Core files
 
-obj-y                          += dev-uart.o
 obj-y                          += clock.o
 obj-y                          += irq.o
 obj-$(CONFIG_S5P_EXT_INT)      += irq-eint.o
@@ -23,5 +22,7 @@ obj-$(CONFIG_S5P_SLEEP)               += sleep.o
 obj-$(CONFIG_S5P_HRT)          += s5p-time.o
 
 # devices
+
+obj-$(CONFIG_S5P_DEV_UART)     += dev-uart.o
 obj-$(CONFIG_S5P_DEV_MFC)      += dev-mfc.o
 obj-$(CONFIG_S5P_SETUP_MIPIPHY)        += setup-mipiphy.o
index 963edea..f68a9bb 100644 (file)
@@ -61,6 +61,20 @@ struct clk clk_fout_apll = {
        .id             = -1,
 };
 
+/* BPLL clock output */
+
+struct clk clk_fout_bpll = {
+       .name           = "fout_bpll",
+       .id             = -1,
+};
+
+/* CPLL clock output */
+
+struct clk clk_fout_cpll = {
+       .name           = "fout_cpll",
+       .id             = -1,
+};
+
 /* MPLL clock output
  * No need .ctrlbit, this is always on
 */
@@ -101,6 +115,28 @@ struct clksrc_sources clk_src_apll = {
        .nr_sources     = ARRAY_SIZE(clk_src_apll_list),
 };
 
+/* Possible clock sources for BPLL Mux */
+static struct clk *clk_src_bpll_list[] = {
+       [0] = &clk_fin_bpll,
+       [1] = &clk_fout_bpll,
+};
+
+struct clksrc_sources clk_src_bpll = {
+       .sources        = clk_src_bpll_list,
+       .nr_sources     = ARRAY_SIZE(clk_src_bpll_list),
+};
+
+/* Possible clock sources for CPLL Mux */
+static struct clk *clk_src_cpll_list[] = {
+       [0] = &clk_fin_cpll,
+       [1] = &clk_fout_cpll,
+};
+
+struct clksrc_sources clk_src_cpll = {
+       .sources        = clk_src_cpll_list,
+       .nr_sources     = ARRAY_SIZE(clk_src_cpll_list),
+};
+
 /* Possible clock sources for MPLL Mux */
 static struct clk *clk_src_mpll_list[] = {
        [0] = &clk_fin_mpll,
index 327acb3..d1bfeca 100644 (file)
@@ -39,19 +39,32 @@ unsigned long s3c_irqwake_eintallow = 0xffffffffL;
 int s3c_irq_wake(struct irq_data *data, unsigned int state)
 {
        unsigned long irqbit;
+       unsigned int irq_rtc_tic, irq_rtc_alarm;
+
+#ifdef CONFIG_ARCH_EXYNOS
+       if (soc_is_exynos5250()) {
+               irq_rtc_tic = EXYNOS5_IRQ_RTC_TIC;
+               irq_rtc_alarm = EXYNOS5_IRQ_RTC_ALARM;
+       } else {
+               irq_rtc_tic = EXYNOS4_IRQ_RTC_TIC;
+               irq_rtc_alarm = EXYNOS4_IRQ_RTC_ALARM;
+       }
+#else
+       irq_rtc_tic = IRQ_RTC_TIC;
+       irq_rtc_alarm = IRQ_RTC_ALARM;
+#endif
+
+       if (data->irq == irq_rtc_tic || data->irq == irq_rtc_alarm) {
+               irqbit = 1 << (data->irq + 1 - irq_rtc_alarm);
 
-       switch (data->irq) {
-       case IRQ_RTC_TIC:
-       case IRQ_RTC_ALARM:
-               irqbit = 1 << (data->irq + 1 - IRQ_RTC_ALARM);
                if (!state)
                        s3c_irqwake_intmask |= irqbit;
                else
                        s3c_irqwake_intmask &= ~irqbit;
-               break;
-       default:
+       } else {
                return -ENOENT;
        }
+
        return 0;
 }
 
index 81c06d4..46b426e 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/init.h>
 #include <linux/io.h>
 
-#include <asm/system.h>
 
 #include <mach/map.h>
 #include <plat/cpu.h>
index 73cb3cf..787ceac 100644 (file)
@@ -42,6 +42,9 @@ extern unsigned long samsung_cpu_id;
 #define EXYNOS4412_CPU_ID      0xE4412200
 #define EXYNOS4_CPU_MASK       0xFFFE0000
 
+#define EXYNOS5250_SOC_ID      0x43520000
+#define EXYNOS5_SOC_MASK       0xFFFFF000
+
 #define IS_SAMSUNG_CPU(name, id, mask)         \
 static inline int is_samsung_##name(void)      \
 {                                              \
@@ -58,6 +61,7 @@ IS_SAMSUNG_CPU(s5pv210, S5PV210_CPU_ID, S5PV210_CPU_MASK)
 IS_SAMSUNG_CPU(exynos4210, EXYNOS4210_CPU_ID, EXYNOS4_CPU_MASK)
 IS_SAMSUNG_CPU(exynos4212, EXYNOS4212_CPU_ID, EXYNOS4_CPU_MASK)
 IS_SAMSUNG_CPU(exynos4412, EXYNOS4412_CPU_ID, EXYNOS4_CPU_MASK)
+IS_SAMSUNG_CPU(exynos5250, EXYNOS5250_SOC_ID, EXYNOS5_SOC_MASK)
 
 #if defined(CONFIG_CPU_S3C2410) || defined(CONFIG_CPU_S3C2412) || \
     defined(CONFIG_CPU_S3C2416) || defined(CONFIG_CPU_S3C2440) || \
@@ -120,6 +124,12 @@ IS_SAMSUNG_CPU(exynos4412, EXYNOS4412_CPU_ID, EXYNOS4_CPU_MASK)
 #define EXYNOS4210_REV_1_0     (0x10)
 #define EXYNOS4210_REV_1_1     (0x11)
 
+#if defined(CONFIG_SOC_EXYNOS5250)
+# define soc_is_exynos5250()   is_samsung_exynos5250()
+#else
+# define soc_is_exynos5250()   0
+#endif
+
 #define IODESC_ENT(x) { (unsigned long)S3C24XX_VA_##x, __phys_to_pfn(S3C24XX_PA_##x), S3C24XX_SZ_##x, MT_DEVICE }
 
 #ifndef MHZ
index 5e7972d..2155d4a 100644 (file)
@@ -26,6 +26,8 @@ struct s3c24xx_uart_resources {
 extern struct s3c24xx_uart_resources s3c2410_uart_resources[];
 extern struct s3c24xx_uart_resources s3c64xx_uart_resources[];
 extern struct s3c24xx_uart_resources s5p_uart_resources[];
+extern struct s3c24xx_uart_resources exynos4_uart_resources[];
+extern struct s3c24xx_uart_resources exynos5_uart_resources[];
 
 extern struct platform_device *s3c24xx_uart_devs[];
 extern struct platform_device *s3c24xx_uart_src[];
index 984bf9e..1de4b32 100644 (file)
@@ -18,6 +18,8 @@
 #define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1)
 
 #define clk_fin_apll clk_ext_xtal_mux
+#define clk_fin_bpll clk_ext_xtal_mux
+#define clk_fin_cpll clk_ext_xtal_mux
 #define clk_fin_mpll clk_ext_xtal_mux
 #define clk_fin_epll clk_ext_xtal_mux
 #define clk_fin_dpll clk_ext_xtal_mux
@@ -29,6 +31,8 @@ extern struct clk clk_xusbxti;
 extern struct clk clk_48m;
 extern struct clk s5p_clk_27m;
 extern struct clk clk_fout_apll;
+extern struct clk clk_fout_bpll;
+extern struct clk clk_fout_cpll;
 extern struct clk clk_fout_mpll;
 extern struct clk clk_fout_epll;
 extern struct clk clk_fout_dpll;
@@ -37,6 +41,8 @@ extern struct clk clk_arm;
 extern struct clk clk_vpll;
 
 extern struct clksrc_sources clk_src_apll;
+extern struct clksrc_sources clk_src_bpll;
+extern struct clksrc_sources clk_src_cpll;
 extern struct clksrc_sources clk_src_mpll;
 extern struct clksrc_sources clk_src_epll;
 extern struct clksrc_sources clk_src_dpll;
index ee48e12..7e068d1 100644 (file)
@@ -37,7 +37,9 @@ static void arch_detect_cpu(void);
 /* how many bytes we allow into the FIFO at a time in FIFO mode */
 #define FIFO_MAX        (14)
 
+#ifdef S3C_PA_UART
 #define uart_base S3C_PA_UART + (S3C_UART_OFFSET * CONFIG_S3C_LOWLEVEL_UART_PORT)
+#endif
 
 static __inline__ void
 uart_wr(unsigned int reg, unsigned int val)
index 51583cd..f980cf3 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/io.h>
 
 #include <mach/map.h>
+#include <plat/cpu.h>
 #include <plat/irq-vic-timer.h>
 #include <plat/regs-timer.h>
 
@@ -57,6 +58,21 @@ void __init s3c_init_vic_timer_irq(unsigned int num, unsigned int timer_irq)
        struct irq_chip_type *ct;
        unsigned int i;
 
+#ifdef CONFIG_ARCH_EXYNOS
+       if (soc_is_exynos5250()) {
+               pirq[0] = EXYNOS5_IRQ_TIMER0_VIC;
+               pirq[1] = EXYNOS5_IRQ_TIMER1_VIC;
+               pirq[2] = EXYNOS5_IRQ_TIMER2_VIC;
+               pirq[3] = EXYNOS5_IRQ_TIMER3_VIC;
+               pirq[4] = EXYNOS5_IRQ_TIMER4_VIC;
+       } else {
+               pirq[0] = EXYNOS4_IRQ_TIMER0_VIC;
+               pirq[1] = EXYNOS4_IRQ_TIMER1_VIC;
+               pirq[2] = EXYNOS4_IRQ_TIMER2_VIC;
+               pirq[3] = EXYNOS4_IRQ_TIMER3_VIC;
+               pirq[4] = EXYNOS4_IRQ_TIMER4_VIC;
+       }
+#endif
        s3c_tgc = irq_alloc_generic_chip("s3c-timer", 1, timer_irq,
                                         S3C64XX_TINT_CSTAT, handle_level_irq);
 
index e3bb806..4dcb11c 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/io.h>
 #include <linux/platform_device.h>
 
-#include <asm/system.h>
 #include <asm/leds.h>
 #include <asm/mach-types.h>
 
index 2b4e3d8..16f203e 100644 (file)
@@ -11,6 +11,7 @@
  * warranty of any kind, whether express or implied.
  */
 #include <linux/io.h>
+#include <asm/system_misc.h>
 #include <asm/hardware/sp810.h>
 #include <mach/hardware.h>
 #include <mach/generic.h>
index 8f3ccdd..858748e 100644 (file)
@@ -18,7 +18,9 @@
 #include <linux/smp.h>
 #include <linux/init.h>
 
+#include <asm/cp15.h>
 #include <asm/cputype.h>
+#include <asm/system_info.h>
 #include <asm/thread_notify.h>
 #include <asm/vfp.h>
 
index 7c756fb..afeae89 100644 (file)
@@ -97,6 +97,7 @@ static struct atmel_nand_data atngw100mkii_nand_data __initdata = {
        .rdy_pin        = GPIO_PIN_PB(28),
        .enable_pin     = GPIO_PIN_PE(23),
        .bus_width_16   = true,
+       .ecc_mode       = NAND_ECC_SOFT,
        .parts          = nand_partitions,
        .num_parts      = ARRAY_SIZE(nand_partitions),
 };
index c56ddac..dc52633 100644 (file)
@@ -95,6 +95,7 @@ static struct atmel_nand_data atstk1006_nand_data __initdata = {
        .ale            = 22,
        .rdy_pin        = GPIO_PIN_PB(30),
        .enable_pin     = GPIO_PIN_PB(29),
+       .ecc_mode       = NAND_ECC_SOFT,
        .parts          = nand_partitions,
        .num_parts      = ARRAY_SIZE(num_partitions),
 };
index e0ac263..6140727 100644 (file)
@@ -15,7 +15,7 @@
 #define __ASM_AVR32_ATOMIC_H
 
 #include <linux/types.h>
-#include <asm/system.h>
+#include <asm/cmpxchg.h>
 
 #define ATOMIC_INIT(i)  { (i) }
 
diff --git a/arch/avr32/include/asm/barrier.h b/arch/avr32/include/asm/barrier.h
new file mode 100644 (file)
index 0000000..808001c
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __ASM_AVR32_BARRIER_H
+#define __ASM_AVR32_BARRIER_H
+
+#define mb()                   asm volatile("" : : : "memory")
+#define rmb()                  mb()
+#define wmb()                  asm volatile("sync 0" : : : "memory")
+#define read_barrier_depends()  do { } while(0)
+#define set_mb(var, value)      do { var = value; mb(); } while(0)
+
+#ifdef CONFIG_SMP
+# error "The AVR32 port does not support SMP"
+#else
+# define smp_mb()              barrier()
+# define smp_rmb()             barrier()
+# define smp_wmb()             barrier()
+# define smp_read_barrier_depends() do { } while(0)
+#endif
+
+
+#endif /* __ASM_AVR32_BARRIER_H */
index b70c19b..ebe7ad3 100644 (file)
@@ -13,7 +13,6 @@
 #endif
 
 #include <asm/byteorder.h>
-#include <asm/system.h>
 
 /*
  * clear_bit() doesn't provide any barrier for the compiler
index 2aa373c..85a92d0 100644 (file)
@@ -70,4 +70,9 @@
 
 #include <asm-generic/bug.h>
 
+struct pt_regs;
+void die(const char *str, struct pt_regs *regs, long err);
+void _exception(long signr, struct pt_regs *regs, int code,
+               unsigned long addr);
+
 #endif /* __ASM_AVR32_BUG_H */
diff --git a/arch/avr32/include/asm/cmpxchg.h b/arch/avr32/include/asm/cmpxchg.h
new file mode 100644 (file)
index 0000000..962a6ae
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Atomic operations that C can't guarantee us.  Useful for
+ * resource counting etc.
+ *
+ * But use these as seldom as possible since they are slower than
+ * regular operations.
+ *
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __ASM_AVR32_CMPXCHG_H
+#define __ASM_AVR32_CMPXCHG_H
+
+#define xchg(ptr,x) \
+       ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
+
+extern void __xchg_called_with_bad_pointer(void);
+
+static inline unsigned long xchg_u32(u32 val, volatile u32 *m)
+{
+       u32 ret;
+
+       asm volatile("xchg %[ret], %[m], %[val]"
+                       : [ret] "=&r"(ret), "=m"(*m)
+                       : "m"(*m), [m] "r"(m), [val] "r"(val)
+                       : "memory");
+       return ret;
+}
+
+static inline unsigned long __xchg(unsigned long x,
+                                      volatile void *ptr,
+                                      int size)
+{
+       switch(size) {
+       case 4:
+               return xchg_u32(x, ptr);
+       default:
+               __xchg_called_with_bad_pointer();
+               return x;
+       }
+}
+
+static inline unsigned long __cmpxchg_u32(volatile int *m, unsigned long old,
+                                         unsigned long new)
+{
+       __u32 ret;
+
+       asm volatile(
+               "1:     ssrf    5\n"
+               "       ld.w    %[ret], %[m]\n"
+               "       cp.w    %[ret], %[old]\n"
+               "       brne    2f\n"
+               "       stcond  %[m], %[new]\n"
+               "       brne    1b\n"
+               "2:\n"
+               : [ret] "=&r"(ret), [m] "=m"(*m)
+               : "m"(m), [old] "ir"(old), [new] "r"(new)
+               : "memory", "cc");
+       return ret;
+}
+
+extern unsigned long __cmpxchg_u64_unsupported_on_32bit_kernels(
+        volatile int * m, unsigned long old, unsigned long new);
+#define __cmpxchg_u64 __cmpxchg_u64_unsupported_on_32bit_kernels
+
+/* This function doesn't exist, so you'll get a linker error
+   if something tries to do an invalid cmpxchg().  */
+extern void __cmpxchg_called_with_bad_pointer(void);
+
+#define __HAVE_ARCH_CMPXCHG 1
+
+static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
+                                     unsigned long new, int size)
+{
+       switch (size) {
+       case 4:
+               return __cmpxchg_u32(ptr, old, new);
+       case 8:
+               return __cmpxchg_u64(ptr, old, new);
+       }
+
+       __cmpxchg_called_with_bad_pointer();
+       return old;
+}
+
+#define cmpxchg(ptr, old, new)                                 \
+       ((typeof(*(ptr)))__cmpxchg((ptr), (unsigned long)(old), \
+                                  (unsigned long)(new),        \
+                                  sizeof(*(ptr))))
+
+#include <asm-generic/cmpxchg-local.h>
+
+static inline unsigned long __cmpxchg_local(volatile void *ptr,
+                                     unsigned long old,
+                                     unsigned long new, int size)
+{
+       switch (size) {
+       case 4:
+               return __cmpxchg_u32(ptr, old, new);
+       default:
+               return __cmpxchg_local_generic(ptr, old, new, size);
+       }
+
+       return old;
+}
+
+#define cmpxchg_local(ptr, old, new)                                   \
+       ((typeof(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(old),   \
+                                  (unsigned long)(new),                \
+                                  sizeof(*(ptr))))
+
+#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
+
+#endif /* __ASM_AVR32_CMPXCHG_H */
diff --git a/arch/avr32/include/asm/exec.h b/arch/avr32/include/asm/exec.h
new file mode 100644 (file)
index 0000000..f467be8
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __ASM_AVR32_EXEC_H
+#define __ASM_AVR32_EXEC_H
+
+#define arch_align_stack(x)    (x)
+
+#endif /* __ASM_AVR32_EXEC_H */
diff --git a/arch/avr32/include/asm/special_insns.h b/arch/avr32/include/asm/special_insns.h
new file mode 100644 (file)
index 0000000..f922218
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __ASM_AVR32_SPECIAL_INSNS_H
+#define __ASM_AVR32_SPECIAL_INSNS_H
+
+#define nop() asm volatile("nop")
+
+#endif /* __ASM_AVR32_SPECIAL_INSNS_H */
diff --git a/arch/avr32/include/asm/switch_to.h b/arch/avr32/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..9a8e9d5
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __ASM_AVR32_SWITCH_TO_H
+#define __ASM_AVR32_SWITCH_TO_H
+
+/*
+ * Help PathFinder and other Nexus-compliant debuggers keep track of
+ * the current PID by emitting an Ownership Trace Message each time we
+ * switch task.
+ */
+#ifdef CONFIG_OWNERSHIP_TRACE
+#include <asm/ocd.h>
+#define finish_arch_switch(prev)                       \
+       do {                                            \
+               ocd_write(PID, prev->pid);              \
+               ocd_write(PID, current->pid);           \
+       } while(0)
+#endif
+
+/*
+ * switch_to(prev, next, last) should switch from task `prev' to task
+ * `next'. `prev' will never be the same as `next'.
+ *
+ * We just delegate everything to the __switch_to assembly function,
+ * which is implemented in arch/avr32/kernel/switch_to.S
+ *
+ * mb() tells GCC not to cache `current' across this call.
+ */
+struct cpu_context;
+struct task_struct;
+extern struct task_struct *__switch_to(struct task_struct *,
+                                      struct cpu_context *,
+                                      struct cpu_context *);
+#define switch_to(prev, next, last)                                    \
+       do {                                                            \
+               last = __switch_to(prev, &prev->thread.cpu_context + 1, \
+                                  &next->thread.cpu_context);          \
+       } while (0)
+
+
+#endif /* __ASM_AVR32_SWITCH_TO_H */
diff --git a/arch/avr32/include/asm/system.h b/arch/avr32/include/asm/system.h
deleted file mode 100644 (file)
index 62d9ded..0000000
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Copyright (C) 2004-2006 Atmel Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#ifndef __ASM_AVR32_SYSTEM_H
-#define __ASM_AVR32_SYSTEM_H
-
-#include <linux/compiler.h>
-#include <linux/linkage.h>
-#include <linux/types.h>
-
-#include <asm/ptrace.h>
-#include <asm/sysreg.h>
-
-#define xchg(ptr,x) \
-       ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
-
-#define nop() asm volatile("nop")
-
-#define mb()                   asm volatile("" : : : "memory")
-#define rmb()                  mb()
-#define wmb()                  asm volatile("sync 0" : : : "memory")
-#define read_barrier_depends()  do { } while(0)
-#define set_mb(var, value)      do { var = value; mb(); } while(0)
-
-/*
- * Help PathFinder and other Nexus-compliant debuggers keep track of
- * the current PID by emitting an Ownership Trace Message each time we
- * switch task.
- */
-#ifdef CONFIG_OWNERSHIP_TRACE
-#include <asm/ocd.h>
-#define finish_arch_switch(prev)                       \
-       do {                                            \
-               ocd_write(PID, prev->pid);              \
-               ocd_write(PID, current->pid);           \
-       } while(0)
-#endif
-
-/*
- * switch_to(prev, next, last) should switch from task `prev' to task
- * `next'. `prev' will never be the same as `next'.
- *
- * We just delegate everything to the __switch_to assembly function,
- * which is implemented in arch/avr32/kernel/switch_to.S
- *
- * mb() tells GCC not to cache `current' across this call.
- */
-struct cpu_context;
-struct task_struct;
-extern struct task_struct *__switch_to(struct task_struct *,
-                                      struct cpu_context *,
-                                      struct cpu_context *);
-#define switch_to(prev, next, last)                                    \
-       do {                                                            \
-               last = __switch_to(prev, &prev->thread.cpu_context + 1, \
-                                  &next->thread.cpu_context);          \
-       } while (0)
-
-#ifdef CONFIG_SMP
-# error "The AVR32 port does not support SMP"
-#else
-# define smp_mb()              barrier()
-# define smp_rmb()             barrier()
-# define smp_wmb()             barrier()
-# define smp_read_barrier_depends() do { } while(0)
-#endif
-
-#include <linux/irqflags.h>
-
-extern void __xchg_called_with_bad_pointer(void);
-
-static inline unsigned long xchg_u32(u32 val, volatile u32 *m)
-{
-       u32 ret;
-
-       asm volatile("xchg %[ret], %[m], %[val]"
-                       : [ret] "=&r"(ret), "=m"(*m)
-                       : "m"(*m), [m] "r"(m), [val] "r"(val)
-                       : "memory");
-       return ret;
-}
-
-static inline unsigned long __xchg(unsigned long x,
-                                      volatile void *ptr,
-                                      int size)
-{
-       switch(size) {
-       case 4:
-               return xchg_u32(x, ptr);
-       default:
-               __xchg_called_with_bad_pointer();
-               return x;
-       }
-}
-
-static inline unsigned long __cmpxchg_u32(volatile int *m, unsigned long old,
-                                         unsigned long new)
-{
-       __u32 ret;
-
-       asm volatile(
-               "1:     ssrf    5\n"
-               "       ld.w    %[ret], %[m]\n"
-               "       cp.w    %[ret], %[old]\n"
-               "       brne    2f\n"
-               "       stcond  %[m], %[new]\n"
-               "       brne    1b\n"
-               "2:\n"
-               : [ret] "=&r"(ret), [m] "=m"(*m)
-               : "m"(m), [old] "ir"(old), [new] "r"(new)
-               : "memory", "cc");
-       return ret;
-}
-
-extern unsigned long __cmpxchg_u64_unsupported_on_32bit_kernels(
-        volatile int * m, unsigned long old, unsigned long new);
-#define __cmpxchg_u64 __cmpxchg_u64_unsupported_on_32bit_kernels
-
-/* This function doesn't exist, so you'll get a linker error
-   if something tries to do an invalid cmpxchg().  */
-extern void __cmpxchg_called_with_bad_pointer(void);
-
-#define __HAVE_ARCH_CMPXCHG 1
-
-static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
-                                     unsigned long new, int size)
-{
-       switch (size) {
-       case 4:
-               return __cmpxchg_u32(ptr, old, new);
-       case 8:
-               return __cmpxchg_u64(ptr, old, new);
-       }
-
-       __cmpxchg_called_with_bad_pointer();
-       return old;
-}
-
-#define cmpxchg(ptr, old, new)                                 \
-       ((typeof(*(ptr)))__cmpxchg((ptr), (unsigned long)(old), \
-                                  (unsigned long)(new),        \
-                                  sizeof(*(ptr))))
-
-#include <asm-generic/cmpxchg-local.h>
-
-static inline unsigned long __cmpxchg_local(volatile void *ptr,
-                                     unsigned long old,
-                                     unsigned long new, int size)
-{
-       switch (size) {
-       case 4:
-               return __cmpxchg_u32(ptr, old, new);
-       default:
-               return __cmpxchg_local_generic(ptr, old, new, size);
-       }
-
-       return old;
-}
-
-#define cmpxchg_local(ptr, old, new)                                   \
-       ((typeof(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(old),   \
-                                  (unsigned long)(new),                \
-                                  sizeof(*(ptr))))
-
-#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
-
-struct pt_regs;
-void die(const char *str, struct pt_regs *regs, long err);
-void _exception(long signr, struct pt_regs *regs, int code,
-               unsigned long addr);
-
-#define arch_align_stack(x)    (x)
-
-#endif /* __ASM_AVR32_SYSTEM_H */
index 6277433..18b7656 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/export.h>
-#include <asm/system.h>
 
 static struct clk *cpuclk;
 
index 67b111c..7173386 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/types.h>
 #include <linux/serial.h>
 #include <linux/platform_data/macb.h>
+#include <linux/platform_data/atmel_nand.h>
 
 #define GPIO_PIN_NONE  (-1)
 
@@ -116,18 +117,6 @@ struct platform_device *
 at32_add_device_cf(unsigned int id, unsigned int extint,
                struct cf_platform_data *data);
 
-/* NAND / SmartMedia */
-struct atmel_nand_data {
-       int     enable_pin;     /* chip enable */
-       int     det_pin;        /* card detect */
-       int     rdy_pin;        /* ready/busy */
-       u8      rdy_pin_active_low;     /* rdy_pin value is inverted */
-       u8      ale;            /* address line number connected to ALE */
-       u8      cle;            /* address line number connected to CLE */
-       u8      bus_width_16;   /* buswidth is 16 bit */
-       struct mtd_partition *parts;
-       unsigned int    num_parts;
-};
 struct platform_device *
 at32_add_device_nand(unsigned int id, struct atmel_nand_data *data);
 
index a3e9b3c..f74b780 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/types.h>
 
 #include <asm/sysreg.h>
-#include <asm/system.h>
 
 #define AVR32_PERFCTR_IRQ_GROUP        0
 #define AVR32_PERFCTR_IRQ_LINE 1
diff --git a/arch/blackfin/include/asm/system.h b/arch/blackfin/include/asm/system.h
deleted file mode 100644 (file)
index a7f4057..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-/* FILE TO BE DELETED. DO NOT ADD STUFF HERE! */
-#include <asm/barrier.h>
-#include <asm/cmpxchg.h>
-#include <asm/exec.h>
-#include <asm/switch_to.h>
index 13dcf78..3af601e 100644 (file)
@@ -3,7 +3,6 @@ include include/asm-generic/Kbuild.asm
 generic-y += atomic.h
 generic-y += auxvec.h
 generic-y += bitsperlong.h
-generic-y += bug.h
 generic-y += bugs.h
 generic-y += cputime.h
 generic-y += current.h
diff --git a/arch/c6x/include/asm/barrier.h b/arch/c6x/include/asm/barrier.h
new file mode 100644 (file)
index 0000000..538240e
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ *  Port on Texas Instruments TMS320C6x architecture
+ *
+ *  Copyright (C) 2004, 2009, 2010, 2011 Texas Instruments Incorporated
+ *  Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com)
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+#ifndef _ASM_C6X_BARRIER_H
+#define _ASM_C6X_BARRIER_H
+
+#define nop()                    asm("NOP\n");
+
+#define mb()                     barrier()
+#define rmb()                    barrier()
+#define wmb()                    barrier()
+#define set_mb(var, value)       do { var = value;  mb(); } while (0)
+#define set_wmb(var, value)      do { var = value; wmb(); } while (0)
+
+#define smp_mb()                barrier()
+#define smp_rmb()               barrier()
+#define smp_wmb()               barrier()
+#define smp_read_barrier_depends()     do { } while (0)
+
+#endif /* _ASM_C6X_BARRIER_H */
index 39ab7e8..0bec7e5 100644 (file)
@@ -15,7 +15,6 @@
 
 #include <linux/bitops.h>
 
-#include <asm/system.h>
 #include <asm/byteorder.h>
 
 /*
diff --git a/arch/c6x/include/asm/bug.h b/arch/c6x/include/asm/bug.h
new file mode 100644 (file)
index 0000000..8d59933
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ *  Port on Texas Instruments TMS320C6x architecture
+ *
+ *  Copyright (C) 2004, 2009, 2010, 2011 Texas Instruments Incorporated
+ *  Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com)
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+#ifndef _ASM_C6X_BUG_H
+#define _ASM_C6X_BUG_H
+
+#include <linux/linkage.h>
+#include <asm-generic/bug.h>
+
+struct pt_regs;
+
+extern void die(char *str, struct pt_regs *fp, int nr);
+extern asmlinkage int process_exception(struct pt_regs *regs);
+extern asmlinkage void enable_exception(void);
+
+#endif /* _ASM_C6X_BUG_H */
diff --git a/arch/c6x/include/asm/cmpxchg.h b/arch/c6x/include/asm/cmpxchg.h
new file mode 100644 (file)
index 0000000..b27c8ce
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ *  Port on Texas Instruments TMS320C6x architecture
+ *
+ *  Copyright (C) 2004, 2009, 2010, 2011 Texas Instruments Incorporated
+ *  Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com)
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+#ifndef _ASM_C6X_CMPXCHG_H
+#define _ASM_C6X_CMPXCHG_H
+
+#include <linux/irqflags.h>
+
+/*
+ * Misc. functions
+ */
+static inline unsigned int __xchg(unsigned int x, volatile void *ptr, int size)
+{
+       unsigned int tmp;
+       unsigned long flags;
+
+       local_irq_save(flags);
+
+       switch (size) {
+       case 1:
+               tmp = 0;
+               tmp = *((unsigned char *) ptr);
+               *((unsigned char *) ptr) = (unsigned char) x;
+               break;
+       case 2:
+               tmp = 0;
+               tmp = *((unsigned short *) ptr);
+               *((unsigned short *) ptr) = x;
+               break;
+       case 4:
+               tmp = 0;
+               tmp = *((unsigned int *) ptr);
+               *((unsigned int *) ptr) = x;
+               break;
+       }
+       local_irq_restore(flags);
+       return tmp;
+}
+
+#define xchg(ptr, x) \
+       ((__typeof__(*(ptr)))__xchg((unsigned int)(x), (void *) (ptr), \
+                                   sizeof(*(ptr))))
+#define tas(ptr)    xchg((ptr), 1)
+
+
+#include <asm-generic/cmpxchg-local.h>
+
+/*
+ * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
+ * them available.
+ */
+#define cmpxchg_local(ptr, o, n)                                       \
+       ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr),             \
+                                                    (unsigned long)(o), \
+                                                    (unsigned long)(n), \
+                                                    sizeof(*(ptr))))
+#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
+
+#include <asm-generic/cmpxchg.h>
+
+#endif /* _ASM_C6X_CMPXCHG_H */
diff --git a/arch/c6x/include/asm/exec.h b/arch/c6x/include/asm/exec.h
new file mode 100644 (file)
index 0000000..0fea482
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _ASM_C6X_EXEC_H
+#define _ASM_C6X_EXEC_H
+
+#define arch_align_stack(x) (x)
+
+#endif /* _ASM_C6X_EXEC_H */
index 77ecbde..3ff7fab 100644 (file)
@@ -129,4 +129,13 @@ extern unsigned long get_wchan(struct task_struct *p);
 
 extern const struct seq_operations cpuinfo_op;
 
+/* Reset the board */
+#define HARD_RESET_NOW()
+
+extern unsigned int c6x_core_freq;
+
+
+extern void (*c6x_restart)(void);
+extern void (*c6x_halt)(void);
+
 #endif /* ASM_C6X_PROCESSOR_H */
index 1808f27..a01e318 100644 (file)
@@ -27,6 +27,7 @@ extern unsigned int c6x_devstat;
 extern unsigned char c6x_fuse_mac[6];
 
 extern void machine_init(unsigned long dt_ptr);
+extern void time_init(void);
 
 #endif /* !__ASSEMBLY__ */
 #endif /* _ASM_C6X_SETUP_H */
diff --git a/arch/c6x/include/asm/special_insns.h b/arch/c6x/include/asm/special_insns.h
new file mode 100644 (file)
index 0000000..59672bc
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ *  Port on Texas Instruments TMS320C6x architecture
+ *
+ *  Copyright (C) 2004, 2009, 2010, 2011 Texas Instruments Incorporated
+ *  Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com)
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+#ifndef _ASM_C6X_SPECIAL_INSNS_H
+#define _ASM_C6X_SPECIAL_INSNS_H
+
+
+#define get_creg(reg) \
+       ({ unsigned int __x; \
+          asm volatile ("mvc .s2 " #reg ",%0\n" : "=b"(__x)); __x; })
+
+#define set_creg(reg, v) \
+       do { unsigned int __x = (unsigned int)(v); \
+               asm volatile ("mvc .s2 %0," #reg "\n" : : "b"(__x)); \
+       } while (0)
+
+#define or_creg(reg, n) \
+       do { unsigned __x, __n = (unsigned)(n);           \
+               asm volatile ("mvc .s2 " #reg ",%0\n"     \
+                             "or  .l2 %1,%0,%0\n"        \
+                             "mvc .s2 %0," #reg "\n"     \
+                             "nop\n"                     \
+                             : "=&b"(__x) : "b"(__n));   \
+       } while (0)
+
+#define and_creg(reg, n) \
+       do { unsigned __x, __n = (unsigned)(n);           \
+               asm volatile ("mvc .s2 " #reg ",%0\n"     \
+                             "and .l2 %1,%0,%0\n"        \
+                             "mvc .s2 %0," #reg "\n"     \
+                             "nop\n"    \
+                             : "=&b"(__x) : "b"(__n));   \
+       } while (0)
+
+#define get_coreid() (get_creg(DNUM) & 0xff)
+
+/* Set/get IST */
+#define set_ist(x)     set_creg(ISTP, x)
+#define get_ist()       get_creg(ISTP)
+
+/*
+ * Exception management
+ */
+#define disable_exception()
+#define get_except_type()        get_creg(EFR)
+#define ack_exception(type)      set_creg(ECR, 1 << (type))
+#define get_iexcept()            get_creg(IERR)
+#define set_iexcept(mask)        set_creg(IERR, (mask))
+
+#define _extu(x, s, e)                                                 \
+       ({      unsigned int __x;                                       \
+               asm volatile ("extu .S2 %3,%1,%2,%0\n" :                \
+                             "=b"(__x) : "n"(s), "n"(e), "b"(x));      \
+              __x; })
+
+#endif /* _ASM_C6X_SPECIAL_INSNS_H */
diff --git a/arch/c6x/include/asm/switch_to.h b/arch/c6x/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..af6c71f
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ *  Port on Texas Instruments TMS320C6x architecture
+ *
+ *  Copyright (C) 2004, 2009, 2010, 2011 Texas Instruments Incorporated
+ *  Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com)
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+#ifndef _ASM_C6X_SWITCH_TO_H
+#define _ASM_C6X_SWITCH_TO_H
+
+#include <linux/linkage.h>
+
+#define prepare_to_switch()    do { } while (0)
+
+struct task_struct;
+struct thread_struct;
+asmlinkage void *__switch_to(struct thread_struct *prev,
+                            struct thread_struct *next,
+                            struct task_struct *tsk);
+
+#define switch_to(prev, next, last)                            \
+       do {                                                    \
+               current->thread.wchan = (u_long) __builtin_return_address(0); \
+               (last) = __switch_to(&(prev)->thread,           \
+                                    &(next)->thread, (prev));  \
+               mb();                                           \
+               current->thread.wchan = 0;                      \
+       } while (0)
+
+#endif /* _ASM_C6X_SWITCH_TO_H */
diff --git a/arch/c6x/include/asm/system.h b/arch/c6x/include/asm/system.h
deleted file mode 100644 (file)
index e076dc0..0000000
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- *  Port on Texas Instruments TMS320C6x architecture
- *
- *  Copyright (C) 2004, 2009, 2010, 2011 Texas Instruments Incorporated
- *  Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com)
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 2 as
- *  published by the Free Software Foundation.
- */
-#ifndef _ASM_C6X_SYSTEM_H
-#define _ASM_C6X_SYSTEM_H
-
-#include <linux/linkage.h>
-#include <linux/irqflags.h>
-
-#define prepare_to_switch()    do { } while (0)
-
-struct task_struct;
-struct thread_struct;
-asmlinkage void *__switch_to(struct thread_struct *prev,
-                            struct thread_struct *next,
-                            struct task_struct *tsk);
-
-#define switch_to(prev, next, last)                            \
-       do {                                                    \
-               current->thread.wchan = (u_long) __builtin_return_address(0); \
-               (last) = __switch_to(&(prev)->thread,           \
-                                    &(next)->thread, (prev));  \
-               mb();                                           \
-               current->thread.wchan = 0;                      \
-       } while (0)
-
-/* Reset the board */
-#define HARD_RESET_NOW()
-
-#define get_creg(reg) \
-       ({ unsigned int __x; \
-          asm volatile ("mvc .s2 " #reg ",%0\n" : "=b"(__x)); __x; })
-
-#define set_creg(reg, v) \
-       do { unsigned int __x = (unsigned int)(v); \
-               asm volatile ("mvc .s2 %0," #reg "\n" : : "b"(__x)); \
-       } while (0)
-
-#define or_creg(reg, n) \
-       do { unsigned __x, __n = (unsigned)(n);           \
-               asm volatile ("mvc .s2 " #reg ",%0\n"     \
-                             "or  .l2 %1,%0,%0\n"        \
-                             "mvc .s2 %0," #reg "\n"     \
-                             "nop\n"                     \
-                             : "=&b"(__x) : "b"(__n));   \
-       } while (0)
-
-#define and_creg(reg, n) \
-       do { unsigned __x, __n = (unsigned)(n);           \
-               asm volatile ("mvc .s2 " #reg ",%0\n"     \
-                             "and .l2 %1,%0,%0\n"        \
-                             "mvc .s2 %0," #reg "\n"     \
-                             "nop\n"    \
-                             : "=&b"(__x) : "b"(__n));   \
-       } while (0)
-
-#define get_coreid() (get_creg(DNUM) & 0xff)
-
-/* Set/get IST */
-#define set_ist(x)     set_creg(ISTP, x)
-#define get_ist()       get_creg(ISTP)
-
-/*
- * Exception management
- */
-asmlinkage void enable_exception(void);
-#define disable_exception()
-#define get_except_type()        get_creg(EFR)
-#define ack_exception(type)      set_creg(ECR, 1 << (type))
-#define get_iexcept()            get_creg(IERR)
-#define set_iexcept(mask)        set_creg(IERR, (mask))
-
-/*
- * Misc. functions
- */
-#define nop()                    asm("NOP\n");
-#define mb()                     barrier()
-#define rmb()                    barrier()
-#define wmb()                    barrier()
-#define set_mb(var, value)       do { var = value;  mb(); } while (0)
-#define set_wmb(var, value)      do { var = value; wmb(); } while (0)
-
-#define smp_mb()                barrier()
-#define smp_rmb()               barrier()
-#define smp_wmb()               barrier()
-#define smp_read_barrier_depends()     do { } while (0)
-
-#define xchg(ptr, x) \
-       ((__typeof__(*(ptr)))__xchg((unsigned int)(x), (void *) (ptr), \
-                                   sizeof(*(ptr))))
-#define tas(ptr)    xchg((ptr), 1)
-
-unsigned int _lmbd(unsigned int, unsigned int);
-unsigned int _bitr(unsigned int);
-
-struct __xchg_dummy { unsigned int a[100]; };
-#define __xg(x) ((volatile struct __xchg_dummy *)(x))
-
-static inline unsigned int __xchg(unsigned int x, volatile void *ptr, int size)
-{
-       unsigned int tmp;
-       unsigned long flags;
-
-       local_irq_save(flags);
-
-       switch (size) {
-       case 1:
-               tmp = 0;
-               tmp = *((unsigned char *) ptr);
-               *((unsigned char *) ptr) = (unsigned char) x;
-               break;
-       case 2:
-               tmp = 0;
-               tmp = *((unsigned short *) ptr);
-               *((unsigned short *) ptr) = x;
-               break;
-       case 4:
-               tmp = 0;
-               tmp = *((unsigned int *) ptr);
-               *((unsigned int *) ptr) = x;
-               break;
-       }
-       local_irq_restore(flags);
-       return tmp;
-}
-
-#include <asm-generic/cmpxchg-local.h>
-
-/*
- * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
- * them available.
- */
-#define cmpxchg_local(ptr, o, n)                                       \
-       ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr),             \
-                                                    (unsigned long)(o), \
-                                                    (unsigned long)(n), \
-                                                    sizeof(*(ptr))))
-#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
-
-#include <asm-generic/cmpxchg.h>
-
-#define _extu(x, s, e)                                                 \
-       ({      unsigned int __x;                                       \
-               asm volatile ("extu .S2 %3,%1,%2,%0\n" :                \
-                             "=b"(__x) : "n"(s), "n"(e), "b"(x));      \
-              __x; })
-
-
-extern unsigned int c6x_core_freq;
-
-struct pt_regs;
-
-extern void die(char *str, struct pt_regs *fp, int nr);
-extern asmlinkage int process_exception(struct pt_regs *regs);
-extern void time_init(void);
-extern void free_initmem(void);
-
-extern void (*c6x_restart)(void);
-extern void (*c6x_halt)(void);
-
-#endif /* _ASM_C6X_SYSTEM_H */
index d77bcfd..65b8ddf 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/kernel_stat.h>
 
 #include <asm/megamod-pic.h>
+#include <asm/special_insns.h>
 
 unsigned long irq_err_count;
 
index 0c07921..ce46186 100644 (file)
@@ -34,6 +34,7 @@
 #include <asm/dscr.h>
 #include <asm/clock.h>
 #include <asm/soc.h>
+#include <asm/special_insns.h>
 
 static const char *c6x_soc_name;
 
index dd45bc3..0748c94 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/module.h>
 #include <linux/ctype.h>
 #include <linux/etherdevice.h>
-#include <asm/system.h>
 #include <asm/setup.h>
 #include <asm/soc.h>
 
index 4c9f136..356ee84 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/timex.h>
 #include <linux/profile.h>
 
+#include <asm/special_insns.h>
 #include <asm/timer64.h>
 
 static u32 sched_clock_multiplier;
index f50e3ed..1be74e5 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/bug.h>
 
 #include <asm/soc.h>
+#include <asm/special_insns.h>
 #include <asm/traps.h>
 
 int (*c6x_nmi_handler)(struct pt_regs *regs);
index 03c03c2..3c73d74 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/of_address.h>
 #include <asm/soc.h>
 #include <asm/dscr.h>
+#include <asm/special_insns.h>
 #include <asm/timer64.h>
 
 struct timer_regs {
index 3d655dc..74f99c6 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/capability.h>
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <arch/svinto.h>
 #include <asm/io.h>
 #include <asm/rtc.h>
index a276f08..609d551 100644 (file)
@@ -24,7 +24,6 @@
 #include <asm/etraxgpio.h>
 #include <arch/svinto.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/irq.h>
 #include <arch/io_interface_mux.h>
 
index c413539..b3d1f9e 100644 (file)
@@ -22,7 +22,6 @@
 
 #include <asm/etraxi2c.h>
 
-#include <asm/system.h>
 #include <arch/svinto.h>
 #include <asm/io.h>
 #include <asm/delay.h>
index 1391b73..9da0568 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/mutex.h>
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/rtc.h>
 
index 466af40..c4b7171 100644 (file)
@@ -27,7 +27,6 @@
 #include <asm/io.h>
 #include <arch/svinto.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/sync_serial.h>
 #include <arch/io_interface_mux.h>
 
index 99851ba..f932c85 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/major.h>
 #include <linux/delay.h>
 #include <linux/tty.h>
-#include <asm/system.h>
 #include <arch/svinto.h>
 #include <asm/io.h>             /* Get SIMCOUT. */
 
index d31504b..5795047 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <asm/dma.h>
 #include <arch/svinto.h>
+#include <arch/system.h>
 
 /* Macro to access ETRAX 100 registers */
 #define SETS(var, reg, field, val) var = (var & ~IO_MASK_(reg##_, field##_)) | \
index 29f97e9..ad64cd1 100644 (file)
@@ -14,6 +14,7 @@
 #include <arch/svinto.h>
 #include <asm/io.h>
 #include <arch/io_interface_mux.h>
+#include <arch/system.h>
 
 
 #define DBG(s)
index 9a57db6..bee8df4 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/fs.h>
 #include <arch/svinto.h>
 #include <linux/init.h>
+#include <arch/system.h>
 
 #ifdef CONFIG_ETRAX_GPIO
 void etrax_gpio_wake_up_check(void); /* drivers/gpio.c */
index 320065f..bfddfb9 100644 (file)
@@ -15,7 +15,6 @@
 #include <asm/uaccess.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/processor.h>
 
 /* 
index de27b50..4f96d71 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/proc_fs.h>
 #include <linux/delay.h>
 #include <linux/param.h>
+#include <arch/system.h>
 
 #ifdef CONFIG_PROC_FS
 #define HAS_FPU                0x0001
index e78fe49..289c584 100644 (file)
@@ -27,6 +27,7 @@
 #include <asm/processor.h>
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
+#include <arch/system.h>
 
 #define DEBUG_SIG 0
 
index 8bebb96..7001bed 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/ptrace.h>
 #include <asm/uaccess.h>
 #include <arch/sv_addr_ag.h>
+#include <arch/system.h>
 
 void
 show_registers(struct pt_regs *regs)
index ddb2399..3b2c82c 100644 (file)
@@ -36,7 +36,6 @@
 
 #include <asm/etraxi2c.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/delay.h>
 
index c845831..0b86dee 100644 (file)
@@ -31,7 +31,6 @@
 #include <hwregs/gio_defs.h>
 #include <hwregs/intr_vect_defs.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/irq.h>
 #include <mach/pinmux.h>
 
index ee90d26..a2ac091 100644 (file)
@@ -30,7 +30,6 @@
 #include <hwregs/gio_defs.h>
 #include <hwregs/intr_vect_defs.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/irq.h>
 
 #ifdef CONFIG_ETRAX_VIRTUAL_GPIO
index 794b364..610909b 100644 (file)
@@ -4,7 +4,6 @@
 
 #include <linux/console.h>
 #include <linux/init.h>
-#include <asm/system.h>
 #include <hwregs/reg_rdwr.h>
 #include <hwregs/reg_map.h>
 #include <hwregs/ser_defs.h>
index 111caa1..ab1551e 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/delay.h>
 
 #include <asm/irq.h>
-#include <asm/system.h>
 
 #include <hwregs/reg_map.h>
 #include <hwregs/reg_rdwr.h>
index 511ece9..f7ad9e8 100644 (file)
@@ -15,7 +15,6 @@
 #include <asm/uaccess.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/processor.h>
 #include <arch/hwregs/supp_reg.h>
 
index f35e4f6..47c64bf 100644 (file)
@@ -9,7 +9,6 @@
 #include <hwregs/clkgen_defs.h>
 #include <hwregs/strmux_defs.h>
 #include <linux/errno.h>
-#include <asm/system.h>
 #include <arbiter.h>
 
 static char used_dma_channels[MAX_DMA_CHANNELS];
index 2d970d7..fc6416a 100644 (file)
@@ -9,7 +9,6 @@
 #include <hwregs/config_defs.h>
 #include <hwregs/strmux_defs.h>
 #include <linux/errno.h>
-#include <asm/system.h>
 #include <mach/arbiter.h>
 
 static char used_dma_channels[MAX_DMA_CHANNELS];
index 1c38ee7..1eb638a 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef __ASMCRIS_ARCH_ELF_H
 #define __ASMCRIS_ARCH_ELF_H
 
+#include <arch/system.h>
+
 #define ELF_MACH EF_CRIS_VARIANT_ANY_V0_V10
 
 /*
index 1324e50..c46d582 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _ASM_CRIS_ELF_H
 #define _ASM_CRIS_ELF_H
 
+#include <arch/system.h>
+
 #define ELF_CORE_EFLAGS EF_CRIS_VARIANT_V32
 
 /*
index 76cea99..db853fb 100644 (file)
@@ -34,14 +34,4 @@ static inline unsigned long rdsp(void)
 /* Write the user-mode stack pointer. */
 #define wrusp(usp) __asm__ __volatile__ ("move %0, $usp" : : "rm" (usp))
 
-#define nop() __asm__ __volatile__ ("nop");
-
-#define xchg(ptr,x) \
-       ((__typeof__(*(ptr)))__xchg((unsigned long) (x),(ptr),sizeof(*(ptr))))
-
-#define tas(ptr) (xchg((ptr),1))
-
-struct __xchg_dummy { unsigned long a[100]; };
-#define __xg(x) ((struct __xchg_dummy *)(x))
-
 #endif /* _ASM_CRIS_ARCH_SYSTEM_H */
index bbf0938..1056a5d 100644 (file)
@@ -5,7 +5,7 @@
 
 #include <linux/compiler.h>
 #include <linux/types.h>
-#include <asm/system.h>
+#include <asm/cmpxchg.h>
 #include <arch/atomic.h>
 
 /*
diff --git a/arch/cris/include/asm/barrier.h b/arch/cris/include/asm/barrier.h
new file mode 100644 (file)
index 0000000..198ad7f
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef __ASM_CRIS_BARRIER_H
+#define __ASM_CRIS_BARRIER_H
+
+#define nop() __asm__ __volatile__ ("nop");
+
+#define barrier() __asm__ __volatile__("": : :"memory")
+#define mb() barrier()
+#define rmb() mb()
+#define wmb() mb()
+#define read_barrier_depends() do { } while(0)
+#define set_mb(var, value)  do { var = value; mb(); } while (0)
+
+#ifdef CONFIG_SMP
+#define smp_mb()        mb()
+#define smp_rmb()       rmb()
+#define smp_wmb()       wmb()
+#define smp_read_barrier_depends()     read_barrier_depends()
+#else
+#define smp_mb()        barrier()
+#define smp_rmb()       barrier()
+#define smp_wmb()       barrier()
+#define smp_read_barrier_depends()     do { } while(0)
+#endif
+
+#endif /* __ASM_CRIS_BARRIER_H */
index a78a2d7..184066c 100644 (file)
@@ -19,7 +19,6 @@
 #endif
 
 #include <arch/bitops.h>
-#include <asm/system.h>
 #include <linux/atomic.h>
 #include <linux/compiler.h>
 
diff --git a/arch/cris/include/asm/cmpxchg.h b/arch/cris/include/asm/cmpxchg.h
new file mode 100644 (file)
index 0000000..b756dac
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef __ASM_CRIS_CMPXCHG__
+#define __ASM_CRIS_CMPXCHG__
+
+#include <linux/irqflags.h>
+
+static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
+{
+  /* since Etrax doesn't have any atomic xchg instructions, we need to disable
+     irq's (if enabled) and do it with move.d's */
+  unsigned long flags,temp;
+  local_irq_save(flags); /* save flags, including irq enable bit and shut off irqs */
+  switch (size) {
+  case 1:
+    *((unsigned char *)&temp) = x;
+    x = *(unsigned char *)ptr;
+    *(unsigned char *)ptr = *((unsigned char *)&temp);
+    break;
+  case 2:
+    *((unsigned short *)&temp) = x;
+    x = *(unsigned short *)ptr;
+    *(unsigned short *)ptr = *((unsigned short *)&temp);
+    break;
+  case 4:
+    temp = x;
+    x = *(unsigned long *)ptr;
+    *(unsigned long *)ptr = temp;
+    break;
+  }
+  local_irq_restore(flags); /* restore irq enable bit */
+  return x;
+}
+
+#define xchg(ptr,x) \
+       ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
+
+#define tas(ptr) (xchg((ptr),1))
+
+#include <asm-generic/cmpxchg-local.h>
+
+/*
+ * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
+ * them available.
+ */
+#define cmpxchg_local(ptr, o, n)                                              \
+       ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
+                       (unsigned long)(n), sizeof(*(ptr))))
+#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
+
+#ifndef CONFIG_SMP
+#include <asm-generic/cmpxchg.h>
+#endif
+
+#endif /* __ASM_CRIS_CMPXCHG__ */
diff --git a/arch/cris/include/asm/exec.h b/arch/cris/include/asm/exec.h
new file mode 100644 (file)
index 0000000..9665dab
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __ASM_CRIS_EXEC_H
+#define __ASM_CRIS_EXEC_H
+
+#define arch_align_stack(x) (x)
+
+#endif /* __ASM_CRIS_EXEC_H */
index 3f7248f..4210d72 100644 (file)
 #ifndef __ASM_CRIS_PROCESSOR_H
 #define __ASM_CRIS_PROCESSOR_H
 
-#include <asm/system.h>
 #include <asm/page.h>
 #include <asm/ptrace.h>
 #include <arch/processor.h>
+#include <arch/system.h>
 
 struct task_struct;
 
@@ -72,4 +72,13 @@ static inline void release_thread(struct task_struct *dead_task)
 
 #define cpu_relax()     barrier()
 
+/*
+ * disable hlt during certain critical i/o operations
+ */
+#define HAVE_DISABLE_HLT
+void disable_hlt(void);
+void enable_hlt(void);
+
+void default_idle(void);
+
 #endif /* __ASM_CRIS_PROCESSOR_H */
diff --git a/arch/cris/include/asm/switch_to.h b/arch/cris/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..d842e11
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef __ASM_CRIS_SWITCH_TO_H
+#define __ASM_CRIS_SWITCH_TO_H
+
+/* the switch_to macro calls resume, an asm function in entry.S which does the actual
+ * task switching.
+ */
+
+extern struct task_struct *resume(struct task_struct *prev, struct task_struct *next, int);
+#define switch_to(prev,next,last) last = resume(prev,next, \
+                                        (int)&((struct task_struct *)0)->thread)
+
+#endif /* __ASM_CRIS_SWITCH_TO_H */
diff --git a/arch/cris/include/asm/system.h b/arch/cris/include/asm/system.h
deleted file mode 100644 (file)
index ea10592..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-#ifndef __ASM_CRIS_SYSTEM_H
-#define __ASM_CRIS_SYSTEM_H
-
-#include <linux/irqflags.h>
-#include <arch/system.h>
-
-/* the switch_to macro calls resume, an asm function in entry.S which does the actual
- * task switching.
- */
-
-extern struct task_struct *resume(struct task_struct *prev, struct task_struct *next, int);
-#define switch_to(prev,next,last) last = resume(prev,next, \
-                                        (int)&((struct task_struct *)0)->thread)
-
-#define barrier() __asm__ __volatile__("": : :"memory")
-#define mb() barrier()
-#define rmb() mb()
-#define wmb() mb()
-#define read_barrier_depends() do { } while(0)
-#define set_mb(var, value)  do { var = value; mb(); } while (0)
-
-#ifdef CONFIG_SMP
-#define smp_mb()        mb()
-#define smp_rmb()       rmb()
-#define smp_wmb()       wmb()
-#define smp_read_barrier_depends()     read_barrier_depends()
-#else
-#define smp_mb()        barrier()
-#define smp_rmb()       barrier()
-#define smp_wmb()       barrier()
-#define smp_read_barrier_depends()     do { } while(0)
-#endif
-
-#define iret()
-
-/*
- * disable hlt during certain critical i/o operations
- */
-#define HAVE_DISABLE_HLT
-void disable_hlt(void);
-void enable_hlt(void);
-
-static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
-{
-  /* since Etrax doesn't have any atomic xchg instructions, we need to disable
-     irq's (if enabled) and do it with move.d's */
-  unsigned long flags,temp;
-  local_irq_save(flags); /* save flags, including irq enable bit and shut off irqs */
-  switch (size) {
-  case 1:
-    *((unsigned char *)&temp) = x;
-    x = *(unsigned char *)ptr;
-    *(unsigned char *)ptr = *((unsigned char *)&temp);
-    break;
-  case 2:
-    *((unsigned short *)&temp) = x;
-    x = *(unsigned short *)ptr;
-    *(unsigned short *)ptr = *((unsigned short *)&temp);
-    break;
-  case 4:
-    temp = x;
-    x = *(unsigned long *)ptr;
-    *(unsigned long *)ptr = temp;
-    break;
-  }
-  local_irq_restore(flags); /* restore irq enable bit */
-  return x;
-}
-
-#include <asm-generic/cmpxchg-local.h>
-
-/*
- * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
- * them available.
- */
-#define cmpxchg_local(ptr, o, n)                                              \
-       ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
-                       (unsigned long)(n), sizeof(*(ptr))))
-#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
-
-#ifndef CONFIG_SMP
-#include <asm-generic/cmpxchg.h>
-#endif
-
-#define arch_align_stack(x) (x)
-
-void default_idle(void);
-
-#endif
index 788eb22..d36836d 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/spinlock.h>
 
 #include <asm/io.h>
+#include <arch/system.h>
 
 /* called by the assembler IRQ entry functions defined in irq.h
  * to dispatch the interrupts to registered handlers
index d8f50ff..891dad8 100644 (file)
@@ -16,7 +16,6 @@
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
 #include <linux/init_task.h>
index 48b0f39..d114ad3 100644 (file)
@@ -21,7 +21,6 @@
 #include <asm/uaccess.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/processor.h>
 
 
index b712f49..32c3d24 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/pfn.h>
 #include <linux/cpu.h>
 #include <asm/setup.h>
+#include <arch/system.h>
 
 /*
  * Setup options
index 8da53f3..a11ad32 100644 (file)
@@ -17,6 +17,7 @@
 
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
+#include <arch/system.h>
 
 extern void arch_enable_nmi(void);
 extern void stop_watchdog(void);
index 9dcac8e..b4760d8 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/module.h>
 #include <linux/wait.h>
 #include <asm/uaccess.h>
+#include <arch/system.h>
 
 extern int find_fixup_code(struct pt_regs *);
 extern void die_if_kernel(const char *, struct pt_regs *, long);
index 0d8a7d6..b86329d 100644 (file)
@@ -16,7 +16,7 @@
 
 #include <linux/types.h>
 #include <asm/spr-regs.h>
-#include <asm/system.h>
+#include <asm/cmpxchg.h>
 
 #ifdef CONFIG_SMP
 #error not SMP safe
@@ -181,61 +181,6 @@ static inline void atomic64_dec(atomic64_t *v)
 #define atomic64_dec_and_test(v)       (atomic64_dec_return((v)) == 0)
 #define atomic64_inc_and_test(v)       (atomic64_inc_return((v)) == 0)
 
-/*****************************************************************************/
-/*
- * exchange value with memory
- */
-extern uint64_t __xchg_64(uint64_t i, volatile void *v);
-
-#ifndef CONFIG_FRV_OUTOFLINE_ATOMIC_OPS
-
-#define xchg(ptr, x)                                                           \
-({                                                                             \
-       __typeof__(ptr) __xg_ptr = (ptr);                                       \
-       __typeof__(*(ptr)) __xg_orig;                                           \
-                                                                               \
-       switch (sizeof(__xg_orig)) {                                            \
-       case 4:                                                                 \
-               asm volatile(                                                   \
-                       "swap%I0 %M0,%1"                                        \
-                       : "+m"(*__xg_ptr), "=r"(__xg_orig)                      \
-                       : "1"(x)                                                \
-                       : "memory"                                              \
-                       );                                                      \
-               break;                                                          \
-                                                                               \
-       default:                                                                \
-               __xg_orig = (__typeof__(__xg_orig))0;                           \
-               asm volatile("break");                                          \
-               break;                                                          \
-       }                                                                       \
-                                                                               \
-       __xg_orig;                                                              \
-})
-
-#else
-
-extern uint32_t __xchg_32(uint32_t i, volatile void *v);
-
-#define xchg(ptr, x)                                                                           \
-({                                                                                             \
-       __typeof__(ptr) __xg_ptr = (ptr);                                                       \
-       __typeof__(*(ptr)) __xg_orig;                                                           \
-                                                                                               \
-       switch (sizeof(__xg_orig)) {                                                            \
-       case 4: __xg_orig = (__typeof__(*(ptr))) __xchg_32((uint32_t) x, __xg_ptr);     break;  \
-       default:                                                                                \
-               __xg_orig = (__typeof__(__xg_orig))0;                                                                   \
-               asm volatile("break");                                                          \
-               break;                                                                          \
-       }                                                                                       \
-       __xg_orig;                                                                              \
-})
-
-#endif
-
-#define tas(ptr) (xchg((ptr), 1))
-
 #define atomic_cmpxchg(v, old, new)    (cmpxchg(&(v)->counter, old, new))
 #define atomic_xchg(v, new)            (xchg(&(v)->counter, new))
 #define atomic64_cmpxchg(v, old, new)  (__cmpxchg_64(old, new, &(v)->counter))
diff --git a/arch/frv/include/asm/barrier.h b/arch/frv/include/asm/barrier.h
new file mode 100644 (file)
index 0000000..06776ad
--- /dev/null
@@ -0,0 +1,29 @@
+/* FR-V CPU memory barrier definitions
+ *
+ * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.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 _ASM_BARRIER_H
+#define _ASM_BARRIER_H
+
+#define nop()                  asm volatile ("nop"::)
+
+#define mb()                   asm volatile ("membar" : : :"memory")
+#define rmb()                  asm volatile ("membar" : : :"memory")
+#define wmb()                  asm volatile ("membar" : : :"memory")
+#define read_barrier_depends() do { } while (0)
+
+#define smp_mb()                       barrier()
+#define smp_rmb()                      barrier()
+#define smp_wmb()                      barrier()
+#define smp_read_barrier_depends()     do {} while(0)
+#define set_mb(var, value) \
+       do { var = (value); barrier(); } while (0)
+
+#endif /* _ASM_BARRIER_H */
index 2e05450..dd01bcf 100644 (file)
@@ -51,4 +51,6 @@ do {                                          \
 
 #include <asm-generic/bug.h>
 
+extern void die_if_kernel(const char *, ...) __attribute__((format(printf, 1, 2)));
+
 #endif
diff --git a/arch/frv/include/asm/cmpxchg.h b/arch/frv/include/asm/cmpxchg.h
new file mode 100644 (file)
index 0000000..5b04dd0
--- /dev/null
@@ -0,0 +1,172 @@
+/* xchg and cmpxchg operation emulation for FR-V
+ *
+ * For an explanation of how atomic ops work in this arch, see:
+ *   Documentation/frv/atomic-ops.txt
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.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 _ASM_CMPXCHG_H
+#define _ASM_CMPXCHG_H
+
+#include <linux/types.h>
+
+/*****************************************************************************/
+/*
+ * exchange value with memory
+ */
+extern uint64_t __xchg_64(uint64_t i, volatile void *v);
+
+#ifndef CONFIG_FRV_OUTOFLINE_ATOMIC_OPS
+
+#define xchg(ptr, x)                                                           \
+({                                                                             \
+       __typeof__(ptr) __xg_ptr = (ptr);                                       \
+       __typeof__(*(ptr)) __xg_orig;                                           \
+                                                                               \
+       switch (sizeof(__xg_orig)) {                                            \
+       case 4:                                                                 \
+               asm volatile(                                                   \
+                       "swap%I0 %M0,%1"                                        \
+                       : "+m"(*__xg_ptr), "=r"(__xg_orig)                      \
+                       : "1"(x)                                                \
+                       : "memory"                                              \
+                       );                                                      \
+               break;                                                          \
+                                                                               \
+       default:                                                                \
+               __xg_orig = (__typeof__(__xg_orig))0;                           \
+               asm volatile("break");                                          \
+               break;                                                          \
+       }                                                                       \
+                                                                               \
+       __xg_orig;                                                              \
+})
+
+#else
+
+extern uint32_t __xchg_32(uint32_t i, volatile void *v);
+
+#define xchg(ptr, x)                                                                           \
+({                                                                                             \
+       __typeof__(ptr) __xg_ptr = (ptr);                                                       \
+       __typeof__(*(ptr)) __xg_orig;                                                           \
+                                                                                               \
+       switch (sizeof(__xg_orig)) {                                                            \
+       case 4: __xg_orig = (__typeof__(*(ptr))) __xchg_32((uint32_t) x, __xg_ptr);     break;  \
+       default:                                                                                \
+               __xg_orig = (__typeof__(__xg_orig))0;                                                                   \
+               asm volatile("break");                                                          \
+               break;                                                                          \
+       }                                                                                       \
+       __xg_orig;                                                                              \
+})
+
+#endif
+
+#define tas(ptr) (xchg((ptr), 1))
+
+/*****************************************************************************/
+/*
+ * compare and conditionally exchange value with memory
+ * - if (*ptr == test) then orig = *ptr; *ptr = test;
+ * - if (*ptr != test) then orig = *ptr;
+ */
+extern uint64_t __cmpxchg_64(uint64_t test, uint64_t new, volatile uint64_t *v);
+
+#ifndef CONFIG_FRV_OUTOFLINE_ATOMIC_OPS
+
+#define cmpxchg(ptr, test, new)                                                        \
+({                                                                             \
+       __typeof__(ptr) __xg_ptr = (ptr);                                       \
+       __typeof__(*(ptr)) __xg_orig, __xg_tmp;                                 \
+       __typeof__(*(ptr)) __xg_test = (test);                                  \
+       __typeof__(*(ptr)) __xg_new = (new);                                    \
+                                                                               \
+       switch (sizeof(__xg_orig)) {                                            \
+       case 4:                                                                 \
+               asm volatile(                                                   \
+                       "0:                                             \n"     \
+                       "       orcc            gr0,gr0,gr0,icc3        \n"     \
+                       "       ckeq            icc3,cc7                \n"     \
+                       "       ld.p            %M0,%1                  \n"     \
+                       "       orcr            cc7,cc7,cc3             \n"     \
+                       "       sub%I4cc        %1,%4,%2,icc0           \n"     \
+                       "       bne             icc0,#0,1f              \n"     \
+                       "       cst.p           %3,%M0          ,cc3,#1 \n"     \
+                       "       corcc           gr29,gr29,gr0   ,cc3,#1 \n"     \
+                       "       beq             icc3,#0,0b              \n"     \
+                       "1:                                             \n"     \
+                       : "+U"(*__xg_ptr), "=&r"(__xg_orig), "=&r"(__xg_tmp)    \
+                       : "r"(__xg_new), "NPr"(__xg_test)                       \
+                       : "memory", "cc7", "cc3", "icc3", "icc0"                \
+                       );                                                      \
+               break;                                                          \
+                                                                               \
+       default:                                                                \
+               __xg_orig = (__typeof__(__xg_orig))0;                           \
+               asm volatile("break");                                          \
+               break;                                                          \
+       }                                                                       \
+                                                                               \
+       __xg_orig;                                                              \
+})
+
+#else
+
+extern uint32_t __cmpxchg_32(uint32_t *v, uint32_t test, uint32_t new);
+
+#define cmpxchg(ptr, test, new)                                                        \
+({                                                                             \
+       __typeof__(ptr) __xg_ptr = (ptr);                                       \
+       __typeof__(*(ptr)) __xg_orig;                                           \
+       __typeof__(*(ptr)) __xg_test = (test);                                  \
+       __typeof__(*(ptr)) __xg_new = (new);                                    \
+                                                                               \
+       switch (sizeof(__xg_orig)) {                                            \
+       case 4: __xg_orig = (__force __typeof__(*ptr))                          \
+                       __cmpxchg_32((__force uint32_t *)__xg_ptr,              \
+                                        (__force uint32_t)__xg_test,           \
+                                        (__force uint32_t)__xg_new); break;    \
+       default:                                                                \
+               __xg_orig = (__typeof__(__xg_orig))0;                           \
+               asm volatile("break");                                          \
+               break;                                                          \
+       }                                                                       \
+                                                                               \
+       __xg_orig;                                                              \
+})
+
+#endif
+
+#include <asm-generic/cmpxchg-local.h>
+
+static inline unsigned long __cmpxchg_local(volatile void *ptr,
+                                     unsigned long old,
+                                     unsigned long new, int size)
+{
+       switch (size) {
+       case 4:
+               return cmpxchg((unsigned long *)ptr, old, new);
+       default:
+               return __cmpxchg_local_generic(ptr, old, new, size);
+       }
+
+       return old;
+}
+
+/*
+ * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
+ * them available.
+ */
+#define cmpxchg_local(ptr, o, n)                                       \
+       ((__typeof__(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(o), \
+                       (unsigned long)(n), sizeof(*(ptr))))
+#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
+
+#endif /* _ASM_CMPXCHG_H */
diff --git a/arch/frv/include/asm/exec.h b/arch/frv/include/asm/exec.h
new file mode 100644 (file)
index 0000000..65c9130
--- /dev/null
@@ -0,0 +1,17 @@
+/* FR-V CPU executable handling
+ *
+ * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.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 _ASM_EXEC_H
+#define _ASM_EXEC_H
+
+#define arch_align_stack(x) (x)
+
+#endif /* _ASM_EXEC_H */
diff --git a/arch/frv/include/asm/switch_to.h b/arch/frv/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..2cf0f6a
--- /dev/null
@@ -0,0 +1,35 @@
+/* FR-V CPU basic task switching
+ *
+ * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.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 _ASM_SWITCH_TO_H
+#define _ASM_SWITCH_TO_H
+
+#include <linux/thread_info.h>
+
+/*
+ * switch_to(prev, next) should switch from task `prev' to `next'
+ * `prev' will never be the same as `next'.
+ * The `mb' is to tell GCC not to cache `current' across this call.
+ */
+extern asmlinkage
+struct task_struct *__switch_to(struct thread_struct *prev_thread,
+                               struct thread_struct *next_thread,
+                               struct task_struct *prev);
+
+#define switch_to(prev, next, last)                                    \
+do {                                                                   \
+       (prev)->thread.sched_lr =                                       \
+               (unsigned long) __builtin_return_address(0);            \
+       (last) = __switch_to(&(prev)->thread, &(next)->thread, (prev)); \
+       mb();                                                           \
+} while(0)
+
+#endif /* _ASM_SWITCH_TO_H */
diff --git a/arch/frv/include/asm/system.h b/arch/frv/include/asm/system.h
deleted file mode 100644 (file)
index 6c10fd2..0000000
+++ /dev/null
@@ -1,158 +0,0 @@
-/* system.h: FR-V CPU control definitions
- *
- * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.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 _ASM_SYSTEM_H
-#define _ASM_SYSTEM_H
-
-#include <linux/types.h>
-#include <linux/linkage.h>
-#include <linux/kernel.h>
-
-struct thread_struct;
-
-/*
- * switch_to(prev, next) should switch from task `prev' to `next'
- * `prev' will never be the same as `next'.
- * The `mb' is to tell GCC not to cache `current' across this call.
- */
-extern asmlinkage
-struct task_struct *__switch_to(struct thread_struct *prev_thread,
-                               struct thread_struct *next_thread,
-                               struct task_struct *prev);
-
-#define switch_to(prev, next, last)                                    \
-do {                                                                   \
-       (prev)->thread.sched_lr =                                       \
-               (unsigned long) __builtin_return_address(0);            \
-       (last) = __switch_to(&(prev)->thread, &(next)->thread, (prev)); \
-       mb();                                                           \
-} while(0)
-
-/*
- * Force strict CPU ordering.
- */
-#define nop()                  asm volatile ("nop"::)
-#define mb()                   asm volatile ("membar" : : :"memory")
-#define rmb()                  asm volatile ("membar" : : :"memory")
-#define wmb()                  asm volatile ("membar" : : :"memory")
-#define read_barrier_depends() do { } while (0)
-
-#define smp_mb()                       barrier()
-#define smp_rmb()                      barrier()
-#define smp_wmb()                      barrier()
-#define smp_read_barrier_depends()     do {} while(0)
-#define set_mb(var, value) \
-       do { var = (value); barrier(); } while (0)
-
-extern void die_if_kernel(const char *, ...) __attribute__((format(printf, 1, 2)));
-extern void free_initmem(void);
-
-#define arch_align_stack(x) (x)
-
-/*****************************************************************************/
-/*
- * compare and conditionally exchange value with memory
- * - if (*ptr == test) then orig = *ptr; *ptr = test;
- * - if (*ptr != test) then orig = *ptr;
- */
-extern uint64_t __cmpxchg_64(uint64_t test, uint64_t new, volatile uint64_t *v);
-
-#ifndef CONFIG_FRV_OUTOFLINE_ATOMIC_OPS
-
-#define cmpxchg(ptr, test, new)                                                        \
-({                                                                             \
-       __typeof__(ptr) __xg_ptr = (ptr);                                       \
-       __typeof__(*(ptr)) __xg_orig, __xg_tmp;                                 \
-       __typeof__(*(ptr)) __xg_test = (test);                                  \
-       __typeof__(*(ptr)) __xg_new = (new);                                    \
-                                                                               \
-       switch (sizeof(__xg_orig)) {                                            \
-       case 4:                                                                 \
-               asm volatile(                                                   \
-                       "0:                                             \n"     \
-                       "       orcc            gr0,gr0,gr0,icc3        \n"     \
-                       "       ckeq            icc3,cc7                \n"     \
-                       "       ld.p            %M0,%1                  \n"     \
-                       "       orcr            cc7,cc7,cc3             \n"     \
-                       "       sub%I4cc        %1,%4,%2,icc0           \n"     \
-                       "       bne             icc0,#0,1f              \n"     \
-                       "       cst.p           %3,%M0          ,cc3,#1 \n"     \
-                       "       corcc           gr29,gr29,gr0   ,cc3,#1 \n"     \
-                       "       beq             icc3,#0,0b              \n"     \
-                       "1:                                             \n"     \
-                       : "+U"(*__xg_ptr), "=&r"(__xg_orig), "=&r"(__xg_tmp)    \
-                       : "r"(__xg_new), "NPr"(__xg_test)                       \
-                       : "memory", "cc7", "cc3", "icc3", "icc0"                \
-                       );                                                      \
-               break;                                                          \
-                                                                               \
-       default:                                                                \
-               __xg_orig = (__typeof__(__xg_orig))0;                           \
-               asm volatile("break");                                          \
-               break;                                                          \
-       }                                                                       \
-                                                                               \
-       __xg_orig;                                                              \
-})
-
-#else
-
-extern uint32_t __cmpxchg_32(uint32_t *v, uint32_t test, uint32_t new);
-
-#define cmpxchg(ptr, test, new)                                                        \
-({                                                                             \
-       __typeof__(ptr) __xg_ptr = (ptr);                                       \
-       __typeof__(*(ptr)) __xg_orig;                                           \
-       __typeof__(*(ptr)) __xg_test = (test);                                  \
-       __typeof__(*(ptr)) __xg_new = (new);                                    \
-                                                                               \
-       switch (sizeof(__xg_orig)) {                                            \
-       case 4: __xg_orig = (__force __typeof__(*ptr))                          \
-                       __cmpxchg_32((__force uint32_t *)__xg_ptr,              \
-                                        (__force uint32_t)__xg_test,           \
-                                        (__force uint32_t)__xg_new); break;    \
-       default:                                                                \
-               __xg_orig = (__typeof__(__xg_orig))0;                           \
-               asm volatile("break");                                          \
-               break;                                                          \
-       }                                                                       \
-                                                                               \
-       __xg_orig;                                                              \
-})
-
-#endif
-
-#include <asm-generic/cmpxchg-local.h>
-
-static inline unsigned long __cmpxchg_local(volatile void *ptr,
-                                     unsigned long old,
-                                     unsigned long new, int size)
-{
-       switch (size) {
-       case 4:
-               return cmpxchg((unsigned long *)ptr, old, new);
-       default:
-               return __cmpxchg_local_generic(ptr, old, new, size);
-       }
-
-       return old;
-}
-
-/*
- * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
- * them available.
- */
-#define cmpxchg_local(ptr, o, n)                                       \
-       ((__typeof__(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(o), \
-                       (unsigned long)(n), sizeof(*(ptr))))
-#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
-
-#endif /* _ASM_SYSTEM_H */
index 2845139..a0228f7 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/serial_reg.h>
 #include <linux/start_kernel.h>
 
-#include <asm/system.h>
 #include <asm/serial-regs.h>
 #include <asm/timer-regs.h>
 #include <asm/irc-regs.h>
index 2ca641d..0707d35 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/serial_reg.h>
 
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/irc-regs.h>
 #include <asm/timer-regs.h>
 #include <asm/gdb-stub.h>
index a6d5381..bbe78b0 100644 (file)
 
 #include <asm/asm-offsets.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/gdb-stub.h>
 
 #define LEDS(x) do { /* *(u32*)0xe1200004 = ~(x); mb(); */ } while(0)
index 9afc2ea..2cc327a 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/bitops.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/delay.h>
 #include <asm/irq.h>
 #include <asm/irc-regs.h>
index 4d4ad09..95e4eb4 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/bitops.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/delay.h>
 #include <asm/irq.h>
 #include <asm/irc-regs.h>
index 4d034c7..ba648da 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/bitops.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/delay.h>
 #include <asm/irq.h>
 #include <asm/irc-regs.h>
index 3facbc2..2239346 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/atomic.h>
 #include <asm/io.h>
 #include <asm/smp.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
 #include <asm/delay.h>
index 29cc497..d4de48b 100644 (file)
@@ -28,7 +28,6 @@
 
 #include <asm/asm-offsets.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/setup.h>
 #include <asm/pgtable.h>
 #include <asm/tlb.h>
index 9d68f7f..3987ff8 100644 (file)
@@ -26,7 +26,6 @@
 #include <asm/uaccess.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/processor.h>
 #include <asm/unistd.h>
 
index 1d2dfe6..5cfd142 100644 (file)
@@ -23,7 +23,6 @@
 #include <asm/asm-offsets.h>
 #include <asm/setup.h>
 #include <asm/fpu.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/siginfo.h>
index a325d57..331c1e2 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/ptrace.h>
 #include <linux/hardirq.h>
 
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
 #include <asm/gdb-stub.h>
index fbe5f0d..a19effc 100644 (file)
@@ -33,7 +33,6 @@
 #include <asm/segment.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/mmu_context.h>
 #include <asm/virtconvert.h>
 #include <asm/sections.h>
index fb78be3..e9217e6 100644 (file)
@@ -21,7 +21,6 @@
 #include <asm/page.h>
 #include <asm/pgalloc.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 #undef DEBUG
 
index f5a38c1..40901e3 100644 (file)
@@ -2,6 +2,7 @@
 #define __ARCH_H8300_ATOMIC__
 
 #include <linux/types.h>
+#include <asm/cmpxchg.h>
 
 /*
  * Atomic operations that C can't guarantee us.  Useful for
@@ -13,7 +14,6 @@
 #define atomic_read(v)         (*(volatile int *)&(v)->counter)
 #define atomic_set(v, i)       (((v)->counter) = i)
 
-#include <asm/system.h>
 #include <linux/kernel.h>
 
 static __inline__ int atomic_add_return(int i, atomic_t *v)
@@ -102,8 +102,6 @@ static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
        return ret;
 }
 
-#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
-
 static inline int __atomic_add_unless(atomic_t *v, int a, int u)
 {
        int ret;
diff --git a/arch/h8300/include/asm/barrier.h b/arch/h8300/include/asm/barrier.h
new file mode 100644 (file)
index 0000000..c7283c3
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef _H8300_BARRIER_H
+#define _H8300_BARRIER_H
+
+#define nop()  asm volatile ("nop"::)
+
+/*
+ * Force strict CPU ordering.
+ * Not really required on H8...
+ */
+#define mb()   asm volatile (""   : : :"memory")
+#define rmb()  asm volatile (""   : : :"memory")
+#define wmb()  asm volatile (""   : : :"memory")
+#define set_mb(var, value) do { xchg(&var, value); } while (0)
+
+#ifdef CONFIG_SMP
+#define smp_mb()       mb()
+#define smp_rmb()      rmb()
+#define smp_wmb()      wmb()
+#define smp_read_barrier_depends()     read_barrier_depends()
+#else
+#define smp_mb()       barrier()
+#define smp_rmb()      barrier()
+#define smp_wmb()      barrier()
+#define smp_read_barrier_depends()     do { } while(0)
+#endif
+
+#endif /* _H8300_BARRIER_H */
index e856c1b..eb34e0c 100644 (file)
@@ -7,7 +7,6 @@
  */
 
 #include <linux/compiler.h>
-#include <asm/system.h>
 
 #ifdef __KERNEL__
 
index 887c197..1e1be81 100644 (file)
@@ -5,4 +5,8 @@
 #define is_valid_bugaddr(addr) (1)
 
 #include <asm-generic/bug.h>
+
+struct pt_regs;
+extern void die(const char *str, struct pt_regs *fp, unsigned long err);
+
 #endif
diff --git a/arch/h8300/include/asm/cmpxchg.h b/arch/h8300/include/asm/cmpxchg.h
new file mode 100644 (file)
index 0000000..cdb203e
--- /dev/null
@@ -0,0 +1,60 @@
+#ifndef __ARCH_H8300_CMPXCHG__
+#define __ARCH_H8300_CMPXCHG__
+
+#include <linux/irqflags.h>
+
+#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
+
+struct __xchg_dummy { unsigned long a[100]; };
+#define __xg(x) ((volatile struct __xchg_dummy *)(x))
+
+static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
+{
+  unsigned long tmp, flags;
+
+  local_irq_save(flags);
+
+  switch (size) {
+  case 1:
+    __asm__ __volatile__
+    ("mov.b %2,%0\n\t"
+     "mov.b %1,%2"
+    : "=&r" (tmp) : "r" (x), "m" (*__xg(ptr)) : "memory");
+    break;
+  case 2:
+    __asm__ __volatile__
+    ("mov.w %2,%0\n\t"
+     "mov.w %1,%2"
+    : "=&r" (tmp) : "r" (x), "m" (*__xg(ptr)) : "memory");
+    break;
+  case 4:
+    __asm__ __volatile__
+    ("mov.l %2,%0\n\t"
+     "mov.l %1,%2"
+    : "=&r" (tmp) : "r" (x), "m" (*__xg(ptr)) : "memory");
+    break;
+  default:
+    tmp = 0;     
+  }
+  local_irq_restore(flags);
+  return tmp;
+}
+
+#include <asm-generic/cmpxchg-local.h>
+
+/*
+ * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
+ * them available.
+ */
+#define cmpxchg_local(ptr, o, n)                                              \
+       ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
+                       (unsigned long)(n), sizeof(*(ptr))))
+#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
+
+#ifndef CONFIG_SMP
+#include <asm-generic/cmpxchg.h>
+#endif
+
+#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
+
+#endif /* __ARCH_H8300_CMPXCHG__ */
diff --git a/arch/h8300/include/asm/exec.h b/arch/h8300/include/asm/exec.h
new file mode 100644 (file)
index 0000000..c01c45c
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _H8300_EXEC_H
+#define _H8300_EXEC_H
+
+#define arch_align_stack(x) (x)
+
+#endif /* _H8300_EXEC_H */
index e834b60..61fabf1 100644 (file)
@@ -135,4 +135,9 @@ unsigned long get_wchan(struct task_struct *p);
 
 #define cpu_relax()    barrier()
 
+#define HARD_RESET_NOW() ({            \
+        local_irq_disable();           \
+        asm("jmp @@0");                        \
+})
+
 #endif
diff --git a/arch/h8300/include/asm/switch_to.h b/arch/h8300/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..cdd8731
--- /dev/null
@@ -0,0 +1,50 @@
+#ifndef _H8300_SWITCH_TO_H
+#define _H8300_SWITCH_TO_H
+
+/*
+ * switch_to(n) should switch tasks to task ptr, first checking that
+ * ptr isn't the current task, in which case it does nothing.  This
+ * also clears the TS-flag if the task we switched to has used the
+ * math co-processor latest.
+ */
+/*
+ * switch_to() saves the extra registers, that are not saved
+ * automatically by SAVE_SWITCH_STACK in resume(), ie. d0-d5 and
+ * a0-a1. Some of these are used by schedule() and its predecessors
+ * and so we might get see unexpected behaviors when a task returns
+ * with unexpected register values.
+ *
+ * syscall stores these registers itself and none of them are used
+ * by syscall after the function in the syscall has been called.
+ *
+ * Beware that resume now expects *next to be in d1 and the offset of
+ * tss to be in a1. This saves a few instructions as we no longer have
+ * to push them onto the stack and read them back right after.
+ *
+ * 02/17/96 - Jes Sorensen (jds@kom.auc.dk)
+ *
+ * Changed 96/09/19 by Andreas Schwab
+ * pass prev in a0, next in a1, offset of tss in d1, and whether
+ * the mm structures are shared in d2 (to avoid atc flushing).
+ *
+ * H8/300 Porting 2002/09/04 Yoshinori Sato
+ */
+
+asmlinkage void resume(void);
+#define switch_to(prev,next,last) {                         \
+  void *_last;                                             \
+  __asm__ __volatile__(                                            \
+                       "mov.l  %1, er0\n\t"                \
+                       "mov.l  %2, er1\n\t"                \
+                        "mov.l  %3, er2\n\t"                \
+                       "jsr @_resume\n\t"                  \
+                        "mov.l  er2,%0\n\t"                 \
+                      : "=r" (_last)                       \
+                      : "r" (&(prev->thread)),             \
+                        "r" (&(next->thread)),             \
+                         "g" (prev)                         \
+                      : "cc", "er0", "er1", "er2", "er3"); \
+  (last) = _last;                                          \
+}
+
+#endif /* _H8300_SWITCH_TO_H */
diff --git a/arch/h8300/include/asm/system.h b/arch/h8300/include/asm/system.h
deleted file mode 100644 (file)
index 2c2382e..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-#ifndef _H8300_SYSTEM_H
-#define _H8300_SYSTEM_H
-
-#include <linux/linkage.h>
-#include <linux/irqflags.h>
-
-struct pt_regs;
-
-/*
- * switch_to(n) should switch tasks to task ptr, first checking that
- * ptr isn't the current task, in which case it does nothing.  This
- * also clears the TS-flag if the task we switched to has used the
- * math co-processor latest.
- */
-/*
- * switch_to() saves the extra registers, that are not saved
- * automatically by SAVE_SWITCH_STACK in resume(), ie. d0-d5 and
- * a0-a1. Some of these are used by schedule() and its predecessors
- * and so we might get see unexpected behaviors when a task returns
- * with unexpected register values.
- *
- * syscall stores these registers itself and none of them are used
- * by syscall after the function in the syscall has been called.
- *
- * Beware that resume now expects *next to be in d1 and the offset of
- * tss to be in a1. This saves a few instructions as we no longer have
- * to push them onto the stack and read them back right after.
- *
- * 02/17/96 - Jes Sorensen (jds@kom.auc.dk)
- *
- * Changed 96/09/19 by Andreas Schwab
- * pass prev in a0, next in a1, offset of tss in d1, and whether
- * the mm structures are shared in d2 (to avoid atc flushing).
- *
- * H8/300 Porting 2002/09/04 Yoshinori Sato
- */
-
-asmlinkage void resume(void);
-#define switch_to(prev,next,last) {                         \
-  void *_last;                                             \
-  __asm__ __volatile__(                                            \
-                       "mov.l  %1, er0\n\t"                \
-                       "mov.l  %2, er1\n\t"                \
-                        "mov.l  %3, er2\n\t"                \
-                       "jsr @_resume\n\t"                  \
-                        "mov.l  er2,%0\n\t"                 \
-                      : "=r" (_last)                       \
-                      : "r" (&(prev->thread)),             \
-                        "r" (&(next->thread)),             \
-                         "g" (prev)                         \
-                      : "cc", "er0", "er1", "er2", "er3"); \
-  (last) = _last;                                          \
-}
-
-#define iret() __asm__ __volatile__ ("rte": : :"memory", "sp", "cc")
-
-/*
- * Force strict CPU ordering.
- * Not really required on H8...
- */
-#define nop()  asm volatile ("nop"::)
-#define mb()   asm volatile (""   : : :"memory")
-#define rmb()  asm volatile (""   : : :"memory")
-#define wmb()  asm volatile (""   : : :"memory")
-#define set_mb(var, value) do { xchg(&var, value); } while (0)
-
-#ifdef CONFIG_SMP
-#define smp_mb()       mb()
-#define smp_rmb()      rmb()
-#define smp_wmb()      wmb()
-#define smp_read_barrier_depends()     read_barrier_depends()
-#else
-#define smp_mb()       barrier()
-#define smp_rmb()      barrier()
-#define smp_wmb()      barrier()
-#define smp_read_barrier_depends()     do { } while(0)
-#endif
-
-#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
-
-struct __xchg_dummy { unsigned long a[100]; };
-#define __xg(x) ((volatile struct __xchg_dummy *)(x))
-
-static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
-{
-  unsigned long tmp, flags;
-
-  local_irq_save(flags);
-
-  switch (size) {
-  case 1:
-    __asm__ __volatile__
-    ("mov.b %2,%0\n\t"
-     "mov.b %1,%2"
-    : "=&r" (tmp) : "r" (x), "m" (*__xg(ptr)) : "memory");
-    break;
-  case 2:
-    __asm__ __volatile__
-    ("mov.w %2,%0\n\t"
-     "mov.w %1,%2"
-    : "=&r" (tmp) : "r" (x), "m" (*__xg(ptr)) : "memory");
-    break;
-  case 4:
-    __asm__ __volatile__
-    ("mov.l %2,%0\n\t"
-     "mov.l %1,%2"
-    : "=&r" (tmp) : "r" (x), "m" (*__xg(ptr)) : "memory");
-    break;
-  default:
-    tmp = 0;     
-  }
-  local_irq_restore(flags);
-  return tmp;
-}
-
-#define HARD_RESET_NOW() ({            \
-        local_irq_disable();           \
-        asm("jmp @@0");                        \
-})
-
-#include <asm-generic/cmpxchg-local.h>
-
-/*
- * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
- * them available.
- */
-#define cmpxchg_local(ptr, o, n)                                              \
-       ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
-                       (unsigned long)(n), sizeof(*(ptr))))
-#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
-
-#ifndef CONFIG_SMP
-#include <asm-generic/cmpxchg.h>
-#endif
-
-#define arch_align_stack(x) (x)
-
-extern void die(const char *str, struct pt_regs *fp, unsigned long err);
-
-#endif /* _H8300_SYSTEM_H */
index 1f67fed..2fa8ac7 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 
-#include <asm/system.h>
 #include <asm/traps.h>
 #include <asm/io.h>
 #include <asm/setup.h>
index 1a173b3..0e9c315 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/slab.h>
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/traps.h>
 #include <asm/setup.h>
 #include <asm/pgtable.h>
index 497fa89..748cf65 100644 (file)
@@ -27,7 +27,6 @@
 #include <asm/uaccess.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/processor.h>
 #include <asm/signal.h>
 
index dfa05bd..7833aa3 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/module.h>
 #include <linux/bug.h>
 
-#include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/traps.h>
 #include <asm/page.h>
index 1d092ab..4725359 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/kernel.h>
 #include <linux/ptrace.h>
 
-#include <asm/system.h>
 #include <asm/pgtable.h>
 
 /*
index 7cc3380..973369c 100644 (file)
@@ -36,7 +36,6 @@
 #include <asm/segment.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 
 #undef DEBUG
 
index 944a502..f79edcd 100644 (file)
@@ -19,7 +19,6 @@
 #include <asm/page.h>
 #include <asm/pgalloc.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 #undef DEBUG
 
index 5552ddf..06e3646 100644 (file)
@@ -26,7 +26,6 @@
 #include <asm/segment.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/traps.h>
 #include <asm/io.h>
 
index e220f90..3e25804 100644 (file)
@@ -23,6 +23,7 @@
 #define _ASM_ATOMIC_H
 
 #include <linux/types.h>
+#include <asm/cmpxchg.h>
 
 #define ATOMIC_INIT(i)         { (i) }
 #define atomic_set(v, i)       ((v)->counter = (i))
diff --git a/arch/hexagon/include/asm/barrier.h b/arch/hexagon/include/asm/barrier.h
new file mode 100644 (file)
index 0000000..a4ed6e2
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Memory barrier definitions for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_BARRIER_H
+#define _ASM_BARRIER_H
+
+#define rmb()                          barrier()
+#define read_barrier_depends()         barrier()
+#define wmb()                          barrier()
+#define mb()                           barrier()
+#define smp_rmb()                      barrier()
+#define smp_read_barrier_depends()     barrier()
+#define smp_wmb()                      barrier()
+#define smp_mb()                       barrier()
+#define smp_mb__before_atomic_dec()    barrier()
+#define smp_mb__after_atomic_dec()     barrier()
+#define smp_mb__before_atomic_inc()    barrier()
+#define smp_mb__after_atomic_inc()     barrier()
+
+/*  Set a value and use a memory barrier.  Used by the scheduler somewhere.  */
+#define set_mb(var, value) \
+       do { var = value; mb(); } while (0)
+
+#endif /* _ASM_BARRIER_H */
index d23461e..4caa649 100644 (file)
@@ -24,7 +24,6 @@
 
 #include <linux/compiler.h>
 #include <asm/byteorder.h>
-#include <asm/system.h>
 #include <asm/atomic.h>
 
 #ifdef __KERNEL__
diff --git a/arch/hexagon/include/asm/cmpxchg.h b/arch/hexagon/include/asm/cmpxchg.h
new file mode 100644 (file)
index 0000000..c5f9527
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * xchg/cmpxchg operations for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_CMPXCHG_H
+#define _ASM_CMPXCHG_H
+
+/*
+ * __xchg - atomically exchange a register and a memory location
+ * @x: value to swap
+ * @ptr: pointer to memory
+ * @size:  size of the value
+ *
+ * Only 4 bytes supported currently.
+ *
+ * Note:  there was an errata for V2 about .new's and memw_locked.
+ *
+ */
+static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
+                                  int size)
+{
+       unsigned long retval;
+
+       /*  Can't seem to use printk or panic here, so just stop  */
+       if (size != 4) do { asm volatile("brkpt;\n"); } while (1);
+
+       __asm__ __volatile__ (
+       "1:     %0 = memw_locked(%1);\n"    /*  load into retval */
+       "       memw_locked(%1,P0) = %2;\n" /*  store into memory */
+       "       if !P0 jump 1b;\n"
+       : "=&r" (retval)
+       : "r" (ptr), "r" (x)
+       : "memory", "p0"
+       );
+       return retval;
+}
+
+/*
+ * Atomically swap the contents of a register with memory.  Should be atomic
+ * between multiple CPU's and within interrupts on the same CPU.
+ */
+#define xchg(ptr, v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v), (ptr), \
+       sizeof(*(ptr))))
+
+/*
+ *  see rt-mutex-design.txt; cmpxchg supposedly checks if *ptr == A and swaps.
+ *  looks just like atomic_cmpxchg on our arch currently with a bunch of
+ *  variable casting.
+ */
+#define __HAVE_ARCH_CMPXCHG 1
+
+#define cmpxchg(ptr, old, new)                                 \
+({                                                             \
+       __typeof__(ptr) __ptr = (ptr);                          \
+       __typeof__(*(ptr)) __old = (old);                       \
+       __typeof__(*(ptr)) __new = (new);                       \
+       __typeof__(*(ptr)) __oldval = 0;                        \
+                                                               \
+       asm volatile(                                           \
+               "1:     %0 = memw_locked(%1);\n"                \
+               "       { P0 = cmp.eq(%0,%2);\n"                \
+               "         if (!P0.new) jump:nt 2f; }\n"         \
+               "       memw_locked(%1,p0) = %3;\n"             \
+               "       if (!P0) jump 1b;\n"                    \
+               "2:\n"                                          \
+               : "=&r" (__oldval)                              \
+               : "r" (__ptr), "r" (__old), "r" (__new)         \
+               : "memory", "p0"                                \
+       );                                                      \
+       __oldval;                                               \
+})
+
+#endif /* _ASM_CMPXCHG_H */
diff --git a/arch/hexagon/include/asm/exec.h b/arch/hexagon/include/asm/exec.h
new file mode 100644 (file)
index 0000000..350e6d4
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Process execution related definitions for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_EXEC_H
+#define _ASM_EXEC_H
+
+/*  Should probably shoot for an 8-byte aligned stack pointer  */
+#define STACK_MASK (~7)
+#define arch_align_stack(x) (x & STACK_MASK)
+
+#endif /* _ASM_EXEC_H */
diff --git a/arch/hexagon/include/asm/switch_to.h b/arch/hexagon/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..28ca0df
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Task switching definitions for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_SWITCH_TO_H
+#define _ASM_SWITCH_TO_H
+
+struct thread_struct;
+
+extern struct task_struct *__switch_to(struct task_struct *,
+       struct task_struct *,
+       struct task_struct *);
+
+#define switch_to(p, n, r) do {\
+       r = __switch_to((p), (n), (r));\
+} while (0)
+
+#endif /* _ASM_SWITCH_TO_H */
diff --git a/arch/hexagon/include/asm/system.h b/arch/hexagon/include/asm/system.h
deleted file mode 100644 (file)
index 323ed1d..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * System level definitions for the Hexagon architecture
- *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#ifndef _ASM_SYSTEM_H
-#define _ASM_SYSTEM_H
-
-#include <linux/linkage.h>
-#include <linux/irqflags.h>
-#include <asm/atomic.h>
-#include <asm/hexagon_vm.h>
-
-struct thread_struct;
-
-extern struct task_struct *__switch_to(struct task_struct *,
-       struct task_struct *,
-       struct task_struct *);
-
-#define switch_to(p, n, r) do {\
-       r = __switch_to((p), (n), (r));\
-} while (0)
-
-
-#define rmb()                          barrier()
-#define read_barrier_depends()         barrier()
-#define wmb()                          barrier()
-#define mb()                           barrier()
-#define smp_rmb()                      barrier()
-#define smp_read_barrier_depends()     barrier()
-#define smp_wmb()                      barrier()
-#define smp_mb()                       barrier()
-#define smp_mb__before_atomic_dec()    barrier()
-#define smp_mb__after_atomic_dec()     barrier()
-#define smp_mb__before_atomic_inc()    barrier()
-#define smp_mb__after_atomic_inc()     barrier()
-
-/*
- * __xchg - atomically exchange a register and a memory location
- * @x: value to swap
- * @ptr: pointer to memory
- * @size:  size of the value
- *
- * Only 4 bytes supported currently.
- *
- * Note:  there was an errata for V2 about .new's and memw_locked.
- *
- */
-static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
-                                  int size)
-{
-       unsigned long retval;
-
-       /*  Can't seem to use printk or panic here, so just stop  */
-       if (size != 4) do { asm volatile("brkpt;\n"); } while (1);
-
-       __asm__ __volatile__ (
-       "1:     %0 = memw_locked(%1);\n"    /*  load into retval */
-       "       memw_locked(%1,P0) = %2;\n" /*  store into memory */
-       "       if !P0 jump 1b;\n"
-       : "=&r" (retval)
-       : "r" (ptr), "r" (x)
-       : "memory", "p0"
-       );
-       return retval;
-}
-
-/*
- * Atomically swap the contents of a register with memory.  Should be atomic
- * between multiple CPU's and within interrupts on the same CPU.
- */
-#define xchg(ptr, v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v), (ptr), \
-       sizeof(*(ptr))))
-
-/*  Set a value and use a memory barrier.  Used by the scheduler somewhere.  */
-#define set_mb(var, value) \
-       do { var = value; mb(); } while (0)
-
-/*
- *  see rt-mutex-design.txt; cmpxchg supposedly checks if *ptr == A and swaps.
- *  looks just like atomic_cmpxchg on our arch currently with a bunch of
- *  variable casting.
- */
-#define __HAVE_ARCH_CMPXCHG 1
-
-#define cmpxchg(ptr, old, new)                                 \
-({                                                             \
-       __typeof__(ptr) __ptr = (ptr);                          \
-       __typeof__(*(ptr)) __old = (old);                       \
-       __typeof__(*(ptr)) __new = (new);                       \
-       __typeof__(*(ptr)) __oldval = 0;                        \
-                                                               \
-       asm volatile(                                           \
-               "1:     %0 = memw_locked(%1);\n"                \
-               "       { P0 = cmp.eq(%0,%2);\n"                \
-               "         if (!P0.new) jump:nt 2f; }\n"         \
-               "       memw_locked(%1,p0) = %3;\n"             \
-               "       if (!P0) jump 1b;\n"                    \
-               "2:\n"                                          \
-               : "=&r" (__oldval)                              \
-               : "r" (__ptr), "r" (__old), "r" (__new)         \
-               : "memory", "p0"                                \
-       );                                                      \
-       __oldval;                                               \
-})
-
-/*  Should probably shoot for an 8-byte aligned stack pointer  */
-#define STACK_MASK (~7)
-#define arch_align_stack(x) (x & STACK_MASK)
-
-#endif
index bea3f08..32342de 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/regset.h>
 #include <linux/user.h>
 
-#include <asm/system.h>
 #include <asm/user.h>
 
 static int genregs_get(struct task_struct *target,
index 0123c63..15d1fd2 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/smp.h>
 #include <linux/spinlock.h>
 
-#include <asm/system.h>  /*  xchg  */
 #include <asm/time.h>    /*  timer_interrupt  */
 #include <asm/hexagon_vm.h>
 
index 986a081..591fc1b 100644 (file)
@@ -22,7 +22,6 @@
 #include <asm/registers.h>
 #include <linux/irq.h>
 #include <linux/hardirq.h>
-#include <asm/system.h>
 
 /*
  * show_regs - print pt_regs structure
index 9196b33..98131e1 100644 (file)
@@ -22,7 +22,7 @@
 
 #include <asm/io.h>
 #include <asm/machvec.h>
-#include <asm/system.h>
+#include <asm/setup.h>
 
 void __init
 dig_setup (char **cmdline_p)
index f5f4ef1..f6ea3a3 100644 (file)
@@ -43,7 +43,6 @@
 #include <asm/io.h>
 #include <asm/page.h>          /* PAGE_OFFSET */
 #include <asm/dma.h>
-#include <asm/system.h>                /* wmb() */
 
 #include <asm/acpi-ext.h>
 
index c5e9baa..28f4b23 100644 (file)
@@ -20,7 +20,6 @@ struct task_struct;   /* forward declaration for elf.h */
 #include <asm/pal.h>
 #include <asm/pgtable.h>
 #include <asm/sal.h>
-#include <asm/system.h>
 
 #include "ssc.h"
 
index 0216e28..271f412 100644 (file)
@@ -13,6 +13,7 @@
 #include <asm/io.h>
 #include <asm/pal.h>
 #include <asm/sal.h>
+#include <asm/setup.h>
 
 #include "ssc.h"
 
index a63218e..c13064e 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/skbuff.h>
 #include <linux/notifier.h>
 #include <linux/bitops.h>
-#include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/hpsim.h>
 
index a06dfb1..301609c 100644 (file)
@@ -32,7 +32,6 @@
 
 #include <linux/init.h>
 #include <linux/numa.h>
-#include <asm/system.h>
 #include <asm/numa.h>
 
 #define COMPILER_DEPENDENT_INT64       long
index 3fad89e..7d91166 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/types.h>
 
 #include <asm/intrinsics.h>
-#include <asm/system.h>
 
 
 #define ATOMIC_INIT(i)         ((atomic_t) { (i) })
index 23cebe5..58277fc 100644 (file)
@@ -8,4 +8,6 @@
 #define AT_SYSINFO     32
 #define AT_SYSINFO_EHDR        33
 
+#define AT_VECTOR_SIZE_ARCH 2 /* entries in ARCH_DLINFO */
+
 #endif /* _ASM_IA64_AUXVEC_H */
diff --git a/arch/ia64/include/asm/barrier.h b/arch/ia64/include/asm/barrier.h
new file mode 100644 (file)
index 0000000..60576e0
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Memory barrier definitions.  This is based on information published
+ * in the Processor Abstraction Layer and the System Abstraction Layer
+ * manual.
+ *
+ * Copyright (C) 1998-2003 Hewlett-Packard Co
+ *     David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1999 Asit Mallick <asit.k.mallick@intel.com>
+ * Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
+ */
+#ifndef _ASM_IA64_BARRIER_H
+#define _ASM_IA64_BARRIER_H
+
+#include <linux/compiler.h>
+
+/*
+ * Macros to force memory ordering.  In these descriptions, "previous"
+ * and "subsequent" refer to program order; "visible" means that all
+ * architecturally visible effects of a memory access have occurred
+ * (at a minimum, this means the memory has been read or written).
+ *
+ *   wmb():    Guarantees that all preceding stores to memory-
+ *             like regions are visible before any subsequent
+ *             stores and that all following stores will be
+ *             visible only after all previous stores.
+ *   rmb():    Like wmb(), but for reads.
+ *   mb():     wmb()/rmb() combo, i.e., all previous memory
+ *             accesses are visible before all subsequent
+ *             accesses and vice versa.  This is also known as
+ *             a "fence."
+ *
+ * Note: "mb()" and its variants cannot be used as a fence to order
+ * accesses to memory mapped I/O registers.  For that, mf.a needs to
+ * be used.  However, we don't want to always use mf.a because (a)
+ * it's (presumably) much slower than mf and (b) mf.a is supported for
+ * sequential memory pages only.
+ */
+#define mb()   ia64_mf()
+#define rmb()  mb()
+#define wmb()  mb()
+#define read_barrier_depends() do { } while(0)
+
+#ifdef CONFIG_SMP
+# define smp_mb()      mb()
+# define smp_rmb()     rmb()
+# define smp_wmb()     wmb()
+# define smp_read_barrier_depends()    read_barrier_depends()
+#else
+# define smp_mb()      barrier()
+# define smp_rmb()     barrier()
+# define smp_wmb()     barrier()
+# define smp_read_barrier_depends()    do { } while(0)
+#endif
+
+/*
+ * XXX check on this ---I suspect what Linus really wants here is
+ * acquire vs release semantics but we can't discuss this stuff with
+ * Linus just yet.  Grrr...
+ */
+#define set_mb(var, value)     do { (var) = (value); mb(); } while (0)
+
+/*
+ * The group barrier in front of the rsm & ssm are necessary to ensure
+ * that none of the previous instructions in the same group are
+ * affected by the rsm/ssm.
+ */
+
+#endif /* _ASM_IA64_BARRIER_H */
diff --git a/arch/ia64/include/asm/exec.h b/arch/ia64/include/asm/exec.h
new file mode 100644 (file)
index 0000000..b262424
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * Process execution defines.
+ *
+ * Copyright (C) 1998-2003 Hewlett-Packard Co
+ *     David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1999 Asit Mallick <asit.k.mallick@intel.com>
+ * Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
+ */
+#ifndef _ASM_IA64_EXEC_H
+#define _ASM_IA64_EXEC_H
+
+#define arch_align_stack(x) (x)
+
+#endif /* _ASM_IA64_EXEC_H */
index 8428525..0ab82cc 100644 (file)
@@ -4,7 +4,6 @@
 #include <linux/futex.h>
 #include <linux/uaccess.h>
 #include <asm/errno.h>
-#include <asm/system.h>
 
 #define __futex_atomic_op1(insn, ret, oldval, uaddr, oparg) \
 do {                                                                   \
index e5a6c35..2c26321 100644 (file)
@@ -71,7 +71,6 @@ extern unsigned int num_io_spaces;
 #include <asm/intrinsics.h>
 #include <asm/machvec.h>
 #include <asm/page.h>
-#include <asm/system.h>
 #include <asm-generic/iomap.h>
 
 /*
index f82d6be..2b68d85 100644 (file)
@@ -10,6 +10,8 @@
 #ifndef _ASM_IA64_IRQFLAGS_H
 #define _ASM_IA64_IRQFLAGS_H
 
+#include <asm/pal.h>
+
 #ifdef CONFIG_IA64_DEBUG_IRQ
 extern unsigned long last_cli_ip;
 static inline void arch_maybe_save_ip(unsigned long flags)
index e1d58f8..aea2b81 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef _ASM_IA64_KEXEC_H
 #define _ASM_IA64_KEXEC_H
 
+#include <asm/setup.h>
 
 /* Maximum physical address we can use pages from */
 #define KEXEC_SOURCE_MEMORY_LIMIT (-1UL)
index bc90c75..b9f82c8 100644 (file)
@@ -261,4 +261,8 @@ struct kvm_debug_exit_arch {
 struct kvm_guest_debug_arch {
 };
 
+/* definition of registers in kvm_run */
+struct kvm_sync_regs {
+};
+
 #endif
index 2689ee5..e35b3a8 100644 (file)
@@ -459,6 +459,9 @@ struct kvm_sal_data {
        unsigned long boot_gp;
 };
 
+struct kvm_arch_memory_slot {
+};
+
 struct kvm_arch {
        spinlock_t dirty_log_lock;
 
index dd2a5b1..13c1d49 100644 (file)
@@ -15,6 +15,8 @@
 #ifndef _ASM_IA64_MCA_ASM_H
 #define _ASM_IA64_MCA_ASM_H
 
+#include <asm/percpu.h>
+
 #define PSR_IC         13
 #define PSR_I          14
 #define        PSR_DT          17
index 961a16f..f1e1b2e 100644 (file)
@@ -221,4 +221,14 @@ get_order (unsigned long size)
                                         (((current->personality & READ_IMPLIES_EXEC) != 0)     \
                                          ? VM_EXEC : 0))
 
+#define GATE_ADDR              RGN_BASE(RGN_GATE)
+
+/*
+ * 0xa000000000000000+2*PERCPU_PAGE_SIZE
+ * - 0xa000000000000000+3*PERCPU_PAGE_SIZE remain unmapped (guard page)
+ */
+#define KERNEL_START            (GATE_ADDR+__IA64_UL_CONST(0x100000000))
+#define PERCPU_ADDR            (-PERCPU_PAGE_SIZE)
+#define LOAD_OFFSET            (KERNEL_START - KERNEL_TR_PAGE_SIZE)
+
 #endif /* _ASM_IA64_PAGE_H */
index b22e5f5..5e04b59 100644 (file)
 #include <asm/scatterlist.h>
 #include <asm/hw_irq.h>
 
+struct pci_vector_struct {
+       __u16 segment;  /* PCI Segment number */
+       __u16 bus;      /* PCI Bus number */
+       __u32 pci_id;   /* ACPI split 16 bits device, 16 bits function (see section 6.1.1) */
+       __u8 pin;       /* PCI PIN (0 = A, 1 = B, 2 = C, 3 = D) */
+       __u32 irq;      /* IRQ assigned */
+};
+
 /*
  * Can be used to override the logic in pci_scan_bus for skipping already-configured bus
  * numbers - to be used for buggy BIOSes or architectures with incomplete PCI setup by the
index 1a97af3..815810c 100644 (file)
@@ -16,7 +16,6 @@
 #include <asm/mman.h>
 #include <asm/page.h>
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/types.h>
 
 #define IA64_MAX_PHYS_BITS     50      /* max. number of physical address bits (architected) */
index 691be0b..483f6c6 100644 (file)
@@ -19,6 +19,9 @@
 #include <asm/ptrace.h>
 #include <asm/ustack.h>
 
+#define __ARCH_WANT_UNLOCKED_CTXSW
+#define ARCH_HAS_PREFETCH_SWITCH_STACK
+
 #define IA64_NUM_PHYS_STACK_REG        96
 #define IA64_NUM_DBG_REGS      8
 
@@ -720,6 +723,11 @@ extern unsigned long boot_option_idle_override;
 enum idle_boot_override {IDLE_NO_OVERRIDE=0, IDLE_HALT, IDLE_FORCE_MWAIT,
                         IDLE_NOMWAIT, IDLE_POLL};
 
+void cpu_idle_wait(void);
+void default_idle(void);
+
+#define ia64_platform_is(x) (strcmp(x, platform_name) == 0)
+
 #endif /* !__ASSEMBLY__ */
 
 #endif /* _ASM_IA64_PROCESSOR_H */
index d19ddba..e504f38 100644 (file)
@@ -40,7 +40,6 @@
 #include <linux/efi.h>
 
 #include <asm/pal.h>
-#include <asm/system.h>
 #include <asm/fpu.h>
 
 extern spinlock_t sal_lock;
index 4399a44..8d56458 100644 (file)
@@ -3,4 +3,22 @@
 
 #define COMMAND_LINE_SIZE      2048
 
+extern struct ia64_boot_param {
+       __u64 command_line;             /* physical address of command line arguments */
+       __u64 efi_systab;               /* physical address of EFI system table */
+       __u64 efi_memmap;               /* physical address of EFI memory map */
+       __u64 efi_memmap_size;          /* size of EFI memory map */
+       __u64 efi_memdesc_size;         /* size of an EFI memory map descriptor */
+       __u32 efi_memdesc_version;      /* memory descriptor version */
+       struct {
+               __u16 num_cols; /* number of columns on console output device */
+               __u16 num_rows; /* number of rows on console output device */
+               __u16 orig_x;   /* cursor's x position */
+               __u16 orig_y;   /* cursor's y position */
+       } console_info;
+       __u64 fpswa;            /* physical address of the fpswa interface */
+       __u64 initrd_start;
+       __u64 initrd_size;
+} *ia64_boot_param;
+
 #endif
index 1c5108d..22ae358 100644 (file)
@@ -10,7 +10,6 @@
 
 #include <linux/cache.h>
 #include <asm/percpu.h>
-#include <asm/system.h>
 
 
 /*
index b77768d..54ff557 100644 (file)
@@ -15,7 +15,6 @@
 
 #include <linux/atomic.h>
 #include <asm/intrinsics.h>
-#include <asm/system.h>
 
 #define arch_spin_lock_init(x)                 ((x)->lock = 0)
 
diff --git a/arch/ia64/include/asm/switch_to.h b/arch/ia64/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..cb2412f
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Low-level task switching. This is based on information published in
+ * the Processor Abstraction Layer and the System Abstraction Layer
+ * manual.
+ *
+ * Copyright (C) 1998-2003 Hewlett-Packard Co
+ *     David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1999 Asit Mallick <asit.k.mallick@intel.com>
+ * Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
+ */
+#ifndef _ASM_IA64_SWITCH_TO_H
+#define _ASM_IA64_SWITCH_TO_H
+
+#include <linux/percpu.h>
+
+struct task_struct;
+
+/*
+ * Context switch from one thread to another.  If the two threads have
+ * different address spaces, schedule() has already taken care of
+ * switching to the new address space by calling switch_mm().
+ *
+ * Disabling access to the fph partition and the debug-register
+ * context switch MUST be done before calling ia64_switch_to() since a
+ * newly created thread returns directly to
+ * ia64_ret_from_syscall_clear_r8.
+ */
+extern struct task_struct *ia64_switch_to (void *next_task);
+
+extern void ia64_save_extra (struct task_struct *task);
+extern void ia64_load_extra (struct task_struct *task);
+
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+extern void ia64_account_on_switch (struct task_struct *prev, struct task_struct *next);
+# define IA64_ACCOUNT_ON_SWITCH(p,n) ia64_account_on_switch(p,n)
+#else
+# define IA64_ACCOUNT_ON_SWITCH(p,n)
+#endif
+
+#ifdef CONFIG_PERFMON
+  DECLARE_PER_CPU(unsigned long, pfm_syst_info);
+# define PERFMON_IS_SYSWIDE() (__get_cpu_var(pfm_syst_info) & 0x1)
+#else
+# define PERFMON_IS_SYSWIDE() (0)
+#endif
+
+#define IA64_HAS_EXTRA_STATE(t)                                                        \
+       ((t)->thread.flags & (IA64_THREAD_DBG_VALID|IA64_THREAD_PM_VALID)       \
+        || PERFMON_IS_SYSWIDE())
+
+#define __switch_to(prev,next,last) do {                                                        \
+       IA64_ACCOUNT_ON_SWITCH(prev, next);                                                      \
+       if (IA64_HAS_EXTRA_STATE(prev))                                                          \
+               ia64_save_extra(prev);                                                           \
+       if (IA64_HAS_EXTRA_STATE(next))                                                          \
+               ia64_load_extra(next);                                                           \
+       ia64_psr(task_pt_regs(next))->dfh = !ia64_is_local_fpu_owner(next);                      \
+       (last) = ia64_switch_to((next));                                                         \
+} while (0)
+
+#ifdef CONFIG_SMP
+/*
+ * In the SMP case, we save the fph state when context-switching away from a thread that
+ * modified fph.  This way, when the thread gets scheduled on another CPU, the CPU can
+ * pick up the state from task->thread.fph, avoiding the complication of having to fetch
+ * the latest fph state from another CPU.  In other words: eager save, lazy restore.
+ */
+# define switch_to(prev,next,last) do {                                                \
+       if (ia64_psr(task_pt_regs(prev))->mfh && ia64_is_local_fpu_owner(prev)) {                               \
+               ia64_psr(task_pt_regs(prev))->mfh = 0;                  \
+               (prev)->thread.flags |= IA64_THREAD_FPH_VALID;                  \
+               __ia64_save_fpu((prev)->thread.fph);                            \
+       }                                                                       \
+       __switch_to(prev, next, last);                                          \
+       /* "next" in old context is "current" in new context */                 \
+       if (unlikely((current->thread.flags & IA64_THREAD_MIGRATION) &&        \
+                    (task_cpu(current) !=                                     \
+                                     task_thread_info(current)->last_cpu))) { \
+               platform_migrate(current);                                     \
+               task_thread_info(current)->last_cpu = task_cpu(current);       \
+       }                                                                      \
+} while (0)
+#else
+# define switch_to(prev,next,last)     __switch_to(prev, next, last)
+#endif
+
+#endif /* _ASM_IA64_SWITCH_TO_H */
diff --git a/arch/ia64/include/asm/system.h b/arch/ia64/include/asm/system.h
deleted file mode 100644 (file)
index 6cca307..0000000
+++ /dev/null
@@ -1,203 +0,0 @@
-#ifndef _ASM_IA64_SYSTEM_H
-#define _ASM_IA64_SYSTEM_H
-
-/*
- * System defines. Note that this is included both from .c and .S
- * files, so it does only defines, not any C code.  This is based
- * on information published in the Processor Abstraction Layer
- * and the System Abstraction Layer manual.
- *
- * Copyright (C) 1998-2003 Hewlett-Packard Co
- *     David Mosberger-Tang <davidm@hpl.hp.com>
- * Copyright (C) 1999 Asit Mallick <asit.k.mallick@intel.com>
- * Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
- */
-
-#include <asm/kregs.h>
-#include <asm/page.h>
-#include <asm/pal.h>
-#include <asm/percpu.h>
-
-#define GATE_ADDR              RGN_BASE(RGN_GATE)
-
-/*
- * 0xa000000000000000+2*PERCPU_PAGE_SIZE
- * - 0xa000000000000000+3*PERCPU_PAGE_SIZE remain unmapped (guard page)
- */
-#define KERNEL_START            (GATE_ADDR+__IA64_UL_CONST(0x100000000))
-#define PERCPU_ADDR            (-PERCPU_PAGE_SIZE)
-#define LOAD_OFFSET            (KERNEL_START - KERNEL_TR_PAGE_SIZE)
-
-#ifndef __ASSEMBLY__
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-
-#define AT_VECTOR_SIZE_ARCH 2 /* entries in ARCH_DLINFO */
-
-struct pci_vector_struct {
-       __u16 segment;  /* PCI Segment number */
-       __u16 bus;      /* PCI Bus number */
-       __u32 pci_id;   /* ACPI split 16 bits device, 16 bits function (see section 6.1.1) */
-       __u8 pin;       /* PCI PIN (0 = A, 1 = B, 2 = C, 3 = D) */
-       __u32 irq;      /* IRQ assigned */
-};
-
-extern struct ia64_boot_param {
-       __u64 command_line;             /* physical address of command line arguments */
-       __u64 efi_systab;               /* physical address of EFI system table */
-       __u64 efi_memmap;               /* physical address of EFI memory map */
-       __u64 efi_memmap_size;          /* size of EFI memory map */
-       __u64 efi_memdesc_size;         /* size of an EFI memory map descriptor */
-       __u32 efi_memdesc_version;      /* memory descriptor version */
-       struct {
-               __u16 num_cols; /* number of columns on console output device */
-               __u16 num_rows; /* number of rows on console output device */
-               __u16 orig_x;   /* cursor's x position */
-               __u16 orig_y;   /* cursor's y position */
-       } console_info;
-       __u64 fpswa;            /* physical address of the fpswa interface */
-       __u64 initrd_start;
-       __u64 initrd_size;
-} *ia64_boot_param;
-
-/*
- * Macros to force memory ordering.  In these descriptions, "previous"
- * and "subsequent" refer to program order; "visible" means that all
- * architecturally visible effects of a memory access have occurred
- * (at a minimum, this means the memory has been read or written).
- *
- *   wmb():    Guarantees that all preceding stores to memory-
- *             like regions are visible before any subsequent
- *             stores and that all following stores will be
- *             visible only after all previous stores.
- *   rmb():    Like wmb(), but for reads.
- *   mb():     wmb()/rmb() combo, i.e., all previous memory
- *             accesses are visible before all subsequent
- *             accesses and vice versa.  This is also known as
- *             a "fence."
- *
- * Note: "mb()" and its variants cannot be used as a fence to order
- * accesses to memory mapped I/O registers.  For that, mf.a needs to
- * be used.  However, we don't want to always use mf.a because (a)
- * it's (presumably) much slower than mf and (b) mf.a is supported for
- * sequential memory pages only.
- */
-#define mb()   ia64_mf()
-#define rmb()  mb()
-#define wmb()  mb()
-#define read_barrier_depends() do { } while(0)
-
-#ifdef CONFIG_SMP
-# define smp_mb()      mb()
-# define smp_rmb()     rmb()
-# define smp_wmb()     wmb()
-# define smp_read_barrier_depends()    read_barrier_depends()
-#else
-# define smp_mb()      barrier()
-# define smp_rmb()     barrier()
-# define smp_wmb()     barrier()
-# define smp_read_barrier_depends()    do { } while(0)
-#endif
-
-/*
- * XXX check on this ---I suspect what Linus really wants here is
- * acquire vs release semantics but we can't discuss this stuff with
- * Linus just yet.  Grrr...
- */
-#define set_mb(var, value)     do { (var) = (value); mb(); } while (0)
-
-/*
- * The group barrier in front of the rsm & ssm are necessary to ensure
- * that none of the previous instructions in the same group are
- * affected by the rsm/ssm.
- */
-
-#ifdef __KERNEL__
-
-/*
- * Context switch from one thread to another.  If the two threads have
- * different address spaces, schedule() has already taken care of
- * switching to the new address space by calling switch_mm().
- *
- * Disabling access to the fph partition and the debug-register
- * context switch MUST be done before calling ia64_switch_to() since a
- * newly created thread returns directly to
- * ia64_ret_from_syscall_clear_r8.
- */
-extern struct task_struct *ia64_switch_to (void *next_task);
-
-struct task_struct;
-
-extern void ia64_save_extra (struct task_struct *task);
-extern void ia64_load_extra (struct task_struct *task);
-
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING
-extern void ia64_account_on_switch (struct task_struct *prev, struct task_struct *next);
-# define IA64_ACCOUNT_ON_SWITCH(p,n) ia64_account_on_switch(p,n)
-#else
-# define IA64_ACCOUNT_ON_SWITCH(p,n)
-#endif
-
-#ifdef CONFIG_PERFMON
-  DECLARE_PER_CPU(unsigned long, pfm_syst_info);
-# define PERFMON_IS_SYSWIDE() (__get_cpu_var(pfm_syst_info) & 0x1)
-#else
-# define PERFMON_IS_SYSWIDE() (0)
-#endif
-
-#define IA64_HAS_EXTRA_STATE(t)                                                        \
-       ((t)->thread.flags & (IA64_THREAD_DBG_VALID|IA64_THREAD_PM_VALID)       \
-        || PERFMON_IS_SYSWIDE())
-
-#define __switch_to(prev,next,last) do {                                                        \
-       IA64_ACCOUNT_ON_SWITCH(prev, next);                                                      \
-       if (IA64_HAS_EXTRA_STATE(prev))                                                          \
-               ia64_save_extra(prev);                                                           \
-       if (IA64_HAS_EXTRA_STATE(next))                                                          \
-               ia64_load_extra(next);                                                           \
-       ia64_psr(task_pt_regs(next))->dfh = !ia64_is_local_fpu_owner(next);                      \
-       (last) = ia64_switch_to((next));                                                         \
-} while (0)
-
-#ifdef CONFIG_SMP
-/*
- * In the SMP case, we save the fph state when context-switching away from a thread that
- * modified fph.  This way, when the thread gets scheduled on another CPU, the CPU can
- * pick up the state from task->thread.fph, avoiding the complication of having to fetch
- * the latest fph state from another CPU.  In other words: eager save, lazy restore.
- */
-# define switch_to(prev,next,last) do {                                                \
-       if (ia64_psr(task_pt_regs(prev))->mfh && ia64_is_local_fpu_owner(prev)) {                               \
-               ia64_psr(task_pt_regs(prev))->mfh = 0;                  \
-               (prev)->thread.flags |= IA64_THREAD_FPH_VALID;                  \
-               __ia64_save_fpu((prev)->thread.fph);                            \
-       }                                                                       \
-       __switch_to(prev, next, last);                                          \
-       /* "next" in old context is "current" in new context */                 \
-       if (unlikely((current->thread.flags & IA64_THREAD_MIGRATION) &&        \
-                    (task_cpu(current) !=                                     \
-                                     task_thread_info(current)->last_cpu))) { \
-               platform_migrate(current);                                     \
-               task_thread_info(current)->last_cpu = task_cpu(current);       \
-       }                                                                      \
-} while (0)
-#else
-# define switch_to(prev,next,last)     __switch_to(prev, next, last)
-#endif
-
-#define __ARCH_WANT_UNLOCKED_CTXSW
-#define ARCH_HAS_PREFETCH_SWITCH_STACK
-#define ia64_platform_is(x) (strcmp(x, platform_name) == 0)
-
-void cpu_idle_wait(void);
-
-#define arch_align_stack(x) (x)
-
-void default_idle(void);
-
-#endif /* __KERNEL__ */
-
-#endif /* __ASSEMBLY__ */
-
-#endif /* _ASM_IA64_SYSTEM_H */
index 61b5bdf..8f6cbaa 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ASM_IA64_UV_UV_H
 #define _ASM_IA64_UV_UV_H
 
-#include <asm/system.h>
 #include <asm/sn/simulator.h>
 
 static inline int is_uv_system(void)
index 19bb1ee..ac795d3 100644 (file)
@@ -50,7 +50,6 @@
 #include <asm/iosapic.h>
 #include <asm/machvec.h>
 #include <asm/page.h>
-#include <asm/system.h>
 #include <asm/numa.h>
 #include <asm/sal.h>
 #include <asm/cyclone.h>
index c38d22e..d37bbd4 100644 (file)
@@ -39,6 +39,7 @@
 #include <asm/pgtable.h>
 #include <asm/processor.h>
 #include <asm/mca.h>
+#include <asm/setup.h>
 #include <asm/tlbflush.h>
 
 #define EFI_DEBUG      0
index 331d42b..f15d860 100644 (file)
@@ -21,7 +21,6 @@
 #include <asm/thread_info.h>
 #include <asm/sal.h>
 #include <asm/signal.h>
-#include <asm/system.h>
 #include <asm/unistd.h>
 
 #include "entry.h"
index 245d3e1..b5f8bdd 100644 (file)
@@ -11,8 +11,9 @@
 #include <asm/errno.h>
 #include <asm/asm-offsets.h>
 #include <asm/sigcontext.h>
-#include <asm/system.h>
 #include <asm/unistd.h>
+#include <asm/kregs.h>
+#include <asm/page.h>
 #include "paravirt_inst.h"
 
 /*
index d32b085..e518f79 100644 (file)
@@ -5,8 +5,7 @@
  * its layout.
  */
 
-
-#include <asm/system.h>
+#include <asm/page.h>
 #include "paravirt_patchlist.h"
 
 SECTIONS
index 17a9fba..629a250 100644 (file)
@@ -30,7 +30,6 @@
 #include <asm/pgtable.h>
 #include <asm/processor.h>
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/mca_asm.h>
 #include <linux/init.h>
 #include <linux/linkage.h>
index b0f9afe..ef4b5d8 100644 (file)
@@ -98,7 +98,6 @@
 #include <asm/machvec.h>
 #include <asm/processor.h>
 #include <asm/ptrace.h>
-#include <asm/system.h>
 
 #undef DEBUG_INTERRUPT_ROUTING
 
index 51da772..5c3e088 100644 (file)
@@ -39,7 +39,6 @@
 #include <asm/hw_irq.h>
 #include <asm/machvec.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/tlbflush.h>
 
 #ifdef CONFIG_PERFMON
index d93e396..fa25689 100644 (file)
@@ -54,7 +54,6 @@
 #include <asm/pgtable.h>
 #include <asm/processor.h>
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/thread_info.h>
 #include <asm/unistd.h>
 #include <asm/errno.h>
index d41a40e..f5a1e52 100644 (file)
@@ -1,7 +1,6 @@
 #include <linux/module.h>
 #include <linux/dma-mapping.h>
 #include <asm/machvec.h>
-#include <asm/system.h>
 
 #ifdef CONFIG_IA64_GENERIC
 
index 26dbbd3..65bf9cd 100644 (file)
@@ -92,7 +92,6 @@
 #include <asm/meminit.h>
 #include <asm/page.h>
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/sal.h>
 #include <asm/mca.h>
 #include <asm/kexec.h>
index 09b4d68..1c2e894 100644 (file)
@@ -28,7 +28,6 @@
 #include <asm/machvec.h>
 #include <asm/page.h>
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/sal.h>
 #include <asm/mca.h>
 
index 68a1311..1cf0917 100644 (file)
@@ -11,7 +11,6 @@
 #include <asm/patch.h>
 #include <asm/processor.h>
 #include <asm/sections.h>
-#include <asm/system.h>
 #include <asm/unistd.h>
 
 /*
index eb11757..7cdc89b 100644 (file)
@@ -12,7 +12,6 @@
 #include <asm/machvec.h>
 #include <linux/dma-mapping.h>
 
-#include <asm/system.h>
 
 #ifdef CONFIG_INTEL_IOMMU
 
index b2c65e0..9d0fd7d 100644 (file)
@@ -49,7 +49,6 @@
 #include <asm/perfmon.h>
 #include <asm/processor.h>
 #include <asm/signal.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/delay.h>
 
index dad9166..4265ff6 100644 (file)
@@ -26,7 +26,6 @@
 #include <asm/processor.h>
 #include <asm/ptrace_offsets.h>
 #include <asm/rse.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/unwind.h>
 #ifdef CONFIG_PERFMON
index 4d1a550..aaefd9b 100644 (file)
@@ -59,7 +59,6 @@
 #include <asm/sections.h>
 #include <asm/setup.h>
 #include <asm/smp.h>
-#include <asm/system.h>
 #include <asm/tlbflush.h>
 #include <asm/unistd.h>
 #include <asm/hpsim.h>
index 8551979..9fcd4e6 100644 (file)
@@ -44,7 +44,6 @@
 #include <asm/processor.h>
 #include <asm/ptrace.h>
 #include <asm/sal.h>
-#include <asm/system.h>
 #include <asm/tlbflush.h>
 #include <asm/unistd.h>
 #include <asm/mca.h>
index 90916be..796f6a5 100644 (file)
@@ -55,7 +55,6 @@
 #include <asm/processor.h>
 #include <asm/ptrace.h>
 #include <asm/sal.h>
-#include <asm/system.h>
 #include <asm/tlbflush.h>
 #include <asm/unistd.h>
 #include <asm/sn/arch.h>
index 43920de..aa94bdd 100644 (file)
@@ -29,7 +29,6 @@
 #include <asm/ptrace.h>
 #include <asm/sal.h>
 #include <asm/sections.h>
-#include <asm/system.h>
 
 #include "fsyscall_gtod_data.h"
 
index fd80e70..bd42b76 100644 (file)
@@ -22,6 +22,7 @@
 #include <asm/intrinsics.h>
 #include <asm/processor.h>
 #include <asm/uaccess.h>
+#include <asm/setup.h>
 
 fpswa_interface_t *fpswa_interface;
 EXPORT_SYMBOL(fpswa_interface);
index 6a867dc..a96bcf8 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/gfp.h>
 #include <asm/page.h>
 #include <asm/pal.h>
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <linux/atomic.h>
 #include <asm/tlbflush.h>
index fed6afa..8f66195 100644 (file)
@@ -41,7 +41,6 @@
 #include <asm/ptrace_offsets.h>
 #include <asm/rse.h>
 #include <asm/sections.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 
 #include "entry.h"
index 53c0ba0..0ccb28f 100644 (file)
@@ -1,7 +1,6 @@
 
 #include <asm/cache.h>
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/pgtable.h>
 
 #include <asm-generic/vmlinux.lds.h>
index 4050520..f5104b7 100644 (file)
@@ -809,10 +809,13 @@ static void kvm_build_io_pmt(struct kvm *kvm)
 #define GUEST_PHYSICAL_RR4     0x2739
 #define VMM_INIT_RR            0x1660
 
-int kvm_arch_init_vm(struct kvm *kvm)
+int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
 {
        BUG_ON(!kvm);
 
+       if (type)
+               return -EINVAL;
+
        kvm->arch.is_sn2 = ia64_platform_is("sn2");
 
        kvm->arch.metaphysical_rr0 = GUEST_PHYSICAL_RR0;
@@ -1169,6 +1172,11 @@ out:
 
 #define PALE_RESET_ENTRY    0x80000000ffffffb0UL
 
+bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu)
+{
+       return irqchip_in_kernel(vcpu->kcm) == (vcpu->arch.apic != NULL);
+}
+
 int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
 {
        struct kvm_vcpu *v;
@@ -1563,6 +1571,21 @@ out:
        return r;
 }
 
+int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf)
+{
+       return VM_FAULT_SIGBUS;
+}
+
+void kvm_arch_free_memslot(struct kvm_memory_slot *free,
+                          struct kvm_memory_slot *dont)
+{
+}
+
+int kvm_arch_create_memslot(struct kvm_memory_slot *slot, unsigned long npages)
+{
+       return 0;
+}
+
 int kvm_arch_prepare_memory_region(struct kvm *kvm,
                struct kvm_memory_slot *memslot,
                struct kvm_memory_slot old,
index 20b3593..02d29c2 100644 (file)
@@ -14,7 +14,6 @@
 
 #include <asm/pgtable.h>
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 
 extern int die(char *, struct pt_regs *, long);
index 13df239..0eab454 100644 (file)
@@ -30,7 +30,6 @@
 #include <asm/pgalloc.h>
 #include <asm/sal.h>
 #include <asm/sections.h>
-#include <asm/system.h>
 #include <asm/tlb.h>
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
index f7b7989..6a219a9 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <asm/ptrace.h>
-#include <asm/system.h>
 
 /*
  * For IA64 we need to perform a complex little dance to get both
index d1ce320..524df42 100644 (file)
@@ -24,7 +24,6 @@
 
 #include <asm/machvec.h>
 #include <asm/page.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/sal.h>
 #include <asm/smp.h>
index 77db0b5..f82e7b4 100644 (file)
@@ -33,9 +33,9 @@
 #include <asm/io.h>
 #include <asm/sal.h>
 #include <asm/machvec.h>
-#include <asm/system.h>
 #include <asm/processor.h>
 #include <asm/vga.h>
+#include <asm/setup.h>
 #include <asm/sn/arch.h>
 #include <asm/sn/addrs.h>
 #include <asm/sn/pda.h>
index e633288..20b88cb 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/slab.h>
 #include <linux/proc_fs.h>
 #include <linux/nodemask.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/sn/sn_sal.h>
 #include <asm/sn/sn_cpuid.h>
index e884ba4..68c8454 100644 (file)
@@ -26,7 +26,6 @@
 #include <asm/processor.h>
 #include <asm/irq.h>
 #include <asm/sal.h>
-#include <asm/system.h>
 #include <asm/delay.h>
 #include <asm/io.h>
 #include <asm/smp.h>
index 0f8844e..abab8f9 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/clocksource.h>
 
 #include <asm/hw_irq.h>
-#include <asm/system.h>
 #include <asm/timex.h>
 
 #include <asm/sn/leds.h>
index 2f406f5..14c1711 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/capability.h>
 #include <linux/device.h>
 #include <linux/delay.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/sn/sn_sal.h>
 #include <asm/sn/addrs.h>
index b820ed0..e29519e 100644 (file)
@@ -7,7 +7,6 @@
 #include <asm/processor.h>
 #include <asm/asmmacro.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/paravirt.h>
 #include <asm/xen/privop.h>
 #include <linux/elfnote.h>
index 1e7f29f..0d81697 100644 (file)
@@ -11,7 +11,8 @@
 
 #include <linux/types.h>
 #include <asm/assembler.h>
-#include <asm/system.h>
+#include <asm/cmpxchg.h>
+#include <asm/dcache_clear.h>
 
 /*
  * Atomic operations that C can't guarantee us.  Useful for
diff --git a/arch/m32r/include/asm/barrier.h b/arch/m32r/include/asm/barrier.h
new file mode 100644 (file)
index 0000000..6976621
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001  Hiroyuki Kondo, Hirokazu Takata, and Hitoshi Yamamoto
+ * Copyright (C) 2004, 2006  Hirokazu Takata <takata at linux-m32r.org>
+ */
+#ifndef _ASM_M32R_BARRIER_H
+#define _ASM_M32R_BARRIER_H
+
+#define nop()  __asm__ __volatile__ ("nop" : : )
+
+/*
+ * Memory barrier.
+ *
+ * mb() prevents loads and stores being reordered across this point.
+ * rmb() prevents loads being reordered across this point.
+ * wmb() prevents stores being reordered across this point.
+ */
+#define mb()   barrier()
+#define rmb()  mb()
+#define wmb()  mb()
+
+/**
+ * read_barrier_depends - Flush all pending reads that subsequents reads
+ * depend on.
+ *
+ * No data-dependent reads from memory-like regions are ever reordered
+ * over this barrier.  All reads preceding this primitive are guaranteed
+ * to access memory (but not necessarily other CPUs' caches) before any
+ * reads following this primitive that depend on the data return by
+ * any of the preceding reads.  This primitive is much lighter weight than
+ * rmb() on most CPUs, and is never heavier weight than is
+ * rmb().
+ *
+ * These ordering constraints are respected by both the local CPU
+ * and the compiler.
+ *
+ * Ordering is not guaranteed by anything other than these primitives,
+ * not even by data dependencies.  See the documentation for
+ * memory_barrier() for examples and URLs to more information.
+ *
+ * For example, the following code would force ordering (the initial
+ * value of "a" is zero, "b" is one, and "p" is "&a"):
+ *
+ * <programlisting>
+ *      CPU 0                           CPU 1
+ *
+ *      b = 2;
+ *      memory_barrier();
+ *      p = &b;                         q = p;
+ *                                      read_barrier_depends();
+ *                                      d = *q;
+ * </programlisting>
+ *
+ *
+ * because the read of "*q" depends on the read of "p" and these
+ * two reads are separated by a read_barrier_depends().  However,
+ * the following code, with the same initial values for "a" and "b":
+ *
+ * <programlisting>
+ *      CPU 0                           CPU 1
+ *
+ *      a = 2;
+ *      memory_barrier();
+ *      b = 3;                          y = b;
+ *                                      read_barrier_depends();
+ *                                      x = a;
+ * </programlisting>
+ *
+ * does not enforce ordering, since there is no data dependency between
+ * the read of "a" and the read of "b".  Therefore, on some CPUs, such
+ * as Alpha, "y" could be set to 3 and "x" to 0.  Use rmb()
+ * in cases like this where there are no data dependencies.
+ **/
+
+#define read_barrier_depends() do { } while (0)
+
+#ifdef CONFIG_SMP
+#define smp_mb()       mb()
+#define smp_rmb()      rmb()
+#define smp_wmb()      wmb()
+#define smp_read_barrier_depends()     read_barrier_depends()
+#define set_mb(var, value) do { (void) xchg(&var, value); } while (0)
+#else
+#define smp_mb()       barrier()
+#define smp_rmb()      barrier()
+#define smp_wmb()      barrier()
+#define smp_read_barrier_depends()     do { } while (0)
+#define set_mb(var, value) do { var = value; barrier(); } while (0)
+#endif
+
+#endif /* _ASM_M32R_BARRIER_H */
index 6300f22..d3dea9a 100644 (file)
 #endif
 
 #include <linux/compiler.h>
+#include <linux/irqflags.h>
 #include <asm/assembler.h>
-#include <asm/system.h>
 #include <asm/byteorder.h>
+#include <asm/dcache_clear.h>
 #include <asm/types.h>
 
 /*
diff --git a/arch/m32r/include/asm/cmpxchg.h b/arch/m32r/include/asm/cmpxchg.h
new file mode 100644 (file)
index 0000000..de651db
--- /dev/null
@@ -0,0 +1,221 @@
+#ifndef _ASM_M32R_CMPXCHG_H
+#define _ASM_M32R_CMPXCHG_H
+
+/*
+ *  M32R version:
+ *    Copyright (C) 2001, 2002  Hitoshi Yamamoto
+ *    Copyright (C) 2004  Hirokazu Takata <takata at linux-m32r.org>
+ */
+
+#include <linux/irqflags.h>
+#include <asm/assembler.h>
+#include <asm/dcache_clear.h>
+
+extern void  __xchg_called_with_bad_pointer(void);
+
+static __always_inline unsigned long
+__xchg(unsigned long x, volatile void *ptr, int size)
+{
+       unsigned long flags;
+       unsigned long tmp = 0;
+
+       local_irq_save(flags);
+
+       switch (size) {
+#ifndef CONFIG_SMP
+       case 1:
+               __asm__ __volatile__ (
+                       "ldb    %0, @%2 \n\t"
+                       "stb    %1, @%2 \n\t"
+                       : "=&r" (tmp) : "r" (x), "r" (ptr) : "memory");
+               break;
+       case 2:
+               __asm__ __volatile__ (
+                       "ldh    %0, @%2 \n\t"
+                       "sth    %1, @%2 \n\t"
+                       : "=&r" (tmp) : "r" (x), "r" (ptr) : "memory");
+               break;
+       case 4:
+               __asm__ __volatile__ (
+                       "ld     %0, @%2 \n\t"
+                       "st     %1, @%2 \n\t"
+                       : "=&r" (tmp) : "r" (x), "r" (ptr) : "memory");
+               break;
+#else  /* CONFIG_SMP */
+       case 4:
+               __asm__ __volatile__ (
+                       DCACHE_CLEAR("%0", "r4", "%2")
+                       "lock   %0, @%2;        \n\t"
+                       "unlock %1, @%2;        \n\t"
+                       : "=&r" (tmp) : "r" (x), "r" (ptr)
+                       : "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+                       , "r4"
+#endif /* CONFIG_CHIP_M32700_TS1 */
+               );
+               break;
+#endif  /* CONFIG_SMP */
+       default:
+               __xchg_called_with_bad_pointer();
+       }
+
+       local_irq_restore(flags);
+
+       return (tmp);
+}
+
+#define xchg(ptr, x)                                                   \
+       ((__typeof__(*(ptr)))__xchg((unsigned long)(x), (ptr), sizeof(*(ptr))))
+
+static __always_inline unsigned long
+__xchg_local(unsigned long x, volatile void *ptr, int size)
+{
+       unsigned long flags;
+       unsigned long tmp = 0;
+
+       local_irq_save(flags);
+
+       switch (size) {
+       case 1:
+               __asm__ __volatile__ (
+                       "ldb    %0, @%2 \n\t"
+                       "stb    %1, @%2 \n\t"
+                       : "=&r" (tmp) : "r" (x), "r" (ptr) : "memory");
+               break;
+       case 2:
+               __asm__ __volatile__ (
+                       "ldh    %0, @%2 \n\t"
+                       "sth    %1, @%2 \n\t"
+                       : "=&r" (tmp) : "r" (x), "r" (ptr) : "memory");
+               break;
+       case 4:
+               __asm__ __volatile__ (
+                       "ld     %0, @%2 \n\t"
+                       "st     %1, @%2 \n\t"
+                       : "=&r" (tmp) : "r" (x), "r" (ptr) : "memory");
+               break;
+       default:
+               __xchg_called_with_bad_pointer();
+       }
+
+       local_irq_restore(flags);
+
+       return (tmp);
+}
+
+#define xchg_local(ptr, x)                                             \
+       ((__typeof__(*(ptr)))__xchg_local((unsigned long)(x), (ptr),    \
+                       sizeof(*(ptr))))
+
+#define __HAVE_ARCH_CMPXCHG    1
+
+static inline unsigned long
+__cmpxchg_u32(volatile unsigned int *p, unsigned int old, unsigned int new)
+{
+       unsigned long flags;
+       unsigned int retval;
+
+       local_irq_save(flags);
+       __asm__ __volatile__ (
+                       DCACHE_CLEAR("%0", "r4", "%1")
+                       M32R_LOCK" %0, @%1;     \n"
+               "       bne     %0, %2, 1f;     \n"
+                       M32R_UNLOCK" %3, @%1;   \n"
+               "       bra     2f;             \n"
+                "       .fillinsn              \n"
+               "1:"
+                       M32R_UNLOCK" %0, @%1;   \n"
+                "       .fillinsn              \n"
+               "2:"
+                       : "=&r" (retval)
+                       : "r" (p), "r" (old), "r" (new)
+                       : "cbit", "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+                       , "r4"
+#endif  /* CONFIG_CHIP_M32700_TS1 */
+               );
+       local_irq_restore(flags);
+
+       return retval;
+}
+
+static inline unsigned long
+__cmpxchg_local_u32(volatile unsigned int *p, unsigned int old,
+                       unsigned int new)
+{
+       unsigned long flags;
+       unsigned int retval;
+
+       local_irq_save(flags);
+       __asm__ __volatile__ (
+                       DCACHE_CLEAR("%0", "r4", "%1")
+                       "ld %0, @%1;            \n"
+               "       bne     %0, %2, 1f;     \n"
+                       "st %3, @%1;            \n"
+               "       bra     2f;             \n"
+               "       .fillinsn               \n"
+               "1:"
+                       "st %0, @%1;            \n"
+               "       .fillinsn               \n"
+               "2:"
+                       : "=&r" (retval)
+                       : "r" (p), "r" (old), "r" (new)
+                       : "cbit", "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+                       , "r4"
+#endif  /* CONFIG_CHIP_M32700_TS1 */
+               );
+       local_irq_restore(flags);
+
+       return retval;
+}
+
+/* This function doesn't exist, so you'll get a linker error
+   if something tries to do an invalid cmpxchg().  */
+extern void __cmpxchg_called_with_bad_pointer(void);
+
+static inline unsigned long
+__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
+{
+       switch (size) {
+       case 4:
+               return __cmpxchg_u32(ptr, old, new);
+#if 0  /* we don't have __cmpxchg_u64 */
+       case 8:
+               return __cmpxchg_u64(ptr, old, new);
+#endif /* 0 */
+       }
+       __cmpxchg_called_with_bad_pointer();
+       return old;
+}
+
+#define cmpxchg(ptr, o, n)                                              \
+       ((__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)(o),       \
+                       (unsigned long)(n), sizeof(*(ptr))))
+
+#include <asm-generic/cmpxchg-local.h>
+
+static inline unsigned long __cmpxchg_local(volatile void *ptr,
+                                     unsigned long old,
+                                     unsigned long new, int size)
+{
+       switch (size) {
+       case 4:
+               return __cmpxchg_local_u32(ptr, old, new);
+       default:
+               return __cmpxchg_local_generic(ptr, old, new, size);
+       }
+
+       return old;
+}
+
+/*
+ * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
+ * them available.
+ */
+#define cmpxchg_local(ptr, o, n)                                           \
+       ((__typeof__(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(o),     \
+                       (unsigned long)(n), sizeof(*(ptr))))
+#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
+
+#endif /* _ASM_M32R_CMPXCHG_H */
diff --git a/arch/m32r/include/asm/dcache_clear.h b/arch/m32r/include/asm/dcache_clear.h
new file mode 100644 (file)
index 0000000..a0ae06c
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001  Hiroyuki Kondo, Hirokazu Takata, and Hitoshi Yamamoto
+ * Copyright (C) 2004, 2006  Hirokazu Takata <takata at linux-m32r.org>
+ */
+#ifndef _ASM_M32R_DCACHE_CLEAR_H
+#define _ASM_M32R_DCACHE_CLEAR_H
+
+#ifdef CONFIG_CHIP_M32700_TS1
+#define DCACHE_CLEAR(reg0, reg1, addr)                         \
+       "seth   "reg1", #high(dcache_dummy);            \n\t"   \
+       "or3    "reg1", "reg1", #low(dcache_dummy);     \n\t"   \
+       "lock   "reg0", @"reg1";                        \n\t"   \
+       "add3   "reg0", "addr", #0x1000;                \n\t"   \
+       "ld     "reg0", @"reg0";                        \n\t"   \
+       "add3   "reg0", "addr", #0x2000;                \n\t"   \
+       "ld     "reg0", @"reg0";                        \n\t"   \
+       "unlock "reg0", @"reg1";                        \n\t"
+       /* FIXME: This workaround code cannot handle kernel modules
+        * correctly under SMP environment.
+        */
+#else  /* CONFIG_CHIP_M32700_TS1 */
+#define DCACHE_CLEAR(reg0, reg1, addr)
+#endif /* CONFIG_CHIP_M32700_TS1 */
+
+#endif /* _ASM_M32R_DCACHE_CLEAR_H */
diff --git a/arch/m32r/include/asm/exec.h b/arch/m32r/include/asm/exec.h
new file mode 100644 (file)
index 0000000..c805dbd
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001  Hiroyuki Kondo, Hirokazu Takata, and Hitoshi Yamamoto
+ * Copyright (C) 2004, 2006  Hirokazu Takata <takata at linux-m32r.org>
+ */
+#ifndef _ASM_M32R_EXEC_H
+#define _ASM_M32R_EXEC_H
+
+#define arch_align_stack(x) (x)
+
+#endif /* _ASM_M32R_EXEC_H */
index 734bca8..4045db3 100644 (file)
@@ -12,7 +12,6 @@
 
 #include <linux/percpu.h>
 #include <asm/assembler.h>
-#include <asm/system.h>
 #include <asm/local.h>
 
 /*
index b0ea2f2..fa13694 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <linux/compiler.h>
 #include <linux/atomic.h>
+#include <asm/dcache_clear.h>
 #include <asm/page.h>
 
 /*
diff --git a/arch/m32r/include/asm/switch_to.h b/arch/m32r/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..4b262f7
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001  Hiroyuki Kondo, Hirokazu Takata, and Hitoshi Yamamoto
+ * Copyright (C) 2004, 2006  Hirokazu Takata <takata at linux-m32r.org>
+ */
+#ifndef _ASM_M32R_SWITCH_TO_H
+#define _ASM_M32R_SWITCH_TO_H
+
+/*
+ * switch_to(prev, next) should switch from task `prev' to `next'
+ * `prev' will never be the same as `next'.
+ *
+ * `next' and `prev' should be struct task_struct, but it isn't always defined
+ */
+
+#if defined(CONFIG_FRAME_POINTER) || \
+       !defined(CONFIG_SCHED_OMIT_FRAME_POINTER)
+#define M32R_PUSH_FP " push fp\n"
+#define M32R_POP_FP  " pop  fp\n"
+#else
+#define M32R_PUSH_FP ""
+#define M32R_POP_FP  ""
+#endif
+
+#define switch_to(prev, next, last)  do { \
+       __asm__ __volatile__ ( \
+               "       seth    lr, #high(1f)                           \n" \
+               "       or3     lr, lr, #low(1f)                        \n" \
+               "       st      lr, @%4  ; store old LR                 \n" \
+               "       ld      lr, @%5  ; load new LR                  \n" \
+                       M32R_PUSH_FP \
+               "       st      sp, @%2  ; store old SP                 \n" \
+               "       ld      sp, @%3  ; load new SP                  \n" \
+               "       push    %1  ; store `prev' on new stack         \n" \
+               "       jmp     lr                                      \n" \
+               "       .fillinsn                                       \n" \
+               "1:                                                     \n" \
+               "       pop     %0  ; restore `__last' from new stack   \n" \
+                       M32R_POP_FP \
+               : "=r" (last) \
+               : "0" (prev), \
+                 "r" (&(prev->thread.sp)), "r" (&(next->thread.sp)), \
+                 "r" (&(prev->thread.lr)), "r" (&(next->thread.lr)) \
+               : "memory", "lr" \
+       ); \
+} while(0)
+
+#endif /* _ASM_M32R_SWITCH_TO_H */
diff --git a/arch/m32r/include/asm/system.h b/arch/m32r/include/asm/system.h
deleted file mode 100644 (file)
index 13c4679..0000000
+++ /dev/null
@@ -1,367 +0,0 @@
-#ifndef _ASM_M32R_SYSTEM_H
-#define _ASM_M32R_SYSTEM_H
-
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2001  Hiroyuki Kondo, Hirokazu Takata, and Hitoshi Yamamoto
- * Copyright (C) 2004, 2006  Hirokazu Takata <takata at linux-m32r.org>
- */
-
-#include <linux/compiler.h>
-#include <linux/irqflags.h>
-#include <asm/assembler.h>
-
-#ifdef __KERNEL__
-
-/*
- * switch_to(prev, next) should switch from task `prev' to `next'
- * `prev' will never be the same as `next'.
- *
- * `next' and `prev' should be struct task_struct, but it isn't always defined
- */
-
-#if defined(CONFIG_FRAME_POINTER) || \
-       !defined(CONFIG_SCHED_OMIT_FRAME_POINTER)
-#define M32R_PUSH_FP " push fp\n"
-#define M32R_POP_FP  " pop  fp\n"
-#else
-#define M32R_PUSH_FP ""
-#define M32R_POP_FP  ""
-#endif
-
-#define switch_to(prev, next, last)  do { \
-       __asm__ __volatile__ ( \
-               "       seth    lr, #high(1f)                           \n" \
-               "       or3     lr, lr, #low(1f)                        \n" \
-               "       st      lr, @%4  ; store old LR                 \n" \
-               "       ld      lr, @%5  ; load new LR                  \n" \
-                       M32R_PUSH_FP \
-               "       st      sp, @%2  ; store old SP                 \n" \
-               "       ld      sp, @%3  ; load new SP                  \n" \
-               "       push    %1  ; store `prev' on new stack         \n" \
-               "       jmp     lr                                      \n" \
-               "       .fillinsn                                       \n" \
-               "1:                                                     \n" \
-               "       pop     %0  ; restore `__last' from new stack   \n" \
-                       M32R_POP_FP \
-               : "=r" (last) \
-               : "0" (prev), \
-                 "r" (&(prev->thread.sp)), "r" (&(next->thread.sp)), \
-                 "r" (&(prev->thread.lr)), "r" (&(next->thread.lr)) \
-               : "memory", "lr" \
-       ); \
-} while(0)
-
-#define nop()  __asm__ __volatile__ ("nop" : : )
-
-#define xchg(ptr, x)                                                   \
-       ((__typeof__(*(ptr)))__xchg((unsigned long)(x), (ptr), sizeof(*(ptr))))
-#define xchg_local(ptr, x)                                             \
-       ((__typeof__(*(ptr)))__xchg_local((unsigned long)(x), (ptr),    \
-                       sizeof(*(ptr))))
-
-extern void  __xchg_called_with_bad_pointer(void);
-
-#ifdef CONFIG_CHIP_M32700_TS1
-#define DCACHE_CLEAR(reg0, reg1, addr)                         \
-       "seth   "reg1", #high(dcache_dummy);            \n\t"   \
-       "or3    "reg1", "reg1", #low(dcache_dummy);     \n\t"   \
-       "lock   "reg0", @"reg1";                        \n\t"   \
-       "add3   "reg0", "addr", #0x1000;                \n\t"   \
-       "ld     "reg0", @"reg0";                        \n\t"   \
-       "add3   "reg0", "addr", #0x2000;                \n\t"   \
-       "ld     "reg0", @"reg0";                        \n\t"   \
-       "unlock "reg0", @"reg1";                        \n\t"
-       /* FIXME: This workaround code cannot handle kernel modules
-        * correctly under SMP environment.
-        */
-#else  /* CONFIG_CHIP_M32700_TS1 */
-#define DCACHE_CLEAR(reg0, reg1, addr)
-#endif /* CONFIG_CHIP_M32700_TS1 */
-
-static __always_inline unsigned long
-__xchg(unsigned long x, volatile void *ptr, int size)
-{
-       unsigned long flags;
-       unsigned long tmp = 0;
-
-       local_irq_save(flags);
-
-       switch (size) {
-#ifndef CONFIG_SMP
-       case 1:
-               __asm__ __volatile__ (
-                       "ldb    %0, @%2 \n\t"
-                       "stb    %1, @%2 \n\t"
-                       : "=&r" (tmp) : "r" (x), "r" (ptr) : "memory");
-               break;
-       case 2:
-               __asm__ __volatile__ (
-                       "ldh    %0, @%2 \n\t"
-                       "sth    %1, @%2 \n\t"
-                       : "=&r" (tmp) : "r" (x), "r" (ptr) : "memory");
-               break;
-       case 4:
-               __asm__ __volatile__ (
-                       "ld     %0, @%2 \n\t"
-                       "st     %1, @%2 \n\t"
-                       : "=&r" (tmp) : "r" (x), "r" (ptr) : "memory");
-               break;
-#else  /* CONFIG_SMP */
-       case 4:
-               __asm__ __volatile__ (
-                       DCACHE_CLEAR("%0", "r4", "%2")
-                       "lock   %0, @%2;        \n\t"
-                       "unlock %1, @%2;        \n\t"
-                       : "=&r" (tmp) : "r" (x), "r" (ptr)
-                       : "memory"
-#ifdef CONFIG_CHIP_M32700_TS1
-                       , "r4"
-#endif /* CONFIG_CHIP_M32700_TS1 */
-               );
-               break;
-#endif  /* CONFIG_SMP */
-       default:
-               __xchg_called_with_bad_pointer();
-       }
-
-       local_irq_restore(flags);
-
-       return (tmp);
-}
-
-static __always_inline unsigned long
-__xchg_local(unsigned long x, volatile void *ptr, int size)
-{
-       unsigned long flags;
-       unsigned long tmp = 0;
-
-       local_irq_save(flags);
-
-       switch (size) {
-       case 1:
-               __asm__ __volatile__ (
-                       "ldb    %0, @%2 \n\t"
-                       "stb    %1, @%2 \n\t"
-                       : "=&r" (tmp) : "r" (x), "r" (ptr) : "memory");
-               break;
-       case 2:
-               __asm__ __volatile__ (
-                       "ldh    %0, @%2 \n\t"
-                       "sth    %1, @%2 \n\t"
-                       : "=&r" (tmp) : "r" (x), "r" (ptr) : "memory");
-               break;
-       case 4:
-               __asm__ __volatile__ (
-                       "ld     %0, @%2 \n\t"
-                       "st     %1, @%2 \n\t"
-                       : "=&r" (tmp) : "r" (x), "r" (ptr) : "memory");
-               break;
-       default:
-               __xchg_called_with_bad_pointer();
-       }
-
-       local_irq_restore(flags);
-
-       return (tmp);
-}
-
-#define __HAVE_ARCH_CMPXCHG    1
-
-static inline unsigned long
-__cmpxchg_u32(volatile unsigned int *p, unsigned int old, unsigned int new)
-{
-       unsigned long flags;
-       unsigned int retval;
-
-       local_irq_save(flags);
-       __asm__ __volatile__ (
-                       DCACHE_CLEAR("%0", "r4", "%1")
-                       M32R_LOCK" %0, @%1;     \n"
-               "       bne     %0, %2, 1f;     \n"
-                       M32R_UNLOCK" %3, @%1;   \n"
-               "       bra     2f;             \n"
-                "       .fillinsn              \n"
-               "1:"
-                       M32R_UNLOCK" %0, @%1;   \n"
-                "       .fillinsn              \n"
-               "2:"
-                       : "=&r" (retval)
-                       : "r" (p), "r" (old), "r" (new)
-                       : "cbit", "memory"
-#ifdef CONFIG_CHIP_M32700_TS1
-                       , "r4"
-#endif  /* CONFIG_CHIP_M32700_TS1 */
-               );
-       local_irq_restore(flags);
-
-       return retval;
-}
-
-static inline unsigned long
-__cmpxchg_local_u32(volatile unsigned int *p, unsigned int old,
-                       unsigned int new)
-{
-       unsigned long flags;
-       unsigned int retval;
-
-       local_irq_save(flags);
-       __asm__ __volatile__ (
-                       DCACHE_CLEAR("%0", "r4", "%1")
-                       "ld %0, @%1;            \n"
-               "       bne     %0, %2, 1f;     \n"
-                       "st %3, @%1;            \n"
-               "       bra     2f;             \n"
-               "       .fillinsn               \n"
-               "1:"
-                       "st %0, @%1;            \n"
-               "       .fillinsn               \n"
-               "2:"
-                       : "=&r" (retval)
-                       : "r" (p), "r" (old), "r" (new)
-                       : "cbit", "memory"
-#ifdef CONFIG_CHIP_M32700_TS1
-                       , "r4"
-#endif  /* CONFIG_CHIP_M32700_TS1 */
-               );
-       local_irq_restore(flags);
-
-       return retval;
-}
-
-/* This function doesn't exist, so you'll get a linker error
-   if something tries to do an invalid cmpxchg().  */
-extern void __cmpxchg_called_with_bad_pointer(void);
-
-static inline unsigned long
-__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
-{
-       switch (size) {
-       case 4:
-               return __cmpxchg_u32(ptr, old, new);
-#if 0  /* we don't have __cmpxchg_u64 */
-       case 8:
-               return __cmpxchg_u64(ptr, old, new);
-#endif /* 0 */
-       }
-       __cmpxchg_called_with_bad_pointer();
-       return old;
-}
-
-#define cmpxchg(ptr, o, n)                                              \
-       ((__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)(o),       \
-                       (unsigned long)(n), sizeof(*(ptr))))
-
-#include <asm-generic/cmpxchg-local.h>
-
-static inline unsigned long __cmpxchg_local(volatile void *ptr,
-                                     unsigned long old,
-                                     unsigned long new, int size)
-{
-       switch (size) {
-       case 4:
-               return __cmpxchg_local_u32(ptr, old, new);
-       default:
-               return __cmpxchg_local_generic(ptr, old, new, size);
-       }
-
-       return old;
-}
-
-/*
- * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
- * them available.
- */
-#define cmpxchg_local(ptr, o, n)                                           \
-       ((__typeof__(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(o),     \
-                       (unsigned long)(n), sizeof(*(ptr))))
-#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
-
-#endif  /* __KERNEL__ */
-
-/*
- * Memory barrier.
- *
- * mb() prevents loads and stores being reordered across this point.
- * rmb() prevents loads being reordered across this point.
- * wmb() prevents stores being reordered across this point.
- */
-#define mb()   barrier()
-#define rmb()  mb()
-#define wmb()  mb()
-
-/**
- * read_barrier_depends - Flush all pending reads that subsequents reads
- * depend on.
- *
- * No data-dependent reads from memory-like regions are ever reordered
- * over this barrier.  All reads preceding this primitive are guaranteed
- * to access memory (but not necessarily other CPUs' caches) before any
- * reads following this primitive that depend on the data return by
- * any of the preceding reads.  This primitive is much lighter weight than
- * rmb() on most CPUs, and is never heavier weight than is
- * rmb().
- *
- * These ordering constraints are respected by both the local CPU
- * and the compiler.
- *
- * Ordering is not guaranteed by anything other than these primitives,
- * not even by data dependencies.  See the documentation for
- * memory_barrier() for examples and URLs to more information.
- *
- * For example, the following code would force ordering (the initial
- * value of "a" is zero, "b" is one, and "p" is "&a"):
- *
- * <programlisting>
- *      CPU 0                           CPU 1
- *
- *      b = 2;
- *      memory_barrier();
- *      p = &b;                         q = p;
- *                                      read_barrier_depends();
- *                                      d = *q;
- * </programlisting>
- *
- *
- * because the read of "*q" depends on the read of "p" and these
- * two reads are separated by a read_barrier_depends().  However,
- * the following code, with the same initial values for "a" and "b":
- *
- * <programlisting>
- *      CPU 0                           CPU 1
- *
- *      a = 2;
- *      memory_barrier();
- *      b = 3;                          y = b;
- *                                      read_barrier_depends();
- *                                      x = a;
- * </programlisting>
- *
- * does not enforce ordering, since there is no data dependency between
- * the read of "a" and the read of "b".  Therefore, on some CPUs, such
- * as Alpha, "y" could be set to 3 and "x" to 0.  Use rmb()
- * in cases like this where there are no data dependencies.
- **/
-
-#define read_barrier_depends() do { } while (0)
-
-#ifdef CONFIG_SMP
-#define smp_mb()       mb()
-#define smp_rmb()      rmb()
-#define smp_wmb()      wmb()
-#define smp_read_barrier_depends()     read_barrier_depends()
-#define set_mb(var, value) do { (void) xchg(&var, value); } while (0)
-#else
-#define smp_mb()       barrier()
-#define smp_rmb()      barrier()
-#define smp_wmb()      barrier()
-#define smp_read_barrier_depends()     do { } while (0)
-#define set_mb(var, value) do { var = value; barrier(); } while (0)
-#endif
-
-#define arch_align_stack(x) (x)
-
-#endif /* _ASM_M32R_SYSTEM_H */
index 2074375..4c03361 100644 (file)
@@ -29,7 +29,6 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/processor.h>
 #include <asm/mmu_context.h>
 
index ee6a919..3bcb207 100644 (file)
@@ -18,7 +18,6 @@
 #include <asm/page.h>
 #include <asm/processor.h>
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <linux/atomic.h>
index 888aab1..80f18cc 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/vt_kern.h>              /* For unblank_screen() */
 
 #include <asm/m32r.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
index 2c9aeb4..3cdfa9c 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/module.h>
 
 #include <asm/m32r.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/hardirq.h>
 #include <asm/mmu_context.h>
index 34671d3..e2dd778 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/init.h>
 #include <linux/device.h>
 
-#include <asm/system.h>
 #include <asm/m32r.h>
 #include <asm/io.h>
 
index 1053e1c..9a4ba8a 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 
-#include <asm/system.h>
 #include <asm/m32r.h>
 #include <asm/io.h>
 
index 35130ac..767d2f4 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 
-#include <asm/system.h>
 #include <asm/m32r.h>
 #include <asm/io.h>
 
index f3ed6b6..76d665a 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 
-#include <asm/system.h>
 #include <asm/m32r.h>
 #include <asm/io.h>
 
index 2408e35..a3646d4 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 
-#include <asm/system.h>
 #include <asm/m32r.h>
 #include <asm/io.h>
 
index 83b46b0..f8373c0 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 
-#include <asm/system.h>
 #include <asm/m32r.h>
 #include <asm/io.h>
 
index 3266070..cd01704 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 
-#include <asm/system.h>
 #include <asm/m32r.h>
 #include <asm/io.h>
 
index 0c7a1e8..dcde0ec 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 
-#include <asm/system.h>
 #include <asm/m32r.h>
 #include <asm/io.h>
 
index 61e5c54..2559eef 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/string.h>
 #include <linux/module.h>
 
-#include <asm/system.h>
 #include <asm/amigahw.h>
 
 static unsigned short *snd_data;
index b95a451..ee01b7a 100644 (file)
@@ -29,7 +29,6 @@
 
 #include <asm/bootinfo.h>
 #include <asm/setup.h>
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/amigahw.h>
 #include <asm/amigaints.h>
index 8d3eafa..0a30406 100644 (file)
@@ -9,7 +9,6 @@
 
 #include <asm/setup.h>
 #include <asm/bootinfo.h>
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/apollohw.h>
 #include <asm/irq.h>
index 8048e1b..783d8f0 100644 (file)
@@ -42,7 +42,6 @@
 #include <linux/seq_file.h>
 #include <linux/module.h>
 
-#include <asm/system.h>
 #include <asm/traps.h>
 
 #include <asm/atarihw.h>
index d266fe8..1c1181e 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/module.h>
 
 #include <asm/atarihw.h>
-#include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/pgtable.h>
 #include <asm/atariints.h>
index c4ac15c..d8eb327 100644 (file)
@@ -39,7 +39,6 @@
 #include <asm/atarihw.h>
 #include <asm/atariints.h>
 #include <asm/atari_stram.h>
-#include <asm/system.h>
 #include <asm/machdep.h>
 #include <asm/hwtest.h>
 #include <asm/io.h>
index 8128647..0bf850a 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/bcd.h>
 
 #include <asm/bootinfo.h>
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/setup.h>
 #include <asm/irq.h>
index 1c4d4c7..cf12a17 100644 (file)
@@ -21,7 +21,6 @@
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/setup.h>
 
 /*
index c87fe69..29a71be 100644 (file)
@@ -15,7 +15,6 @@
 #include <asm/machdep.h>
 #include <asm/irq.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/traps.h>
 #include <asm/blinken.h>
 
index 4eba796..336e617 100644 (file)
@@ -2,7 +2,7 @@
 #define __ARCH_M68K_ATOMIC__
 
 #include <linux/types.h>
-#include <asm/system.h>
+#include <linux/irqflags.h>
 
 /*
  * Atomic operations that C can't guarantee us.  Useful for
diff --git a/arch/m68k/include/asm/barrier.h b/arch/m68k/include/asm/barrier.h
new file mode 100644 (file)
index 0000000..445ce22
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef _M68K_BARRIER_H
+#define _M68K_BARRIER_H
+
+/*
+ * Force strict CPU ordering.
+ * Not really required on m68k...
+ */
+#define nop()          do { asm volatile ("nop"); barrier(); } while (0)
+#define mb()           barrier()
+#define rmb()          barrier()
+#define wmb()          barrier()
+#define read_barrier_depends() ((void)0)
+#define set_mb(var, value)     ({ (var) = (value); wmb(); })
+
+#define smp_mb()       barrier()
+#define smp_rmb()      barrier()
+#define smp_wmb()      barrier()
+#define smp_read_barrier_depends()     ((void)0)
+
+#endif /* _M68K_BARRIER_H */
diff --git a/arch/m68k/include/asm/cmpxchg.h b/arch/m68k/include/asm/cmpxchg.h
new file mode 100644 (file)
index 0000000..5c81d0e
--- /dev/null
@@ -0,0 +1,141 @@
+#ifndef __ARCH_M68K_CMPXCHG__
+#define __ARCH_M68K_CMPXCHG__
+
+#include <linux/irqflags.h>
+
+struct __xchg_dummy { unsigned long a[100]; };
+#define __xg(x) ((volatile struct __xchg_dummy *)(x))
+
+extern unsigned long __invalid_xchg_size(unsigned long, volatile void *, int);
+
+#ifndef CONFIG_RMW_INSNS
+static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
+{
+       unsigned long flags, tmp;
+
+       local_irq_save(flags);
+
+       switch (size) {
+       case 1:
+               tmp = *(u8 *)ptr;
+               *(u8 *)ptr = x;
+               x = tmp;
+               break;
+       case 2:
+               tmp = *(u16 *)ptr;
+               *(u16 *)ptr = x;
+               x = tmp;
+               break;
+       case 4:
+               tmp = *(u32 *)ptr;
+               *(u32 *)ptr = x;
+               x = tmp;
+               break;
+       default:
+               tmp = __invalid_xchg_size(x, ptr, size);
+               break;
+       }
+
+       local_irq_restore(flags);
+       return x;
+}
+#else
+static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
+{
+       switch (size) {
+       case 1:
+               __asm__ __volatile__
+                       ("moveb %2,%0\n\t"
+                        "1:\n\t"
+                        "casb %0,%1,%2\n\t"
+                        "jne 1b"
+                        : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
+               break;
+       case 2:
+               __asm__ __volatile__
+                       ("movew %2,%0\n\t"
+                        "1:\n\t"
+                        "casw %0,%1,%2\n\t"
+                        "jne 1b"
+                        : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
+               break;
+       case 4:
+               __asm__ __volatile__
+                       ("movel %2,%0\n\t"
+                        "1:\n\t"
+                        "casl %0,%1,%2\n\t"
+                        "jne 1b"
+                        : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
+               break;
+       default:
+               x = __invalid_xchg_size(x, ptr, size);
+               break;
+       }
+       return x;
+}
+#endif
+
+#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
+
+#include <asm-generic/cmpxchg-local.h>
+
+#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
+
+extern unsigned long __invalid_cmpxchg_size(volatile void *,
+                                           unsigned long, unsigned long, int);
+
+/*
+ * Atomic compare and exchange.  Compare OLD with MEM, if identical,
+ * store NEW in MEM.  Return the initial value in MEM.  Success is
+ * indicated by comparing RETURN with OLD.
+ */
+#ifdef CONFIG_RMW_INSNS
+#define __HAVE_ARCH_CMPXCHG    1
+
+static inline unsigned long __cmpxchg(volatile void *p, unsigned long old,
+                                     unsigned long new, int size)
+{
+       switch (size) {
+       case 1:
+               __asm__ __volatile__ ("casb %0,%2,%1"
+                                     : "=d" (old), "=m" (*(char *)p)
+                                     : "d" (new), "0" (old), "m" (*(char *)p));
+               break;
+       case 2:
+               __asm__ __volatile__ ("casw %0,%2,%1"
+                                     : "=d" (old), "=m" (*(short *)p)
+                                     : "d" (new), "0" (old), "m" (*(short *)p));
+               break;
+       case 4:
+               __asm__ __volatile__ ("casl %0,%2,%1"
+                                     : "=d" (old), "=m" (*(int *)p)
+                                     : "d" (new), "0" (old), "m" (*(int *)p));
+               break;
+       default:
+               old = __invalid_cmpxchg_size(p, old, new, size);
+               break;
+       }
+       return old;
+}
+
+#define cmpxchg(ptr, o, n)                                                 \
+       ((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o),           \
+                       (unsigned long)(n), sizeof(*(ptr))))
+#define cmpxchg_local(ptr, o, n)                                           \
+       ((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o),           \
+                       (unsigned long)(n), sizeof(*(ptr))))
+#else
+
+/*
+ * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
+ * them available.
+ */
+#define cmpxchg_local(ptr, o, n)                                              \
+       ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
+                       (unsigned long)(n), sizeof(*(ptr))))
+
+#include <asm-generic/cmpxchg.h>
+
+#endif
+
+#endif /* __ARCH_M68K_CMPXCHG__ */
diff --git a/arch/m68k/include/asm/exec.h b/arch/m68k/include/asm/exec.h
new file mode 100644 (file)
index 0000000..0499adf
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _M68K_EXEC_H
+#define _M68K_EXEC_H
+
+#define arch_align_stack(x) (x)
+
+#endif /* _M68K_EXEC_H */
index 32c45f8..95231e2 100644 (file)
@@ -11,7 +11,6 @@
 
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/sun3x.h>
 
diff --git a/arch/m68k/include/asm/switch_to.h b/arch/m68k/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..16fd6b6
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef _M68K_SWITCH_TO_H
+#define _M68K_SWITCH_TO_H
+
+/*
+ * switch_to(n) should switch tasks to task ptr, first checking that
+ * ptr isn't the current task, in which case it does nothing.  This
+ * also clears the TS-flag if the task we switched to has used the
+ * math co-processor latest.
+ */
+/*
+ * switch_to() saves the extra registers, that are not saved
+ * automatically by SAVE_SWITCH_STACK in resume(), ie. d0-d5 and
+ * a0-a1. Some of these are used by schedule() and its predecessors
+ * and so we might get see unexpected behaviors when a task returns
+ * with unexpected register values.
+ *
+ * syscall stores these registers itself and none of them are used
+ * by syscall after the function in the syscall has been called.
+ *
+ * Beware that resume now expects *next to be in d1 and the offset of
+ * tss to be in a1. This saves a few instructions as we no longer have
+ * to push them onto the stack and read them back right after.
+ *
+ * 02/17/96 - Jes Sorensen (jds@kom.auc.dk)
+ *
+ * Changed 96/09/19 by Andreas Schwab
+ * pass prev in a0, next in a1
+ */
+asmlinkage void resume(void);
+#define switch_to(prev,next,last) do { \
+  register void *_prev __asm__ ("a0") = (prev); \
+  register void *_next __asm__ ("a1") = (next); \
+  register void *_last __asm__ ("d1"); \
+  __asm__ __volatile__("jbsr resume" \
+                      : "=a" (_prev), "=a" (_next), "=d" (_last) \
+                      : "0" (_prev), "1" (_next) \
+                      : "d0", "d2", "d3", "d4", "d5"); \
+  (last) = _last; \
+} while (0)
+
+#endif /* _M68K_SWITCH_TO_H */
diff --git a/arch/m68k/include/asm/system.h b/arch/m68k/include/asm/system.h
deleted file mode 100644 (file)
index 8dc6817..0000000
+++ /dev/null
@@ -1,194 +0,0 @@
-#ifndef _M68K_SYSTEM_H
-#define _M68K_SYSTEM_H
-
-#include <linux/linkage.h>
-#include <linux/kernel.h>
-#include <linux/bug.h>
-#include <linux/irqflags.h>
-#include <asm/segment.h>
-#include <asm/entry.h>
-
-#ifdef __KERNEL__
-
-/*
- * switch_to(n) should switch tasks to task ptr, first checking that
- * ptr isn't the current task, in which case it does nothing.  This
- * also clears the TS-flag if the task we switched to has used the
- * math co-processor latest.
- */
-/*
- * switch_to() saves the extra registers, that are not saved
- * automatically by SAVE_SWITCH_STACK in resume(), ie. d0-d5 and
- * a0-a1. Some of these are used by schedule() and its predecessors
- * and so we might get see unexpected behaviors when a task returns
- * with unexpected register values.
- *
- * syscall stores these registers itself and none of them are used
- * by syscall after the function in the syscall has been called.
- *
- * Beware that resume now expects *next to be in d1 and the offset of
- * tss to be in a1. This saves a few instructions as we no longer have
- * to push them onto the stack and read them back right after.
- *
- * 02/17/96 - Jes Sorensen (jds@kom.auc.dk)
- *
- * Changed 96/09/19 by Andreas Schwab
- * pass prev in a0, next in a1
- */
-asmlinkage void resume(void);
-#define switch_to(prev,next,last) do { \
-  register void *_prev __asm__ ("a0") = (prev); \
-  register void *_next __asm__ ("a1") = (next); \
-  register void *_last __asm__ ("d1"); \
-  __asm__ __volatile__("jbsr resume" \
-                      : "=a" (_prev), "=a" (_next), "=d" (_last) \
-                      : "0" (_prev), "1" (_next) \
-                      : "d0", "d2", "d3", "d4", "d5"); \
-  (last) = _last; \
-} while (0)
-
-
-/*
- * Force strict CPU ordering.
- * Not really required on m68k...
- */
-#define nop()          do { asm volatile ("nop"); barrier(); } while (0)
-#define mb()           barrier()
-#define rmb()          barrier()
-#define wmb()          barrier()
-#define read_barrier_depends() ((void)0)
-#define set_mb(var, value)     ({ (var) = (value); wmb(); })
-
-#define smp_mb()       barrier()
-#define smp_rmb()      barrier()
-#define smp_wmb()      barrier()
-#define smp_read_barrier_depends()     ((void)0)
-
-#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
-
-struct __xchg_dummy { unsigned long a[100]; };
-#define __xg(x) ((volatile struct __xchg_dummy *)(x))
-
-#ifndef CONFIG_RMW_INSNS
-static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
-{
-       unsigned long flags, tmp;
-
-       local_irq_save(flags);
-
-       switch (size) {
-       case 1:
-               tmp = *(u8 *)ptr;
-               *(u8 *)ptr = x;
-               x = tmp;
-               break;
-       case 2:
-               tmp = *(u16 *)ptr;
-               *(u16 *)ptr = x;
-               x = tmp;
-               break;
-       case 4:
-               tmp = *(u32 *)ptr;
-               *(u32 *)ptr = x;
-               x = tmp;
-               break;
-       default:
-               BUG();
-       }
-
-       local_irq_restore(flags);
-       return x;
-}
-#else
-static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
-{
-       switch (size) {
-           case 1:
-               __asm__ __volatile__
-                       ("moveb %2,%0\n\t"
-                        "1:\n\t"
-                        "casb %0,%1,%2\n\t"
-                        "jne 1b"
-                        : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
-               break;
-           case 2:
-               __asm__ __volatile__
-                       ("movew %2,%0\n\t"
-                        "1:\n\t"
-                        "casw %0,%1,%2\n\t"
-                        "jne 1b"
-                        : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
-               break;
-           case 4:
-               __asm__ __volatile__
-                       ("movel %2,%0\n\t"
-                        "1:\n\t"
-                        "casl %0,%1,%2\n\t"
-                        "jne 1b"
-                        : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
-               break;
-       }
-       return x;
-}
-#endif
-
-#include <asm-generic/cmpxchg-local.h>
-
-#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
-
-/*
- * Atomic compare and exchange.  Compare OLD with MEM, if identical,
- * store NEW in MEM.  Return the initial value in MEM.  Success is
- * indicated by comparing RETURN with OLD.
- */
-#ifdef CONFIG_RMW_INSNS
-#define __HAVE_ARCH_CMPXCHG    1
-
-static inline unsigned long __cmpxchg(volatile void *p, unsigned long old,
-                                     unsigned long new, int size)
-{
-       switch (size) {
-       case 1:
-               __asm__ __volatile__ ("casb %0,%2,%1"
-                                     : "=d" (old), "=m" (*(char *)p)
-                                     : "d" (new), "0" (old), "m" (*(char *)p));
-               break;
-       case 2:
-               __asm__ __volatile__ ("casw %0,%2,%1"
-                                     : "=d" (old), "=m" (*(short *)p)
-                                     : "d" (new), "0" (old), "m" (*(short *)p));
-               break;
-       case 4:
-               __asm__ __volatile__ ("casl %0,%2,%1"
-                                     : "=d" (old), "=m" (*(int *)p)
-                                     : "d" (new), "0" (old), "m" (*(int *)p));
-               break;
-       }
-       return old;
-}
-
-#define cmpxchg(ptr, o, n)                                                 \
-       ((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o),           \
-                       (unsigned long)(n), sizeof(*(ptr))))
-#define cmpxchg_local(ptr, o, n)                                           \
-       ((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o),           \
-                       (unsigned long)(n), sizeof(*(ptr))))
-#else
-
-/*
- * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
- * them available.
- */
-#define cmpxchg_local(ptr, o, n)                                              \
-       ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
-                       (unsigned long)(n), sizeof(*(ptr))))
-
-#include <asm-generic/cmpxchg.h>
-
-#endif
-
-#define arch_align_stack(x) (x)
-
-#endif /* __KERNEL__ */
-
-#endif /* _M68K_SYSTEM_H */
index 74fefac..6b32b64 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/init.h>
 
 #include <asm/setup.h>
-#include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/traps.h>
 #include <asm/page.h>
index c73988c..9ab4f55 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/seq_file.h>
-#include <asm/system.h>
 #include <asm/traps.h>
 
 asmlinkage void do_IRQ(int irq, struct pt_regs *regs)
index c54ef92..c488e3c 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/mqueue.h>
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/traps.h>
 #include <asm/machdep.h>
 #include <asm/setup.h>
index 149a05f..8b4a222 100644 (file)
@@ -23,7 +23,6 @@
 #include <asm/uaccess.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/processor.h>
 
 /*
index daaa918..388e5cc 100644 (file)
@@ -32,7 +32,6 @@
 
 #include <asm/setup.h>
 #include <asm/fpu.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/traps.h>
 #include <asm/pgalloc.h>
index 147b03f..322c977 100644 (file)
@@ -25,7 +25,6 @@
 
 #include <asm/setup.h>
 #include <asm/fpu.h>
-#include <asm/system.h>
 #include <asm/traps.h>
 
 /* assembler routines */
index f60ff5f..96fa6ed 100644 (file)
@@ -30,7 +30,6 @@
 #include <asm/setup.h>
 #include <asm/bootinfo.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/pgtable.h>
index eb91555..5e08555 100644 (file)
@@ -19,7 +19,6 @@
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/rtc.h>
-#include <asm/system.h>
 #include <asm/segment.h>
 #include <asm/setup.h>
 #include <asm/macintosh.h>
index 2db6099..6b020a8 100644 (file)
@@ -13,7 +13,6 @@
 
 #include <asm/setup.h>
 #include <asm/traps.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
 
index 89f3b20..f77f258 100644 (file)
@@ -23,7 +23,6 @@
 #include <asm/uaccess.h>
 #include <asm/page.h>
 #include <asm/pgalloc.h>
-#include <asm/system.h>
 #include <asm/traps.h>
 #include <asm/machdep.h>
 #include <asm/io.h>
index 1e33d39..345ec0d 100644 (file)
@@ -36,7 +36,6 @@
 #include <asm/segment.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/machdep.h>
 
 /*
index 1cc2bed..568cfad 100644 (file)
@@ -20,7 +20,6 @@
 #include <asm/page.h>
 #include <asm/pgalloc.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 #undef DEBUG
 
index a5dbb74..250b8b7 100644 (file)
@@ -17,7 +17,6 @@
 #include <asm/segment.h>
 #include <asm/page.h>
 #include <asm/pgalloc.h>
-#include <asm/system.h>
 #include <asm/traps.h>
 #include <asm/machdep.h>
 
index 8b3db1c..0dafa69 100644 (file)
@@ -24,7 +24,6 @@
 #include <asm/uaccess.h>
 #include <asm/page.h>
 #include <asm/pgalloc.h>
-#include <asm/system.h>
 #include <asm/machdep.h>
 #include <asm/io.h>
 #include <asm/dma.h>
index 1b902db..e080406 100644 (file)
@@ -21,7 +21,6 @@
 #include <asm/uaccess.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/machdep.h>
 #include <asm/io.h>
 
index 5de924e..a41c091 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/interrupt.h>
 
 #include <asm/bootinfo.h>
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/setup.h>
 #include <asm/irq.h>
index c3fb3bd..b6d7d8a 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/module.h>
 
 #include <asm/bootinfo.h>
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/setup.h>
 #include <asm/irq.h>
index 39c79eb..6ef7a81 100644 (file)
@@ -20,7 +20,6 @@
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/setup.h>
 
 /*
index 44b8665..8c20e89 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/rtc.h>
-#include <asm/system.h>
 #include <asm/machdep.h>
 #include <asm/MC68328.h>
 #if defined(CONFIG_PILOT) || defined(CONFIG_INIT_LCD)
index b15ddef..c801c17 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/clocksource.h>
 #include <linux/rtc.h>
 #include <asm/setup.h>
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/machdep.h>
 #include <asm/MC68VZ328.h>
index 599a594..255fc03 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/irq.h>
 
 #include <asm/setup.h>
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/machdep.h>
 #include <asm/m68360.h>
index dd2c535..4f158d5 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/rtc.h>
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/machdep.h>
 #include <asm/MC68EZ328.h>
index 25ec673..2ed8dc3 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/irq.h>
 #include <linux/rtc.h>
 
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/machdep.h>
 #include <asm/MC68VZ328.h>
index be93648..512adb6 100644 (file)
@@ -29,7 +29,6 @@
 #include <asm/io.h>
 #include <asm/rtc.h>
 #include <asm/bootinfo.h>
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/setup.h>
 #include <asm/irq.h>
index 2b88849..513f9bb 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/irq.h>
 
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/traps.h>
 
 #include <asm/q40_master.h>
index 0116d20..94fe801 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/rtc.h>
 
 #include <asm/errno.h>
-#include <asm/system.h>
 #include <asm/rtc.h>
 #include <asm/intersil.h>
 
index 94f81ec..8edc510 100644 (file)
@@ -17,7 +17,6 @@
 
 #include <asm/setup.h>
 #include <asm/traps.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
index 2bcb6e4..e923643 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/sched.h>
 #include <asm/openprom.h>
 #include <asm/oplib.h>
-#include <asm/system.h>
 #include <linux/string.h>
 
 /* Non blocking get character from console input device, returns -1
index fc599fa..dd306c8 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/console.h>
 #include <linux/init.h>
 
-#include <asm/system.h>
 #include <asm/machdep.h>
 #include <asm/irq.h>
 #include <asm/sun3xprom.h>
index 536a04a..1d0a724 100644 (file)
@@ -15,7 +15,6 @@
 
 #include <asm/irq.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/traps.h>
 #include <asm/sun3x.h>
 #include <asm/sun3ints.h>
index 615f539..472d8bf 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef _ASM_MICROBLAZE_ATOMIC_H
 #define _ASM_MICROBLAZE_ATOMIC_H
 
+#include <asm/cmpxchg.h>
 #include <asm-generic/atomic.h>
 #include <asm-generic/atomic64.h>
 
diff --git a/arch/microblaze/include/asm/barrier.h b/arch/microblaze/include/asm/barrier.h
new file mode 100644 (file)
index 0000000..df5be3e
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_BARRIER_H
+#define _ASM_MICROBLAZE_BARRIER_H
+
+#define nop()                  asm volatile ("nop")
+
+#define smp_read_barrier_depends()     do {} while (0)
+#define read_barrier_depends()         do {} while (0)
+
+#define mb()                   barrier()
+#define rmb()                  mb()
+#define wmb()                  mb()
+#define set_mb(var, value)     do { var = value; mb(); } while (0)
+#define set_wmb(var, value)    do { var = value; wmb(); } while (0)
+
+#define smp_mb()               mb()
+#define smp_rmb()              rmb()
+#define smp_wmb()              wmb()
+
+#endif /* _ASM_MICROBLAZE_BARRIER_H */
diff --git a/arch/microblaze/include/asm/cmpxchg.h b/arch/microblaze/include/asm/cmpxchg.h
new file mode 100644 (file)
index 0000000..0094859
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef _ASM_MICROBLAZE_CMPXCHG_H
+#define _ASM_MICROBLAZE_CMPXCHG_H
+
+void __bad_xchg(volatile void *ptr, int size);
+
+static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
+                                                               int size)
+{
+       unsigned long ret;
+       unsigned long flags;
+
+       switch (size) {
+       case 1:
+               local_irq_save(flags);
+               ret = *(volatile unsigned char *)ptr;
+               *(volatile unsigned char *)ptr = x;
+               local_irq_restore(flags);
+               break;
+
+       case 4:
+               local_irq_save(flags);
+               ret = *(volatile unsigned long *)ptr;
+               *(volatile unsigned long *)ptr = x;
+               local_irq_restore(flags);
+               break;
+       default:
+               __bad_xchg(ptr, size), ret = 0;
+               break;
+       }
+
+       return ret;
+}
+
+#define xchg(ptr, x) \
+       ((__typeof__(*(ptr))) __xchg((unsigned long)(x), (ptr), sizeof(*(ptr))))
+
+#include <asm-generic/cmpxchg.h>
+#include <asm-generic/cmpxchg-local.h>
+
+#endif /* _ASM_MICROBLAZE_CMPXCHG_H */
diff --git a/arch/microblaze/include/asm/exec.h b/arch/microblaze/include/asm/exec.h
new file mode 100644 (file)
index 0000000..e750de1
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_EXEC_H
+#define _ASM_MICROBLAZE_EXEC_H
+
+#define arch_align_stack(x) (x)
+
+#endif /* _ASM_MICROBLAZE_EXEC_H */
index 352cc23..287c548 100644 (file)
@@ -138,6 +138,8 @@ extern unsigned long memory_start;
 extern unsigned long memory_size;
 extern unsigned long lowmem_size;
 
+extern unsigned long kernel_tlb;
+
 extern int page_is_ram(unsigned long pfn);
 
 # define phys_to_pfn(phys)     (PFN_DOWN(phys))
index 7283bfb..510a8e1 100644 (file)
@@ -125,7 +125,6 @@ struct thread_struct {
        .pgdir = swapper_pg_dir, \
 }
 
-
 /* Free all resources held by a thread. */
 extern inline void release_thread(struct task_struct *dead_task)
 {
@@ -144,6 +143,8 @@ static inline void exit_thread(void)
 
 unsigned long get_wchan(struct task_struct *p);
 
+extern void ret_from_fork(void);
+
 /* The size allocated for kernel stacks. This _must_ be a power of two! */
 # define KERNEL_STACK_SIZE     0x2000
 
@@ -166,6 +167,14 @@ unsigned long get_wchan(struct task_struct *p);
 #  define STACK_TOP    TASK_SIZE
 #  define STACK_TOP_MAX        STACK_TOP
 
+void disable_hlt(void);
+void enable_hlt(void);
+void default_idle(void);
+
+#ifdef CONFIG_DEBUG_FS
+extern struct dentry *of_debugfs_root;
+#endif
+
 #  endif /* __ASSEMBLY__ */
 # endif /* CONFIG_MMU */
 #endif /* _ASM_MICROBLAZE_PROCESSOR_H */
index 9f195c0..0061aa1 100644 (file)
@@ -20,6 +20,8 @@ extern unsigned int boot_cpuid; /* move to smp.h */
 
 extern char cmd_line[COMMAND_LINE_SIZE];
 
+extern char *klimit;
+
 void early_printk(const char *fmt, ...);
 
 int setup_early_printk(char *opt);
@@ -47,6 +49,10 @@ void machine_shutdown(void);
 void machine_halt(void);
 void machine_power_off(void);
 
+void free_init_pages(char *what, unsigned long begin, unsigned long end);
+extern void *alloc_maybe_bootmem(size_t size, gfp_t mask);
+extern void *zalloc_maybe_bootmem(size_t size, gfp_t mask);
+
 #  endif/* __KERNEL__ */
 # endif /* __ASSEMBLY__ */
 #endif /* _ASM_MICROBLAZE_SETUP_H */
diff --git a/arch/microblaze/include/asm/switch_to.h b/arch/microblaze/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..f45baa2
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_SWITCH_TO_H
+#define _ASM_MICROBLAZE_SWITCH_TO_H
+
+struct task_struct;
+struct thread_info;
+
+extern struct task_struct *_switch_to(struct thread_info *prev,
+                                       struct thread_info *next);
+
+#define switch_to(prev, next, last)                                    \
+       do {                                                            \
+               (last) = _switch_to(task_thread_info(prev),             \
+                                       task_thread_info(next));        \
+       } while (0)
+
+#endif /* _ASM_MICROBLAZE_SWITCH_TO_H */
diff --git a/arch/microblaze/include/asm/system.h b/arch/microblaze/include/asm/system.h
deleted file mode 100644 (file)
index 01228d2..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#ifndef _ASM_MICROBLAZE_SYSTEM_H
-#define _ASM_MICROBLAZE_SYSTEM_H
-
-#include <asm/registers.h>
-#include <asm/setup.h>
-#include <asm/irqflags.h>
-#include <asm/cache.h>
-
-#include <asm-generic/cmpxchg.h>
-#include <asm-generic/cmpxchg-local.h>
-
-struct task_struct;
-struct thread_info;
-
-extern struct task_struct *_switch_to(struct thread_info *prev,
-                                       struct thread_info *next);
-
-#define switch_to(prev, next, last)                                    \
-       do {                                                            \
-               (last) = _switch_to(task_thread_info(prev),             \
-                                       task_thread_info(next));        \
-       } while (0)
-
-#define smp_read_barrier_depends()     do {} while (0)
-#define read_barrier_depends()         do {} while (0)
-
-#define nop()                  asm volatile ("nop")
-#define mb()                   barrier()
-#define rmb()                  mb()
-#define wmb()                  mb()
-#define set_mb(var, value)     do { var = value; mb(); } while (0)
-#define set_wmb(var, value)    do { var = value; wmb(); } while (0)
-
-#define smp_mb()               mb()
-#define smp_rmb()              rmb()
-#define smp_wmb()              wmb()
-
-void __bad_xchg(volatile void *ptr, int size);
-
-static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
-                                                               int size)
-{
-       unsigned long ret;
-       unsigned long flags;
-
-       switch (size) {
-       case 1:
-               local_irq_save(flags);
-               ret = *(volatile unsigned char *)ptr;
-               *(volatile unsigned char *)ptr = x;
-               local_irq_restore(flags);
-               break;
-
-       case 4:
-               local_irq_save(flags);
-               ret = *(volatile unsigned long *)ptr;
-               *(volatile unsigned long *)ptr = x;
-               local_irq_restore(flags);
-               break;
-       default:
-               __bad_xchg(ptr, size), ret = 0;
-               break;
-       }
-
-       return ret;
-}
-
-void disable_hlt(void);
-void enable_hlt(void);
-void default_idle(void);
-
-#define xchg(ptr, x) \
-       ((__typeof__(*(ptr))) __xchg((unsigned long)(x), (ptr), sizeof(*(ptr))))
-
-void free_init_pages(char *what, unsigned long begin, unsigned long end);
-void free_initmem(void);
-extern char *klimit;
-extern unsigned long kernel_tlb;
-extern void ret_from_fork(void);
-
-extern void *alloc_maybe_bootmem(size_t size, gfp_t mask);
-extern void *zalloc_maybe_bootmem(size_t size, gfp_t mask);
-
-#ifdef CONFIG_DEBUG_FS
-extern struct dentry *of_debugfs_root;
-#endif
-
-#define arch_align_stack(x) (x)
-
-#endif /* _ASM_MICROBLAZE_SYSTEM_H */
index 488c1ed..3a749d5 100644 (file)
@@ -12,7 +12,6 @@
 
 #include <linux/kernel.h>
 #include <linux/compiler.h>
-#include <asm/system.h>
 #include <asm/exceptions.h>
 #include <asm/pvr.h>
 
index 49faeb4..bb4907c 100644 (file)
@@ -18,7 +18,6 @@
 #include <asm/cacheflush.h>
 #include <linux/io.h>
 #include <asm/page.h>
-#include <asm/system.h>
 #include <linux/ftrace.h>
 #include <linux/uaccess.h>
 
index 9155f7d..883b927 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/pm.h>
 #include <linux/tick.h>
 #include <linux/bitops.h>
-#include <asm/system.h>
 #include <asm/pgalloc.h>
 #include <asm/uaccess.h> /* for USER_DS macros */
 #include <asm/cacheflush.h>
index 80d314e..4a764cc 100644 (file)
@@ -36,7 +36,6 @@
 #include <asm/processor.h>
 #include <asm/irq.h>
 #include <linux/io.h>
-#include <asm/system.h>
 #include <asm/mmu.h>
 #include <asm/pgtable.h>
 #include <asm/sections.h>
index 9f79fb3..71af974 100644 (file)
@@ -30,7 +30,6 @@
 #include <asm/entry.h>
 #include <asm/cpuinfo.h>
 
-#include <asm/system.h>
 #include <asm/prom.h>
 #include <asm/pgtable.h>
 
index cadfd56..522defa 100644 (file)
@@ -27,7 +27,6 @@
 #include <asm/setup.h>
 #include <asm/prom.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <linux/cnt32_to_63.h>
 
 #ifdef CONFIG_SELFMOD_TIMER
index ba034d4..5541ac5 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/debug_locks.h>
 
 #include <asm/exceptions.h>
-#include <asm/system.h>
 #include <asm/unwind.h>
 
 void trap_init(void)
index 52746e7..fe9c53f 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/module.h>
 
 #include <linux/string.h>
-#include <asm/system.h>
 
 #ifdef __HAVE_ARCH_MEMCPY
 #ifndef CONFIG_OPT_LIB_FUNCTION
index ae97d2c..c38a265 100644 (file)
@@ -33,7 +33,6 @@
 #include <asm/pgtable.h>
 #include <asm/mmu.h>
 #include <asm/mmu_context.h>
-#include <asm/system.h>
 #include <linux/uaccess.h>
 #include <asm/exceptions.h>
 
index 260b273..d3a9f01 100644 (file)
@@ -24,7 +24,6 @@
 #include <asm/processor.h>
 #include <asm/reboot.h>
 #include <asm/smp-ops.h>
-#include <asm/system.h>
 #include <asm/irq_cpu.h>
 #include <asm/mipsregs.h>
 #include <asm/bootinfo.h>
index b1535fe..c3e2b85 100644 (file)
@@ -15,8 +15,8 @@
 #include <linux/module.h>
 
 #include <asm/mmu_context.h>
-#include <asm/system.h>
 #include <asm/time.h>
+#include <asm/setup.h>
 
 #include <asm/octeon/octeon.h>
 
index 7abce66..5abf4e8 100644 (file)
@@ -24,7 +24,6 @@
 #include <asm/irq_regs.h>
 #include <asm/processor.h>
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/traps.h>
 
 #include <asm/dec/ecc.h>
index 94d23b4..44d8a87 100644 (file)
@@ -22,7 +22,6 @@
 #include <asm/mipsregs.h>
 #include <asm/page.h>
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/traps.h>
 #include <asm/uaccess.h>
 
index 07ca540..ebb73c5 100644 (file)
@@ -21,7 +21,6 @@
 #include <asm/addrspace.h>
 #include <asm/irq_regs.h>
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/traps.h>
 
 #include <asm/dec/kn02ca.h>
index 925c052..43feddd 100644 (file)
@@ -17,8 +17,8 @@
 #include <linux/init.h>
 
 #include <asm/bootinfo.h>
-#include <asm/system.h>
 #include <asm/wbflush.h>
+#include <asm/barrier.h>
 
 static void wbflush_kn01(void);
 static void wbflush_kn210(void);
index 7798887..b5f0825 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/delay.h>
 
 #include <asm/irq_cpu.h>
-#include <asm/system.h>
 #include <asm/mipsregs.h>
 #include <asm/addrspace.h>
 #include <asm/bootinfo.h>
index 29627fb..7cf80ca 100644 (file)
@@ -17,7 +17,6 @@
 #include <asm/fw/arc/types.h>
 #include <asm/sgialib.h>
 #include <asm/bootinfo.h>
-#include <asm/system.h>
 
 VOID
 ArcHalt(VOID)
index 1d93f81..3f4c5cb 100644 (file)
@@ -18,8 +18,8 @@
 #include <linux/types.h>
 #include <asm/barrier.h>
 #include <asm/cpu-features.h>
+#include <asm/cmpxchg.h>
 #include <asm/war.h>
-#include <asm/system.h>
 
 #define ATOMIC_INIT(i)    { (i) }
 
index c0884f0..f7fdc24 100644 (file)
@@ -8,6 +8,8 @@
 #ifndef __ASM_BARRIER_H
 #define __ASM_BARRIER_H
 
+#include <asm/addrspace.h>
+
 /*
  * read_barrier_depends - Flush all pending reads that subsequents reads
  * depend on.
index d8d1c28..285a41f 100644 (file)
@@ -9,6 +9,130 @@
 #define __ASM_CMPXCHG_H
 
 #include <linux/irqflags.h>
+#include <asm/war.h>
+
+static inline unsigned long __xchg_u32(volatile int * m, unsigned int val)
+{
+       __u32 retval;
+
+       smp_mb__before_llsc();
+
+       if (kernel_uses_llsc && R10000_LLSC_WAR) {
+               unsigned long dummy;
+
+               __asm__ __volatile__(
+               "       .set    mips3                                   \n"
+               "1:     ll      %0, %3                  # xchg_u32      \n"
+               "       .set    mips0                                   \n"
+               "       move    %2, %z4                                 \n"
+               "       .set    mips3                                   \n"
+               "       sc      %2, %1                                  \n"
+               "       beqzl   %2, 1b                                  \n"
+               "       .set    mips0                                   \n"
+               : "=&r" (retval), "=m" (*m), "=&r" (dummy)
+               : "R" (*m), "Jr" (val)
+               : "memory");
+       } else if (kernel_uses_llsc) {
+               unsigned long dummy;
+
+               do {
+                       __asm__ __volatile__(
+                       "       .set    mips3                           \n"
+                       "       ll      %0, %3          # xchg_u32      \n"
+                       "       .set    mips0                           \n"
+                       "       move    %2, %z4                         \n"
+                       "       .set    mips3                           \n"
+                       "       sc      %2, %1                          \n"
+                       "       .set    mips0                           \n"
+                       : "=&r" (retval), "=m" (*m), "=&r" (dummy)
+                       : "R" (*m), "Jr" (val)
+                       : "memory");
+               } while (unlikely(!dummy));
+       } else {
+               unsigned long flags;
+
+               raw_local_irq_save(flags);
+               retval = *m;
+               *m = val;
+               raw_local_irq_restore(flags);   /* implies memory barrier  */
+       }
+
+       smp_llsc_mb();
+
+       return retval;
+}
+
+#ifdef CONFIG_64BIT
+static inline __u64 __xchg_u64(volatile __u64 * m, __u64 val)
+{
+       __u64 retval;
+
+       smp_mb__before_llsc();
+
+       if (kernel_uses_llsc && R10000_LLSC_WAR) {
+               unsigned long dummy;
+
+               __asm__ __volatile__(
+               "       .set    mips3                                   \n"
+               "1:     lld     %0, %3                  # xchg_u64      \n"
+               "       move    %2, %z4                                 \n"
+               "       scd     %2, %1                                  \n"
+               "       beqzl   %2, 1b                                  \n"
+               "       .set    mips0                                   \n"
+               : "=&r" (retval), "=m" (*m), "=&r" (dummy)
+               : "R" (*m), "Jr" (val)
+               : "memory");
+       } else if (kernel_uses_llsc) {
+               unsigned long dummy;
+
+               do {
+                       __asm__ __volatile__(
+                       "       .set    mips3                           \n"
+                       "       lld     %0, %3          # xchg_u64      \n"
+                       "       move    %2, %z4                         \n"
+                       "       scd     %2, %1                          \n"
+                       "       .set    mips0                           \n"
+                       : "=&r" (retval), "=m" (*m), "=&r" (dummy)
+                       : "R" (*m), "Jr" (val)
+                       : "memory");
+               } while (unlikely(!dummy));
+       } else {
+               unsigned long flags;
+
+               raw_local_irq_save(flags);
+               retval = *m;
+               *m = val;
+               raw_local_irq_restore(flags);   /* implies memory barrier  */
+       }
+
+       smp_llsc_mb();
+
+       return retval;
+}
+#else
+extern __u64 __xchg_u64_unsupported_on_32bit_kernels(volatile __u64 * m, __u64 val);
+#define __xchg_u64 __xchg_u64_unsupported_on_32bit_kernels
+#endif
+
+static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
+{
+       switch (size) {
+       case 4:
+               return __xchg_u32(ptr, x);
+       case 8:
+               return __xchg_u64(ptr, x);
+       }
+
+       return x;
+}
+
+#define xchg(ptr, x)                                                   \
+({                                                                     \
+       BUILD_BUG_ON(sizeof(*(ptr)) & ~0xc);                            \
+                                                                       \
+       ((__typeof__(*(ptr)))                                           \
+               __xchg((unsigned long)(x), (ptr), sizeof(*(ptr))));     \
+})
 
 #define __HAVE_ARCH_CMPXCHG 1
 
index 2d47da6..f5097f6 100644 (file)
@@ -15,7 +15,6 @@
 #include <asm/io.h>                    /* need byte IO */
 #include <linux/spinlock.h>            /* And spinlocks */
 #include <linux/delay.h>
-#include <asm/system.h>
 
 
 #ifdef HAVE_REALLY_SLOW_DMA_CONTROLLER
diff --git a/arch/mips/include/asm/exec.h b/arch/mips/include/asm/exec.h
new file mode 100644 (file)
index 0000000..c1f6afa
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1994, 95, 96, 97, 98, 99, 2003, 06 by Ralf Baechle
+ * Copyright (C) 1996 by Paul M. Antoine
+ * Copyright (C) 1999 Silicon Graphics
+ * Kevin D. Kissell, kevink@mips.org and Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc.
+ */
+#ifndef _ASM_EXEC_H
+#define _ASM_EXEC_H
+
+extern unsigned long arch_align_stack(unsigned long sp);
+
+#endif /* _ASM_EXEC_H */
index 59f5b55..ba4cf0e 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/io.h>          /* need byte IO */
 #include <linux/spinlock.h>    /* And spinlocks */
 #include <linux/delay.h>
-#include <asm/system.h>
 
 #define NUM_AU1000_DMA_CHANNELS        8
 
index c104f10..20e9dcf 100644 (file)
@@ -19,7 +19,6 @@
 #include <asm/cpu-info.h>
 #include <asm/mipsregs.h>
 #include <asm/prefetch.h>
-#include <asm/system.h>
 
 /*
  * Return current * instruction pointer ("program counter").
@@ -356,6 +355,12 @@ unsigned long get_wchan(struct task_struct *p);
 #define ARCH_HAS_PREFETCHW
 #define prefetchw(x) __builtin_prefetch((x), 1, 1)
 
+/*
+ * See Documentation/scheduler/sched-arch.txt; prevents deadlock on SMP
+ * systems.
+ */
+#define __ARCH_WANT_UNLOCKED_CTXSW
+
 #endif
 
 #endif /* _ASM_PROCESSOR_H */
index 50511aa..6dce6d8 100644 (file)
@@ -5,6 +5,17 @@
 
 #ifdef  __KERNEL__
 extern void setup_early_printk(void);
+
+extern void set_handler(unsigned long offset, void *addr, unsigned long len);
+extern void set_uncached_handler(unsigned long offset, void *addr, unsigned long len);
+
+typedef void (*vi_handler_t)(void);
+extern void *set_vi_handler(int n, vi_handler_t addr);
+
+extern void *set_except_vector(int n, void *addr);
+extern unsigned long ebase;
+extern void per_cpu_trap_init(void);
+
 #endif /* __KERNEL__ */
 
 #endif /* __SETUP_H */
diff --git a/arch/mips/include/asm/switch_to.h b/arch/mips/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..5d33621
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1994, 95, 96, 97, 98, 99, 2003, 06 by Ralf Baechle
+ * Copyright (C) 1996 by Paul M. Antoine
+ * Copyright (C) 1999 Silicon Graphics
+ * Kevin D. Kissell, kevink@mips.org and Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc.
+ */
+#ifndef _ASM_SWITCH_TO_H
+#define _ASM_SWITCH_TO_H
+
+#include <asm/cpu-features.h>
+#include <asm/watch.h>
+#include <asm/dsp.h>
+
+struct task_struct;
+
+/*
+ * switch_to(n) should switch tasks to task nr n, first
+ * checking that n isn't the current task, in which case it does nothing.
+ */
+extern asmlinkage void *resume(void *last, void *next, void *next_ti);
+
+extern unsigned int ll_bit;
+extern struct task_struct *ll_task;
+
+#ifdef CONFIG_MIPS_MT_FPAFF
+
+/*
+ * Handle the scheduler resume end of FPU affinity management.  We do this
+ * inline to try to keep the overhead down. If we have been forced to run on
+ * a "CPU" with an FPU because of a previous high level of FP computation,
+ * but did not actually use the FPU during the most recent time-slice (CU1
+ * isn't set), we undo the restriction on cpus_allowed.
+ *
+ * We're not calling set_cpus_allowed() here, because we have no need to
+ * force prompt migration - we're already switching the current CPU to a
+ * different thread.
+ */
+
+#define __mips_mt_fpaff_switch_to(prev)                                        \
+do {                                                                   \
+       struct thread_info *__prev_ti = task_thread_info(prev);         \
+                                                                       \
+       if (cpu_has_fpu &&                                              \
+           test_ti_thread_flag(__prev_ti, TIF_FPUBOUND) &&             \
+           (!(KSTK_STATUS(prev) & ST0_CU1))) {                         \
+               clear_ti_thread_flag(__prev_ti, TIF_FPUBOUND);          \
+               prev->cpus_allowed = prev->thread.user_cpus_allowed;    \
+       }                                                               \
+       next->thread.emulated_fp = 0;                                   \
+} while(0)
+
+#else
+#define __mips_mt_fpaff_switch_to(prev) do { (void) (prev); } while (0)
+#endif
+
+#define __clear_software_ll_bit()                                      \
+do {                                                                   \
+       if (!__builtin_constant_p(cpu_has_llsc) || !cpu_has_llsc)       \
+               ll_bit = 0;                                             \
+} while (0)
+
+#define switch_to(prev, next, last)                                    \
+do {                                                                   \
+       __mips_mt_fpaff_switch_to(prev);                                \
+       if (cpu_has_dsp)                                                \
+               __save_dsp(prev);                                       \
+       __clear_software_ll_bit();                                      \
+       (last) = resume(prev, next, task_thread_info(next));            \
+} while (0)
+
+#define finish_arch_switch(prev)                                       \
+do {                                                                   \
+       if (cpu_has_dsp)                                                \
+               __restore_dsp(current);                                 \
+       if (cpu_has_userlocal)                                          \
+               write_c0_userlocal(current_thread_info()->tp_value);    \
+       __restore_watch();                                              \
+} while (0)
+
+#endif /* _ASM_SWITCH_TO_H */
diff --git a/arch/mips/include/asm/system.h b/arch/mips/include/asm/system.h
deleted file mode 100644 (file)
index 6018c80..0000000
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1994, 95, 96, 97, 98, 99, 2003, 06 by Ralf Baechle
- * Copyright (C) 1996 by Paul M. Antoine
- * Copyright (C) 1999 Silicon Graphics
- * Kevin D. Kissell, kevink@mips.org and Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 2000 MIPS Technologies, Inc.
- */
-#ifndef _ASM_SYSTEM_H
-#define _ASM_SYSTEM_H
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/irqflags.h>
-
-#include <asm/addrspace.h>
-#include <asm/barrier.h>
-#include <asm/cmpxchg.h>
-#include <asm/cpu-features.h>
-#include <asm/dsp.h>
-#include <asm/watch.h>
-#include <asm/war.h>
-
-
-/*
- * switch_to(n) should switch tasks to task nr n, first
- * checking that n isn't the current task, in which case it does nothing.
- */
-extern asmlinkage void *resume(void *last, void *next, void *next_ti);
-
-struct task_struct;
-
-extern unsigned int ll_bit;
-extern struct task_struct *ll_task;
-
-#ifdef CONFIG_MIPS_MT_FPAFF
-
-/*
- * Handle the scheduler resume end of FPU affinity management.  We do this
- * inline to try to keep the overhead down. If we have been forced to run on
- * a "CPU" with an FPU because of a previous high level of FP computation,
- * but did not actually use the FPU during the most recent time-slice (CU1
- * isn't set), we undo the restriction on cpus_allowed.
- *
- * We're not calling set_cpus_allowed() here, because we have no need to
- * force prompt migration - we're already switching the current CPU to a
- * different thread.
- */
-
-#define __mips_mt_fpaff_switch_to(prev)                                        \
-do {                                                                   \
-       struct thread_info *__prev_ti = task_thread_info(prev);         \
-                                                                       \
-       if (cpu_has_fpu &&                                              \
-           test_ti_thread_flag(__prev_ti, TIF_FPUBOUND) &&             \
-           (!(KSTK_STATUS(prev) & ST0_CU1))) {                         \
-               clear_ti_thread_flag(__prev_ti, TIF_FPUBOUND);          \
-               prev->cpus_allowed = prev->thread.user_cpus_allowed;    \
-       }                                                               \
-       next->thread.emulated_fp = 0;                                   \
-} while(0)
-
-#else
-#define __mips_mt_fpaff_switch_to(prev) do { (void) (prev); } while (0)
-#endif
-
-#define __clear_software_ll_bit()                                      \
-do {                                                                   \
-       if (!__builtin_constant_p(cpu_has_llsc) || !cpu_has_llsc)       \
-               ll_bit = 0;                                             \
-} while (0)
-
-#define switch_to(prev, next, last)                                    \
-do {                                                                   \
-       __mips_mt_fpaff_switch_to(prev);                                \
-       if (cpu_has_dsp)                                                \
-               __save_dsp(prev);                                       \
-       __clear_software_ll_bit();                                      \
-       (last) = resume(prev, next, task_thread_info(next));            \
-} while (0)
-
-#define finish_arch_switch(prev)                                       \
-do {                                                                   \
-       if (cpu_has_dsp)                                                \
-               __restore_dsp(current);                                 \
-       if (cpu_has_userlocal)                                          \
-               write_c0_userlocal(current_thread_info()->tp_value);    \
-       __restore_watch();                                              \
-} while (0)
-
-static inline unsigned long __xchg_u32(volatile int * m, unsigned int val)
-{
-       __u32 retval;
-
-       smp_mb__before_llsc();
-
-       if (kernel_uses_llsc && R10000_LLSC_WAR) {
-               unsigned long dummy;
-
-               __asm__ __volatile__(
-               "       .set    mips3                                   \n"
-               "1:     ll      %0, %3                  # xchg_u32      \n"
-               "       .set    mips0                                   \n"
-               "       move    %2, %z4                                 \n"
-               "       .set    mips3                                   \n"
-               "       sc      %2, %1                                  \n"
-               "       beqzl   %2, 1b                                  \n"
-               "       .set    mips0                                   \n"
-               : "=&r" (retval), "=m" (*m), "=&r" (dummy)
-               : "R" (*m), "Jr" (val)
-               : "memory");
-       } else if (kernel_uses_llsc) {
-               unsigned long dummy;
-
-               do {
-                       __asm__ __volatile__(
-                       "       .set    mips3                           \n"
-                       "       ll      %0, %3          # xchg_u32      \n"
-                       "       .set    mips0                           \n"
-                       "       move    %2, %z4                         \n"
-                       "       .set    mips3                           \n"
-                       "       sc      %2, %1                          \n"
-                       "       .set    mips0                           \n"
-                       : "=&r" (retval), "=m" (*m), "=&r" (dummy)
-                       : "R" (*m), "Jr" (val)
-                       : "memory");
-               } while (unlikely(!dummy));
-       } else {
-               unsigned long flags;
-
-               raw_local_irq_save(flags);
-               retval = *m;
-               *m = val;
-               raw_local_irq_restore(flags);   /* implies memory barrier  */
-       }
-
-       smp_llsc_mb();
-
-       return retval;
-}
-
-#ifdef CONFIG_64BIT
-static inline __u64 __xchg_u64(volatile __u64 * m, __u64 val)
-{
-       __u64 retval;
-
-       smp_mb__before_llsc();
-
-       if (kernel_uses_llsc && R10000_LLSC_WAR) {
-               unsigned long dummy;
-
-               __asm__ __volatile__(
-               "       .set    mips3                                   \n"
-               "1:     lld     %0, %3                  # xchg_u64      \n"
-               "       move    %2, %z4                                 \n"
-               "       scd     %2, %1                                  \n"
-               "       beqzl   %2, 1b                                  \n"
-               "       .set    mips0                                   \n"
-               : "=&r" (retval), "=m" (*m), "=&r" (dummy)
-               : "R" (*m), "Jr" (val)
-               : "memory");
-       } else if (kernel_uses_llsc) {
-               unsigned long dummy;
-
-               do {
-                       __asm__ __volatile__(
-                       "       .set    mips3                           \n"
-                       "       lld     %0, %3          # xchg_u64      \n"
-                       "       move    %2, %z4                         \n"
-                       "       scd     %2, %1                          \n"
-                       "       .set    mips0                           \n"
-                       : "=&r" (retval), "=m" (*m), "=&r" (dummy)
-                       : "R" (*m), "Jr" (val)
-                       : "memory");
-               } while (unlikely(!dummy));
-       } else {
-               unsigned long flags;
-
-               raw_local_irq_save(flags);
-               retval = *m;
-               *m = val;
-               raw_local_irq_restore(flags);   /* implies memory barrier  */
-       }
-
-       smp_llsc_mb();
-
-       return retval;
-}
-#else
-extern __u64 __xchg_u64_unsupported_on_32bit_kernels(volatile __u64 * m, __u64 val);
-#define __xchg_u64 __xchg_u64_unsupported_on_32bit_kernels
-#endif
-
-static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
-{
-       switch (size) {
-       case 4:
-               return __xchg_u32(ptr, x);
-       case 8:
-               return __xchg_u64(ptr, x);
-       }
-
-       return x;
-}
-
-#define xchg(ptr, x)                                                   \
-({                                                                     \
-       BUILD_BUG_ON(sizeof(*(ptr)) & ~0xc);                            \
-                                                                       \
-       ((__typeof__(*(ptr)))                                           \
-               __xchg((unsigned long)(x), (ptr), sizeof(*(ptr))));     \
-})
-
-extern void set_handler(unsigned long offset, void *addr, unsigned long len);
-extern void set_uncached_handler(unsigned long offset, void *addr, unsigned long len);
-
-typedef void (*vi_handler_t)(void);
-extern void *set_vi_handler(int n, vi_handler_t addr);
-
-extern void *set_except_vector(int n, void *addr);
-extern unsigned long ebase;
-extern void per_cpu_trap_init(void);
-
-/*
- * See include/asm-ia64/system.h; prevents deadlock on SMP
- * systems.
- */
-#define __ARCH_WANT_UNLOCKED_CTXSW
-
-extern unsigned long arch_align_stack(unsigned long sp);
-
-#endif /* _ASM_SYSTEM_H */
index a409c44..8808d7f 100644 (file)
@@ -12,7 +12,6 @@
 
 #include <asm/txx9/tx3927.h>
 #include <asm/addrspace.h>
-#include <asm/system.h>
 #include <asm/txx9irq.h>
 
 /* CS */
index f305ca1..d6a1864 100644 (file)
@@ -16,7 +16,7 @@
 #include <asm/cpu.h>
 #include <asm/fpu.h>
 #include <asm/mipsregs.h>
-#include <asm/system.h>
+#include <asm/setup.h>
 
 static char bug64hit[] __initdata =
        "reliable operation impossible!\n%s";
index 0bab464..5099201 100644 (file)
@@ -22,7 +22,6 @@
 #include <asm/cpu.h>
 #include <asm/fpu.h>
 #include <asm/mipsregs.h>
-#include <asm/system.h>
 #include <asm/watch.h>
 #include <asm/elf.h>
 #include <asm/spram.h>
index a8a8977..b0662cf 100644 (file)
@@ -16,7 +16,6 @@
 
 #include <asm/irq_cpu.h>
 #include <asm/mipsregs.h>
-#include <asm/system.h>
 
 static inline void unmask_rm7k_irq(struct irq_data *d)
 {
index 38874a4..1282b9a 100644 (file)
@@ -17,7 +17,6 @@
 
 #include <asm/irq_cpu.h>
 #include <asm/mipsregs.h>
-#include <asm/system.h>
 
 static inline void unmask_rm9k_irq(struct irq_data *d)
 {
index 7f50318..a5aa43d 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/ftrace.h>
 
 #include <linux/atomic.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 
 #ifdef CONFIG_KGDB
index 191eb52..972263b 100644 (file)
@@ -35,7 +35,6 @@
 #include <asm/irq_cpu.h>
 #include <asm/mipsregs.h>
 #include <asm/mipsmtregs.h>
-#include <asm/system.h>
 
 static inline void unmask_mips_irq(struct irq_data *d)
 {
index c23d11f..7f3376b 100644 (file)
@@ -13,7 +13,6 @@
 #include <asm/cpu.h>
 #include <asm/processor.h>
 #include <linux/atomic.h>
-#include <asm/system.h>
 #include <asm/hardirq.h>
 #include <asm/mmu_context.h>
 #include <asm/mipsmtregs.h>
index 61f1cb4..e9a5fd7 100644 (file)
@@ -32,7 +32,6 @@
 #include <asm/dsp.h>
 #include <asm/fpu.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/mipsregs.h>
 #include <asm/processor.h>
 #include <asm/uaccess.h>
index 7786b60..7c24c29 100644 (file)
@@ -34,7 +34,6 @@
 #include <asm/mipsmtregs.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/bootinfo.h>
 #include <asm/reg.h>
index 32644b4..a3b0178 100644 (file)
@@ -32,7 +32,6 @@
 #include <asm/mipsmtregs.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/bootinfo.h>
 
index a9d801d..b8c18dc 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/atomic.h>
 #include <asm/cpu.h>
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/vpe.h>
 #include <asm/rtlx.h>
 
index 058e964..c504b21 100644 (file)
@@ -31,7 +31,6 @@
 #include <asm/sections.h>
 #include <asm/setup.h>
 #include <asm/smp-ops.h>
-#include <asm/system.h>
 #include <asm/prom.h>
 
 struct cpuinfo_mips cpu_data[NR_CPUS] __read_mostly;
index f852400..185ca00 100644 (file)
@@ -34,6 +34,7 @@
 #include <asm/cpu-features.h>
 #include <asm/war.h>
 #include <asm/vdso.h>
+#include <asm/dsp.h>
 
 #include "signal-common.h"
 
index aae9866..06b5da3 100644 (file)
 #include <asm/cacheflush.h>
 #include <asm/sim.h>
 #include <asm/ucontext.h>
-#include <asm/system.h>
 #include <asm/fpu.h>
 #include <asm/war.h>
 #include <asm/vdso.h>
+#include <asm/dsp.h>
 
 #include "signal-common.h"
 
index ee24d81..ae29e89 100644 (file)
@@ -35,7 +35,6 @@
 #include <asm/sim.h>
 #include <asm/uaccess.h>
 #include <asm/ucontext.h>
-#include <asm/system.h>
 #include <asm/fpu.h>
 #include <asm/cpu-features.h>
 #include <asm/war.h>
index d5e950a..ca67356 100644 (file)
@@ -28,7 +28,6 @@
 #include <asm/time.h>
 #include <asm/pgtable.h>
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/bootinfo.h>
 #include <asm/pmon.h>
 #include <asm/cacheflush.h>
index fe30951..e7e03ec 100644 (file)
@@ -29,7 +29,6 @@
 #include <asm/cacheflush.h>
 #include <asm/cpu.h>
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/hardirq.h>
 #include <asm/mmu_context.h>
 #include <asm/smp.h>
index ce9e286..ff17868 100644 (file)
@@ -28,7 +28,6 @@
 #include <asm/cacheflush.h>
 #include <asm/cpu.h>
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/hardirq.h>
 #include <asm/mmu_context.h>
 #include <asm/time.h>
index 32c1e95..9c1cce9 100644 (file)
@@ -38,9 +38,9 @@
 #include <asm/cpu.h>
 #include <asm/processor.h>
 #include <asm/r4k-timer.h>
-#include <asm/system.h>
 #include <asm/mmu_context.h>
 #include <asm/time.h>
+#include <asm/setup.h>
 
 #ifdef CONFIG_MIPS_MT_SMTC
 #include <asm/mipsmtregs.h>
index 928a5a6..145771c 100644 (file)
@@ -11,7 +11,6 @@
 #include <asm/cpu.h>
 #include <asm/processor.h>
 #include <linux/atomic.h>
-#include <asm/system.h>
 #include <asm/hardirq.h>
 #include <asm/mmu_context.h>
 #include <asm/mipsregs.h>
index 0a42ff3..c4f75bb 100644 (file)
@@ -31,7 +31,6 @@
 #include <asm/cpu.h>
 #include <asm/processor.h>
 #include <linux/atomic.h>
-#include <asm/system.h>
 #include <asm/hardirq.h>
 #include <asm/hazards.h>
 #include <asm/irq.h>
index 1821d12..6af08d8 100644 (file)
@@ -15,7 +15,6 @@
 
 #include <asm/fpu.h>
 #include <asm/mipsregs.h>
-#include <asm/system.h>
 #include <asm/r4kcache.h>
 #include <asm/hazards.h>
 
index d027657..b08220c 100644 (file)
@@ -37,6 +37,7 @@
 #include <asm/shmparam.h>
 #include <asm/sysmips.h>
 #include <asm/uaccess.h>
+#include <asm/switch_to.h>
 
 /*
  * For historic reasons the pipe(2) syscall on MIPS has an unusual calling
index d79ae54..cfdaaa4 100644 (file)
@@ -45,7 +45,6 @@
 #include <asm/pgtable.h>
 #include <asm/ptrace.h>
 #include <asm/sections.h>
-#include <asm/system.h>
 #include <asm/tlbdebug.h>
 #include <asm/traps.h>
 #include <asm/uaccess.h>
index aedb894..9c58bdf 100644 (file)
@@ -85,7 +85,6 @@
 #include <asm/cop2.h>
 #include <asm/inst.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 
 #define STR(x)  __STR(x)
 #define __STR(x)  #x
index bfa12a4..f6f9152 100644 (file)
@@ -49,7 +49,6 @@
 #include <asm/cpu.h>
 #include <asm/mips_mt.h>
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/vpe.h>
 #include <asm/kspd.h>
 
index b1e7a89..e21f0b9 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/pm.h>
 
 #include <asm/reboot.h>
-#include <asm/system.h>
 #include <asm/lasat/lasat.h>
 
 #include "picvue.h"
index 3c4a8c5..384a3b0 100644 (file)
@@ -12,7 +12,6 @@
 #include <asm/uaccess.h>
 #include <asm/branch.h>
 #include <asm/mipsregs.h>
-#include <asm/system.h>
 #include <asm/cacheflush.h>
 
 #include <asm/fpu_emulator.h>
index 9150639..3c104ab 100644 (file)
@@ -28,7 +28,6 @@
 #include <asm/cpu.h>
 #include <asm/processor.h>
 #include <asm/smtc.h>
-#include <asm/system.h>
 #include <asm/mmu_context.h>
 #include <asm/smtc_ipi.h>
 
index 5492c42..77bad3c 100644 (file)
@@ -11,6 +11,7 @@
 #include <asm/hardirq.h>
 #include <asm/div64.h>
 #include <asm/cpu.h>
+#include <asm/setup.h>
 #include <asm/time.h>
 #include <asm/irq.h>
 #include <asm/mc146818-time.h>
index cf7895d..1f9ca07 100644 (file)
@@ -21,7 +21,6 @@
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/r4kcache.h>
-#include <asm/system.h>
 #include <asm/mmu_context.h>
 #include <asm/war.h>
 
index 0765583..031c4c2 100644 (file)
@@ -18,7 +18,6 @@
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/mmu_context.h>
-#include <asm/system.h>
 #include <asm/isadep.h>
 #include <asm/io.h>
 #include <asm/bootinfo.h>
index c97087d..bda8eb2 100644 (file)
@@ -29,7 +29,6 @@
 #include <asm/pgtable.h>
 #include <asm/r4kcache.h>
 #include <asm/sections.h>
-#include <asm/system.h>
 #include <asm/mmu_context.h>
 #include <asm/war.h>
 #include <asm/cacheflush.h> /* for run_uncached() */
index a43c197..87d23ca 100644 (file)
@@ -18,7 +18,6 @@
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/mmu_context.h>
-#include <asm/system.h>
 #include <asm/isadep.h>
 #include <asm/io.h>
 #include <asm/bootinfo.h>
index 69ebd58..c14f6df 100644 (file)
@@ -22,7 +22,6 @@
 
 #include <asm/branch.h>
 #include <asm/mmu_context.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/ptrace.h>
 #include <asm/highmem.h>               /* For VMALLOC_END */
index 36272f7..cc0b626 100644 (file)
@@ -22,7 +22,6 @@
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/prefetch.h>
-#include <asm/system.h>
 #include <asm/bootinfo.h>
 #include <asm/mipsregs.h>
 #include <asm/mmu_context.h>
index a6bd11f..1eb708e 100644 (file)
@@ -12,7 +12,6 @@
 #include <asm/bcache.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/bootinfo.h>
 #include <asm/sgi/ip22.h>
 #include <asm/sgi/mc.h>
index 9cca8de..93d937b 100644 (file)
@@ -11,7 +11,6 @@
 #include <asm/cacheops.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/mmu_context.h>
 #include <asm/r4kcache.h>
 
index ae1e533..8d90ff2 100644 (file)
@@ -12,7 +12,6 @@
 #include <asm/cacheops.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/mmu_context.h>
 #include <asm/r4kcache.h>
 
index ed1fa46..a63d1ed 100644 (file)
@@ -19,7 +19,6 @@
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/mmu_context.h>
-#include <asm/system.h>
 #include <asm/tlbmisc.h>
 #include <asm/isadep.h>
 #include <asm/io.h>
index 2dc6253..d2572cb 100644 (file)
@@ -18,7 +18,6 @@
 #include <asm/bootinfo.h>
 #include <asm/mmu_context.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/tlbmisc.h>
 
 extern void build_tlb_refill_handler(void);
index 3d95f76..91c2499 100644 (file)
@@ -17,7 +17,6 @@
 #include <asm/bootinfo.h>
 #include <asm/mmu_context.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 
 extern void build_tlb_refill_handler(void);
 
index e06370f..0bc485b 100644 (file)
@@ -32,6 +32,7 @@
 #include <asm/pgtable.h>
 #include <asm/war.h>
 #include <asm/uasm.h>
+#include <asm/setup.h>
 
 /*
  * TLB load/store/modify handlers.
index 4b988b9..27a6cdb 100644 (file)
@@ -26,7 +26,6 @@
 #include <asm/bootinfo.h>
 #include <asm/gt64120.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/cacheflush.h>
 #include <asm/smp-ops.h>
 #include <asm/traps.h>
index a588b5c..7b13a4c 100644 (file)
@@ -44,6 +44,7 @@
 #include <asm/msc01_ic.h>
 #include <asm/gic.h>
 #include <asm/gcmpregs.h>
+#include <asm/setup.h>
 
 int gcmp_present = -1;
 int gic_present;
index f8ee945..115f5bc 100644 (file)
@@ -35,6 +35,7 @@
 #include <asm/irq.h>
 #include <asm/div64.h>
 #include <asm/cpu.h>
+#include <asm/setup.h>
 #include <asm/time.h>
 #include <asm/mc146818-time.h>
 #include <asm/msc01_ic.h>
index 49a4f6c..e52bfcb 100644 (file)
@@ -43,7 +43,6 @@
 
 #include <asm/errno.h>
 #include <asm/signal.h>
-#include <asm/system.h>
 #include <asm/ptrace.h>
 #include <asm/mipsregs.h>
 #include <asm/thread_info.h>
index c4fa2d7..2e6f7ca 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/irq.h>
 
 #include <asm/mipsregs.h>
-#include <asm/system.h>
 
 #include <msp_cic_int.h>
 #include <msp_regs.h>
index 98fd009..598b6a6 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/bitops.h>
 
 #include <asm/mipsregs.h>
-#include <asm/system.h>
 
 #include <msp_cic_int.h>
 #include <msp_regs.h>
index 5bbcc47..83a1c5e 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/bitops.h>
 
 #include <asm/mipsregs.h>
-#include <asm/system.h>
 
 #include <msp_slp_int.h>
 #include <msp_regs.h>
index 25bbbf4..6590812 100644 (file)
@@ -44,7 +44,6 @@
 #include <asm/irq.h>
 #include <asm/irq_cpu.h>
 #include <asm/mipsregs.h>
-#include <asm/system.h>
 #include <asm/titan_dep.h>
 
 /* Hypertransport specific */
index dcc926e..6a2754c 100644 (file)
@@ -20,7 +20,6 @@
 #include <asm/processor.h>
 #include <asm/reboot.h>
 #include <asm/smp-ops.h>
-#include <asm/system.h>
 #include <asm/bootinfo.h>
 #include <asm/pmon.h>
 
index adc171c..a86d5d5 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/interrupt.h>
 #include <asm/mipsregs.h>
 #include <asm/irq_cpu.h>
+#include <asm/setup.h>
 #include <irq.h>
 #include <irq-mapping.h>
 #include <gpio.h>
index 529c44a..99d82e1 100644 (file)
@@ -34,6 +34,7 @@
 #include <asm/irq_cpu.h>
 #include <linux/io.h>
 #include <asm/irq_regs.h>
+#include <asm/setup.h>
 #include <asm/mips-boards/generic.h>
 
 #include <asm/mach-powertv/asic_regs.h>
index 7fb97fb..fa9ae95 100644 (file)
@@ -17,7 +17,6 @@
 
 #include <asm/irq_cpu.h>
 #include <asm/mipsregs.h>
-#include <asm/system.h>
 
 #include <asm/mach-powertv/asic_regs.h>
 
index 8355228..1cf5abb 100644 (file)
@@ -26,7 +26,6 @@
 
 #include <asm/bootinfo.h>
 #include <linux/io.h>
-#include <asm/system.h>
 #include <asm/cacheflush.h>
 #include <asm/traps.h>
 
index 7c6db74..f298430 100644 (file)
@@ -42,7 +42,6 @@
 #include <asm/bootinfo.h>
 #include <asm/time.h>
 #include <asm/mipsregs.h>
-#include <asm/system.h>
 
 #include <asm/mach-rc32434/irq.h>
 #include <asm/mach-rc32434/gpio.h>
index 911d399..3f6ccd5 100644 (file)
@@ -9,7 +9,6 @@
 #include <linux/sched.h>
 
 #include <asm/addrspace.h>
-#include <asm/system.h>
 #include <asm/traps.h>
 #include <asm/branch.h>
 #include <asm/irq_regs.h>
index 45b6694..20363d2 100644 (file)
@@ -18,7 +18,6 @@
 
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/reboot.h>
 #include <asm/sgialib.h>
 #include <asm/sgi/ioc.h>
index 88c684e..0626555 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/seq_file.h>
 
 #include <asm/addrspace.h>
-#include <asm/system.h>
 #include <asm/traps.h>
 #include <asm/branch.h>
 #include <asm/irq_regs.h>
index 2364223..69a939a 100644 (file)
@@ -27,7 +27,6 @@
 #include <asm/bootinfo.h>
 #include <asm/io.h>
 #include <asm/mipsregs.h>
-#include <asm/system.h>
 
 #include <asm/processor.h>
 #include <asm/pci/bridge.h>
index c170761..f347bc6 100644 (file)
@@ -19,7 +19,6 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/reboot.h>
-#include <asm/system.h>
 #include <asm/sgialib.h>
 #include <asm/sn/addrs.h>
 #include <asm/sn/arch.h>
index a092860..e7d5054 100644 (file)
@@ -22,7 +22,6 @@
 #include <asm/irq_cpu.h>
 #include <asm/mipsregs.h>
 #include <asm/signal.h>
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/ip32/crime.h>
 #include <asm/ip32/mace.h>
index 9b95d80..1f823da 100644 (file)
@@ -20,7 +20,6 @@
 #include <asm/addrspace.h>
 #include <asm/irq.h>
 #include <asm/reboot.h>
-#include <asm/system.h>
 #include <asm/wbflush.h>
 #include <asm/ip32/mace.h>
 #include <asm/ip32/crime.h>
index 09740d6..215713e 100644 (file)
@@ -27,7 +27,6 @@
 #include <asm/errno.h>
 #include <asm/irq_regs.h>
 #include <asm/signal.h>
-#include <asm/system.h>
 #include <asm/io.h>
 
 #include <asm/sibyte/bcm1480_regs.h>
index 48853ab..e8c4538 100644 (file)
@@ -53,7 +53,6 @@
 #define K_INT_PERF_CNT K_BCM1480_INT_PERF_CNT
 #endif
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 
 #define SBPROF_TB_MAJOR 240
index 45274bd..86e6e54 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/interrupt.h>
 #include <linux/sched.h>
 #include <linux/proc_fs.h>
-#include <asm/system.h>
 #include <asm/io.h>
 
 #include <asm/sibyte/sb1250.h>
index 76ee045..340aaf6 100644 (file)
@@ -26,7 +26,6 @@
 
 #include <asm/errno.h>
 #include <asm/signal.h>
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/io.h>
 
index 79f8d70..244f942 100644 (file)
@@ -5,7 +5,6 @@
  */
 #include <asm/io.h>
 #include <asm/reboot.h>
-#include <asm/system.h>
 #include <asm/sni.h>
 
 /*
index fad2bef..ae0e4ee 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/irq.h>
 
 #include <asm/irq_cpu.h>
-#include <asm/system.h>
 #include <asm/vr41xx/irq.h>
 
 typedef struct irq_cascade {
index 692b4e8..9fbf5f0 100644 (file)
@@ -30,7 +30,6 @@
 #include <asm/io.h>
 #include <asm/processor.h>
 #include <asm/reboot.h>
-#include <asm/system.h>
 
 #define PMU_TYPE1_BASE 0x0b0000a0UL
 #define PMU_TYPE1_SIZE 0x0eUL
index b9a8f84..975e184 100644 (file)
 #define _ASM_ATOMIC_H
 
 #include <asm/irqflags.h>
-
-#ifndef __ASSEMBLY__
-
-#ifdef CONFIG_SMP
-#ifdef CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT
-static inline
-unsigned long __xchg(volatile unsigned long *m, unsigned long val)
-{
-       unsigned long status;
-       unsigned long oldval;
-
-       asm volatile(
-               "1:     mov     %4,(_AAR,%3)    \n"
-               "       mov     (_ADR,%3),%1    \n"
-               "       mov     %5,(_ADR,%3)    \n"
-               "       mov     (_ADR,%3),%0    \n"     /* flush */
-               "       mov     (_ASR,%3),%0    \n"
-               "       or      %0,%0           \n"
-               "       bne     1b              \n"
-               : "=&r"(status), "=&r"(oldval), "=m"(*m)
-               : "a"(ATOMIC_OPS_BASE_ADDR), "r"(m), "r"(val)
-               : "memory", "cc");
-
-       return oldval;
-}
-
-static inline unsigned long __cmpxchg(volatile unsigned long *m,
-                                     unsigned long old, unsigned long new)
-{
-       unsigned long status;
-       unsigned long oldval;
-
-       asm volatile(
-               "1:     mov     %4,(_AAR,%3)    \n"
-               "       mov     (_ADR,%3),%1    \n"
-               "       cmp     %5,%1           \n"
-               "       bne     2f              \n"
-               "       mov     %6,(_ADR,%3)    \n"
-               "2:     mov     (_ADR,%3),%0    \n"     /* flush */
-               "       mov     (_ASR,%3),%0    \n"
-               "       or      %0,%0           \n"
-               "       bne     1b              \n"
-               : "=&r"(status), "=&r"(oldval), "=m"(*m)
-               : "a"(ATOMIC_OPS_BASE_ADDR), "r"(m),
-                 "r"(old), "r"(new)
-               : "memory", "cc");
-
-       return oldval;
-}
-#else  /* CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT */
-#error "No SMP atomic operation support!"
-#endif /* CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT */
-
-#else  /* CONFIG_SMP */
-
-/*
- * Emulate xchg for non-SMP MN10300
- */
-struct __xchg_dummy { unsigned long a[100]; };
-#define __xg(x) ((struct __xchg_dummy *)(x))
-
-static inline
-unsigned long __xchg(volatile unsigned long *m, unsigned long val)
-{
-       unsigned long oldval;
-       unsigned long flags;
-
-       flags = arch_local_cli_save();
-       oldval = *m;
-       *m = val;
-       arch_local_irq_restore(flags);
-       return oldval;
-}
-
-/*
- * Emulate cmpxchg for non-SMP MN10300
- */
-static inline unsigned long __cmpxchg(volatile unsigned long *m,
-                                     unsigned long old, unsigned long new)
-{
-       unsigned long oldval;
-       unsigned long flags;
-
-       flags = arch_local_cli_save();
-       oldval = *m;
-       if (oldval == old)
-               *m = new;
-       arch_local_irq_restore(flags);
-       return oldval;
-}
-
-#endif /* CONFIG_SMP */
-
-#define xchg(ptr, v)                                           \
-       ((__typeof__(*(ptr))) __xchg((unsigned long *)(ptr),    \
-                                    (unsigned long)(v)))
-
-#define cmpxchg(ptr, o, n)                                     \
-       ((__typeof__(*(ptr))) __cmpxchg((unsigned long *)(ptr), \
-                                       (unsigned long)(o),     \
-                                       (unsigned long)(n)))
-
-#define atomic_xchg(ptr, v)            (xchg(&(ptr)->counter, (v)))
-#define atomic_cmpxchg(v, old, new)    (cmpxchg(&((v)->counter), (old), (new)))
-
-#endif /* !__ASSEMBLY__ */
+#include <asm/cmpxchg.h>
 
 #ifndef CONFIG_SMP
 #include <asm-generic/atomic.h>
@@ -269,6 +164,8 @@ static inline void atomic_dec(atomic_t *v)
        c;                                                      \
 })
 
+#define atomic_xchg(ptr, v)            (xchg(&(ptr)->counter, (v)))
+#define atomic_cmpxchg(v, old, new)    (cmpxchg(&((v)->counter), (old), (new)))
 
 /**
  * atomic_clear_mask - Atomically clear bits in memory
diff --git a/arch/mn10300/include/asm/barrier.h b/arch/mn10300/include/asm/barrier.h
new file mode 100644 (file)
index 0000000..2bd97a5
--- /dev/null
@@ -0,0 +1,37 @@
+/* MN10300 memory barrier definitions
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_BARRIER_H
+#define _ASM_BARRIER_H
+
+#define nop()  asm volatile ("nop")
+
+#define mb()   asm volatile ("": : :"memory")
+#define rmb()  mb()
+#define wmb()  asm volatile ("": : :"memory")
+
+#ifdef CONFIG_SMP
+#define smp_mb()       mb()
+#define smp_rmb()      rmb()
+#define smp_wmb()      wmb()
+#define set_mb(var, value)  do { xchg(&var, value); } while (0)
+#else  /* CONFIG_SMP */
+#define smp_mb()       barrier()
+#define smp_rmb()      barrier()
+#define smp_wmb()      barrier()
+#define set_mb(var, value)  do { var = value;  mb(); } while (0)
+#endif /* CONFIG_SMP */
+
+#define set_wmb(var, value) do { var = value; wmb(); } while (0)
+
+#define read_barrier_depends()         do {} while (0)
+#define smp_read_barrier_depends()     do {} while (0)
+
+#endif /* _ASM_BARRIER_H */
diff --git a/arch/mn10300/include/asm/cmpxchg.h b/arch/mn10300/include/asm/cmpxchg.h
new file mode 100644 (file)
index 0000000..97a4aaf
--- /dev/null
@@ -0,0 +1,115 @@
+/* MN10300 Atomic xchg/cmpxchg operations
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_CMPXCHG_H
+#define _ASM_CMPXCHG_H
+
+#include <asm/irqflags.h>
+
+#ifdef CONFIG_SMP
+#ifdef CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT
+static inline
+unsigned long __xchg(volatile unsigned long *m, unsigned long val)
+{
+       unsigned long status;
+       unsigned long oldval;
+
+       asm volatile(
+               "1:     mov     %4,(_AAR,%3)    \n"
+               "       mov     (_ADR,%3),%1    \n"
+               "       mov     %5,(_ADR,%3)    \n"
+               "       mov     (_ADR,%3),%0    \n"     /* flush */
+               "       mov     (_ASR,%3),%0    \n"
+               "       or      %0,%0           \n"
+               "       bne     1b              \n"
+               : "=&r"(status), "=&r"(oldval), "=m"(*m)
+               : "a"(ATOMIC_OPS_BASE_ADDR), "r"(m), "r"(val)
+               : "memory", "cc");
+
+       return oldval;
+}
+
+static inline unsigned long __cmpxchg(volatile unsigned long *m,
+                                     unsigned long old, unsigned long new)
+{
+       unsigned long status;
+       unsigned long oldval;
+
+       asm volatile(
+               "1:     mov     %4,(_AAR,%3)    \n"
+               "       mov     (_ADR,%3),%1    \n"
+               "       cmp     %5,%1           \n"
+               "       bne     2f              \n"
+               "       mov     %6,(_ADR,%3)    \n"
+               "2:     mov     (_ADR,%3),%0    \n"     /* flush */
+               "       mov     (_ASR,%3),%0    \n"
+               "       or      %0,%0           \n"
+               "       bne     1b              \n"
+               : "=&r"(status), "=&r"(oldval), "=m"(*m)
+               : "a"(ATOMIC_OPS_BASE_ADDR), "r"(m),
+                 "r"(old), "r"(new)
+               : "memory", "cc");
+
+       return oldval;
+}
+#else  /* CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT */
+#error "No SMP atomic operation support!"
+#endif /* CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT */
+
+#else  /* CONFIG_SMP */
+
+/*
+ * Emulate xchg for non-SMP MN10300
+ */
+struct __xchg_dummy { unsigned long a[100]; };
+#define __xg(x) ((struct __xchg_dummy *)(x))
+
+static inline
+unsigned long __xchg(volatile unsigned long *m, unsigned long val)
+{
+       unsigned long oldval;
+       unsigned long flags;
+
+       flags = arch_local_cli_save();
+       oldval = *m;
+       *m = val;
+       arch_local_irq_restore(flags);
+       return oldval;
+}
+
+/*
+ * Emulate cmpxchg for non-SMP MN10300
+ */
+static inline unsigned long __cmpxchg(volatile unsigned long *m,
+                                     unsigned long old, unsigned long new)
+{
+       unsigned long oldval;
+       unsigned long flags;
+
+       flags = arch_local_cli_save();
+       oldval = *m;
+       if (oldval == old)
+               *m = new;
+       arch_local_irq_restore(flags);
+       return oldval;
+}
+
+#endif /* CONFIG_SMP */
+
+#define xchg(ptr, v)                                           \
+       ((__typeof__(*(ptr))) __xchg((unsigned long *)(ptr),    \
+                                    (unsigned long)(v)))
+
+#define cmpxchg(ptr, o, n)                                     \
+       ((__typeof__(*(ptr))) __cmpxchg((unsigned long *)(ptr), \
+                                       (unsigned long)(o),     \
+                                       (unsigned long)(n)))
+
+#endif /* _ASM_CMPXCHG_H */
index 098df2e..10b77d4 100644 (file)
@@ -11,7 +11,6 @@
 #ifndef _ASM_DMA_H
 #define _ASM_DMA_H
 
-#include <asm/system.h>
 #include <linux/spinlock.h>
 #include <asm/io.h>
 #include <linux/delay.h>
diff --git a/arch/mn10300/include/asm/exec.h b/arch/mn10300/include/asm/exec.h
new file mode 100644 (file)
index 0000000..c74e367
--- /dev/null
@@ -0,0 +1,16 @@
+/* MN10300 process execution definitions
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_EXEC_H
+#define _ASM_EXEC_H
+
+#define arch_align_stack(x) (x)
+
+#endif /* _ASM_EXEC_H */
diff --git a/arch/mn10300/include/asm/switch_to.h b/arch/mn10300/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..393d311
--- /dev/null
@@ -0,0 +1,49 @@
+/* MN10300 task switching definitions
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _ASM_SWITCH_TO_H
+#define _ASM_SWITCH_TO_H
+
+#include <asm/barrier.h>
+
+struct task_struct;
+struct thread_struct;
+
+#if !defined(CONFIG_LAZY_SAVE_FPU)
+struct fpu_state_struct;
+extern asmlinkage void fpu_save(struct fpu_state_struct *);
+#define switch_fpu(prev, next)                                         \
+       do {                                                            \
+               if ((prev)->thread.fpu_flags & THREAD_HAS_FPU) {        \
+                       (prev)->thread.fpu_flags &= ~THREAD_HAS_FPU;    \
+                       (prev)->thread.uregs->epsw &= ~EPSW_FE;         \
+                       fpu_save(&(prev)->thread.fpu_state);            \
+               }                                                       \
+       } while (0)
+#else
+#define switch_fpu(prev, next) do {} while (0)
+#endif
+
+/* context switching is now performed out-of-line in switch_to.S */
+extern asmlinkage
+struct task_struct *__switch_to(struct thread_struct *prev,
+                               struct thread_struct *next,
+                               struct task_struct *prev_task);
+
+#define switch_to(prev, next, last)                                    \
+do {                                                                   \
+       switch_fpu(prev, next);                                         \
+       current->thread.wchan = (u_long) __builtin_return_address(0);   \
+       (last) = __switch_to(&(prev)->thread, &(next)->thread, (prev)); \
+       mb();                                                           \
+       current->thread.wchan = 0;                                      \
+} while (0)
+
+#endif /* _ASM_SWITCH_TO_H */
diff --git a/arch/mn10300/include/asm/system.h b/arch/mn10300/include/asm/system.h
deleted file mode 100644 (file)
index 94b4c5e..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-/* MN10300 System definitions
- *
- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public Licence
- * as published by the Free Software Foundation; either version
- * 2 of the Licence, or (at your option) any later version.
- */
-#ifndef _ASM_SYSTEM_H
-#define _ASM_SYSTEM_H
-
-#include <asm/cpu-regs.h>
-#include <asm/intctl-regs.h>
-
-#ifdef __KERNEL__
-#ifndef __ASSEMBLY__
-
-#include <linux/kernel.h>
-#include <linux/irqflags.h>
-#include <linux/atomic.h>
-
-#if !defined(CONFIG_LAZY_SAVE_FPU)
-struct fpu_state_struct;
-extern asmlinkage void fpu_save(struct fpu_state_struct *);
-#define switch_fpu(prev, next)                                         \
-       do {                                                            \
-               if ((prev)->thread.fpu_flags & THREAD_HAS_FPU) {        \
-                       (prev)->thread.fpu_flags &= ~THREAD_HAS_FPU;    \
-                       (prev)->thread.uregs->epsw &= ~EPSW_FE;         \
-                       fpu_save(&(prev)->thread.fpu_state);            \
-               }                                                       \
-       } while (0)
-#else
-#define switch_fpu(prev, next) do {} while (0)
-#endif
-
-struct task_struct;
-struct thread_struct;
-
-extern asmlinkage
-struct task_struct *__switch_to(struct thread_struct *prev,
-                               struct thread_struct *next,
-                               struct task_struct *prev_task);
-
-/* context switching is now performed out-of-line in switch_to.S */
-#define switch_to(prev, next, last)                                    \
-do {                                                                   \
-       switch_fpu(prev, next);                                         \
-       current->thread.wchan = (u_long) __builtin_return_address(0);   \
-       (last) = __switch_to(&(prev)->thread, &(next)->thread, (prev)); \
-       mb();                                                           \
-       current->thread.wchan = 0;                                      \
-} while (0)
-
-#define arch_align_stack(x) (x)
-
-#define nop() asm volatile ("nop")
-
-/*
- * Force strict CPU ordering.
- * And yes, this is required on UP too when we're talking
- * to devices.
- *
- * For now, "wmb()" doesn't actually do anything, as all
- * Intel CPU's follow what Intel calls a *Processor Order*,
- * in which all writes are seen in the program order even
- * outside the CPU.
- *
- * I expect future Intel CPU's to have a weaker ordering,
- * but I'd also expect them to finally get their act together
- * and add some real memory barriers if so.
- *
- * Some non intel clones support out of order store. wmb() ceases to be a
- * nop for these.
- */
-
-#define mb()   asm volatile ("": : :"memory")
-#define rmb()  mb()
-#define wmb()  asm volatile ("": : :"memory")
-
-#ifdef CONFIG_SMP
-#define smp_mb()       mb()
-#define smp_rmb()      rmb()
-#define smp_wmb()      wmb()
-#define set_mb(var, value)  do { xchg(&var, value); } while (0)
-#else  /* CONFIG_SMP */
-#define smp_mb()       barrier()
-#define smp_rmb()      barrier()
-#define smp_wmb()      barrier()
-#define set_mb(var, value)  do { var = value;  mb(); } while (0)
-#endif /* CONFIG_SMP */
-
-#define set_wmb(var, value) do { var = value; wmb(); } while (0)
-
-#define read_barrier_depends()         do {} while (0)
-#define smp_read_barrier_depends()     do {} while (0)
-
-#endif /* !__ASSEMBLY__ */
-#endif /* __KERNEL__ */
-#endif /* _ASM_SYSTEM_H */
index 3e3620d..8e11f9f 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/sys.h>
 #include <linux/linkage.h>
 #include <asm/smp.h>
-#include <asm/system.h>
 #include <asm/irqflags.h>
 #include <asm/thread_info.h>
 #include <asm/intctl-regs.h>
index bb5fa7d..064fa19 100644 (file)
@@ -12,7 +12,6 @@
 #include <asm/fpu.h>
 #include <asm/elf.h>
 #include <asm/exceptions.h>
-#include <asm/system.h>
 
 #ifdef CONFIG_LAZY_SAVE_FPU
 struct task_struct *fpu_state_owner;
index f28dc99..df51242 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/nmi.h>
 
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/gdb-stub.h>
 #include <asm/exceptions.h>
 #include <asm/serial-regs.h>
index c859cac..caae8ca 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/init.h>
 #include <linux/tty.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/gdb-stub.h>
 #include <asm/exceptions.h>
 #include <unit/clock.h>
index 522eb8a..a128c57 100644 (file)
 #include <linux/bug.h>
 
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/gdb-stub.h>
 #include <asm/exceptions.h>
 #include <asm/debugger.h>
index 94901c5..339cef4 100644 (file)
@@ -36,7 +36,6 @@ static const char serial_revdate[] = "2007-11-06";
 #include <linux/console.h>
 #include <linux/sysrq.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/bitops.h>
index a45f0c7..db64a71 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/kernel_stat.h>
 #include <linux/nmi.h>
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <linux/atomic.h>
 #include <asm/intctl-regs.h>
 #include <asm/rtc-regs.h>
index cac401d..14707f2 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/slab.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/processor.h>
 #include <asm/mmu_context.h>
index 5c0b07e..5bd5851 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/tracehook.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/processor.h>
 #include <asm/cacheflush.h>
 #include <asm/fpu.h>
index 9e7a320..33c3bd1 100644 (file)
@@ -26,7 +26,6 @@
 #include <asm/processor.h>
 #include <linux/console.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/setup.h>
 #include <asm/io.h>
 #include <asm/smp.h>
index 72938ce..71f1b2f 100644 (file)
@@ -13,9 +13,9 @@
 #include <linux/sys.h>
 #include <linux/linkage.h>
 #include <asm/smp.h>
-#include <asm/system.h>
 #include <asm/thread_info.h>
 #include <asm/cpu-regs.h>
+#include <asm/intctl-regs.h>
 #include <proc/smp-regs.h>
 #include <asm/asm-offsets.h>
 #include <asm/frame.inc>
index 9242e9f..910dddf 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/profile.h>
 #include <linux/smp.h>
 #include <asm/tlbflush.h>
-#include <asm/system.h>
 #include <asm/bitops.h>
 #include <asm/processor.h>
 #include <asm/bug.h>
index 9220a75..94a9c6d 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/bug.h>
 #include <linux/irq.h>
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <linux/uaccess.h>
 #include <asm/io.h>
 #include <linux/atomic.h>
index a66c6cd..37309cd 100644 (file)
@@ -10,7 +10,6 @@
  */
 #include <linux/module.h>
 #include <asm/bitops.h>
-#include <asm/system.h>
 
 /*
  * try flipping a bit using BSET and BCLR
index 0945409..90f346f 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/init.h>
 #include <linux/vt_kern.h>             /* For unblank_screen() */
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
 #include <asm/hardirq.h>
index 1380182..e57e5bc 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/gfp.h>
 
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
index f9bb8cb..b9920b1 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <linux/atomic.h>
index 450f7ba..4ebf117 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/spinlock.h>
 #include <linux/quicklist.h>
 
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
 #include <asm/tlb.h>
index 9a77749..3e57faf 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/profile.h>
 #include <linux/smp.h>
 #include <asm/tlbflush.h>
-#include <asm/system.h>
 #include <asm/bitops.h>
 #include <asm/processor.h>
 #include <asm/bug.h>
index fe6e249..ee6d03d 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/interrupt.h>
 
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <linux/atomic.h>
index 11162e6..dcea5a0 100644 (file)
@@ -4,6 +4,7 @@ header-y += spr_defs.h
 
 generic-y += atomic.h
 generic-y += auxvec.h
+generic-y += barrier.h
 generic-y += bitsperlong.h
 generic-y += bug.h
 generic-y += bugs.h
@@ -19,6 +20,7 @@ generic-y += div64.h
 generic-y += dma.h
 generic-y += emergency-restart.h
 generic-y += errno.h
+generic-y += exec.h
 generic-y += fb.h
 generic-y += fcntl.h
 generic-y += ftrace.h
@@ -55,6 +57,7 @@ generic-y += sockios.h
 generic-y += statfs.h
 generic-y += stat.h
 generic-y += string.h
+generic-y += switch_to.h
 generic-y += swab.h
 generic-y += termbits.h
 generic-y += termios.h
diff --git a/arch/openrisc/include/asm/system.h b/arch/openrisc/include/asm/system.h
deleted file mode 100644 (file)
index cf65888..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * OpenRISC Linux
- *
- * Linux architectural port borrowing liberally from similar works of
- * others.  All original copyrights apply as per the original source
- * declaration.
- *
- * OpenRISC implementation:
- * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
- * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
- * et al.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __ASM_OPENRISC_SYSTEM_H
-#define __ASM_OPENRISC_SYSTEM_H
-
-#ifdef __KERNEL__
-#ifndef __ASSEMBLY__
-
-#include <asm/spr.h>
-#include <asm-generic/system.h>
-
-/* We probably need this definition, but the generic system.h provides it
- * and it's not used on our arch anyway...
- */
-/*#define nop() __asm__ __volatile__ ("l.nop"::)*/
-
-#endif /* __ASSEMBLY__ */
-#endif /* __KERNEL__ */
-#endif /* __ASM_OPENRISC_SYSTEM_H */
index e5fc788..7d618fe 100644 (file)
@@ -31,7 +31,6 @@
 
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/processor.h>
 #include <asm/mmu.h>
index e4209af..55210f3 100644 (file)
@@ -38,7 +38,6 @@
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/processor.h>
 #include <asm/spr_defs.h>
index 3d4478f..5869e3f 100644 (file)
@@ -42,7 +42,6 @@
 #include <asm/processor.h>
 #include <asm/irq.h>
 #include <linux/io.h>
-#include <asm/system.h>
 #include <asm/mmu.h>
 #include <asm/pgtable.h>
 #include <asm/sections.h>
index 6deacb6..e71781d 100644 (file)
@@ -33,7 +33,6 @@
 #include <asm/segment.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 
 /*
  * Copy the thread state to a regset that can be interpreted by userspace.
index bf5eba2..f4d5bed 100644 (file)
@@ -41,7 +41,6 @@
 #include <linux/of_platform.h>
 
 #include <asm/segment.h>
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/types.h>
 #include <asm/setup.h>
index a2ee129..5cce396 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/kallsyms.h>
 #include <asm/uaccess.h>
 
-#include <asm/system.h>
 #include <asm/segment.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
index 736f6b2..79dea97 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/pagemap.h>
 #include <linux/memblock.h>
 
-#include <asm/system.h>
 #include <asm/segment.h>
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
index 56b0b89..683bd4d 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/mm.h>
 #include <linux/init.h>
 
-#include <asm/system.h>
 #include <asm/segment.h>
 #include <asm/tlbflush.h>
 #include <asm/pgtable.h>
index 4054b31..3ae5607 100644 (file)
@@ -6,7 +6,6 @@
 #define _ASM_PARISC_ATOMIC_H_
 
 #include <linux/types.h>
-#include <asm/system.h>
 
 /*
  * Atomic operations that C can't guarantee us.  Useful for
diff --git a/arch/parisc/include/asm/barrier.h b/arch/parisc/include/asm/barrier.h
new file mode 100644 (file)
index 0000000..e77d834
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef __PARISC_BARRIER_H
+#define __PARISC_BARRIER_H
+
+/*
+** This is simply the barrier() macro from linux/kernel.h but when serial.c
+** uses tqueue.h uses smp_mb() defined using barrier(), linux/kernel.h
+** hasn't yet been included yet so it fails, thus repeating the macro here.
+**
+** PA-RISC architecture allows for weakly ordered memory accesses although
+** none of the processors use it. There is a strong ordered bit that is
+** set in the O-bit of the page directory entry. Operating systems that
+** can not tolerate out of order accesses should set this bit when mapping
+** pages. The O-bit of the PSW should also be set to 1 (I don't believe any
+** of the processor implemented the PSW O-bit). The PCX-W ERS states that
+** the TLB O-bit is not implemented so the page directory does not need to
+** have the O-bit set when mapping pages (section 3.1). This section also
+** states that the PSW Y, Z, G, and O bits are not implemented.
+** So it looks like nothing needs to be done for parisc-linux (yet).
+** (thanks to chada for the above comment -ggg)
+**
+** The __asm__ op below simple prevents gcc/ld from reordering
+** instructions across the mb() "call".
+*/
+#define mb()           __asm__ __volatile__("":::"memory")     /* barrier() */
+#define rmb()          mb()
+#define wmb()          mb()
+#define smp_mb()       mb()
+#define smp_rmb()      mb()
+#define smp_wmb()      mb()
+#define smp_read_barrier_depends()     do { } while(0)
+#define read_barrier_depends()         do { } while(0)
+
+#define set_mb(var, value)             do { var = value; mb(); } while (0)
+
+#endif /* __PARISC_BARRIER_H */
index 7a75e98..912ee7e 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef _PARISC_DELAY_H
 #define _PARISC_DELAY_H
 
-#include <asm/system.h>    /* for mfctl() */
+#include <asm/special_insns.h>    /* for mfctl() */
 #include <asm/processor.h> /* for boot_cpu_data */
 
 
index f7a18f9..fd48ae2 100644 (file)
@@ -9,7 +9,6 @@
 #define _ASM_DMA_H
 
 #include <asm/io.h>            /* need byte IO */
-#include <asm/system.h>        
 
 #define dma_outb       outb
 #define dma_inb                inb
diff --git a/arch/parisc/include/asm/exec.h b/arch/parisc/include/asm/exec.h
new file mode 100644 (file)
index 0000000..6bb5af7
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __PARISC_EXEC_H
+#define __PARISC_EXEC_H
+
+#define arch_align_stack(x) (x)
+
+#endif /* __PARISC_EXEC_H */
diff --git a/arch/parisc/include/asm/ldcw.h b/arch/parisc/include/asm/ldcw.h
new file mode 100644 (file)
index 0000000..d2d11b7
--- /dev/null
@@ -0,0 +1,48 @@
+#ifndef __PARISC_LDCW_H
+#define __PARISC_LDCW_H
+
+#ifndef CONFIG_PA20
+/* Because kmalloc only guarantees 8-byte alignment for kmalloc'd data,
+   and GCC only guarantees 8-byte alignment for stack locals, we can't
+   be assured of 16-byte alignment for atomic lock data even if we
+   specify "__attribute ((aligned(16)))" in the type declaration.  So,
+   we use a struct containing an array of four ints for the atomic lock
+   type and dynamically select the 16-byte aligned int from the array
+   for the semaphore.  */
+
+#define __PA_LDCW_ALIGNMENT    16
+#define __ldcw_align(a) ({                                     \
+       unsigned long __ret = (unsigned long) &(a)->lock[0];    \
+       __ret = (__ret + __PA_LDCW_ALIGNMENT - 1)               \
+               & ~(__PA_LDCW_ALIGNMENT - 1);                   \
+       (volatile unsigned int *) __ret;                        \
+})
+#define __LDCW "ldcw"
+
+#else /*CONFIG_PA20*/
+/* From: "Jim Hull" <jim.hull of hp.com>
+   I've attached a summary of the change, but basically, for PA 2.0, as
+   long as the ",CO" (coherent operation) completer is specified, then the
+   16-byte alignment requirement for ldcw and ldcd is relaxed, and instead
+   they only require "natural" alignment (4-byte for ldcw, 8-byte for
+   ldcd). */
+
+#define __PA_LDCW_ALIGNMENT    4
+#define __ldcw_align(a) (&(a)->slock)
+#define __LDCW "ldcw,co"
+
+#endif /*!CONFIG_PA20*/
+
+/* LDCW, the only atomic read-write operation PA-RISC has. *sigh*.  */
+#define __ldcw(a) ({                                           \
+       unsigned __ret;                                         \
+       __asm__ __volatile__(__LDCW " 0(%2),%0"                 \
+               : "=r" (__ret), "+m" (*(a)) : "r" (a));         \
+       __ret;                                                  \
+})
+
+#ifdef CONFIG_SMP
+# define __lock_aligned __attribute__((__section__(".data..lock_aligned")))
+#endif
+
+#endif /* __PARISC_LDCW_H */
index 7213ec9..acdf4ca 100644 (file)
@@ -16,7 +16,6 @@
 #include <asm/pdc.h>
 #include <asm/ptrace.h>
 #include <asm/types.h>
-#include <asm/system.h>
 #include <asm/percpu.h>
 
 #endif /* __ASSEMBLY__ */
@@ -169,6 +168,7 @@ struct thread_struct {
  * Return saved PC of a blocked thread.  This is used by ps mostly.
  */
 
+struct task_struct;
 unsigned long thread_saved_pc(struct task_struct *t);
 void show_trace(struct task_struct *task, unsigned long *stack);
 
index 5a3e23c..ad69a35 100644 (file)
 #define USER_PSW_MASK (WIDE_PSW | PSW_T | PSW_N | PSW_X | PSW_B | PSW_V | PSW_CB)
 #define USER_PSW      (PSW_C | PSW_Q | PSW_P | PSW_D | PSW_I)
 
+#ifndef __ASSEMBLY__
+
+/* The program status word as bitfields.  */
+struct pa_psw {
+       unsigned int y:1;
+       unsigned int z:1;
+       unsigned int rv:2;
+       unsigned int w:1;
+       unsigned int e:1;
+       unsigned int s:1;
+       unsigned int t:1;
+
+       unsigned int h:1;
+       unsigned int l:1;
+       unsigned int n:1;
+       unsigned int x:1;
+       unsigned int b:1;
+       unsigned int c:1;
+       unsigned int v:1;
+       unsigned int m:1;
+
+       unsigned int cb:8;
+
+       unsigned int o:1;
+       unsigned int g:1;
+       unsigned int f:1;
+       unsigned int r:1;
+       unsigned int q:1;
+       unsigned int p:1;
+       unsigned int d:1;
+       unsigned int i:1;
+};
+
+#ifdef CONFIG_64BIT
+#define pa_psw(task) ((struct pa_psw *) ((char *) (task) + TASK_PT_PSW + 4))
+#else
+#define pa_psw(task) ((struct pa_psw *) ((char *) (task) + TASK_PT_PSW))
+#endif
+
+#endif /* !__ASSEMBLY__ */
+
 #endif
diff --git a/arch/parisc/include/asm/special_insns.h b/arch/parisc/include/asm/special_insns.h
new file mode 100644 (file)
index 0000000..d306b75
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef __PARISC_SPECIAL_INSNS_H
+#define __PARISC_SPECIAL_INSNS_H
+
+#define mfctl(reg)     ({              \
+       unsigned long cr;               \
+       __asm__ __volatile__(           \
+               "mfctl " #reg ",%0" :   \
+                "=r" (cr)              \
+       );                              \
+       cr;                             \
+})
+
+#define mtctl(gr, cr) \
+       __asm__ __volatile__("mtctl %0,%1" \
+               : /* no outputs */ \
+               : "r" (gr), "i" (cr) : "memory")
+
+/* these are here to de-mystefy the calling code, and to provide hooks */
+/* which I needed for debugging EIEM problems -PB */
+#define get_eiem() mfctl(15)
+static inline void set_eiem(unsigned long val)
+{
+       mtctl(val, 15);
+}
+
+#define mfsp(reg)      ({              \
+       unsigned long cr;               \
+       __asm__ __volatile__(           \
+               "mfsp " #reg ",%0" :    \
+                "=r" (cr)              \
+       );                              \
+       cr;                             \
+})
+
+#define mtsp(gr, cr) \
+       __asm__ __volatile__("mtsp %0,%1" \
+               : /* no outputs */ \
+               : "r" (gr), "i" (cr) : "memory")
+
+#endif /* __PARISC_SPECIAL_INSNS_H */
index 74036f4..804aa28 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __ASM_SPINLOCK_H
 #define __ASM_SPINLOCK_H
 
-#include <asm/system.h>
 #include <asm/processor.h>
 #include <asm/spinlock_types.h>
 
diff --git a/arch/parisc/include/asm/switch_to.h b/arch/parisc/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..8ed8fea
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef __PARISC_SWITCH_TO_H
+#define __PARISC_SWITCH_TO_H
+
+struct task_struct;
+
+extern struct task_struct *_switch_to(struct task_struct *, struct task_struct *);
+
+#define switch_to(prev, next, last) do {                       \
+       (last) = _switch_to(prev, next);                        \
+} while(0)
+
+#endif /* __PARISC_SWITCH_TO_H */
diff --git a/arch/parisc/include/asm/system.h b/arch/parisc/include/asm/system.h
deleted file mode 100644 (file)
index b19e63a..0000000
+++ /dev/null
@@ -1,165 +0,0 @@
-#ifndef __PARISC_SYSTEM_H
-#define __PARISC_SYSTEM_H
-
-#include <linux/irqflags.h>
-
-/* The program status word as bitfields.  */
-struct pa_psw {
-       unsigned int y:1;
-       unsigned int z:1;
-       unsigned int rv:2;
-       unsigned int w:1;
-       unsigned int e:1;
-       unsigned int s:1;
-       unsigned int t:1;
-
-       unsigned int h:1;
-       unsigned int l:1;
-       unsigned int n:1;
-       unsigned int x:1;
-       unsigned int b:1;
-       unsigned int c:1;
-       unsigned int v:1;
-       unsigned int m:1;
-
-       unsigned int cb:8;
-
-       unsigned int o:1;
-       unsigned int g:1;
-       unsigned int f:1;
-       unsigned int r:1;
-       unsigned int q:1;
-       unsigned int p:1;
-       unsigned int d:1;
-       unsigned int i:1;
-};
-
-#ifdef CONFIG_64BIT
-#define pa_psw(task) ((struct pa_psw *) ((char *) (task) + TASK_PT_PSW + 4))
-#else
-#define pa_psw(task) ((struct pa_psw *) ((char *) (task) + TASK_PT_PSW))
-#endif
-
-struct task_struct;
-
-extern struct task_struct *_switch_to(struct task_struct *, struct task_struct *);
-
-#define switch_to(prev, next, last) do {                       \
-       (last) = _switch_to(prev, next);                        \
-} while(0)
-
-#define mfctl(reg)     ({              \
-       unsigned long cr;               \
-       __asm__ __volatile__(           \
-               "mfctl " #reg ",%0" :   \
-                "=r" (cr)              \
-       );                              \
-       cr;                             \
-})
-
-#define mtctl(gr, cr) \
-       __asm__ __volatile__("mtctl %0,%1" \
-               : /* no outputs */ \
-               : "r" (gr), "i" (cr) : "memory")
-
-/* these are here to de-mystefy the calling code, and to provide hooks */
-/* which I needed for debugging EIEM problems -PB */
-#define get_eiem() mfctl(15)
-static inline void set_eiem(unsigned long val)
-{
-       mtctl(val, 15);
-}
-
-#define mfsp(reg)      ({              \
-       unsigned long cr;               \
-       __asm__ __volatile__(           \
-               "mfsp " #reg ",%0" :    \
-                "=r" (cr)              \
-       );                              \
-       cr;                             \
-})
-
-#define mtsp(gr, cr) \
-       __asm__ __volatile__("mtsp %0,%1" \
-               : /* no outputs */ \
-               : "r" (gr), "i" (cr) : "memory")
-
-
-/*
-** This is simply the barrier() macro from linux/kernel.h but when serial.c
-** uses tqueue.h uses smp_mb() defined using barrier(), linux/kernel.h
-** hasn't yet been included yet so it fails, thus repeating the macro here.
-**
-** PA-RISC architecture allows for weakly ordered memory accesses although
-** none of the processors use it. There is a strong ordered bit that is
-** set in the O-bit of the page directory entry. Operating systems that
-** can not tolerate out of order accesses should set this bit when mapping
-** pages. The O-bit of the PSW should also be set to 1 (I don't believe any
-** of the processor implemented the PSW O-bit). The PCX-W ERS states that
-** the TLB O-bit is not implemented so the page directory does not need to
-** have the O-bit set when mapping pages (section 3.1). This section also
-** states that the PSW Y, Z, G, and O bits are not implemented.
-** So it looks like nothing needs to be done for parisc-linux (yet).
-** (thanks to chada for the above comment -ggg)
-**
-** The __asm__ op below simple prevents gcc/ld from reordering
-** instructions across the mb() "call".
-*/
-#define mb()           __asm__ __volatile__("":::"memory")     /* barrier() */
-#define rmb()          mb()
-#define wmb()          mb()
-#define smp_mb()       mb()
-#define smp_rmb()      mb()
-#define smp_wmb()      mb()
-#define smp_read_barrier_depends()     do { } while(0)
-#define read_barrier_depends()         do { } while(0)
-
-#define set_mb(var, value)             do { var = value; mb(); } while (0)
-
-#ifndef CONFIG_PA20
-/* Because kmalloc only guarantees 8-byte alignment for kmalloc'd data,
-   and GCC only guarantees 8-byte alignment for stack locals, we can't
-   be assured of 16-byte alignment for atomic lock data even if we
-   specify "__attribute ((aligned(16)))" in the type declaration.  So,
-   we use a struct containing an array of four ints for the atomic lock
-   type and dynamically select the 16-byte aligned int from the array
-   for the semaphore.  */
-
-#define __PA_LDCW_ALIGNMENT    16
-#define __ldcw_align(a) ({                                     \
-       unsigned long __ret = (unsigned long) &(a)->lock[0];    \
-       __ret = (__ret + __PA_LDCW_ALIGNMENT - 1)               \
-               & ~(__PA_LDCW_ALIGNMENT - 1);                   \
-       (volatile unsigned int *) __ret;                        \
-})
-#define __LDCW "ldcw"
-
-#else /*CONFIG_PA20*/
-/* From: "Jim Hull" <jim.hull of hp.com>
-   I've attached a summary of the change, but basically, for PA 2.0, as
-   long as the ",CO" (coherent operation) completer is specified, then the
-   16-byte alignment requirement for ldcw and ldcd is relaxed, and instead
-   they only require "natural" alignment (4-byte for ldcw, 8-byte for
-   ldcd). */
-
-#define __PA_LDCW_ALIGNMENT    4
-#define __ldcw_align(a) (&(a)->slock)
-#define __LDCW "ldcw,co"
-
-#endif /*!CONFIG_PA20*/
-
-/* LDCW, the only atomic read-write operation PA-RISC has. *sigh*.  */
-#define __ldcw(a) ({                                           \
-       unsigned __ret;                                         \
-       __asm__ __volatile__(__LDCW " 0(%2),%0"                 \
-               : "=r" (__ret), "+m" (*(a)) : "r" (a));         \
-       __ret;                                                  \
-})
-
-#ifdef CONFIG_SMP
-# define __lock_aligned __attribute__((__section__(".data..lock_aligned")))
-#endif
-
-#define arch_align_stack(x) (x)
-
-#endif
index 6d9c7c7..83ae7dd 100644 (file)
@@ -5,6 +5,7 @@
 
 #ifndef __ASSEMBLY__
 #include <asm/processor.h>
+#include <asm/special_insns.h>
 
 struct thread_info {
        struct task_struct *task;       /* main task structure */
index 3b68d77..2bd51f6 100644 (file)
@@ -6,7 +6,6 @@
 #ifndef _ASMPARISC_TIMEX_H
 #define _ASMPARISC_TIMEX_H
 
-#include <asm/system.h>
 
 #define CLOCK_TICK_RATE        1193180 /* Underlying HZ */
 
index ff4cf9d..9ac0660 100644 (file)
@@ -5,7 +5,6 @@
  * User space memory access functions
  */
 #include <asm/page.h>
-#include <asm/system.h>
 #include <asm/cache.h>
 #include <asm/errno.h>
 #include <asm-generic/uaccess-unaligned.h>
index 83335f3..9d18189 100644 (file)
@@ -22,7 +22,6 @@
 #include <asm/cache.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
-#include <asm/system.h>
 #include <asm/page.h>
 #include <asm/pgalloc.h>
 #include <asm/processor.h>
index 4896ed0..f65fa48 100644 (file)
@@ -67,7 +67,6 @@
 #include <asm/page.h>
 #include <asm/pdc.h>
 #include <asm/pdcpat.h>
-#include <asm/system.h>
 #include <asm/processor.h>     /* for boot_cpu_data */
 
 static DEFINE_SPINLOCK(pdc_lock);
index 74d544b..24644ac 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/types.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/superio.h>
 
 #define DEBUG_RESOURCES 0
index 2905b1f..857c2f5 100644 (file)
@@ -22,7 +22,6 @@
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/processor.h>
 #include <asm/asm-offsets.h>
 
index 32d5884..5006e8e 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/bitops.h>
 #include <linux/ftrace.h>
 
-#include <asm/system.h>
 #include <linux/atomic.h>
 #include <asm/current.h>
 #include <asm/delay.h>
index f19e660..45ba99f 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/bug.h>
 
 #include <asm/assembly.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/irq.h>
index a8bffd8..1871188 100644 (file)
@@ -8,7 +8,6 @@
 
 #include <linux/kernel.h>
 #include <linux/spinlock.h>
-#include <asm/system.h>
 #include <linux/atomic.h>
 
 #ifdef CONFIG_SMP
index 12da77e..1c1aadc 100644 (file)
@@ -27,7 +27,6 @@ zImage.bin.*
 zImage.chrp
 zImage.coff
 zImage.holly
-zImage.iseries
 zImage.*lds
 zImage.miboot
 zImage.pmac
index 14174e8..da29032 100644 (file)
@@ -5,13 +5,9 @@
  * PowerPC atomic operations
  */
 
-#include <linux/types.h>
-
 #ifdef __KERNEL__
-#include <linux/compiler.h>
-#include <asm/synch.h>
-#include <asm/asm-compat.h>
-#include <asm/system.h>
+#include <linux/types.h>
+#include <asm/cmpxchg.h>
 
 #define ATOMIC_INIT(i)         { (i) }
 
index 19a099b..ce17d2c 100644 (file)
@@ -16,4 +16,6 @@
  */
 #define AT_SYSINFO_EHDR                33
 
+#define AT_VECTOR_SIZE_ARCH 6 /* entries in ARCH_DLINFO */
+
 #endif
diff --git a/arch/powerpc/include/asm/barrier.h b/arch/powerpc/include/asm/barrier.h
new file mode 100644 (file)
index 0000000..ae78225
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu>
+ */
+#ifndef _ASM_POWERPC_BARRIER_H
+#define _ASM_POWERPC_BARRIER_H
+
+/*
+ * Memory barrier.
+ * The sync instruction guarantees that all memory accesses initiated
+ * by this processor have been performed (with respect to all other
+ * mechanisms that access memory).  The eieio instruction is a barrier
+ * providing an ordering (separately) for (a) cacheable stores and (b)
+ * loads and stores to non-cacheable memory (e.g. I/O devices).
+ *
+ * mb() prevents loads and stores being reordered across this point.
+ * rmb() prevents loads being reordered across this point.
+ * wmb() prevents stores being reordered across this point.
+ * read_barrier_depends() prevents data-dependent loads being reordered
+ *     across this point (nop on PPC).
+ *
+ * *mb() variants without smp_ prefix must order all types of memory
+ * operations with one another. sync is the only instruction sufficient
+ * to do this.
+ *
+ * For the smp_ barriers, ordering is for cacheable memory operations
+ * only. We have to use the sync instruction for smp_mb(), since lwsync
+ * doesn't order loads with respect to previous stores.  Lwsync can be
+ * used for smp_rmb() and smp_wmb().
+ *
+ * However, on CPUs that don't support lwsync, lwsync actually maps to a
+ * heavy-weight sync, so smp_wmb() can be a lighter-weight eieio.
+ */
+#define mb()   __asm__ __volatile__ ("sync" : : : "memory")
+#define rmb()  __asm__ __volatile__ ("sync" : : : "memory")
+#define wmb()  __asm__ __volatile__ ("sync" : : : "memory")
+#define read_barrier_depends()  do { } while(0)
+
+#define set_mb(var, value)     do { var = value; mb(); } while (0)
+
+#ifdef CONFIG_SMP
+
+#ifdef __SUBARCH_HAS_LWSYNC
+#    define SMPWMB      LWSYNC
+#else
+#    define SMPWMB      eieio
+#endif
+
+#define smp_mb()       mb()
+#define smp_rmb()      __asm__ __volatile__ (stringify_in_c(LWSYNC) : : :"memory")
+#define smp_wmb()      __asm__ __volatile__ (stringify_in_c(SMPWMB) : : :"memory")
+#define smp_read_barrier_depends()     read_barrier_depends()
+#else
+#define smp_mb()       barrier()
+#define smp_rmb()      barrier()
+#define smp_wmb()      barrier()
+#define smp_read_barrier_depends()     do { } while(0)
+#endif /* CONFIG_SMP */
+
+/*
+ * This is a barrier which prevents following instructions from being
+ * started until the value of the argument x is known.  For example, if
+ * x is a variable loaded from memory, this prevents following
+ * instructions from being executed until the load has been performed.
+ */
+#define data_barrier(x)        \
+       asm volatile("twi 0,%0,0; isync" : : "r" (x) : "memory");
+
+#endif /* _ASM_POWERPC_BARRIER_H */
index 065c590..3eb53d7 100644 (file)
 
 #include <asm-generic/bug.h>
 
+#ifndef __ASSEMBLY__
+
+struct pt_regs;
+extern int do_page_fault(struct pt_regs *, unsigned long, unsigned long);
+extern void bad_page_fault(struct pt_regs *, unsigned long, int);
+extern void _exception(int, struct pt_regs *, int, unsigned long);
+extern void die(const char *, struct pt_regs *, long);
+extern void print_backtrace(unsigned long *);
+
+#endif /* !__ASSEMBLY__ */
+
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_BUG_H */
index 4b50941..9e495c9 100644 (file)
@@ -42,8 +42,24 @@ extern struct ppc64_caches ppc64_caches;
 #endif /* __powerpc64__ && ! __ASSEMBLY__ */
 
 #if !defined(__ASSEMBLY__)
+
 #define __read_mostly __attribute__((__section__(".data..read_mostly")))
+
+#ifdef CONFIG_6xx
+extern long _get_L2CR(void);
+extern long _get_L3CR(void);
+extern void _set_L2CR(unsigned long);
+extern void _set_L3CR(unsigned long);
+#else
+#define _get_L2CR()    0L
+#define _get_L3CR()    0L
+#define _set_L2CR(val) do { } while(0)
+#define _set_L3CR(val) do { } while(0)
 #endif
 
+extern void cacheable_memzero(void *p, unsigned int nb);
+extern void *cacheable_memcpy(void *, const void *, unsigned int);
+
+#endif /* !__ASSEMBLY__ */
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_CACHE_H */
diff --git a/arch/powerpc/include/asm/cmpxchg.h b/arch/powerpc/include/asm/cmpxchg.h
new file mode 100644 (file)
index 0000000..e245aab
--- /dev/null
@@ -0,0 +1,309 @@
+#ifndef _ASM_POWERPC_CMPXCHG_H_
+#define _ASM_POWERPC_CMPXCHG_H_
+
+#ifdef __KERNEL__
+#include <linux/compiler.h>
+#include <asm/synch.h>
+#include <asm/asm-compat.h>
+
+/*
+ * Atomic exchange
+ *
+ * Changes the memory location '*ptr' to be val and returns
+ * the previous value stored there.
+ */
+static __always_inline unsigned long
+__xchg_u32(volatile void *p, unsigned long val)
+{
+       unsigned long prev;
+
+       __asm__ __volatile__(
+       PPC_RELEASE_BARRIER
+"1:    lwarx   %0,0,%2 \n"
+       PPC405_ERR77(0,%2)
+"      stwcx.  %3,0,%2 \n\
+       bne-    1b"
+       PPC_ACQUIRE_BARRIER
+       : "=&r" (prev), "+m" (*(volatile unsigned int *)p)
+       : "r" (p), "r" (val)
+       : "cc", "memory");
+
+       return prev;
+}
+
+/*
+ * Atomic exchange
+ *
+ * Changes the memory location '*ptr' to be val and returns
+ * the previous value stored there.
+ */
+static __always_inline unsigned long
+__xchg_u32_local(volatile void *p, unsigned long val)
+{
+       unsigned long prev;
+
+       __asm__ __volatile__(
+"1:    lwarx   %0,0,%2 \n"
+       PPC405_ERR77(0,%2)
+"      stwcx.  %3,0,%2 \n\
+       bne-    1b"
+       : "=&r" (prev), "+m" (*(volatile unsigned int *)p)
+       : "r" (p), "r" (val)
+       : "cc", "memory");
+
+       return prev;
+}
+
+#ifdef CONFIG_PPC64
+static __always_inline unsigned long
+__xchg_u64(volatile void *p, unsigned long val)
+{
+       unsigned long prev;
+
+       __asm__ __volatile__(
+       PPC_RELEASE_BARRIER
+"1:    ldarx   %0,0,%2 \n"
+       PPC405_ERR77(0,%2)
+"      stdcx.  %3,0,%2 \n\
+       bne-    1b"
+       PPC_ACQUIRE_BARRIER
+       : "=&r" (prev), "+m" (*(volatile unsigned long *)p)
+       : "r" (p), "r" (val)
+       : "cc", "memory");
+
+       return prev;
+}
+
+static __always_inline unsigned long
+__xchg_u64_local(volatile void *p, unsigned long val)
+{
+       unsigned long prev;
+
+       __asm__ __volatile__(
+"1:    ldarx   %0,0,%2 \n"
+       PPC405_ERR77(0,%2)
+"      stdcx.  %3,0,%2 \n\
+       bne-    1b"
+       : "=&r" (prev), "+m" (*(volatile unsigned long *)p)
+       : "r" (p), "r" (val)
+       : "cc", "memory");
+
+       return prev;
+}
+#endif
+
+/*
+ * This function doesn't exist, so you'll get a linker error
+ * if something tries to do an invalid xchg().
+ */
+extern void __xchg_called_with_bad_pointer(void);
+
+static __always_inline unsigned long
+__xchg(volatile void *ptr, unsigned long x, unsigned int size)
+{
+       switch (size) {
+       case 4:
+               return __xchg_u32(ptr, x);
+#ifdef CONFIG_PPC64
+       case 8:
+               return __xchg_u64(ptr, x);
+#endif
+       }
+       __xchg_called_with_bad_pointer();
+       return x;
+}
+
+static __always_inline unsigned long
+__xchg_local(volatile void *ptr, unsigned long x, unsigned int size)
+{
+       switch (size) {
+       case 4:
+               return __xchg_u32_local(ptr, x);
+#ifdef CONFIG_PPC64
+       case 8:
+               return __xchg_u64_local(ptr, x);
+#endif
+       }
+       __xchg_called_with_bad_pointer();
+       return x;
+}
+#define xchg(ptr,x)                                                         \
+  ({                                                                        \
+     __typeof__(*(ptr)) _x_ = (x);                                          \
+     (__typeof__(*(ptr))) __xchg((ptr), (unsigned long)_x_, sizeof(*(ptr))); \
+  })
+
+#define xchg_local(ptr,x)                                                   \
+  ({                                                                        \
+     __typeof__(*(ptr)) _x_ = (x);                                          \
+     (__typeof__(*(ptr))) __xchg_local((ptr),                               \
+               (unsigned long)_x_, sizeof(*(ptr)));                         \
+  })
+
+/*
+ * Compare and exchange - if *p == old, set it to new,
+ * and return the old value of *p.
+ */
+#define __HAVE_ARCH_CMPXCHG    1
+
+static __always_inline unsigned long
+__cmpxchg_u32(volatile unsigned int *p, unsigned long old, unsigned long new)
+{
+       unsigned int prev;
+
+       __asm__ __volatile__ (
+       PPC_RELEASE_BARRIER
+"1:    lwarx   %0,0,%2         # __cmpxchg_u32\n\
+       cmpw    0,%0,%3\n\
+       bne-    2f\n"
+       PPC405_ERR77(0,%2)
+"      stwcx.  %4,0,%2\n\
+       bne-    1b"
+       PPC_ACQUIRE_BARRIER
+       "\n\
+2:"
+       : "=&r" (prev), "+m" (*p)
+       : "r" (p), "r" (old), "r" (new)
+       : "cc", "memory");
+
+       return prev;
+}
+
+static __always_inline unsigned long
+__cmpxchg_u32_local(volatile unsigned int *p, unsigned long old,
+                       unsigned long new)
+{
+       unsigned int prev;
+
+       __asm__ __volatile__ (
+"1:    lwarx   %0,0,%2         # __cmpxchg_u32\n\
+       cmpw    0,%0,%3\n\
+       bne-    2f\n"
+       PPC405_ERR77(0,%2)
+"      stwcx.  %4,0,%2\n\
+       bne-    1b"
+       "\n\
+2:"
+       : "=&r" (prev), "+m" (*p)
+       : "r" (p), "r" (old), "r" (new)
+       : "cc", "memory");
+
+       return prev;
+}
+
+#ifdef CONFIG_PPC64
+static __always_inline unsigned long
+__cmpxchg_u64(volatile unsigned long *p, unsigned long old, unsigned long new)
+{
+       unsigned long prev;
+
+       __asm__ __volatile__ (
+       PPC_RELEASE_BARRIER
+"1:    ldarx   %0,0,%2         # __cmpxchg_u64\n\
+       cmpd    0,%0,%3\n\
+       bne-    2f\n\
+       stdcx.  %4,0,%2\n\
+       bne-    1b"
+       PPC_ACQUIRE_BARRIER
+       "\n\
+2:"
+       : "=&r" (prev), "+m" (*p)
+       : "r" (p), "r" (old), "r" (new)
+       : "cc", "memory");
+
+       return prev;
+}
+
+static __always_inline unsigned long
+__cmpxchg_u64_local(volatile unsigned long *p, unsigned long old,
+                       unsigned long new)
+{
+       unsigned long prev;
+
+       __asm__ __volatile__ (
+"1:    ldarx   %0,0,%2         # __cmpxchg_u64\n\
+       cmpd    0,%0,%3\n\
+       bne-    2f\n\
+       stdcx.  %4,0,%2\n\
+       bne-    1b"
+       "\n\
+2:"
+       : "=&r" (prev), "+m" (*p)
+       : "r" (p), "r" (old), "r" (new)
+       : "cc", "memory");
+
+       return prev;
+}
+#endif
+
+/* This function doesn't exist, so you'll get a linker error
+   if something tries to do an invalid cmpxchg().  */
+extern void __cmpxchg_called_with_bad_pointer(void);
+
+static __always_inline unsigned long
+__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new,
+         unsigned int size)
+{
+       switch (size) {
+       case 4:
+               return __cmpxchg_u32(ptr, old, new);
+#ifdef CONFIG_PPC64
+       case 8:
+               return __cmpxchg_u64(ptr, old, new);
+#endif
+       }
+       __cmpxchg_called_with_bad_pointer();
+       return old;
+}
+
+static __always_inline unsigned long
+__cmpxchg_local(volatile void *ptr, unsigned long old, unsigned long new,
+         unsigned int size)
+{
+       switch (size) {
+       case 4:
+               return __cmpxchg_u32_local(ptr, old, new);
+#ifdef CONFIG_PPC64
+       case 8:
+               return __cmpxchg_u64_local(ptr, old, new);
+#endif
+       }
+       __cmpxchg_called_with_bad_pointer();
+       return old;
+}
+
+#define cmpxchg(ptr, o, n)                                              \
+  ({                                                                    \
+     __typeof__(*(ptr)) _o_ = (o);                                      \
+     __typeof__(*(ptr)) _n_ = (n);                                      \
+     (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,          \
+                                   (unsigned long)_n_, sizeof(*(ptr))); \
+  })
+
+
+#define cmpxchg_local(ptr, o, n)                                        \
+  ({                                                                    \
+     __typeof__(*(ptr)) _o_ = (o);                                      \
+     __typeof__(*(ptr)) _n_ = (n);                                      \
+     (__typeof__(*(ptr))) __cmpxchg_local((ptr), (unsigned long)_o_,    \
+                                   (unsigned long)_n_, sizeof(*(ptr))); \
+  })
+
+#ifdef CONFIG_PPC64
+#define cmpxchg64(ptr, o, n)                                           \
+  ({                                                                   \
+       BUILD_BUG_ON(sizeof(*(ptr)) != 8);                              \
+       cmpxchg((ptr), (o), (n));                                       \
+  })
+#define cmpxchg64_local(ptr, o, n)                                     \
+  ({                                                                   \
+       BUILD_BUG_ON(sizeof(*(ptr)) != 8);                              \
+       cmpxchg_local((ptr), (o), (n));                                 \
+  })
+#else
+#include <asm-generic/cmpxchg-local.h>
+#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
+#endif
+
+#endif /* __KERNEL__ */
+#endif /* _ASM_POWERPC_CMPXCHG_H_ */
diff --git a/arch/powerpc/include/asm/debug.h b/arch/powerpc/include/asm/debug.h
new file mode 100644 (file)
index 0000000..716d2f0
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu>
+ */
+#ifndef _ASM_POWERPC_DEBUG_H
+#define _ASM_POWERPC_DEBUG_H
+
+struct pt_regs;
+
+extern struct dentry *powerpc_debugfs_root;
+
+#if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC)
+
+extern int (*__debugger)(struct pt_regs *regs);
+extern int (*__debugger_ipi)(struct pt_regs *regs);
+extern int (*__debugger_bpt)(struct pt_regs *regs);
+extern int (*__debugger_sstep)(struct pt_regs *regs);
+extern int (*__debugger_iabr_match)(struct pt_regs *regs);
+extern int (*__debugger_dabr_match)(struct pt_regs *regs);
+extern int (*__debugger_fault_handler)(struct pt_regs *regs);
+
+#define DEBUGGER_BOILERPLATE(__NAME) \
+static inline int __NAME(struct pt_regs *regs) \
+{ \
+       if (unlikely(__ ## __NAME)) \
+               return __ ## __NAME(regs); \
+       return 0; \
+}
+
+DEBUGGER_BOILERPLATE(debugger)
+DEBUGGER_BOILERPLATE(debugger_ipi)
+DEBUGGER_BOILERPLATE(debugger_bpt)
+DEBUGGER_BOILERPLATE(debugger_sstep)
+DEBUGGER_BOILERPLATE(debugger_iabr_match)
+DEBUGGER_BOILERPLATE(debugger_dabr_match)
+DEBUGGER_BOILERPLATE(debugger_fault_handler)
+
+#else
+static inline int debugger(struct pt_regs *regs) { return 0; }
+static inline int debugger_ipi(struct pt_regs *regs) { return 0; }
+static inline int debugger_bpt(struct pt_regs *regs) { return 0; }
+static inline int debugger_sstep(struct pt_regs *regs) { return 0; }
+static inline int debugger_iabr_match(struct pt_regs *regs) { return 0; }
+static inline int debugger_dabr_match(struct pt_regs *regs) { return 0; }
+static inline int debugger_fault_handler(struct pt_regs *regs) { return 0; }
+#endif
+
+extern int set_dabr(unsigned long dabr);
+#ifdef CONFIG_PPC_ADV_DEBUG_REGS
+extern void do_send_trap(struct pt_regs *regs, unsigned long address,
+                        unsigned long error_code, int signal_code, int brkpt);
+#else
+extern void do_dabr(struct pt_regs *regs, unsigned long address,
+                   unsigned long error_code);
+#endif
+
+#endif /* _ASM_POWERPC_DEBUG_H */
index adadb99..f6813e9 100644 (file)
@@ -24,7 +24,6 @@
 
 #include <asm/io.h>
 #include <linux/spinlock.h>
-#include <asm/system.h>
 
 #ifndef MAX_DMA_CHANNELS
 #define MAX_DMA_CHANNELS       8
diff --git a/arch/powerpc/include/asm/exec.h b/arch/powerpc/include/asm/exec.h
new file mode 100644 (file)
index 0000000..8196e9c
--- /dev/null
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu>
+ */
+#ifndef _ASM_POWERPC_EXEC_H
+#define _ASM_POWERPC_EXEC_H
+
+extern unsigned long arch_align_stack(unsigned long sp);
+
+#endif /* _ASM_POWERPC_EXEC_H */
index 80fd4d2..be04330 100644 (file)
@@ -35,7 +35,7 @@ struct arch_hw_breakpoint {
 
 #include <linux/kdebug.h>
 #include <asm/reg.h>
-#include <asm/system.h>
+#include <asm/debug.h>
 
 struct perf_event;
 struct pmu;
index edfc980..957a83f 100644 (file)
@@ -112,7 +112,6 @@ extern void iommu_unmap_page(struct iommu_table *tbl, dma_addr_t dma_handle,
                             struct dma_attrs *attrs);
 
 extern void iommu_init_early_pSeries(void);
-extern void iommu_init_early_iSeries(void);
 extern void iommu_init_early_dart(void);
 extern void iommu_init_early_pasemi(void);
 
index fe0b09d..cf417e5 100644 (file)
@@ -27,12 +27,6 @@ extern atomic_t ppc_n_lost_interrupts;
 /* This number is used when no interrupt has been assigned */
 #define NO_IRQ                 (0)
 
-/* This is a special irq number to return from get_irq() to tell that
- * no interrupt happened _and_ ignore it (don't count it as bad). Some
- * platforms like iSeries rely on that.
- */
-#define NO_IRQ_IGNORE          ((unsigned int)-1)
-
 /* Total number of virq in the platform */
 #define NR_IRQS                CONFIG_NR_IRQS
 
index f7727d9..b921c3f 100644 (file)
@@ -265,12 +265,9 @@ struct kvm_debug_exit_arch {
 struct kvm_guest_debug_arch {
 };
 
-#define KVM_REG_MASK           0x001f
-#define KVM_REG_EXT_MASK       0xffe0
-#define KVM_REG_GPR            0x0000
-#define KVM_REG_FPR            0x0020
-#define KVM_REG_QPR            0x0040
-#define KVM_REG_FQPR           0x0060
+/* definition of registers in kvm_run */
+struct kvm_sync_regs {
+};
 
 #define KVM_INTERRUPT_SET      -1U
 #define KVM_INTERRUPT_UNSET    -2U
@@ -292,4 +289,41 @@ struct kvm_allocate_rma {
        __u64 rma_size;
 };
 
+struct kvm_book3e_206_tlb_entry {
+       __u32 mas8;
+       __u32 mas1;
+       __u64 mas2;
+       __u64 mas7_3;
+};
+
+struct kvm_book3e_206_tlb_params {
+       /*
+        * For mmu types KVM_MMU_FSL_BOOKE_NOHV and KVM_MMU_FSL_BOOKE_HV:
+        *
+        * - The number of ways of TLB0 must be a power of two between 2 and
+        *   16.
+        * - TLB1 must be fully associative.
+        * - The size of TLB0 must be a multiple of the number of ways, and
+        *   the number of sets must be a power of two.
+        * - The size of TLB1 may not exceed 64 entries.
+        * - TLB0 supports 4 KiB pages.
+        * - The page sizes supported by TLB1 are as indicated by
+        *   TLB1CFG (if MMUCFG[MAVN] = 0) or TLB1PS (if MMUCFG[MAVN] = 1)
+        *   as returned by KVM_GET_SREGS.
+        * - TLB2 and TLB3 are reserved, and their entries in tlb_sizes[]
+        *   and tlb_ways[] must be zero.
+        *
+        * tlb_ways[n] = tlb_sizes[n] means the array is fully associative.
+        *
+        * KVM will adjust TLBnCFG based on the sizes configured here,
+        * though arrays greater than 2048 entries will have TLBnCFG[NENTRY]
+        * set to zero.
+        */
+       __u32 tlb_sizes[4];
+       __u32 tlb_ways[4];
+       __u32 reserved[8];
+};
+
+#define KVM_REG_PPC_HIOR       (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x1)
+
 #endif /* __LINUX_KVM_POWERPC_H */
index 69c7377..aa795cc 100644 (file)
@@ -90,6 +90,8 @@ struct kvmppc_vcpu_book3s {
 #endif
        int context_id[SID_CONTEXTS];
 
+       bool hior_explicit;             /* HIOR is set by ioctl, not PVR */
+
        struct hlist_head hpte_hash_pte[HPTEG_HASH_NUM_PTE];
        struct hlist_head hpte_hash_pte_long[HPTEG_HASH_NUM_PTE_LONG];
        struct hlist_head hpte_hash_vpte[HPTEG_HASH_NUM_VPTE];
@@ -119,6 +121,11 @@ extern void kvmppc_mmu_book3s_hv_init(struct kvm_vcpu *vcpu);
 extern int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte);
 extern int kvmppc_mmu_map_segment(struct kvm_vcpu *vcpu, ulong eaddr);
 extern void kvmppc_mmu_flush_segments(struct kvm_vcpu *vcpu);
+extern int kvmppc_book3s_hv_page_fault(struct kvm_run *run,
+                       struct kvm_vcpu *vcpu, unsigned long addr,
+                       unsigned long status);
+extern long kvmppc_hv_find_lock_hpte(struct kvm *kvm, gva_t eaddr,
+                       unsigned long slb_v, unsigned long valid);
 
 extern void kvmppc_mmu_hpte_cache_map(struct kvm_vcpu *vcpu, struct hpte_cache *pte);
 extern struct hpte_cache *kvmppc_mmu_hpte_cache_next(struct kvm_vcpu *vcpu);
@@ -138,6 +145,21 @@ extern void kvmppc_set_bat(struct kvm_vcpu *vcpu, struct kvmppc_bat *bat,
 extern void kvmppc_giveup_ext(struct kvm_vcpu *vcpu, ulong msr);
 extern int kvmppc_emulate_paired_single(struct kvm_run *run, struct kvm_vcpu *vcpu);
 extern pfn_t kvmppc_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn);
+extern void kvmppc_add_revmap_chain(struct kvm *kvm, struct revmap_entry *rev,
+                       unsigned long *rmap, long pte_index, int realmode);
+extern void kvmppc_invalidate_hpte(struct kvm *kvm, unsigned long *hptep,
+                       unsigned long pte_index);
+void kvmppc_clear_ref_hpte(struct kvm *kvm, unsigned long *hptep,
+                       unsigned long pte_index);
+extern void *kvmppc_pin_guest_page(struct kvm *kvm, unsigned long addr,
+                       unsigned long *nb_ret);
+extern void kvmppc_unpin_guest_page(struct kvm *kvm, void *addr);
+extern long kvmppc_virtmode_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
+                       long pte_index, unsigned long pteh, unsigned long ptel);
+extern long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
+                       long pte_index, unsigned long pteh, unsigned long ptel);
+extern long kvmppc_hv_get_dirty_log(struct kvm *kvm,
+                       struct kvm_memory_slot *memslot);
 
 extern void kvmppc_entry_trampoline(void);
 extern void kvmppc_hv_entry_trampoline(void);
@@ -183,7 +205,9 @@ static inline void kvmppc_update_int_pending(struct kvm_vcpu *vcpu,
 static inline void kvmppc_set_gpr(struct kvm_vcpu *vcpu, int num, ulong val)
 {
        if ( num < 14 ) {
-               to_svcpu(vcpu)->gpr[num] = val;
+               struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
+               svcpu->gpr[num] = val;
+               svcpu_put(svcpu);
                to_book3s(vcpu)->shadow_vcpu->gpr[num] = val;
        } else
                vcpu->arch.gpr[num] = val;
@@ -191,80 +215,120 @@ static inline void kvmppc_set_gpr(struct kvm_vcpu *vcpu, int num, ulong val)
 
 static inline ulong kvmppc_get_gpr(struct kvm_vcpu *vcpu, int num)
 {
-       if ( num < 14 )
-               return to_svcpu(vcpu)->gpr[num];
-       else
+       if ( num < 14 ) {
+               struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
+               ulong r = svcpu->gpr[num];
+               svcpu_put(svcpu);
+               return r;
+       } else
                return vcpu->arch.gpr[num];
 }
 
 static inline void kvmppc_set_cr(struct kvm_vcpu *vcpu, u32 val)
 {
-       to_svcpu(vcpu)->cr = val;
+       struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
+       svcpu->cr = val;
+       svcpu_put(svcpu);
        to_book3s(vcpu)->shadow_vcpu->cr = val;
 }
 
 static inline u32 kvmppc_get_cr(struct kvm_vcpu *vcpu)
 {
-       return to_svcpu(vcpu)->cr;
+       struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
+       u32 r;
+       r = svcpu->cr;
+       svcpu_put(svcpu);
+       return r;
 }
 
 static inline void kvmppc_set_xer(struct kvm_vcpu *vcpu, u32 val)
 {
-       to_svcpu(vcpu)->xer = val;
+       struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
+       svcpu->xer = val;
        to_book3s(vcpu)->shadow_vcpu->xer = val;
+       svcpu_put(svcpu);
 }
 
 static inline u32 kvmppc_get_xer(struct kvm_vcpu *vcpu)
 {
-       return to_svcpu(vcpu)->xer;
+       struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
+       u32 r;
+       r = svcpu->xer;
+       svcpu_put(svcpu);
+       return r;
 }
 
 static inline void kvmppc_set_ctr(struct kvm_vcpu *vcpu, ulong val)
 {
-       to_svcpu(vcpu)->ctr = val;
+       struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
+       svcpu->ctr = val;
+       svcpu_put(svcpu);
 }
 
 static inline ulong kvmppc_get_ctr(struct kvm_vcpu *vcpu)
 {
-       return to_svcpu(vcpu)->ctr;
+       struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
+       ulong r;
+       r = svcpu->ctr;
+       svcpu_put(svcpu);
+       return r;
 }
 
 static inline void kvmppc_set_lr(struct kvm_vcpu *vcpu, ulong val)
 {
-       to_svcpu(vcpu)->lr = val;
+       struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
+       svcpu->lr = val;
+       svcpu_put(svcpu);
 }
 
 static inline ulong kvmppc_get_lr(struct kvm_vcpu *vcpu)
 {
-       return to_svcpu(vcpu)->lr;
+       struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
+       ulong r;
+       r = svcpu->lr;
+       svcpu_put(svcpu);
+       return r;
 }
 
 static inline void kvmppc_set_pc(struct kvm_vcpu *vcpu, ulong val)
 {
-       to_svcpu(vcpu)->pc = val;
+       struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
+       svcpu->pc = val;
+       svcpu_put(svcpu);
 }
 
 static inline ulong kvmppc_get_pc(struct kvm_vcpu *vcpu)
 {
-       return to_svcpu(vcpu)->pc;
+       struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
+       ulong r;
+       r = svcpu->pc;
+       svcpu_put(svcpu);
+       return r;
 }
 
 static inline u32 kvmppc_get_last_inst(struct kvm_vcpu *vcpu)
 {
        ulong pc = kvmppc_get_pc(vcpu);
-       struct kvmppc_book3s_shadow_vcpu *svcpu = to_svcpu(vcpu);
+       struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
+       u32 r;
 
        /* Load the instruction manually if it failed to do so in the
         * exit path */
        if (svcpu->last_inst == KVM_INST_FETCH_FAILED)
                kvmppc_ld(vcpu, &pc, sizeof(u32), &svcpu->last_inst, false);
 
-       return svcpu->last_inst;
+       r = svcpu->last_inst;
+       svcpu_put(svcpu);
+       return r;
 }
 
 static inline ulong kvmppc_get_fault_dar(struct kvm_vcpu *vcpu)
 {
-       return to_svcpu(vcpu)->fault_dar;
+       struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
+       ulong r;
+       r = svcpu->fault_dar;
+       svcpu_put(svcpu);
+       return r;
 }
 
 static inline bool kvmppc_critical_section(struct kvm_vcpu *vcpu)
index de604db..38040ff 100644 (file)
 #ifndef __ASM_KVM_BOOK3S_32_H__
 #define __ASM_KVM_BOOK3S_32_H__
 
-static inline struct kvmppc_book3s_shadow_vcpu *to_svcpu(struct kvm_vcpu *vcpu)
+static inline struct kvmppc_book3s_shadow_vcpu *svcpu_get(struct kvm_vcpu *vcpu)
 {
        return to_book3s(vcpu)->shadow_vcpu;
 }
 
+static inline void svcpu_put(struct kvmppc_book3s_shadow_vcpu *svcpu)
+{
+}
+
 #define PTE_SIZE       12
 #define VSID_ALL       0
 #define SR_INVALID     0x00000001      /* VSID 1 should always be unused */
index d0ac94f..b0c08b1 100644 (file)
 #define __ASM_KVM_BOOK3S_64_H__
 
 #ifdef CONFIG_KVM_BOOK3S_PR
-static inline struct kvmppc_book3s_shadow_vcpu *to_svcpu(struct kvm_vcpu *vcpu)
+static inline struct kvmppc_book3s_shadow_vcpu *svcpu_get(struct kvm_vcpu *vcpu)
 {
+       preempt_disable();
        return &get_paca()->shadow_vcpu;
 }
+
+static inline void svcpu_put(struct kvmppc_book3s_shadow_vcpu *svcpu)
+{
+       preempt_enable();
+}
 #endif
 
 #define SPAPR_TCE_SHIFT                12
 
+#ifdef CONFIG_KVM_BOOK3S_64_HV
+/* For now use fixed-size 16MB page table */
+#define HPT_ORDER      24
+#define HPT_NPTEG      (1ul << (HPT_ORDER - 7))        /* 128B per pteg */
+#define HPT_NPTE       (HPT_NPTEG << 3)                /* 8 PTEs per PTEG */
+#define HPT_HASH_MASK  (HPT_NPTEG - 1)
+#endif
+
+#define VRMA_VSID      0x1ffffffUL     /* 1TB VSID reserved for VRMA */
+
+/*
+ * We use a lock bit in HPTE dword 0 to synchronize updates and
+ * accesses to each HPTE, and another bit to indicate non-present
+ * HPTEs.
+ */
+#define HPTE_V_HVLOCK  0x40UL
+#define HPTE_V_ABSENT  0x20UL
+
+static inline long try_lock_hpte(unsigned long *hpte, unsigned long bits)
+{
+       unsigned long tmp, old;
+
+       asm volatile("  ldarx   %0,0,%2\n"
+                    "  and.    %1,%0,%3\n"
+                    "  bne     2f\n"
+                    "  ori     %0,%0,%4\n"
+                    "  stdcx.  %0,0,%2\n"
+                    "  beq+    2f\n"
+                    "  li      %1,%3\n"
+                    "2:        isync"
+                    : "=&r" (tmp), "=&r" (old)
+                    : "r" (hpte), "r" (bits), "i" (HPTE_V_HVLOCK)
+                    : "cc", "memory");
+       return old == 0;
+}
+
 static inline unsigned long compute_tlbie_rb(unsigned long v, unsigned long r,
                                             unsigned long pte_index)
 {
@@ -62,4 +104,140 @@ static inline unsigned long compute_tlbie_rb(unsigned long v, unsigned long r,
        return rb;
 }
 
+static inline unsigned long hpte_page_size(unsigned long h, unsigned long l)
+{
+       /* only handle 4k, 64k and 16M pages for now */
+       if (!(h & HPTE_V_LARGE))
+               return 1ul << 12;               /* 4k page */
+       if ((l & 0xf000) == 0x1000 && cpu_has_feature(CPU_FTR_ARCH_206))
+               return 1ul << 16;               /* 64k page */
+       if ((l & 0xff000) == 0)
+               return 1ul << 24;               /* 16M page */
+       return 0;                               /* error */
+}
+
+static inline unsigned long hpte_rpn(unsigned long ptel, unsigned long psize)
+{
+       return ((ptel & HPTE_R_RPN) & ~(psize - 1)) >> PAGE_SHIFT;
+}
+
+static inline int hpte_is_writable(unsigned long ptel)
+{
+       unsigned long pp = ptel & (HPTE_R_PP0 | HPTE_R_PP);
+
+       return pp != PP_RXRX && pp != PP_RXXX;
+}
+
+static inline unsigned long hpte_make_readonly(unsigned long ptel)
+{
+       if ((ptel & HPTE_R_PP0) || (ptel & HPTE_R_PP) == PP_RWXX)
+               ptel = (ptel & ~HPTE_R_PP) | PP_RXXX;
+       else
+               ptel |= PP_RXRX;
+       return ptel;
+}
+
+static inline int hpte_cache_flags_ok(unsigned long ptel, unsigned long io_type)
+{
+       unsigned int wimg = ptel & HPTE_R_WIMG;
+
+       /* Handle SAO */
+       if (wimg == (HPTE_R_W | HPTE_R_I | HPTE_R_M) &&
+           cpu_has_feature(CPU_FTR_ARCH_206))
+               wimg = HPTE_R_M;
+
+       if (!io_type)
+               return wimg == HPTE_R_M;
+
+       return (wimg & (HPTE_R_W | HPTE_R_I)) == io_type;
+}
+
+/*
+ * Lock and read a linux PTE.  If it's present and writable, atomically
+ * set dirty and referenced bits and return the PTE, otherwise return 0.
+ */
+static inline pte_t kvmppc_read_update_linux_pte(pte_t *p, int writing)
+{
+       pte_t pte, tmp;
+
+       /* wait until _PAGE_BUSY is clear then set it atomically */
+       __asm__ __volatile__ (
+               "1:     ldarx   %0,0,%3\n"
+               "       andi.   %1,%0,%4\n"
+               "       bne-    1b\n"
+               "       ori     %1,%0,%4\n"
+               "       stdcx.  %1,0,%3\n"
+               "       bne-    1b"
+               : "=&r" (pte), "=&r" (tmp), "=m" (*p)
+               : "r" (p), "i" (_PAGE_BUSY)
+               : "cc");
+
+       if (pte_present(pte)) {
+               pte = pte_mkyoung(pte);
+               if (writing && pte_write(pte))
+                       pte = pte_mkdirty(pte);
+       }
+
+       *p = pte;       /* clears _PAGE_BUSY */
+
+       return pte;
+}
+
+/* Return HPTE cache control bits corresponding to Linux pte bits */
+static inline unsigned long hpte_cache_bits(unsigned long pte_val)
+{
+#if _PAGE_NO_CACHE == HPTE_R_I && _PAGE_WRITETHRU == HPTE_R_W
+       return pte_val & (HPTE_R_W | HPTE_R_I);
+#else
+       return ((pte_val & _PAGE_NO_CACHE) ? HPTE_R_I : 0) +
+               ((pte_val & _PAGE_WRITETHRU) ? HPTE_R_W : 0);
+#endif
+}
+
+static inline bool hpte_read_permission(unsigned long pp, unsigned long key)
+{
+       if (key)
+               return PP_RWRX <= pp && pp <= PP_RXRX;
+       return 1;
+}
+
+static inline bool hpte_write_permission(unsigned long pp, unsigned long key)
+{
+       if (key)
+               return pp == PP_RWRW;
+       return pp <= PP_RWRW;
+}
+
+static inline int hpte_get_skey_perm(unsigned long hpte_r, unsigned long amr)
+{
+       unsigned long skey;
+
+       skey = ((hpte_r & HPTE_R_KEY_HI) >> 57) |
+               ((hpte_r & HPTE_R_KEY_LO) >> 9);
+       return (amr >> (62 - 2 * skey)) & 3;
+}
+
+static inline void lock_rmap(unsigned long *rmap)
+{
+       do {
+               while (test_bit(KVMPPC_RMAP_LOCK_BIT, rmap))
+                       cpu_relax();
+       } while (test_and_set_bit_lock(KVMPPC_RMAP_LOCK_BIT, rmap));
+}
+
+static inline void unlock_rmap(unsigned long *rmap)
+{
+       __clear_bit_unlock(KVMPPC_RMAP_LOCK_BIT, rmap);
+}
+
+static inline bool slot_is_aligned(struct kvm_memory_slot *memslot,
+                                  unsigned long pagesize)
+{
+       unsigned long mask = (pagesize >> PAGE_SHIFT) - 1;
+
+       if (pagesize <= PAGE_SIZE)
+               return 1;
+       return !(memslot->base_gfn & mask) && !(memslot->npages & mask);
+}
+
 #endif /* __ASM_KVM_BOOK3S_64_H__ */
index adbfca9..8cd50a5 100644 (file)
 #define E500_PID_NUM   3
 #define E500_TLB_NUM   2
 
-struct tlbe{
-       u32 mas1;
-       u32 mas2;
-       u32 mas3;
-       u32 mas7;
-};
-
 #define E500_TLB_VALID 1
 #define E500_TLB_DIRTY 2
 
-struct tlbe_priv {
+struct tlbe_ref {
        pfn_t pfn;
        unsigned int flags; /* E500_TLB_* */
 };
 
+struct tlbe_priv {
+       struct tlbe_ref ref; /* TLB0 only -- TLB1 uses tlb_refs */
+};
+
 struct vcpu_id_table;
 
+struct kvmppc_e500_tlb_params {
+       int entries, ways, sets;
+};
+
 struct kvmppc_vcpu_e500 {
-       /* Unmodified copy of the guest's TLB. */
-       struct tlbe *gtlb_arch[E500_TLB_NUM];
+       /* Unmodified copy of the guest's TLB -- shared with host userspace. */
+       struct kvm_book3e_206_tlb_entry *gtlb_arch;
+
+       /* Starting entry number in gtlb_arch[] */
+       int gtlb_offset[E500_TLB_NUM];
 
        /* KVM internal information associated with each guest TLB entry */
        struct tlbe_priv *gtlb_priv[E500_TLB_NUM];
 
-       unsigned int gtlb_size[E500_TLB_NUM];
+       struct kvmppc_e500_tlb_params gtlb_params[E500_TLB_NUM];
+
        unsigned int gtlb_nv[E500_TLB_NUM];
 
+       /*
+        * information associated with each host TLB entry --
+        * TLB1 only for now.  If/when guest TLB1 entries can be
+        * mapped with host TLB0, this will be used for that too.
+        *
+        * We don't want to use this for guest TLB0 because then we'd
+        * have the overhead of doing the translation again even if
+        * the entry is still in the guest TLB (e.g. we swapped out
+        * and back, and our host TLB entries got evicted).
+        */
+       struct tlbe_ref *tlb_refs[E500_TLB_NUM];
+       unsigned int host_tlb1_nv;
+
        u32 host_pid[E500_PID_NUM];
        u32 pid[E500_PID_NUM];
        u32 svr;
 
-       u32 mas0;
-       u32 mas1;
-       u32 mas2;
-       u32 mas3;
-       u32 mas4;
-       u32 mas5;
-       u32 mas6;
-       u32 mas7;
-
        /* vcpu id table */
        struct vcpu_id_table *idt;
 
@@ -73,6 +82,9 @@ struct kvmppc_vcpu_e500 {
        u32 tlb1cfg;
        u64 mcar;
 
+       struct page **shared_tlb_pages;
+       int num_shared_tlb_pages;
+
        struct kvm_vcpu vcpu;
 };
 
index bf8af5d..52eb9c1 100644 (file)
 #include <linux/atomic.h>
 #include <asm/kvm_asm.h>
 #include <asm/processor.h>
+#include <asm/page.h>
 
 #define KVM_MAX_VCPUS          NR_CPUS
 #define KVM_MAX_VCORES         NR_CPUS
 #define KVM_MEMORY_SLOTS 32
 /* memory slots that does not exposed to userspace */
 #define KVM_PRIVATE_MEM_SLOTS 4
+#define KVM_MEM_SLOTS_NUM (KVM_MEMORY_SLOTS + KVM_PRIVATE_MEM_SLOTS)
 
 #ifdef CONFIG_KVM_MMIO
 #define KVM_COALESCED_MMIO_PAGE_OFFSET 1
 #endif
 
+#ifdef CONFIG_KVM_BOOK3S_64_HV
+#include <linux/mmu_notifier.h>
+
+#define KVM_ARCH_WANT_MMU_NOTIFIER
+
+struct kvm;
+extern int kvm_unmap_hva(struct kvm *kvm, unsigned long hva);
+extern int kvm_age_hva(struct kvm *kvm, unsigned long hva);
+extern int kvm_test_age_hva(struct kvm *kvm, unsigned long hva);
+extern void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte);
+
+#endif
+
 /* We don't currently support large pages. */
 #define KVM_HPAGE_GFN_SHIFT(x) 0
 #define KVM_NR_PAGE_SIZES      1
@@ -158,34 +173,72 @@ struct kvmppc_spapr_tce_table {
        struct page *pages[0];
 };
 
-struct kvmppc_rma_info {
+struct kvmppc_linear_info {
        void            *base_virt;
        unsigned long    base_pfn;
        unsigned long    npages;
        struct list_head list;
-       atomic_t         use_count;
+       atomic_t         use_count;
+       int              type;
+};
+
+/*
+ * The reverse mapping array has one entry for each HPTE,
+ * which stores the guest's view of the second word of the HPTE
+ * (including the guest physical address of the mapping),
+ * plus forward and backward pointers in a doubly-linked ring
+ * of HPTEs that map the same host page.  The pointers in this
+ * ring are 32-bit HPTE indexes, to save space.
+ */
+struct revmap_entry {
+       unsigned long guest_rpte;
+       unsigned int forw, back;
+};
+
+/*
+ * We use the top bit of each memslot->rmap entry as a lock bit,
+ * and bit 32 as a present flag.  The bottom 32 bits are the
+ * index in the guest HPT of a HPTE that points to the page.
+ */
+#define KVMPPC_RMAP_LOCK_BIT   63
+#define KVMPPC_RMAP_RC_SHIFT   32
+#define KVMPPC_RMAP_REFERENCED (HPTE_R_R << KVMPPC_RMAP_RC_SHIFT)
+#define KVMPPC_RMAP_CHANGED    (HPTE_R_C << KVMPPC_RMAP_RC_SHIFT)
+#define KVMPPC_RMAP_PRESENT    0x100000000ul
+#define KVMPPC_RMAP_INDEX      0xfffffffful
+
+/* Low-order bits in kvm->arch.slot_phys[][] */
+#define KVMPPC_PAGE_ORDER_MASK 0x1f
+#define KVMPPC_PAGE_NO_CACHE   HPTE_R_I        /* 0x20 */
+#define KVMPPC_PAGE_WRITETHRU  HPTE_R_W        /* 0x40 */
+#define KVMPPC_GOT_PAGE                0x80
+
+struct kvm_arch_memory_slot {
 };
 
 struct kvm_arch {
 #ifdef CONFIG_KVM_BOOK3S_64_HV
        unsigned long hpt_virt;
-       unsigned long ram_npages;
-       unsigned long ram_psize;
-       unsigned long ram_porder;
-       struct kvmppc_pginfo *ram_pginfo;
+       struct revmap_entry *revmap;
        unsigned int lpid;
        unsigned int host_lpid;
        unsigned long host_lpcr;
        unsigned long sdr1;
        unsigned long host_sdr1;
        int tlbie_lock;
-       int n_rma_pages;
        unsigned long lpcr;
        unsigned long rmor;
-       struct kvmppc_rma_info *rma;
+       struct kvmppc_linear_info *rma;
+       unsigned long vrma_slb_v;
+       int rma_setup_done;
+       int using_mmu_notifiers;
        struct list_head spapr_tce_tables;
+       spinlock_t slot_phys_lock;
+       unsigned long *slot_phys[KVM_MEM_SLOTS_NUM];
+       int slot_npages[KVM_MEM_SLOTS_NUM];
        unsigned short last_vcpu[NR_CPUS];
        struct kvmppc_vcore *vcores[KVM_MAX_VCORES];
+       struct kvmppc_linear_info *hpt_li;
 #endif /* CONFIG_KVM_BOOK3S_64_HV */
 };
 
@@ -318,10 +371,6 @@ struct kvm_vcpu_arch {
        u32 vrsave; /* also USPRG0 */
        u32 mmucr;
        ulong shadow_msr;
-       ulong sprg4;
-       ulong sprg5;
-       ulong sprg6;
-       ulong sprg7;
        ulong csrr0;
        ulong csrr1;
        ulong dsrr0;
@@ -329,16 +378,14 @@ struct kvm_vcpu_arch {
        ulong mcsrr0;
        ulong mcsrr1;
        ulong mcsr;
-       ulong esr;
        u32 dec;
        u32 decar;
        u32 tbl;
        u32 tbu;
        u32 tcr;
-       u32 tsr;
+       ulong tsr; /* we need to perform set/clr_bits() which requires ulong */
        u32 ivor[64];
        ulong ivpr;
-       u32 pir;
        u32 pvr;
 
        u32 shadow_pid;
@@ -427,9 +474,14 @@ struct kvm_vcpu_arch {
 #ifdef CONFIG_KVM_BOOK3S_64_HV
        struct kvm_vcpu_arch_shared shregs;
 
+       unsigned long pgfault_addr;
+       long pgfault_index;
+       unsigned long pgfault_hpte[2];
+
        struct list_head run_list;
        struct task_struct *run_task;
        struct kvm_run *kvm_run;
+       pgd_t *pgdir;
 #endif
 };
 
@@ -438,4 +490,12 @@ struct kvm_vcpu_arch {
 #define KVMPPC_VCPU_BUSY_IN_HOST       1
 #define KVMPPC_VCPU_RUNNABLE           2
 
+/* Values for vcpu->arch.io_gpr */
+#define KVM_MMIO_REG_MASK      0x001f
+#define KVM_MMIO_REG_EXT_MASK  0xffe0
+#define KVM_MMIO_REG_GPR       0x0000
+#define KVM_MMIO_REG_FPR       0x0020
+#define KVM_MMIO_REG_QPR       0x0040
+#define KVM_MMIO_REG_FQPR      0x0060
+
 #endif /* __POWERPC_KVM_HOST_H__ */
index 50533f9..7b754e7 100644 (file)
 
 #include <linux/types.h>
 
+/*
+ * Additions to this struct must only occur at the end, and should be
+ * accompanied by a KVM_MAGIC_FEAT flag to advertise that they are present
+ * (albeit not necessarily relevant to the current target hardware platform).
+ *
+ * Struct fields are always 32 or 64 bit aligned, depending on them being 32
+ * or 64 bit wide respectively.
+ *
+ * See Documentation/virtual/kvm/ppc-pv.txt
+ */
 struct kvm_vcpu_arch_shared {
        __u64 scratch1;
        __u64 scratch2;
@@ -33,11 +43,35 @@ struct kvm_vcpu_arch_shared {
        __u64 sprg3;
        __u64 srr0;
        __u64 srr1;
-       __u64 dar;
+       __u64 dar;              /* dear on BookE */
        __u64 msr;
        __u32 dsisr;
        __u32 int_pending;      /* Tells the guest if we have an interrupt */
        __u32 sr[16];
+       __u32 mas0;
+       __u32 mas1;
+       __u64 mas7_3;
+       __u64 mas2;
+       __u32 mas4;
+       __u32 mas6;
+       __u32 esr;
+       __u32 pir;
+
+       /*
+        * SPRG4-7 are user-readable, so we can only keep these consistent
+        * between the shared area and the real registers when there's an
+        * intervening exit to KVM.  This also applies to SPRG3 on some
+        * chips.
+        *
+        * This suffices for access by guest userspace, since in PR-mode
+        * KVM, an exit must occur when changing the guest's MSR[PR].
+        * If the guest kernel writes to SPRG3-7 via the shared area, it
+        * must also use the shared area for reading while in kernel space.
+        */
+       __u64 sprg4;
+       __u64 sprg5;
+       __u64 sprg6;
+       __u64 sprg7;
 };
 
 #define KVM_SC_MAGIC_R0                0x4b564d21 /* "KVM!" */
@@ -47,7 +81,10 @@ struct kvm_vcpu_arch_shared {
 
 #define KVM_FEATURE_MAGIC_PAGE 1
 
-#define KVM_MAGIC_FEAT_SR      (1 << 0)
+#define KVM_MAGIC_FEAT_SR              (1 << 0)
+
+/* MASn, ESR, PIR, and high SPRGs */
+#define KVM_MAGIC_FEAT_MAS0_TO_SPRG7   (1 << 1)
 
 #ifdef __KERNEL__
 
index 46efd1a..9d6dee0 100644 (file)
@@ -66,6 +66,7 @@ extern int kvmppc_emulate_instruction(struct kvm_run *run,
 extern int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu);
 extern void kvmppc_emulate_dec(struct kvm_vcpu *vcpu);
 extern u32 kvmppc_get_dec(struct kvm_vcpu *vcpu, u64 tb);
+extern void kvmppc_decrementer_func(unsigned long data);
 extern int kvmppc_sanity_check(struct kvm_vcpu *vcpu);
 
 /* Core-specific hooks */
@@ -94,7 +95,7 @@ extern int kvmppc_core_vcpu_translate(struct kvm_vcpu *vcpu,
 extern void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu);
 extern void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu);
 
-extern void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu);
+extern void kvmppc_core_prepare_to_enter(struct kvm_vcpu *vcpu);
 extern int kvmppc_core_pending_dec(struct kvm_vcpu *vcpu);
 extern void kvmppc_core_queue_program(struct kvm_vcpu *vcpu, ulong flags);
 extern void kvmppc_core_queue_dec(struct kvm_vcpu *vcpu);
@@ -120,15 +121,17 @@ extern long kvmppc_alloc_hpt(struct kvm *kvm);
 extern void kvmppc_free_hpt(struct kvm *kvm);
 extern long kvmppc_prepare_vrma(struct kvm *kvm,
                                struct kvm_userspace_memory_region *mem);
-extern void kvmppc_map_vrma(struct kvm *kvm,
-                           struct kvm_userspace_memory_region *mem);
+extern void kvmppc_map_vrma(struct kvm_vcpu *vcpu,
+                       struct kvm_memory_slot *memslot, unsigned long porder);
 extern int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu);
 extern long kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm,
                                struct kvm_create_spapr_tce *args);
 extern long kvm_vm_ioctl_allocate_rma(struct kvm *kvm,
                                struct kvm_allocate_rma *rma);
-extern struct kvmppc_rma_info *kvm_alloc_rma(void);
-extern void kvm_release_rma(struct kvmppc_rma_info *ri);
+extern struct kvmppc_linear_info *kvm_alloc_rma(void);
+extern void kvm_release_rma(struct kvmppc_linear_info *ri);
+extern struct kvmppc_linear_info *kvm_alloc_hpt(void);
+extern void kvm_release_hpt(struct kvmppc_linear_info *li);
 extern int kvmppc_core_init_vm(struct kvm *kvm);
 extern void kvmppc_core_destroy_vm(struct kvm *kvm);
 extern int kvmppc_core_prepare_memory_region(struct kvm *kvm,
@@ -175,6 +178,9 @@ int kvmppc_core_set_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs);
 void kvmppc_get_sregs_ivor(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs);
 int kvmppc_set_sregs_ivor(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs);
 
+int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg);
+int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg);
+
 void kvmppc_set_pid(struct kvm_vcpu *vcpu, u32 pid);
 
 #ifdef CONFIG_KVM_BOOK3S_64_HV
@@ -183,14 +189,19 @@ static inline void kvmppc_set_xics_phys(int cpu, unsigned long addr)
        paca[cpu].kvm_hstate.xics_phys = addr;
 }
 
-extern void kvm_rma_init(void);
+extern void kvm_linear_init(void);
 
 #else
 static inline void kvmppc_set_xics_phys(int cpu, unsigned long addr)
 {}
 
-static inline void kvm_rma_init(void)
+static inline void kvm_linear_init(void)
 {}
 #endif
 
+int kvm_vcpu_ioctl_config_tlb(struct kvm_vcpu *vcpu,
+                             struct kvm_config_tlb *cfg);
+int kvm_vcpu_ioctl_dirty_tlb(struct kvm_vcpu *vcpu,
+                            struct kvm_dirty_tlb *cfg);
+
 #endif /* __POWERPC_KVM_PPC_H__ */
index bf37931..42ce570 100644 (file)
@@ -99,9 +99,7 @@ struct machdep_calls {
 
        void            (*init_IRQ)(void);
 
-       /* Return an irq, or NO_IRQ to indicate there are none pending.
-        * If for some reason there is no irq, but the interrupt
-        * shouldn't be counted as spurious, return NO_IRQ_IGNORE. */
+       /* Return an irq, or NO_IRQ to indicate there are none pending. */
        unsigned int    (*get_irq)(void);
 
        /* PCI stuff */
index f5f89ca..cdb5421 100644 (file)
 /* MAS registers bit definitions */
 
 #define MAS0_TLBSEL(x)         (((x) << 28) & 0x30000000)
-#define MAS0_ESEL(x)           (((x) << 16) & 0x0FFF0000)
-#define MAS0_NV(x)             ((x) & 0x00000FFF)
 #define MAS0_ESEL_MASK         0x0FFF0000
+#define MAS0_ESEL_SHIFT                16
+#define MAS0_ESEL(x)           (((x) << MAS0_ESEL_SHIFT) & MAS0_ESEL_MASK)
+#define MAS0_NV(x)             ((x) & 0x00000FFF)
 #define MAS0_HES               0x00004000
 #define MAS0_WQ_ALLWAYS                0x00000000
 #define MAS0_WQ_COND           0x00001000
 #define TLBnCFG_MAXSIZE                0x000f0000      /* Maximum Page Size (v1.0) */
 #define TLBnCFG_MAXSIZE_SHIFT  16
 #define TLBnCFG_ASSOC          0xff000000      /* Associativity */
+#define TLBnCFG_ASSOC_SHIFT    24
 
 /* TLBnPS encoding */
 #define TLBnPS_4K              0x00000004
index 412ba49..1c65a59 100644 (file)
@@ -108,11 +108,11 @@ extern char initial_stab[];
 #define HPTE_V_VRMA_MASK       ASM_CONST(0x4001ffffff000000)
 
 /* Values for PP (assumes Ks=0, Kp=1) */
-/* pp0 will always be 0 for linux     */
 #define PP_RWXX        0       /* Supervisor read/write, User none */
 #define PP_RWRX 1      /* Supervisor read/write, User read */
 #define PP_RWRW 2      /* Supervisor read/write, User read/write */
 #define PP_RXRX 3      /* Supervisor read,       User read */
+#define PP_RXXX        (HPTE_R_PP0 | 2)        /* Supervisor read, user none */
 
 #ifndef __ASSEMBLY__
 
@@ -267,7 +267,6 @@ extern void demote_segment_4k(struct mm_struct *mm, unsigned long addr);
 
 extern void hpte_init_native(void);
 extern void hpte_init_lpar(void);
-extern void hpte_init_iSeries(void);
 extern void hpte_init_beat(void);
 extern void hpte_init_beat_v3(void);
 
@@ -325,9 +324,6 @@ extern void slb_set_size(u16 size);
  * WARNING - If you change these you must make sure the asm
  * implementations in slb_allocate (slb_low.S), do_stab_bolted
  * (head.S) and ASM_VSID_SCRAMBLE (below) are changed accordingly.
- *
- * You'll also need to change the precomputed VSID values in head.S
- * which are used by the iSeries firmware.
  */
 
 #define VSID_MULTIPLIER_256M   ASM_CONST(200730139)    /* 28-bit prime */
@@ -484,14 +480,6 @@ static inline unsigned long get_vsid(unsigned long context, unsigned long ea,
                             | (ea >> SID_SHIFT_1T), 1T);
 }
 
-/*
- * This is only used on legacy iSeries in lparmap.c,
- * hence the 256MB segment assumption.
- */
-#define VSID_SCRAMBLE(pvsid)   (((pvsid) * VSID_MULTIPLIER_256M) %     \
-                                VSID_MODULUS_256M)
-#define KERNEL_VSID(ea)                VSID_SCRAMBLE(GET_ESID(ea))
-
 #endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_POWERPC_MMU_HASH64_H_ */
index 5d48765..ac39e6a 100644 (file)
@@ -155,14 +155,7 @@ struct pci_dn {
 
        struct  pci_dev *pcidev;        /* back-pointer to the pci device */
 #ifdef CONFIG_EEH
-       int     class_code;             /* pci device class */
-       int     eeh_mode;               /* See eeh.h for possible EEH_MODEs */
-       int     eeh_config_addr;
-       int     eeh_pe_config_addr; /* new-style partition endpoint address */
-       int     eeh_check_count;        /* # times driver ignored error */
-       int     eeh_freeze_count;       /* # times this device froze up. */
-       int     eeh_false_positives;    /* # times this device reported #ff's */
-       u32     config_space[16];       /* saved PCI config space */
+       struct eeh_dev *edev;           /* eeh device */
 #endif
 #define IODA_INVALID_PE                (-1)
 #ifdef CONFIG_PPC_POWERNV
@@ -185,6 +178,13 @@ static inline int pci_device_from_OF_node(struct device_node *np,
        return 0;
 }
 
+#if defined(CONFIG_EEH)
+static inline struct eeh_dev *of_node_to_eeh_dev(struct device_node *dn)
+{
+       return PCI_DN(dn)->edev;
+}
+#endif
+
 /** Find the bus corresponding to the indicated device node */
 extern struct pci_bus *pcibios_find_pci_bus(struct device_node *dn);
 
index 1a8093f..078019b 100644 (file)
@@ -47,6 +47,8 @@ struct power_pmu {
  */
 #define PPMU_LIMITED_PMC5_6    1       /* PMC5/6 have limited function */
 #define PPMU_ALT_SIPR          2       /* uses alternate posn for SIPR/HV */
+#define PPMU_NO_SIPR           4       /* no SIPR/HV in MMCRA at all */
+#define PPMU_NO_CONT_SAMPLING  8       /* no continuous sampling */
 
 /*
  * Values for flags to get_alternatives()
index e980faa..d81f994 100644 (file)
@@ -45,6 +45,7 @@
 #define PPC_INST_MFSPR_DSCR_MASK       0xfc1fffff
 #define PPC_INST_MTSPR_DSCR            0x7c1103a6
 #define PPC_INST_MTSPR_DSCR_MASK       0xfc1fffff
+#define PPC_INST_SLBFEE                        0x7c0007a7
 
 #define PPC_INST_STRING                        0x7c00042a
 #define PPC_INST_STRING_MASK           0xfc0007fe
                                        __PPC_RS(t) | __PPC_RA(a) | __PPC_RB(b))
 #define PPC_ERATSX_DOT(t, a, w)        stringify_in_c(.long PPC_INST_ERATSX_DOT | \
                                        __PPC_RS(t) | __PPC_RA(a) | __PPC_RB(b))
-
+#define PPC_SLBFEE_DOT(t, b)   stringify_in_c(.long PPC_INST_SLBFEE | \
+                                       __PPC_RT(t) | __PPC_RB(b))
 
 /*
  * Define what the VSX XX1 form instructions will look like, then add
index b585bff..8e2d037 100644 (file)
@@ -385,6 +385,36 @@ static inline unsigned long get_clean_sp(struct pt_regs *regs, int is_32)
 extern unsigned long cpuidle_disable;
 enum idle_boot_override {IDLE_NO_OVERRIDE = 0, IDLE_POWERSAVE_OFF};
 
+extern int powersave_nap;      /* set if nap mode can be used in idle loop */
+void cpu_idle_wait(void);
+
+#ifdef CONFIG_PSERIES_IDLE
+extern void update_smt_snooze_delay(int snooze);
+extern int pseries_notify_cpuidle_add_cpu(int cpu);
+#else
+static inline void update_smt_snooze_delay(int snooze) {}
+static inline int pseries_notify_cpuidle_add_cpu(int cpu) { return 0; }
+#endif
+
+extern void flush_instruction_cache(void);
+extern void hard_reset_now(void);
+extern void poweroff_now(void);
+extern int fix_alignment(struct pt_regs *);
+extern void cvt_fd(float *from, double *to);
+extern void cvt_df(double *from, float *to);
+extern void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val);
+
+#ifdef CONFIG_PPC64
+/*
+ * We handle most unaligned accesses in hardware. On the other hand 
+ * unaligned DMA can be very expensive on some ppc64 IO chips (it does
+ * powers of 2 writes until it reaches sufficient alignment).
+ *
+ * Based on this we disable the IP header alignment in network drivers.
+ */
+#define NET_IP_ALIGN   0
+#endif
+
 #endif /* __KERNEL__ */
 #endif /* __ASSEMBLY__ */
 #endif /* _ASM_POWERPC_PROCESSOR_H */
index b1a215e..9d7f0fb 100644 (file)
 #define   DSISR_ISSTORE                0x02000000      /* access was a store */
 #define   DSISR_DABRMATCH      0x00400000      /* hit data breakpoint */
 #define   DSISR_NOSEGMENT      0x00200000      /* STAB/SLB miss */
+#define   DSISR_KEYFAULT       0x00200000      /* Key fault */
 #define SPRN_TBRL      0x10C   /* Time Base Read Lower Register (user, R/O) */
 #define SPRN_TBRU      0x10D   /* Time Base Read Upper Register (user, R/O) */
 #define SPRN_TBWL      0x11C   /* Time Base Lower Register (super, R/W) */
 #define   LPCR_ISL     (1ul << (63-2))
 #define   LPCR_VC_SH   (63-2)
 #define   LPCR_DPFD_SH (63-11)
+#define   LPCR_VRMASD  (0x1ful << (63-16))
 #define   LPCR_VRMA_L  (1ul << (63-12))
 #define   LPCR_VRMA_LP0        (1ul << (63-15))
 #define   LPCR_VRMA_LP1        (1ul << (63-16))
 #define SPRN_SPRG7     0x117   /* Special Purpose Register General 7 */
 #define SPRN_SRR0      0x01A   /* Save/Restore Register 0 */
 #define SPRN_SRR1      0x01B   /* Save/Restore Register 1 */
+#define   SRR1_ISI_NOPT                0x40000000 /* ISI: Not found in hash */
+#define   SRR1_ISI_N_OR_G      0x10000000 /* ISI: Access is no-exec or G */
+#define   SRR1_ISI_PROT                0x08000000 /* ISI: Other protection fault */
 #define   SRR1_WAKEMASK                0x00380000 /* reason for wakeup */
 #define   SRR1_WAKESYSERR      0x00300000 /* System error */
 #define   SRR1_WAKEEE          0x00200000 /* External interrupt */
index 8a97aa7..b86faa9 100644 (file)
 #ifndef __ASM_POWERPC_REG_BOOKE_H__
 #define __ASM_POWERPC_REG_BOOKE_H__
 
+#ifdef CONFIG_BOOKE_WDT
+extern u32 booke_wdt_enabled;
+extern u32 booke_wdt_period;
+#endif /* CONFIG_BOOKE_WDT */
+
 /* Machine State Register (MSR) Fields */
 #define MSR_GS         (1<<28) /* Guest state */
 #define MSR_UCLE       (1<<26) /* User-mode cache lock enable */
index 01c143b..557cff8 100644 (file)
@@ -74,7 +74,6 @@ struct rtas_suspend_me_data {
 /* RTAS event classes */
 #define RTAS_INTERNAL_ERROR            0x80000000 /* set bit 0 */
 #define RTAS_EPOW_WARNING              0x40000000 /* set bit 1 */
-#define RTAS_POWERMGM_EVENTS           0x20000000 /* set bit 2 */
 #define RTAS_HOTPLUG_EVENTS            0x10000000 /* set bit 3 */
 #define RTAS_IO_EVENTS                 0x08000000 /* set bit 4 */
 #define RTAS_EVENT_SCAN_ALL_EVENTS     0xffffffff
@@ -204,6 +203,39 @@ struct rtas_ext_event_log_v6 {
                                        /* Variable length.             */
 };
 
+/* pSeries event log format */
+
+/* Two bytes ASCII section IDs */
+#define PSERIES_ELOG_SECT_ID_PRIV_HDR          (('P' << 8) | 'H')
+#define PSERIES_ELOG_SECT_ID_USER_HDR          (('U' << 8) | 'H')
+#define PSERIES_ELOG_SECT_ID_PRIMARY_SRC       (('P' << 8) | 'S')
+#define PSERIES_ELOG_SECT_ID_EXTENDED_UH       (('E' << 8) | 'H')
+#define PSERIES_ELOG_SECT_ID_FAILING_MTMS      (('M' << 8) | 'T')
+#define PSERIES_ELOG_SECT_ID_SECONDARY_SRC     (('S' << 8) | 'S')
+#define PSERIES_ELOG_SECT_ID_DUMP_LOCATOR      (('D' << 8) | 'H')
+#define PSERIES_ELOG_SECT_ID_FW_ERROR          (('S' << 8) | 'W')
+#define PSERIES_ELOG_SECT_ID_IMPACT_PART_ID    (('L' << 8) | 'P')
+#define PSERIES_ELOG_SECT_ID_LOGIC_RESOURCE_ID (('L' << 8) | 'R')
+#define PSERIES_ELOG_SECT_ID_HMC_ID            (('H' << 8) | 'M')
+#define PSERIES_ELOG_SECT_ID_EPOW              (('E' << 8) | 'P')
+#define PSERIES_ELOG_SECT_ID_IO_EVENT          (('I' << 8) | 'E')
+#define PSERIES_ELOG_SECT_ID_MANUFACT_INFO     (('M' << 8) | 'I')
+#define PSERIES_ELOG_SECT_ID_CALL_HOME         (('C' << 8) | 'H')
+#define PSERIES_ELOG_SECT_ID_USER_DEF          (('U' << 8) | 'D')
+
+/* Vendor specific Platform Event Log Format, Version 6, section header */
+struct pseries_errorlog {
+       uint16_t id;                    /* 0x00 2-byte ASCII section ID */
+       uint16_t length;                /* 0x02 Section length in bytes */
+       uint8_t version;                /* 0x04 Section version         */
+       uint8_t subtype;                /* 0x05 Section subtype         */
+       uint16_t creator_component;     /* 0x06 Creator component ID    */
+       uint8_t data[];                 /* 0x08 Start of section data   */
+};
+
+struct pseries_errorlog *get_pseries_errorlog(struct rtas_error_log *log,
+                                             uint16_t section_id);
+
 /*
  * This can be set by the rtas_flash module so that it can get called
  * as the absolutely last thing before the kernel terminates.
@@ -325,5 +357,7 @@ static inline int page_is_rtas_user_buf(unsigned long pfn)
 static inline int page_is_rtas_user_buf(unsigned long pfn) { return 0;}
 #endif
 
+extern int call_rtas(const char *, int, int, unsigned long *, ...);
+
 #endif /* __KERNEL__ */
 #endif /* _POWERPC_RTAS_H */
diff --git a/arch/powerpc/include/asm/runlatch.h b/arch/powerpc/include/asm/runlatch.h
new file mode 100644 (file)
index 0000000..54e9b96
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu>
+ */
+#ifndef _ASM_POWERPC_RUNLATCH_H
+#define _ASM_POWERPC_RUNLATCH_H
+
+#ifdef CONFIG_PPC64
+
+extern void __ppc64_runlatch_on(void);
+extern void __ppc64_runlatch_off(void);
+
+/*
+ * We manually hard enable-disable, this is called
+ * in the idle loop and we don't want to mess up
+ * with soft-disable/enable & interrupt replay.
+ */
+#define ppc64_runlatch_off()                                   \
+       do {                                                    \
+               if (cpu_has_feature(CPU_FTR_CTRL) &&            \
+                   test_thread_local_flags(_TLF_RUNLATCH)) {   \
+                       unsigned long msr = mfmsr();            \
+                       __hard_irq_disable();                   \
+                       __ppc64_runlatch_off();                 \
+                       if (msr & MSR_EE)                       \
+                               __hard_irq_enable();            \
+               }                                               \
+       } while (0)
+
+#define ppc64_runlatch_on()                                    \
+       do {                                                    \
+               if (cpu_has_feature(CPU_FTR_CTRL) &&            \
+                   !test_thread_local_flags(_TLF_RUNLATCH)) {  \
+                       unsigned long msr = mfmsr();            \
+                       __hard_irq_disable();                   \
+                       __ppc64_runlatch_on();                  \
+                       if (msr & MSR_EE)                       \
+                               __hard_irq_enable();            \
+               }                                               \
+       } while (0)
+#else
+#define ppc64_runlatch_on()
+#define ppc64_runlatch_off()
+#endif /* CONFIG_PPC64 */
+
+#endif /* _ASM_POWERPC_RUNLATCH_H */
index 186e0fb..d084ce1 100644 (file)
@@ -5,6 +5,28 @@
 
 #ifndef __ASSEMBLY__
 extern void ppc_printk_progress(char *s, unsigned short hex);
-#endif
+
+extern unsigned int rtas_data;
+extern int mem_init_done;      /* set on boot once kmalloc can be called */
+extern int init_bootmem_done;  /* set once bootmem is available */
+extern phys_addr_t memory_limit;
+extern unsigned long klimit;
+extern void *zalloc_maybe_bootmem(size_t size, gfp_t mask);
+
+extern void via_cuda_init(void);
+extern void read_rtc_time(void);
+extern void pmac_find_display(void);
+
+struct device_node;
+extern void note_scsi_host(struct device_node *, void *);
+
+/* Used in very early kernel initialization. */
+extern unsigned long reloc_offset(void);
+extern unsigned long add_reloc_offset(unsigned long);
+extern void reloc_got2(unsigned long);
+
+#define PTRRELOC(x)    ((typeof(x)) add_reloc_offset((unsigned long)(x)))
+
+#endif /* !__ASSEMBLY__ */
 
 #endif /* _ASM_POWERPC_SETUP_H */
index adba970..ebc24dc 100644 (file)
@@ -122,7 +122,6 @@ extern void smp_muxed_ipi_set_data(int cpu, unsigned long data);
 extern void smp_muxed_ipi_message_pass(int cpu, int msg);
 extern irqreturn_t smp_ipi_demux(void);
 
-void smp_init_iSeries(void);
 void smp_init_pSeries(void);
 void smp_init_cell(void);
 void smp_init_celleb(void);
diff --git a/arch/powerpc/include/asm/switch_to.h b/arch/powerpc/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..caf82d0
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu>
+ */
+#ifndef _ASM_POWERPC_SWITCH_TO_H
+#define _ASM_POWERPC_SWITCH_TO_H
+
+struct thread_struct;
+struct task_struct;
+struct pt_regs;
+
+extern struct task_struct *__switch_to(struct task_struct *,
+       struct task_struct *);
+#define switch_to(prev, next, last)    ((last) = __switch_to((prev), (next)))
+
+struct thread_struct;
+extern struct task_struct *_switch(struct thread_struct *prev,
+                                  struct thread_struct *next);
+
+extern void giveup_fpu(struct task_struct *);
+extern void disable_kernel_fp(void);
+extern void enable_kernel_fp(void);
+extern void flush_fp_to_thread(struct task_struct *);
+extern void enable_kernel_altivec(void);
+extern void giveup_altivec(struct task_struct *);
+extern void load_up_altivec(struct task_struct *);
+extern int emulate_altivec(struct pt_regs *);
+extern void __giveup_vsx(struct task_struct *);
+extern void giveup_vsx(struct task_struct *);
+extern void enable_kernel_spe(void);
+extern void giveup_spe(struct task_struct *);
+extern void load_up_spe(struct task_struct *);
+
+#ifndef CONFIG_SMP
+extern void discard_lazy_cpu_state(void);
+#else
+static inline void discard_lazy_cpu_state(void)
+{
+}
+#endif
+
+#ifdef CONFIG_ALTIVEC
+extern void flush_altivec_to_thread(struct task_struct *);
+#else
+static inline void flush_altivec_to_thread(struct task_struct *t)
+{
+}
+#endif
+
+#ifdef CONFIG_VSX
+extern void flush_vsx_to_thread(struct task_struct *);
+#else
+static inline void flush_vsx_to_thread(struct task_struct *t)
+{
+}
+#endif
+
+#ifdef CONFIG_SPE
+extern void flush_spe_to_thread(struct task_struct *);
+#else
+static inline void flush_spe_to_thread(struct task_struct *t)
+{
+}
+#endif
+
+#endif /* _ASM_POWERPC_SWITCH_TO_H */
diff --git a/arch/powerpc/include/asm/system.h b/arch/powerpc/include/asm/system.h
deleted file mode 100644 (file)
index a02883d..0000000
+++ /dev/null
@@ -1,592 +0,0 @@
-/*
- * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu>
- */
-#ifndef _ASM_POWERPC_SYSTEM_H
-#define _ASM_POWERPC_SYSTEM_H
-
-#include <linux/kernel.h>
-#include <linux/irqflags.h>
-
-#include <asm/hw_irq.h>
-
-/*
- * Memory barrier.
- * The sync instruction guarantees that all memory accesses initiated
- * by this processor have been performed (with respect to all other
- * mechanisms that access memory).  The eieio instruction is a barrier
- * providing an ordering (separately) for (a) cacheable stores and (b)
- * loads and stores to non-cacheable memory (e.g. I/O devices).
- *
- * mb() prevents loads and stores being reordered across this point.
- * rmb() prevents loads being reordered across this point.
- * wmb() prevents stores being reordered across this point.
- * read_barrier_depends() prevents data-dependent loads being reordered
- *     across this point (nop on PPC).
- *
- * *mb() variants without smp_ prefix must order all types of memory
- * operations with one another. sync is the only instruction sufficient
- * to do this.
- *
- * For the smp_ barriers, ordering is for cacheable memory operations
- * only. We have to use the sync instruction for smp_mb(), since lwsync
- * doesn't order loads with respect to previous stores.  Lwsync can be
- * used for smp_rmb() and smp_wmb().
- *
- * However, on CPUs that don't support lwsync, lwsync actually maps to a
- * heavy-weight sync, so smp_wmb() can be a lighter-weight eieio.
- */
-#define mb()   __asm__ __volatile__ ("sync" : : : "memory")
-#define rmb()  __asm__ __volatile__ ("sync" : : : "memory")
-#define wmb()  __asm__ __volatile__ ("sync" : : : "memory")
-#define read_barrier_depends()  do { } while(0)
-
-#define set_mb(var, value)     do { var = value; mb(); } while (0)
-
-#ifdef __KERNEL__
-#define AT_VECTOR_SIZE_ARCH 6 /* entries in ARCH_DLINFO */
-#ifdef CONFIG_SMP
-
-#ifdef __SUBARCH_HAS_LWSYNC
-#    define SMPWMB      LWSYNC
-#else
-#    define SMPWMB      eieio
-#endif
-
-#define smp_mb()       mb()
-#define smp_rmb()      __asm__ __volatile__ (stringify_in_c(LWSYNC) : : :"memory")
-#define smp_wmb()      __asm__ __volatile__ (stringify_in_c(SMPWMB) : : :"memory")
-#define smp_read_barrier_depends()     read_barrier_depends()
-#else
-#define smp_mb()       barrier()
-#define smp_rmb()      barrier()
-#define smp_wmb()      barrier()
-#define smp_read_barrier_depends()     do { } while(0)
-#endif /* CONFIG_SMP */
-
-/*
- * This is a barrier which prevents following instructions from being
- * started until the value of the argument x is known.  For example, if
- * x is a variable loaded from memory, this prevents following
- * instructions from being executed until the load has been performed.
- */
-#define data_barrier(x)        \
-       asm volatile("twi 0,%0,0; isync" : : "r" (x) : "memory");
-
-struct task_struct;
-struct pt_regs;
-
-#if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC)
-
-extern int (*__debugger)(struct pt_regs *regs);
-extern int (*__debugger_ipi)(struct pt_regs *regs);
-extern int (*__debugger_bpt)(struct pt_regs *regs);
-extern int (*__debugger_sstep)(struct pt_regs *regs);
-extern int (*__debugger_iabr_match)(struct pt_regs *regs);
-extern int (*__debugger_dabr_match)(struct pt_regs *regs);
-extern int (*__debugger_fault_handler)(struct pt_regs *regs);
-
-#define DEBUGGER_BOILERPLATE(__NAME) \
-static inline int __NAME(struct pt_regs *regs) \
-{ \
-       if (unlikely(__ ## __NAME)) \
-               return __ ## __NAME(regs); \
-       return 0; \
-}
-
-DEBUGGER_BOILERPLATE(debugger)
-DEBUGGER_BOILERPLATE(debugger_ipi)
-DEBUGGER_BOILERPLATE(debugger_bpt)
-DEBUGGER_BOILERPLATE(debugger_sstep)
-DEBUGGER_BOILERPLATE(debugger_iabr_match)
-DEBUGGER_BOILERPLATE(debugger_dabr_match)
-DEBUGGER_BOILERPLATE(debugger_fault_handler)
-
-#else
-static inline int debugger(struct pt_regs *regs) { return 0; }
-static inline int debugger_ipi(struct pt_regs *regs) { return 0; }
-static inline int debugger_bpt(struct pt_regs *regs) { return 0; }
-static inline int debugger_sstep(struct pt_regs *regs) { return 0; }
-static inline int debugger_iabr_match(struct pt_regs *regs) { return 0; }
-static inline int debugger_dabr_match(struct pt_regs *regs) { return 0; }
-static inline int debugger_fault_handler(struct pt_regs *regs) { return 0; }
-#endif
-
-extern int set_dabr(unsigned long dabr);
-#ifdef CONFIG_PPC_ADV_DEBUG_REGS
-extern void do_send_trap(struct pt_regs *regs, unsigned long address,
-                        unsigned long error_code, int signal_code, int brkpt);
-#else
-extern void do_dabr(struct pt_regs *regs, unsigned long address,
-                   unsigned long error_code);
-#endif
-extern void print_backtrace(unsigned long *);
-extern void flush_instruction_cache(void);
-extern void hard_reset_now(void);
-extern void poweroff_now(void);
-
-#ifdef CONFIG_6xx
-extern long _get_L2CR(void);
-extern long _get_L3CR(void);
-extern void _set_L2CR(unsigned long);
-extern void _set_L3CR(unsigned long);
-#else
-#define _get_L2CR()    0L
-#define _get_L3CR()    0L
-#define _set_L2CR(val) do { } while(0)
-#define _set_L3CR(val) do { } while(0)
-#endif
-
-extern void via_cuda_init(void);
-extern void read_rtc_time(void);
-extern void pmac_find_display(void);
-extern void giveup_fpu(struct task_struct *);
-extern void disable_kernel_fp(void);
-extern void enable_kernel_fp(void);
-extern void flush_fp_to_thread(struct task_struct *);
-extern void enable_kernel_altivec(void);
-extern void giveup_altivec(struct task_struct *);
-extern void load_up_altivec(struct task_struct *);
-extern int emulate_altivec(struct pt_regs *);
-extern void __giveup_vsx(struct task_struct *);
-extern void giveup_vsx(struct task_struct *);
-extern void enable_kernel_spe(void);
-extern void giveup_spe(struct task_struct *);
-extern void load_up_spe(struct task_struct *);
-extern int fix_alignment(struct pt_regs *);
-extern void cvt_fd(float *from, double *to);
-extern void cvt_df(double *from, float *to);
-
-#ifndef CONFIG_SMP
-extern void discard_lazy_cpu_state(void);
-#else
-static inline void discard_lazy_cpu_state(void)
-{
-}
-#endif
-
-#ifdef CONFIG_ALTIVEC
-extern void flush_altivec_to_thread(struct task_struct *);
-#else
-static inline void flush_altivec_to_thread(struct task_struct *t)
-{
-}
-#endif
-
-#ifdef CONFIG_VSX
-extern void flush_vsx_to_thread(struct task_struct *);
-#else
-static inline void flush_vsx_to_thread(struct task_struct *t)
-{
-}
-#endif
-
-#ifdef CONFIG_SPE
-extern void flush_spe_to_thread(struct task_struct *);
-#else
-static inline void flush_spe_to_thread(struct task_struct *t)
-{
-}
-#endif
-
-extern int call_rtas(const char *, int, int, unsigned long *, ...);
-extern void cacheable_memzero(void *p, unsigned int nb);
-extern void *cacheable_memcpy(void *, const void *, unsigned int);
-extern int do_page_fault(struct pt_regs *, unsigned long, unsigned long);
-extern void bad_page_fault(struct pt_regs *, unsigned long, int);
-extern void _exception(int, struct pt_regs *, int, unsigned long);
-extern void die(const char *, struct pt_regs *, long);
-extern void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val);
-
-#ifdef CONFIG_BOOKE_WDT
-extern u32 booke_wdt_enabled;
-extern u32 booke_wdt_period;
-#endif /* CONFIG_BOOKE_WDT */
-
-struct device_node;
-extern void note_scsi_host(struct device_node *, void *);
-
-extern struct task_struct *__switch_to(struct task_struct *,
-       struct task_struct *);
-#define switch_to(prev, next, last)    ((last) = __switch_to((prev), (next)))
-
-struct thread_struct;
-extern struct task_struct *_switch(struct thread_struct *prev,
-                                  struct thread_struct *next);
-
-extern unsigned int rtas_data;
-extern int mem_init_done;      /* set on boot once kmalloc can be called */
-extern int init_bootmem_done;  /* set once bootmem is available */
-extern phys_addr_t memory_limit;
-extern unsigned long klimit;
-extern void *zalloc_maybe_bootmem(size_t size, gfp_t mask);
-
-extern int powersave_nap;      /* set if nap mode can be used in idle loop */
-void cpu_idle_wait(void);
-
-#ifdef CONFIG_PSERIES_IDLE
-extern void update_smt_snooze_delay(int snooze);
-extern int pseries_notify_cpuidle_add_cpu(int cpu);
-#else
-static inline void update_smt_snooze_delay(int snooze) {}
-static inline int pseries_notify_cpuidle_add_cpu(int cpu) { return 0; }
-#endif
-
-/*
- * Atomic exchange
- *
- * Changes the memory location '*ptr' to be val and returns
- * the previous value stored there.
- */
-static __always_inline unsigned long
-__xchg_u32(volatile void *p, unsigned long val)
-{
-       unsigned long prev;
-
-       __asm__ __volatile__(
-       PPC_RELEASE_BARRIER
-"1:    lwarx   %0,0,%2 \n"
-       PPC405_ERR77(0,%2)
-"      stwcx.  %3,0,%2 \n\
-       bne-    1b"
-       PPC_ACQUIRE_BARRIER
-       : "=&r" (prev), "+m" (*(volatile unsigned int *)p)
-       : "r" (p), "r" (val)
-       : "cc", "memory");
-
-       return prev;
-}
-
-/*
- * Atomic exchange
- *
- * Changes the memory location '*ptr' to be val and returns
- * the previous value stored there.
- */
-static __always_inline unsigned long
-__xchg_u32_local(volatile void *p, unsigned long val)
-{
-       unsigned long prev;
-
-       __asm__ __volatile__(
-"1:    lwarx   %0,0,%2 \n"
-       PPC405_ERR77(0,%2)
-"      stwcx.  %3,0,%2 \n\
-       bne-    1b"
-       : "=&r" (prev), "+m" (*(volatile unsigned int *)p)
-       : "r" (p), "r" (val)
-       : "cc", "memory");
-
-       return prev;
-}
-
-#ifdef CONFIG_PPC64
-static __always_inline unsigned long
-__xchg_u64(volatile void *p, unsigned long val)
-{
-       unsigned long prev;
-
-       __asm__ __volatile__(
-       PPC_RELEASE_BARRIER
-"1:    ldarx   %0,0,%2 \n"
-       PPC405_ERR77(0,%2)
-"      stdcx.  %3,0,%2 \n\
-       bne-    1b"
-       PPC_ACQUIRE_BARRIER
-       : "=&r" (prev), "+m" (*(volatile unsigned long *)p)
-       : "r" (p), "r" (val)
-       : "cc", "memory");
-
-       return prev;
-}
-
-static __always_inline unsigned long
-__xchg_u64_local(volatile void *p, unsigned long val)
-{
-       unsigned long prev;
-
-       __asm__ __volatile__(
-"1:    ldarx   %0,0,%2 \n"
-       PPC405_ERR77(0,%2)
-"      stdcx.  %3,0,%2 \n\
-       bne-    1b"
-       : "=&r" (prev), "+m" (*(volatile unsigned long *)p)
-       : "r" (p), "r" (val)
-       : "cc", "memory");
-
-       return prev;
-}
-#endif
-
-/*
- * This function doesn't exist, so you'll get a linker error
- * if something tries to do an invalid xchg().
- */
-extern void __xchg_called_with_bad_pointer(void);
-
-static __always_inline unsigned long
-__xchg(volatile void *ptr, unsigned long x, unsigned int size)
-{
-       switch (size) {
-       case 4:
-               return __xchg_u32(ptr, x);
-#ifdef CONFIG_PPC64
-       case 8:
-               return __xchg_u64(ptr, x);
-#endif
-       }
-       __xchg_called_with_bad_pointer();
-       return x;
-}
-
-static __always_inline unsigned long
-__xchg_local(volatile void *ptr, unsigned long x, unsigned int size)
-{
-       switch (size) {
-       case 4:
-               return __xchg_u32_local(ptr, x);
-#ifdef CONFIG_PPC64
-       case 8:
-               return __xchg_u64_local(ptr, x);
-#endif
-       }
-       __xchg_called_with_bad_pointer();
-       return x;
-}
-#define xchg(ptr,x)                                                         \
-  ({                                                                        \
-     __typeof__(*(ptr)) _x_ = (x);                                          \
-     (__typeof__(*(ptr))) __xchg((ptr), (unsigned long)_x_, sizeof(*(ptr))); \
-  })
-
-#define xchg_local(ptr,x)                                                   \
-  ({                                                                        \
-     __typeof__(*(ptr)) _x_ = (x);                                          \
-     (__typeof__(*(ptr))) __xchg_local((ptr),                               \
-               (unsigned long)_x_, sizeof(*(ptr)));                         \
-  })
-
-/*
- * Compare and exchange - if *p == old, set it to new,
- * and return the old value of *p.
- */
-#define __HAVE_ARCH_CMPXCHG    1
-
-static __always_inline unsigned long
-__cmpxchg_u32(volatile unsigned int *p, unsigned long old, unsigned long new)
-{
-       unsigned int prev;
-
-       __asm__ __volatile__ (
-       PPC_RELEASE_BARRIER
-"1:    lwarx   %0,0,%2         # __cmpxchg_u32\n\
-       cmpw    0,%0,%3\n\
-       bne-    2f\n"
-       PPC405_ERR77(0,%2)
-"      stwcx.  %4,0,%2\n\
-       bne-    1b"
-       PPC_ACQUIRE_BARRIER
-       "\n\
-2:"
-       : "=&r" (prev), "+m" (*p)
-       : "r" (p), "r" (old), "r" (new)
-       : "cc", "memory");
-
-       return prev;
-}
-
-static __always_inline unsigned long
-__cmpxchg_u32_local(volatile unsigned int *p, unsigned long old,
-                       unsigned long new)
-{
-       unsigned int prev;
-
-       __asm__ __volatile__ (
-"1:    lwarx   %0,0,%2         # __cmpxchg_u32\n\
-       cmpw    0,%0,%3\n\
-       bne-    2f\n"
-       PPC405_ERR77(0,%2)
-"      stwcx.  %4,0,%2\n\
-       bne-    1b"
-       "\n\
-2:"
-       : "=&r" (prev), "+m" (*p)
-       : "r" (p), "r" (old), "r" (new)
-       : "cc", "memory");
-
-       return prev;
-}
-
-#ifdef CONFIG_PPC64
-static __always_inline unsigned long
-__cmpxchg_u64(volatile unsigned long *p, unsigned long old, unsigned long new)
-{
-       unsigned long prev;
-
-       __asm__ __volatile__ (
-       PPC_RELEASE_BARRIER
-"1:    ldarx   %0,0,%2         # __cmpxchg_u64\n\
-       cmpd    0,%0,%3\n\
-       bne-    2f\n\
-       stdcx.  %4,0,%2\n\
-       bne-    1b"
-       PPC_ACQUIRE_BARRIER
-       "\n\
-2:"
-       : "=&r" (prev), "+m" (*p)
-       : "r" (p), "r" (old), "r" (new)
-       : "cc", "memory");
-
-       return prev;
-}
-
-static __always_inline unsigned long
-__cmpxchg_u64_local(volatile unsigned long *p, unsigned long old,
-                       unsigned long new)
-{
-       unsigned long prev;
-
-       __asm__ __volatile__ (
-"1:    ldarx   %0,0,%2         # __cmpxchg_u64\n\
-       cmpd    0,%0,%3\n\
-       bne-    2f\n\
-       stdcx.  %4,0,%2\n\
-       bne-    1b"
-       "\n\
-2:"
-       : "=&r" (prev), "+m" (*p)
-       : "r" (p), "r" (old), "r" (new)
-       : "cc", "memory");
-
-       return prev;
-}
-#endif
-
-/* This function doesn't exist, so you'll get a linker error
-   if something tries to do an invalid cmpxchg().  */
-extern void __cmpxchg_called_with_bad_pointer(void);
-
-static __always_inline unsigned long
-__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new,
-         unsigned int size)
-{
-       switch (size) {
-       case 4:
-               return __cmpxchg_u32(ptr, old, new);
-#ifdef CONFIG_PPC64
-       case 8:
-               return __cmpxchg_u64(ptr, old, new);
-#endif
-       }
-       __cmpxchg_called_with_bad_pointer();
-       return old;
-}
-
-static __always_inline unsigned long
-__cmpxchg_local(volatile void *ptr, unsigned long old, unsigned long new,
-         unsigned int size)
-{
-       switch (size) {
-       case 4:
-               return __cmpxchg_u32_local(ptr, old, new);
-#ifdef CONFIG_PPC64
-       case 8:
-               return __cmpxchg_u64_local(ptr, old, new);
-#endif
-       }
-       __cmpxchg_called_with_bad_pointer();
-       return old;
-}
-
-#define cmpxchg(ptr, o, n)                                              \
-  ({                                                                    \
-     __typeof__(*(ptr)) _o_ = (o);                                      \
-     __typeof__(*(ptr)) _n_ = (n);                                      \
-     (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,          \
-                                   (unsigned long)_n_, sizeof(*(ptr))); \
-  })
-
-
-#define cmpxchg_local(ptr, o, n)                                        \
-  ({                                                                    \
-     __typeof__(*(ptr)) _o_ = (o);                                      \
-     __typeof__(*(ptr)) _n_ = (n);                                      \
-     (__typeof__(*(ptr))) __cmpxchg_local((ptr), (unsigned long)_o_,    \
-                                   (unsigned long)_n_, sizeof(*(ptr))); \
-  })
-
-#ifdef CONFIG_PPC64
-/*
- * We handle most unaligned accesses in hardware. On the other hand 
- * unaligned DMA can be very expensive on some ppc64 IO chips (it does
- * powers of 2 writes until it reaches sufficient alignment).
- *
- * Based on this we disable the IP header alignment in network drivers.
- */
-#define NET_IP_ALIGN   0
-
-#define cmpxchg64(ptr, o, n)                                           \
-  ({                                                                   \
-       BUILD_BUG_ON(sizeof(*(ptr)) != 8);                              \
-       cmpxchg((ptr), (o), (n));                                       \
-  })
-#define cmpxchg64_local(ptr, o, n)                                     \
-  ({                                                                   \
-       BUILD_BUG_ON(sizeof(*(ptr)) != 8);                              \
-       cmpxchg_local((ptr), (o), (n));                                 \
-  })
-#else
-#include <asm-generic/cmpxchg-local.h>
-#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
-#endif
-
-extern unsigned long arch_align_stack(unsigned long sp);
-
-/* Used in very early kernel initialization. */
-extern unsigned long reloc_offset(void);
-extern unsigned long add_reloc_offset(unsigned long);
-extern void reloc_got2(unsigned long);
-
-#define PTRRELOC(x)    ((typeof(x)) add_reloc_offset((unsigned long)(x)))
-
-extern struct dentry *powerpc_debugfs_root;
-
-#ifdef CONFIG_PPC64
-
-extern void __ppc64_runlatch_on(void);
-extern void __ppc64_runlatch_off(void);
-
-/*
- * We manually hard enable-disable, this is called
- * in the idle loop and we don't want to mess up
- * with soft-disable/enable & interrupt replay.
- */
-#define ppc64_runlatch_off()                                   \
-       do {                                                    \
-               if (cpu_has_feature(CPU_FTR_CTRL) &&            \
-                   test_thread_local_flags(_TLF_RUNLATCH)) {   \
-                       unsigned long msr = mfmsr();            \
-                       __hard_irq_disable();                   \
-                       __ppc64_runlatch_off();                 \
-                       if (msr & MSR_EE)                       \
-                               __hard_irq_enable();            \
-               }                                               \
-       } while (0)
-
-#define ppc64_runlatch_on()                                    \
-       do {                                                    \
-               if (cpu_has_feature(CPU_FTR_CTRL) &&            \
-                   !test_thread_local_flags(_TLF_RUNLATCH)) {  \
-                       unsigned long msr = mfmsr();            \
-                       __hard_irq_disable();                   \
-                       __ppc64_runlatch_on();                  \
-                       if (msr & MSR_EE)                       \
-                               __hard_irq_enable();            \
-               }                                               \
-       } while (0)
-#else
-#define ppc64_runlatch_on()
-#define ppc64_runlatch_off()
-#endif /* CONFIG_PPC64 */
-
-#endif /* __KERNEL__ */
-#endif /* _ASM_POWERPC_SYSTEM_H */
index 8338aef..b303881 100644 (file)
@@ -44,7 +44,6 @@ extern void __init udbg_init_debug_lpar_hvsi(void);
 extern void __init udbg_init_pmac_realmode(void);
 extern void __init udbg_init_maple_realmode(void);
 extern void __init udbg_init_pas_realmode(void);
-extern void __init udbg_init_iseries(void);
 extern void __init udbg_init_rtas_panel(void);
 extern void __init udbg_init_rtas_console(void);
 extern void __init udbg_init_debug_beat(void);
index 0a290a1..6bfd5ff 100644 (file)
@@ -69,6 +69,7 @@ struct vio_dev {
 };
 
 struct vio_driver {
+       const char *name;
        const struct vio_device_id *id_table;
        int (*probe)(struct vio_dev *dev, const struct vio_device_id *id);
        int (*remove)(struct vio_dev *dev);
@@ -76,10 +77,17 @@ struct vio_driver {
         * be loaded in a CMO environment if it uses DMA.
         */
        unsigned long (*get_desired_dma)(struct vio_dev *dev);
+       const struct dev_pm_ops *pm;
        struct device_driver driver;
 };
 
-extern int vio_register_driver(struct vio_driver *drv);
+extern int __vio_register_driver(struct vio_driver *drv, struct module *owner,
+                                const char *mod_name);
+/*
+ * vio_register_driver must be a macro so that KBUILD_MODNAME can be expanded
+ */
+#define vio_register_driver(driver)            \
+       __vio_register_driver(driver, THIS_MODULE, KBUILD_MODNAME)
 extern void vio_unregister_driver(struct vio_driver *drv);
 
 extern int vio_cmo_entitlement_update(size_t);
index 8184ee9..ee5b690 100644 (file)
 #include <linux/mm.h>
 #include <asm/processor.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/cache.h>
 #include <asm/cputable.h>
 #include <asm/emulated_ops.h>
+#include <asm/switch_to.h>
 
 struct aligninfo {
        unsigned char len;
index cc492e4..34b8afe 100644 (file)
@@ -412,16 +412,23 @@ int main(void)
        DEFINE(VCPU_SPRG2, offsetof(struct kvm_vcpu, arch.shregs.sprg2));
        DEFINE(VCPU_SPRG3, offsetof(struct kvm_vcpu, arch.shregs.sprg3));
 #endif
-       DEFINE(VCPU_SPRG4, offsetof(struct kvm_vcpu, arch.sprg4));
-       DEFINE(VCPU_SPRG5, offsetof(struct kvm_vcpu, arch.sprg5));
-       DEFINE(VCPU_SPRG6, offsetof(struct kvm_vcpu, arch.sprg6));
-       DEFINE(VCPU_SPRG7, offsetof(struct kvm_vcpu, arch.sprg7));
+       DEFINE(VCPU_SHARED_SPRG4, offsetof(struct kvm_vcpu_arch_shared, sprg4));
+       DEFINE(VCPU_SHARED_SPRG5, offsetof(struct kvm_vcpu_arch_shared, sprg5));
+       DEFINE(VCPU_SHARED_SPRG6, offsetof(struct kvm_vcpu_arch_shared, sprg6));
+       DEFINE(VCPU_SHARED_SPRG7, offsetof(struct kvm_vcpu_arch_shared, sprg7));
        DEFINE(VCPU_SHADOW_PID, offsetof(struct kvm_vcpu, arch.shadow_pid));
        DEFINE(VCPU_SHADOW_PID1, offsetof(struct kvm_vcpu, arch.shadow_pid1));
        DEFINE(VCPU_SHARED, offsetof(struct kvm_vcpu, arch.shared));
        DEFINE(VCPU_SHARED_MSR, offsetof(struct kvm_vcpu_arch_shared, msr));
        DEFINE(VCPU_SHADOW_MSR, offsetof(struct kvm_vcpu, arch.shadow_msr));
 
+       DEFINE(VCPU_SHARED_MAS0, offsetof(struct kvm_vcpu_arch_shared, mas0));
+       DEFINE(VCPU_SHARED_MAS1, offsetof(struct kvm_vcpu_arch_shared, mas1));
+       DEFINE(VCPU_SHARED_MAS2, offsetof(struct kvm_vcpu_arch_shared, mas2));
+       DEFINE(VCPU_SHARED_MAS7_3, offsetof(struct kvm_vcpu_arch_shared, mas7_3));
+       DEFINE(VCPU_SHARED_MAS4, offsetof(struct kvm_vcpu_arch_shared, mas4));
+       DEFINE(VCPU_SHARED_MAS6, offsetof(struct kvm_vcpu_arch_shared, mas6));
+
        /* book3s */
 #ifdef CONFIG_KVM_BOOK3S_64_HV
        DEFINE(KVM_LPID, offsetof(struct kvm, arch.lpid));
@@ -434,6 +441,7 @@ int main(void)
        DEFINE(KVM_LAST_VCPU, offsetof(struct kvm, arch.last_vcpu));
        DEFINE(KVM_LPCR, offsetof(struct kvm, arch.lpcr));
        DEFINE(KVM_RMOR, offsetof(struct kvm, arch.rmor));
+       DEFINE(KVM_VRMA_SLB_V, offsetof(struct kvm, arch.vrma_slb_v));
        DEFINE(VCPU_DSISR, offsetof(struct kvm_vcpu, arch.shregs.dsisr));
        DEFINE(VCPU_DAR, offsetof(struct kvm_vcpu, arch.shregs.dar));
 #endif
index 138ae18..455faa3 100644 (file)
@@ -20,6 +20,7 @@
 #include <asm/cputable.h>
 #include <asm/prom.h>          /* for PTRRELOC on ARCH=ppc */
 #include <asm/mmu.h>
+#include <asm/setup.h>
 
 struct cpu_spec* cur_cpu_spec = NULL;
 EXPORT_SYMBOL(cur_cpu_spec);
index abef751..fdcd8f5 100644 (file)
@@ -27,8 +27,8 @@
 #include <asm/kdump.h>
 #include <asm/prom.h>
 #include <asm/smp.h>
-#include <asm/system.h>
 #include <asm/setjmp.h>
+#include <asm/debug.h>
 
 /*
  * The primary CPU waits a while for all secondary CPUs to enter. This is to
index 2d0868a..cb705fd 100644 (file)
@@ -101,14 +101,14 @@ data_access_not_stab:
 END_MMU_FTR_SECTION_IFCLR(MMU_FTR_SLB)
 #endif
        EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, data_access_common, EXC_STD,
-                                KVMTEST_PR, 0x300)
+                                KVMTEST, 0x300)
 
        . = 0x380
        .globl data_access_slb_pSeries
 data_access_slb_pSeries:
        HMT_MEDIUM
        SET_SCRATCH0(r13)
-       EXCEPTION_PROLOG_1(PACA_EXSLB, KVMTEST_PR, 0x380)
+       EXCEPTION_PROLOG_1(PACA_EXSLB, KVMTEST, 0x380)
        std     r3,PACA_EXSLB+EX_R3(r13)
        mfspr   r3,SPRN_DAR
 #ifdef __DISABLED__
@@ -330,8 +330,8 @@ do_stab_bolted_pSeries:
        EXCEPTION_PROLOG_PSERIES_1(.do_stab_bolted, EXC_STD)
 #endif /* CONFIG_POWER4_ONLY */
 
-       KVM_HANDLER_PR_SKIP(PACA_EXGEN, EXC_STD, 0x300)
-       KVM_HANDLER_PR_SKIP(PACA_EXSLB, EXC_STD, 0x380)
+       KVM_HANDLER_SKIP(PACA_EXGEN, EXC_STD, 0x300)
+       KVM_HANDLER_SKIP(PACA_EXSLB, EXC_STD, 0x380)
        KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0x400)
        KVM_HANDLER_PR(PACA_EXSLB, EXC_STD, 0x480)
        KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0x900)
index e8e8211..6d2209a 100644 (file)
 #include <linux/sysctl.h>
 #include <linux/tick.h>
 
-#include <asm/system.h>
 #include <asm/processor.h>
 #include <asm/cputable.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
+#include <asm/runlatch.h>
 #include <asm/smp.h>
 
 #ifdef CONFIG_HOTPLUG_CPU
index a3d128e..243dbab 100644 (file)
@@ -57,7 +57,6 @@
 #include <linux/of_irq.h>
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/irq.h>
@@ -67,6 +66,7 @@
 #include <asm/machdep.h>
 #include <asm/udbg.h>
 #include <asm/smp.h>
+#include <asm/debug.h>
 
 #ifdef CONFIG_PPC64
 #include <asm/paca.h>
@@ -208,8 +208,8 @@ notrace void arch_local_irq_restore(unsigned long en)
         * we are checking the "new" CPU instead of the old one. This
         * is only a problem if an event happened on the "old" CPU.
         *
-        * External interrupt events on non-iseries will have caused
-        * interrupts to be hard-disabled, so there is no problem, we
+        * External interrupt events will have caused interrupts to
+        * be hard-disabled, so there is no problem, we
         * cannot have preempted.
         */
        irq_happened = get_irq_happened();
@@ -445,9 +445,9 @@ void do_IRQ(struct pt_regs *regs)
        may_hard_irq_enable();
 
        /* And finally process it */
-       if (irq != NO_IRQ && irq != NO_IRQ_IGNORE)
+       if (irq != NO_IRQ)
                handle_one_irq(irq);
-       else if (irq != NO_IRQ_IGNORE)
+       else
                __get_cpu_var(irq_stat).spurious_irqs++;
 
        irq_exit();
index bc47352..e88c643 100644 (file)
@@ -35,7 +35,6 @@
 #include <asm/cacheflush.h>
 #include <asm/sstep.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 
 #ifdef CONFIG_PPC_ADV_DEBUG_REGS
 #define MSR_SINGLESTEP (MSR_DE)
index 2985338..62bdf23 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2010 SUSE Linux Products GmbH. All rights reserved.
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
  *
  * Authors:
  *     Alexander Graf <agraf@suse.de>
@@ -29,6 +30,7 @@
 #include <asm/sections.h>
 #include <asm/cacheflush.h>
 #include <asm/disassemble.h>
+#include <asm/ppc-opcode.h>
 
 #define KVM_MAGIC_PAGE         (-4096L)
 #define magic_var(x) KVM_MAGIC_PAGE + offsetof(struct kvm_vcpu_arch_shared, x)
 #define KVM_INST_B             0x48000000
 #define KVM_INST_B_MASK                0x03ffffff
 #define KVM_INST_B_MAX         0x01ffffff
+#define KVM_INST_LI            0x38000000
 
 #define KVM_MASK_RT            0x03e00000
 #define KVM_RT_30              0x03c00000
 #define KVM_MASK_RB            0x0000f800
 #define KVM_INST_MFMSR         0x7c0000a6
-#define KVM_INST_MFSPR_SPRG0   0x7c1042a6
-#define KVM_INST_MFSPR_SPRG1   0x7c1142a6
-#define KVM_INST_MFSPR_SPRG2   0x7c1242a6
-#define KVM_INST_MFSPR_SPRG3   0x7c1342a6
-#define KVM_INST_MFSPR_SRR0    0x7c1a02a6
-#define KVM_INST_MFSPR_SRR1    0x7c1b02a6
-#define KVM_INST_MFSPR_DAR     0x7c1302a6
-#define KVM_INST_MFSPR_DSISR   0x7c1202a6
-
-#define KVM_INST_MTSPR_SPRG0   0x7c1043a6
-#define KVM_INST_MTSPR_SPRG1   0x7c1143a6
-#define KVM_INST_MTSPR_SPRG2   0x7c1243a6
-#define KVM_INST_MTSPR_SPRG3   0x7c1343a6
-#define KVM_INST_MTSPR_SRR0    0x7c1a03a6
-#define KVM_INST_MTSPR_SRR1    0x7c1b03a6
-#define KVM_INST_MTSPR_DAR     0x7c1303a6
-#define KVM_INST_MTSPR_DSISR   0x7c1203a6
+
+#define SPR_FROM               0
+#define SPR_TO                 0x100
+
+#define KVM_INST_SPR(sprn, moveto) (0x7c0002a6 | \
+                                   (((sprn) & 0x1f) << 16) | \
+                                   (((sprn) & 0x3e0) << 6) | \
+                                   (moveto))
+
+#define KVM_INST_MFSPR(sprn)   KVM_INST_SPR(sprn, SPR_FROM)
+#define KVM_INST_MTSPR(sprn)   KVM_INST_SPR(sprn, SPR_TO)
 
 #define KVM_INST_TLBSYNC       0x7c00046c
 #define KVM_INST_MTMSRD_L0     0x7c000164
 #define KVM_INST_MTMSRD_L1     0x7c010164
 #define KVM_INST_MTMSR         0x7c000124
 
+#define KVM_INST_WRTEE         0x7c000106
 #define KVM_INST_WRTEEI_0      0x7c000146
 #define KVM_INST_WRTEEI_1      0x7c008146
 
@@ -270,26 +268,27 @@ static void kvm_patch_ins_mtmsr(u32 *inst, u32 rt)
 
 #ifdef CONFIG_BOOKE
 
-extern u32 kvm_emulate_wrteei_branch_offs;
-extern u32 kvm_emulate_wrteei_ee_offs;
-extern u32 kvm_emulate_wrteei_len;
-extern u32 kvm_emulate_wrteei[];
+extern u32 kvm_emulate_wrtee_branch_offs;
+extern u32 kvm_emulate_wrtee_reg_offs;
+extern u32 kvm_emulate_wrtee_orig_ins_offs;
+extern u32 kvm_emulate_wrtee_len;
+extern u32 kvm_emulate_wrtee[];
 
-static void kvm_patch_ins_wrteei(u32 *inst)
+static void kvm_patch_ins_wrtee(u32 *inst, u32 rt, int imm_one)
 {
        u32 *p;
        int distance_start;
        int distance_end;
        ulong next_inst;
 
-       p = kvm_alloc(kvm_emulate_wrteei_len * 4);
+       p = kvm_alloc(kvm_emulate_wrtee_len * 4);
        if (!p)
                return;
 
        /* Find out where we are and put everything there */
        distance_start = (ulong)p - (ulong)inst;
        next_inst = ((ulong)inst + 4);
-       distance_end = next_inst - (ulong)&p[kvm_emulate_wrteei_branch_offs];
+       distance_end = next_inst - (ulong)&p[kvm_emulate_wrtee_branch_offs];
 
        /* Make sure we only write valid b instructions */
        if (distance_start > KVM_INST_B_MAX) {
@@ -298,10 +297,65 @@ static void kvm_patch_ins_wrteei(u32 *inst)
        }
 
        /* Modify the chunk to fit the invocation */
-       memcpy(p, kvm_emulate_wrteei, kvm_emulate_wrteei_len * 4);
-       p[kvm_emulate_wrteei_branch_offs] |= distance_end & KVM_INST_B_MASK;
-       p[kvm_emulate_wrteei_ee_offs] |= (*inst & MSR_EE);
-       flush_icache_range((ulong)p, (ulong)p + kvm_emulate_wrteei_len * 4);
+       memcpy(p, kvm_emulate_wrtee, kvm_emulate_wrtee_len * 4);
+       p[kvm_emulate_wrtee_branch_offs] |= distance_end & KVM_INST_B_MASK;
+
+       if (imm_one) {
+               p[kvm_emulate_wrtee_reg_offs] =
+                       KVM_INST_LI | __PPC_RT(30) | MSR_EE;
+       } else {
+               /* Make clobbered registers work too */
+               switch (get_rt(rt)) {
+               case 30:
+                       kvm_patch_ins_ll(&p[kvm_emulate_wrtee_reg_offs],
+                                        magic_var(scratch2), KVM_RT_30);
+                       break;
+               case 31:
+                       kvm_patch_ins_ll(&p[kvm_emulate_wrtee_reg_offs],
+                                        magic_var(scratch1), KVM_RT_30);
+                       break;
+               default:
+                       p[kvm_emulate_wrtee_reg_offs] |= rt;
+                       break;
+               }
+       }
+
+       p[kvm_emulate_wrtee_orig_ins_offs] = *inst;
+       flush_icache_range((ulong)p, (ulong)p + kvm_emulate_wrtee_len * 4);
+
+       /* Patch the invocation */
+       kvm_patch_ins_b(inst, distance_start);
+}
+
+extern u32 kvm_emulate_wrteei_0_branch_offs;
+extern u32 kvm_emulate_wrteei_0_len;
+extern u32 kvm_emulate_wrteei_0[];
+
+static void kvm_patch_ins_wrteei_0(u32 *inst)
+{
+       u32 *p;
+       int distance_start;
+       int distance_end;
+       ulong next_inst;
+
+       p = kvm_alloc(kvm_emulate_wrteei_0_len * 4);
+       if (!p)
+               return;
+
+       /* Find out where we are and put everything there */
+       distance_start = (ulong)p - (ulong)inst;
+       next_inst = ((ulong)inst + 4);
+       distance_end = next_inst - (ulong)&p[kvm_emulate_wrteei_0_branch_offs];
+
+       /* Make sure we only write valid b instructions */
+       if (distance_start > KVM_INST_B_MAX) {
+               kvm_patching_worked = false;
+               return;
+       }
+
+       memcpy(p, kvm_emulate_wrteei_0, kvm_emulate_wrteei_0_len * 4);
+       p[kvm_emulate_wrteei_0_branch_offs] |= distance_end & KVM_INST_B_MASK;
+       flush_icache_range((ulong)p, (ulong)p + kvm_emulate_wrteei_0_len * 4);
 
        /* Patch the invocation */
        kvm_patch_ins_b(inst, distance_start);
@@ -380,56 +434,191 @@ static void kvm_check_ins(u32 *inst, u32 features)
        case KVM_INST_MFMSR:
                kvm_patch_ins_ld(inst, magic_var(msr), inst_rt);
                break;
-       case KVM_INST_MFSPR_SPRG0:
+       case KVM_INST_MFSPR(SPRN_SPRG0):
                kvm_patch_ins_ld(inst, magic_var(sprg0), inst_rt);
                break;
-       case KVM_INST_MFSPR_SPRG1:
+       case KVM_INST_MFSPR(SPRN_SPRG1):
                kvm_patch_ins_ld(inst, magic_var(sprg1), inst_rt);
                break;
-       case KVM_INST_MFSPR_SPRG2:
+       case KVM_INST_MFSPR(SPRN_SPRG2):
                kvm_patch_ins_ld(inst, magic_var(sprg2), inst_rt);
                break;
-       case KVM_INST_MFSPR_SPRG3:
+       case KVM_INST_MFSPR(SPRN_SPRG3):
                kvm_patch_ins_ld(inst, magic_var(sprg3), inst_rt);
                break;
-       case KVM_INST_MFSPR_SRR0:
+       case KVM_INST_MFSPR(SPRN_SRR0):
                kvm_patch_ins_ld(inst, magic_var(srr0), inst_rt);
                break;
-       case KVM_INST_MFSPR_SRR1:
+       case KVM_INST_MFSPR(SPRN_SRR1):
                kvm_patch_ins_ld(inst, magic_var(srr1), inst_rt);
                break;
-       case KVM_INST_MFSPR_DAR:
+#ifdef CONFIG_BOOKE
+       case KVM_INST_MFSPR(SPRN_DEAR):
+#else
+       case KVM_INST_MFSPR(SPRN_DAR):
+#endif
                kvm_patch_ins_ld(inst, magic_var(dar), inst_rt);
                break;
-       case KVM_INST_MFSPR_DSISR:
+       case KVM_INST_MFSPR(SPRN_DSISR):
                kvm_patch_ins_lwz(inst, magic_var(dsisr), inst_rt);
                break;
 
+#ifdef CONFIG_PPC_BOOK3E_MMU
+       case KVM_INST_MFSPR(SPRN_MAS0):
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_lwz(inst, magic_var(mas0), inst_rt);
+               break;
+       case KVM_INST_MFSPR(SPRN_MAS1):
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_lwz(inst, magic_var(mas1), inst_rt);
+               break;
+       case KVM_INST_MFSPR(SPRN_MAS2):
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_ld(inst, magic_var(mas2), inst_rt);
+               break;
+       case KVM_INST_MFSPR(SPRN_MAS3):
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_lwz(inst, magic_var(mas7_3) + 4, inst_rt);
+               break;
+       case KVM_INST_MFSPR(SPRN_MAS4):
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_lwz(inst, magic_var(mas4), inst_rt);
+               break;
+       case KVM_INST_MFSPR(SPRN_MAS6):
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_lwz(inst, magic_var(mas6), inst_rt);
+               break;
+       case KVM_INST_MFSPR(SPRN_MAS7):
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_lwz(inst, magic_var(mas7_3), inst_rt);
+               break;
+#endif /* CONFIG_PPC_BOOK3E_MMU */
+
+       case KVM_INST_MFSPR(SPRN_SPRG4):
+#ifdef CONFIG_BOOKE
+       case KVM_INST_MFSPR(SPRN_SPRG4R):
+#endif
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_ld(inst, magic_var(sprg4), inst_rt);
+               break;
+       case KVM_INST_MFSPR(SPRN_SPRG5):
+#ifdef CONFIG_BOOKE
+       case KVM_INST_MFSPR(SPRN_SPRG5R):
+#endif
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_ld(inst, magic_var(sprg5), inst_rt);
+               break;
+       case KVM_INST_MFSPR(SPRN_SPRG6):
+#ifdef CONFIG_BOOKE
+       case KVM_INST_MFSPR(SPRN_SPRG6R):
+#endif
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_ld(inst, magic_var(sprg6), inst_rt);
+               break;
+       case KVM_INST_MFSPR(SPRN_SPRG7):
+#ifdef CONFIG_BOOKE
+       case KVM_INST_MFSPR(SPRN_SPRG7R):
+#endif
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_ld(inst, magic_var(sprg7), inst_rt);
+               break;
+
+#ifdef CONFIG_BOOKE
+       case KVM_INST_MFSPR(SPRN_ESR):
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_lwz(inst, magic_var(esr), inst_rt);
+               break;
+#endif
+
+       case KVM_INST_MFSPR(SPRN_PIR):
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_lwz(inst, magic_var(pir), inst_rt);
+               break;
+
+
        /* Stores */
-       case KVM_INST_MTSPR_SPRG0:
+       case KVM_INST_MTSPR(SPRN_SPRG0):
                kvm_patch_ins_std(inst, magic_var(sprg0), inst_rt);
                break;
-       case KVM_INST_MTSPR_SPRG1:
+       case KVM_INST_MTSPR(SPRN_SPRG1):
                kvm_patch_ins_std(inst, magic_var(sprg1), inst_rt);
                break;
-       case KVM_INST_MTSPR_SPRG2:
+       case KVM_INST_MTSPR(SPRN_SPRG2):
                kvm_patch_ins_std(inst, magic_var(sprg2), inst_rt);
                break;
-       case KVM_INST_MTSPR_SPRG3:
+       case KVM_INST_MTSPR(SPRN_SPRG3):
                kvm_patch_ins_std(inst, magic_var(sprg3), inst_rt);
                break;
-       case KVM_INST_MTSPR_SRR0:
+       case KVM_INST_MTSPR(SPRN_SRR0):
                kvm_patch_ins_std(inst, magic_var(srr0), inst_rt);
                break;
-       case KVM_INST_MTSPR_SRR1:
+       case KVM_INST_MTSPR(SPRN_SRR1):
                kvm_patch_ins_std(inst, magic_var(srr1), inst_rt);
                break;
-       case KVM_INST_MTSPR_DAR:
+#ifdef CONFIG_BOOKE
+       case KVM_INST_MTSPR(SPRN_DEAR):
+#else
+       case KVM_INST_MTSPR(SPRN_DAR):
+#endif
                kvm_patch_ins_std(inst, magic_var(dar), inst_rt);
                break;
-       case KVM_INST_MTSPR_DSISR:
+       case KVM_INST_MTSPR(SPRN_DSISR):
                kvm_patch_ins_stw(inst, magic_var(dsisr), inst_rt);
                break;
+#ifdef CONFIG_PPC_BOOK3E_MMU
+       case KVM_INST_MTSPR(SPRN_MAS0):
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_stw(inst, magic_var(mas0), inst_rt);
+               break;
+       case KVM_INST_MTSPR(SPRN_MAS1):
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_stw(inst, magic_var(mas1), inst_rt);
+               break;
+       case KVM_INST_MTSPR(SPRN_MAS2):
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_std(inst, magic_var(mas2), inst_rt);
+               break;
+       case KVM_INST_MTSPR(SPRN_MAS3):
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_stw(inst, magic_var(mas7_3) + 4, inst_rt);
+               break;
+       case KVM_INST_MTSPR(SPRN_MAS4):
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_stw(inst, magic_var(mas4), inst_rt);
+               break;
+       case KVM_INST_MTSPR(SPRN_MAS6):
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_stw(inst, magic_var(mas6), inst_rt);
+               break;
+       case KVM_INST_MTSPR(SPRN_MAS7):
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_stw(inst, magic_var(mas7_3), inst_rt);
+               break;
+#endif /* CONFIG_PPC_BOOK3E_MMU */
+
+       case KVM_INST_MTSPR(SPRN_SPRG4):
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_std(inst, magic_var(sprg4), inst_rt);
+               break;
+       case KVM_INST_MTSPR(SPRN_SPRG5):
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_std(inst, magic_var(sprg5), inst_rt);
+               break;
+       case KVM_INST_MTSPR(SPRN_SPRG6):
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_std(inst, magic_var(sprg6), inst_rt);
+               break;
+       case KVM_INST_MTSPR(SPRN_SPRG7):
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_std(inst, magic_var(sprg7), inst_rt);
+               break;
+
+#ifdef CONFIG_BOOKE
+       case KVM_INST_MTSPR(SPRN_ESR):
+               if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
+                       kvm_patch_ins_stw(inst, magic_var(esr), inst_rt);
+               break;
+#endif
 
        /* Nops */
        case KVM_INST_TLBSYNC:
@@ -444,6 +633,11 @@ static void kvm_check_ins(u32 *inst, u32 features)
        case KVM_INST_MTMSRD_L0:
                kvm_patch_ins_mtmsr(inst, inst_rt);
                break;
+#ifdef CONFIG_BOOKE
+       case KVM_INST_WRTEE:
+               kvm_patch_ins_wrtee(inst, inst_rt, 0);
+               break;
+#endif
        }
 
        switch (inst_no_rt & ~KVM_MASK_RB) {
@@ -461,13 +655,19 @@ static void kvm_check_ins(u32 *inst, u32 features)
        switch (_inst) {
 #ifdef CONFIG_BOOKE
        case KVM_INST_WRTEEI_0:
+               kvm_patch_ins_wrteei_0(inst);
+               break;
+
        case KVM_INST_WRTEEI_1:
-               kvm_patch_ins_wrteei(inst);
+               kvm_patch_ins_wrtee(inst, 0, 1);
                break;
 #endif
        }
 }
 
+extern u32 kvm_template_start[];
+extern u32 kvm_template_end[];
+
 static void kvm_use_magic_page(void)
 {
        u32 *p;
@@ -488,8 +688,23 @@ static void kvm_use_magic_page(void)
        start = (void*)_stext;
        end = (void*)_etext;
 
-       for (p = start; p < end; p++)
+       /*
+        * Being interrupted in the middle of patching would
+        * be bad for SPRG4-7, which KVM can't keep in sync
+        * with emulated accesses because reads don't trap.
+        */
+       local_irq_disable();
+
+       for (p = start; p < end; p++) {
+               /* Avoid patching the template code */
+               if (p >= kvm_template_start && p < kvm_template_end) {
+                       p = kvm_template_end - 1;
+                       continue;
+               }
                kvm_check_ins(p, features);
+       }
+
+       local_irq_enable();
 
        printk(KERN_INFO "KVM: Live patching for a fast VM %s\n",
                         kvm_patching_worked ? "worked" : "failed");
index f2b1b25..e291cf3 100644 (file)
@@ -13,6 +13,7 @@
  * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *
  * Copyright SUSE Linux Products GmbH 2010
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
  *
  * Authors: Alexander Graf <agraf@suse.de>
  */
@@ -65,6 +66,9 @@ kvm_hypercall_start:
           shared->critical == r1 and r2 is always != r1 */             \
        STL64(r2, KVM_MAGIC_PAGE + KVM_MAGIC_CRITICAL, 0);
 
+.global kvm_template_start
+kvm_template_start:
+
 .global kvm_emulate_mtmsrd
 kvm_emulate_mtmsrd:
 
@@ -167,6 +171,9 @@ maybe_stay_in_guest:
 kvm_emulate_mtmsr_reg2:
        ori     r30, r0, 0
 
+       /* Put MSR into magic page because we don't call mtmsr */
+       STL64(r30, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
+
        /* Check if we have to fetch an interrupt */
        lwz     r31, (KVM_MAGIC_PAGE + KVM_MAGIC_INT)(0)
        cmpwi   r31, 0
@@ -174,15 +181,10 @@ kvm_emulate_mtmsr_reg2:
 
        /* Check if we may trigger an interrupt */
        andi.   r31, r30, MSR_EE
-       beq     no_mtmsr
-
-       b       do_mtmsr
+       bne     do_mtmsr
 
 no_mtmsr:
 
-       /* Put MSR into magic page because we don't call mtmsr */
-       STL64(r30, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
-
        SCRATCH_RESTORE
 
        /* Go back to caller */
@@ -210,24 +212,80 @@ kvm_emulate_mtmsr_orig_ins_offs:
 kvm_emulate_mtmsr_len:
        .long (kvm_emulate_mtmsr_end - kvm_emulate_mtmsr) / 4
 
+/* also used for wrteei 1 */
+.global kvm_emulate_wrtee
+kvm_emulate_wrtee:
+
+       SCRATCH_SAVE
+
+       /* Fetch old MSR in r31 */
+       LL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
+
+       /* Insert new MSR[EE] */
+kvm_emulate_wrtee_reg:
+       ori     r30, r0, 0
+       rlwimi  r31, r30, 0, MSR_EE
+
+       /*
+        * If MSR[EE] is now set, check for a pending interrupt.
+        * We could skip this if MSR[EE] was already on, but that
+        * should be rare, so don't bother.
+        */
+       andi.   r30, r30, MSR_EE
+
+       /* Put MSR into magic page because we don't call wrtee */
+       STL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
+
+       beq     no_wrtee
+
+       /* Check if we have to fetch an interrupt */
+       lwz     r30, (KVM_MAGIC_PAGE + KVM_MAGIC_INT)(0)
+       cmpwi   r30, 0
+       bne     do_wrtee
+
+no_wrtee:
+       SCRATCH_RESTORE
+
+       /* Go back to caller */
+kvm_emulate_wrtee_branch:
+       b       .
+
+do_wrtee:
+       SCRATCH_RESTORE
 
+       /* Just fire off the wrtee if it's critical */
+kvm_emulate_wrtee_orig_ins:
+       wrtee   r0
 
-.global kvm_emulate_wrteei
-kvm_emulate_wrteei:
+       b       kvm_emulate_wrtee_branch
 
+kvm_emulate_wrtee_end:
+
+.global kvm_emulate_wrtee_branch_offs
+kvm_emulate_wrtee_branch_offs:
+       .long (kvm_emulate_wrtee_branch - kvm_emulate_wrtee) / 4
+
+.global kvm_emulate_wrtee_reg_offs
+kvm_emulate_wrtee_reg_offs:
+       .long (kvm_emulate_wrtee_reg - kvm_emulate_wrtee) / 4
+
+.global kvm_emulate_wrtee_orig_ins_offs
+kvm_emulate_wrtee_orig_ins_offs:
+       .long (kvm_emulate_wrtee_orig_ins - kvm_emulate_wrtee) / 4
+
+.global kvm_emulate_wrtee_len
+kvm_emulate_wrtee_len:
+       .long (kvm_emulate_wrtee_end - kvm_emulate_wrtee) / 4
+
+.global kvm_emulate_wrteei_0
+kvm_emulate_wrteei_0:
        SCRATCH_SAVE
 
        /* Fetch old MSR in r31 */
        LL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
 
        /* Remove MSR_EE from old MSR */
-       li      r30, 0
-       ori     r30, r30, MSR_EE
-       andc    r31, r31, r30
-
-       /* OR new MSR_EE onto the old MSR */
-kvm_emulate_wrteei_ee:
-       ori     r31, r31, 0
+       rlwinm  r31, r31, 0, ~MSR_EE
 
        /* Write new MSR value back */
        STL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0)
@@ -235,22 +293,17 @@ kvm_emulate_wrteei_ee:
        SCRATCH_RESTORE
 
        /* Go back to caller */
-kvm_emulate_wrteei_branch:
+kvm_emulate_wrteei_0_branch:
        b       .
-kvm_emulate_wrteei_end:
-
-.global kvm_emulate_wrteei_branch_offs
-kvm_emulate_wrteei_branch_offs:
-       .long (kvm_emulate_wrteei_branch - kvm_emulate_wrteei) / 4
+kvm_emulate_wrteei_0_end:
 
-.global kvm_emulate_wrteei_ee_offs
-kvm_emulate_wrteei_ee_offs:
-       .long (kvm_emulate_wrteei_ee - kvm_emulate_wrteei) / 4
-
-.global kvm_emulate_wrteei_len
-kvm_emulate_wrteei_len:
-       .long (kvm_emulate_wrteei_end - kvm_emulate_wrteei) / 4
+.global kvm_emulate_wrteei_0_branch_offs
+kvm_emulate_wrteei_0_branch_offs:
+       .long (kvm_emulate_wrteei_0_branch - kvm_emulate_wrteei_0) / 4
 
+.global kvm_emulate_wrteei_0_len
+kvm_emulate_wrteei_0_len:
+       .long (kvm_emulate_wrteei_0_end - kvm_emulate_wrteei_0) / 4
 
 .global kvm_emulate_mtsrin
 kvm_emulate_mtsrin:
@@ -300,3 +353,6 @@ kvm_emulate_mtsrin_orig_ins_offs:
 .global kvm_emulate_mtsrin_len
 kvm_emulate_mtsrin_len:
        .long (kvm_emulate_mtsrin_end - kvm_emulate_mtsrin) / 4
+
+.global kvm_template_end
+kvm_template_end:
index ac12bd8..f5725bc 100644 (file)
@@ -30,7 +30,6 @@
 #include <asm/hvcall.h>
 #include <asm/firmware.h>
 #include <asm/rtas.h>
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/prom.h>
 #include <asm/vdso_datapage.h>
index d3114a7..786a270 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/cuda.h>
 #include <linux/pmu.h>
 #include <asm/prom.h>
-#include <asm/system.h>
 #include <asm/pci-bridge.h>
 #include <asm/irq.h>
 #include <asm/pmac_feature.h>
@@ -43,6 +42,7 @@
 #include <asm/signal.h>
 #include <asm/dcr.h>
 #include <asm/ftrace.h>
+#include <asm/switch_to.h>
 
 #ifdef CONFIG_PPC32
 extern void transfer_to_handler(void);
index e407070..f88698c 100644 (file)
 
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/processor.h>
 #include <asm/mmu.h>
 #include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/time.h>
+#include <asm/runlatch.h>
 #include <asm/syscalls.h>
+#include <asm/switch_to.h>
+#include <asm/debug.h>
 #ifdef CONFIG_PPC64
 #include <asm/firmware.h>
 #endif
index 89e850a..f191bf0 100644 (file)
@@ -41,7 +41,6 @@
 #include <asm/io.h>
 #include <asm/kdump.h>
 #include <asm/smp.h>
-#include <asm/system.h>
 #include <asm/mmu.h>
 #include <asm/paca.h>
 #include <asm/pgtable.h>
index e2d5990..9986027 100644 (file)
@@ -35,7 +35,6 @@
 #include <asm/irq.h>
 #include <asm/io.h>
 #include <asm/smp.h>
-#include <asm/system.h>
 #include <asm/mmu.h>
 #include <asm/pgtable.h>
 #include <asm/pci.h>
@@ -447,7 +446,7 @@ static void __init __attribute__((noreturn)) prom_panic(const char *reason)
        if (RELOC(of_platform) == PLATFORM_POWERMAC)
                asm("trap\n");
 
-       /* ToDo: should put up an SRC here on p/iSeries */
+       /* ToDo: should put up an SRC here on pSeries */
        call_prom("exit", 0, 0);
 
        for (;;)                        /* should never get here */
index 5b43325..8d8e028 100644 (file)
@@ -36,7 +36,7 @@
 #include <asm/uaccess.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
+#include <asm/switch_to.h>
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/syscalls.h>
index 69c4be9..469349d 100644 (file)
@@ -32,7 +32,7 @@
 #include <asm/uaccess.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
+#include <asm/switch_to.h>
 
 /*
  * does not yet catch signals sent when the child dies.
index 9f843cd..fcec382 100644 (file)
@@ -33,7 +33,6 @@
 #include <asm/firmware.h>
 #include <asm/page.h>
 #include <asm/param.h>
-#include <asm/system.h>
 #include <asm/delay.h>
 #include <asm/uaccess.h>
 #include <asm/udbg.h>
@@ -868,6 +867,40 @@ int rtas_ibm_suspend_me(struct rtas_args *args)
 }
 #endif
 
+/**
+ * Find a specific pseries error log in an RTAS extended event log.
+ * @log: RTAS error/event log
+ * @section_id: two character section identifier
+ *
+ * Returns a pointer to the specified errorlog or NULL if not found.
+ */
+struct pseries_errorlog *get_pseries_errorlog(struct rtas_error_log *log,
+                                             uint16_t section_id)
+{
+       struct rtas_ext_event_log_v6 *ext_log =
+               (struct rtas_ext_event_log_v6 *)log->buffer;
+       struct pseries_errorlog *sect;
+       unsigned char *p, *log_end;
+
+       /* Check that we understand the format */
+       if (log->extended_log_length < sizeof(struct rtas_ext_event_log_v6) ||
+           ext_log->log_format != RTAS_V6EXT_LOG_FORMAT_EVENT_LOG ||
+           ext_log->company_id != RTAS_V6EXT_COMPANY_ID_IBM)
+               return NULL;
+
+       log_end = log->buffer + log->extended_log_length;
+       p = ext_log->vendor_log;
+
+       while (p < log_end) {
+               sect = (struct pseries_errorlog *)p;
+               if (sect->id == section_id)
+                       return sect;
+               p += sect->length;
+       }
+
+       return NULL;
+}
+
 asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
 {
        struct rtas_args args;
index b0ebdea..afd4f05 100644 (file)
@@ -51,7 +51,6 @@
 #include <asm/btext.h>
 #include <asm/nvram.h>
 #include <asm/setup.h>
-#include <asm/system.h>
 #include <asm/rtas.h>
 #include <asm/iommu.h>
 #include <asm/serial.h>
index ac76108..9825f29 100644 (file)
@@ -30,7 +30,6 @@
 #include <asm/btext.h>
 #include <asm/machdep.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/pmac_feature.h>
 #include <asm/sections.h>
 #include <asm/nvram.h>
index 4cb8f1e..389bd4f 100644 (file)
@@ -52,7 +52,6 @@
 #include <asm/btext.h>
 #include <asm/nvram.h>
 #include <asm/setup.h>
-#include <asm/system.h>
 #include <asm/rtas.h>
 #include <asm/iommu.h>
 #include <asm/serial.h>
@@ -598,7 +597,7 @@ void __init setup_arch(char **cmdline_p)
        /* Initialize the MMU context management stuff */
        mmu_context_init();
 
-       kvm_rma_init();
+       kvm_linear_init();
 
        ppc64_boot_msg(0x15, "Setup Done");
 }
index 7006b7f..651c596 100644 (file)
@@ -15,6 +15,7 @@
 #include <asm/hw_breakpoint.h>
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
+#include <asm/debug.h>
 
 #include "signal.h"
 
index e061ef5..45eb998 100644 (file)
@@ -43,6 +43,7 @@
 #include <asm/syscalls.h>
 #include <asm/sigcontext.h>
 #include <asm/vdso.h>
+#include <asm/switch_to.h>
 #ifdef CONFIG_PPC64
 #include "ppc32.h"
 #include <asm/unistd.h>
index a50b5ec..2692efd 100644 (file)
@@ -33,6 +33,7 @@
 #include <asm/cacheflush.h>
 #include <asm/syscalls.h>
 #include <asm/vdso.h>
+#include <asm/switch_to.h>
 
 #include "signal.h"
 
index 46695fe..d9f9441 100644 (file)
 #include <asm/machdep.h>
 #include <asm/cputhreads.h>
 #include <asm/cputable.h>
-#include <asm/system.h>
 #include <asm/mpic.h>
 #include <asm/vdso_datapage.h>
 #ifdef CONFIG_PPC64
 #include <asm/paca.h>
 #endif
+#include <asm/debug.h>
 
 #ifdef DEBUG
 #include <asm/udbg.h>
index af0e829..29b2f81 100644 (file)
@@ -26,7 +26,6 @@
 
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/io.h>
 
 /* Eventually we may need a look-up table, but this works for now.
index 641f9ad..eae33e1 100644 (file)
@@ -10,9 +10,9 @@
  */
 
 #include <linux/sched.h>
-#include <asm/system.h>
 #include <asm/current.h>
 #include <asm/mmu_context.h>
+#include <asm/switch_to.h>
 
 void save_processor_state(void)
 {
index 168e884..0e899e4 100644 (file)
@@ -6,7 +6,6 @@
  * GPLv2
  */
 
-#include <asm/system.h>
 #include <asm/iommu.h>
 #include <linux/irq.h>
 #include <linux/sched.h>
index 4e5bf1e..81c5706 100644 (file)
@@ -50,6 +50,7 @@
 #include <asm/mmu_context.h>
 #include <asm/ppc-pci.h>
 #include <asm/syscalls.h>
+#include <asm/switch_to.h>
 
 
 asmlinkage long ppc32_select(u32 n, compat_ulong_t __user *inp,
index 0c683d3..3529446 100644 (file)
@@ -17,7 +17,6 @@
 #include <asm/machdep.h>
 #include <asm/smp.h>
 #include <asm/pmc.h>
-#include <asm/system.h>
 
 #include "cacheinfo.h"
 
index a750409..6aa0c66 100644 (file)
@@ -39,7 +39,6 @@
 #include <asm/emulated_ops.h>
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/machdep.h>
 #include <asm/rtas.h>
@@ -58,6 +57,8 @@
 #include <asm/ppc-opcode.h>
 #include <asm/rio.h>
 #include <asm/fadump.h>
+#include <asm/switch_to.h>
+#include <asm/debug.h>
 
 #if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC)
 int (*__debugger)(struct pt_regs *regs) __read_mostly;
index 57fa2c0..c39c1ca 100644 (file)
@@ -46,9 +46,6 @@ void __init udbg_early_init(void)
 #elif defined(CONFIG_PPC_EARLY_DEBUG_MAPLE)
        /* Maple real mode debug */
        udbg_init_maple_realmode();
-#elif defined(CONFIG_PPC_EARLY_DEBUG_ISERIES)
-       /* For iSeries - hit Ctrl-x Ctrl-x to see the output */
-       udbg_init_iseries();
 #elif defined(CONFIG_PPC_EARLY_DEBUG_BEAT)
        udbg_init_debug_beat();
 #elif defined(CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE)
index d36ee10..9eb5b9b 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/memblock.h>
 
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/processor.h>
 #include <asm/mmu.h>
 #include <asm/mmu_context.h>
@@ -721,10 +720,10 @@ static int __init vdso_init(void)
        vdso_data->version.minor = SYSTEMCFG_MINOR;
        vdso_data->processor = mfspr(SPRN_PVR);
        /*
-        * Fake the old platform number for pSeries and iSeries and add
+        * Fake the old platform number for pSeries and add
         * in LPAR bit if necessary
         */
-       vdso_data->platform = machine_is(iseries) ? 0x200 : 0x100;
+       vdso_data->platform = 0x100;
        if (firmware_has_feature(FW_FEATURE_LPAR))
                vdso_data->platform |= 1;
        vdso_data->physicalMemorySize = memblock_phys_mem_size();
index bca3fc4..b2f7c84 100644 (file)
@@ -1159,17 +1159,21 @@ static int vio_bus_remove(struct device *dev)
  * vio_register_driver: - Register a new vio driver
  * @drv:       The vio_driver structure to be registered.
  */
-int vio_register_driver(struct vio_driver *viodrv)
+int __vio_register_driver(struct vio_driver *viodrv, struct module *owner,
+                         const char *mod_name)
 {
-       printk(KERN_DEBUG "%s: driver %s registering\n", __func__,
-               viodrv->driver.name);
+       pr_debug("%s: driver %s registering\n", __func__, viodrv->name);
 
        /* fill in 'struct driver' fields */
+       viodrv->driver.name = viodrv->name;
+       viodrv->driver.pm = viodrv->pm;
        viodrv->driver.bus = &vio_bus_type;
+       viodrv->driver.owner = owner;
+       viodrv->driver.mod_name = mod_name;
 
        return driver_register(&viodrv->driver);
 }
-EXPORT_SYMBOL(vio_register_driver);
+EXPORT_SYMBOL(__vio_register_driver);
 
 /**
  * vio_unregister_driver - Remove registration of vio driver.
index 78133de..8f64709 100644 (file)
@@ -69,6 +69,7 @@ config KVM_BOOK3S_64
 config KVM_BOOK3S_64_HV
        bool "KVM support for POWER7 and PPC970 using hypervisor mode in host"
        depends on KVM_BOOK3S_64
+       select MMU_NOTIFIER
        ---help---
          Support running unmodified book3s_64 guest kernels in
          virtual machines on POWER7 and PPC970 processors that have
index e41ac6f..7d54f4e 100644 (file)
@@ -258,7 +258,7 @@ static bool clear_irqprio(struct kvm_vcpu *vcpu, unsigned int priority)
        return true;
 }
 
-void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu)
+void kvmppc_core_prepare_to_enter(struct kvm_vcpu *vcpu)
 {
        unsigned long *pending = &vcpu->arch.pending_exceptions;
        unsigned long old_pending = vcpu->arch.pending_exceptions;
@@ -423,10 +423,10 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
        regs->sprg1 = vcpu->arch.shared->sprg1;
        regs->sprg2 = vcpu->arch.shared->sprg2;
        regs->sprg3 = vcpu->arch.shared->sprg3;
-       regs->sprg4 = vcpu->arch.sprg4;
-       regs->sprg5 = vcpu->arch.sprg5;
-       regs->sprg6 = vcpu->arch.sprg6;
-       regs->sprg7 = vcpu->arch.sprg7;
+       regs->sprg4 = vcpu->arch.shared->sprg4;
+       regs->sprg5 = vcpu->arch.shared->sprg5;
+       regs->sprg6 = vcpu->arch.shared->sprg6;
+       regs->sprg7 = vcpu->arch.shared->sprg7;
 
        for (i = 0; i < ARRAY_SIZE(regs->gpr); i++)
                regs->gpr[i] = kvmppc_get_gpr(vcpu, i);
@@ -450,10 +450,10 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
        vcpu->arch.shared->sprg1 = regs->sprg1;
        vcpu->arch.shared->sprg2 = regs->sprg2;
        vcpu->arch.shared->sprg3 = regs->sprg3;
-       vcpu->arch.sprg4 = regs->sprg4;
-       vcpu->arch.sprg5 = regs->sprg5;
-       vcpu->arch.sprg6 = regs->sprg6;
-       vcpu->arch.sprg7 = regs->sprg7;
+       vcpu->arch.shared->sprg4 = regs->sprg4;
+       vcpu->arch.shared->sprg5 = regs->sprg5;
+       vcpu->arch.shared->sprg6 = regs->sprg6;
+       vcpu->arch.shared->sprg7 = regs->sprg7;
 
        for (i = 0; i < ARRAY_SIZE(regs->gpr); i++)
                kvmppc_set_gpr(vcpu, i, regs->gpr[i]);
@@ -477,41 +477,10 @@ int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu,
        return 0;
 }
 
-/*
- * Get (and clear) the dirty memory log for a memory slot.
- */
-int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
-                                     struct kvm_dirty_log *log)
+void kvmppc_decrementer_func(unsigned long data)
 {
-       struct kvm_memory_slot *memslot;
-       struct kvm_vcpu *vcpu;
-       ulong ga, ga_end;
-       int is_dirty = 0;
-       int r;
-       unsigned long n;
-
-       mutex_lock(&kvm->slots_lock);
-
-       r = kvm_get_dirty_log(kvm, log, &is_dirty);
-       if (r)
-               goto out;
-
-       /* If nothing is dirty, don't bother messing with page tables. */
-       if (is_dirty) {
-               memslot = id_to_memslot(kvm->memslots, log->slot);
+       struct kvm_vcpu *vcpu = (struct kvm_vcpu *)data;
 
-               ga = memslot->base_gfn << PAGE_SHIFT;
-               ga_end = ga + (memslot->npages << PAGE_SHIFT);
-
-               kvm_for_each_vcpu(n, vcpu, kvm)
-                       kvmppc_mmu_pte_pflush(vcpu, ga, ga_end);
-
-               n = kvm_dirty_bitmap_bytes(memslot);
-               memset(memslot->dirty_bitmap, 0, n);
-       }
-
-       r = 0;
-out:
-       mutex_unlock(&kvm->slots_lock);
-       return r;
+       kvmppc_core_queue_dec(vcpu);
+       kvm_vcpu_kick(vcpu);
 }
index 9fecbfb..f922c29 100644 (file)
@@ -151,13 +151,15 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
        bool primary = false;
        bool evict = false;
        struct hpte_cache *pte;
+       int r = 0;
 
        /* Get host physical address for gpa */
        hpaddr = kvmppc_gfn_to_pfn(vcpu, orig_pte->raddr >> PAGE_SHIFT);
        if (is_error_pfn(hpaddr)) {
                printk(KERN_INFO "Couldn't get guest page for gfn %lx!\n",
                                 orig_pte->eaddr);
-               return -EINVAL;
+               r = -EINVAL;
+               goto out;
        }
        hpaddr <<= PAGE_SHIFT;
 
@@ -249,7 +251,8 @@ next_pteg:
 
        kvmppc_mmu_hpte_cache_map(vcpu, pte);
 
-       return 0;
+out:
+       return r;
 }
 
 static struct kvmppc_sid_map *create_sid_map(struct kvm_vcpu *vcpu, u64 gvsid)
@@ -297,12 +300,14 @@ int kvmppc_mmu_map_segment(struct kvm_vcpu *vcpu, ulong eaddr)
        u64 gvsid;
        u32 sr;
        struct kvmppc_sid_map *map;
-       struct kvmppc_book3s_shadow_vcpu *svcpu = to_svcpu(vcpu);
+       struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
+       int r = 0;
 
        if (vcpu->arch.mmu.esid_to_vsid(vcpu, esid, &gvsid)) {
                /* Invalidate an entry */
                svcpu->sr[esid] = SR_INVALID;
-               return -ENOENT;
+               r = -ENOENT;
+               goto out;
        }
 
        map = find_sid_vsid(vcpu, gvsid);
@@ -315,17 +320,21 @@ int kvmppc_mmu_map_segment(struct kvm_vcpu *vcpu, ulong eaddr)
 
        dprintk_sr("MMU: mtsr %d, 0x%x\n", esid, sr);
 
-       return 0;
+out:
+       svcpu_put(svcpu);
+       return r;
 }
 
 void kvmppc_mmu_flush_segments(struct kvm_vcpu *vcpu)
 {
        int i;
-       struct kvmppc_book3s_shadow_vcpu *svcpu = to_svcpu(vcpu);
+       struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
 
        dprintk_sr("MMU: flushing all segments (%d)\n", ARRAY_SIZE(svcpu->sr));
        for (i = 0; i < ARRAY_SIZE(svcpu->sr); i++)
                svcpu->sr[i] = SR_INVALID;
+
+       svcpu_put(svcpu);
 }
 
 void kvmppc_mmu_destroy(struct kvm_vcpu *vcpu)
index fa2f084..6f87f39 100644 (file)
@@ -88,12 +88,14 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
        int vflags = 0;
        int attempt = 0;
        struct kvmppc_sid_map *map;
+       int r = 0;
 
        /* Get host physical address for gpa */
        hpaddr = kvmppc_gfn_to_pfn(vcpu, orig_pte->raddr >> PAGE_SHIFT);
        if (is_error_pfn(hpaddr)) {
                printk(KERN_INFO "Couldn't get guest page for gfn %lx!\n", orig_pte->eaddr);
-               return -EINVAL;
+               r = -EINVAL;
+               goto out;
        }
        hpaddr <<= PAGE_SHIFT;
        hpaddr |= orig_pte->raddr & (~0xfffULL & ~PAGE_MASK);
@@ -110,7 +112,8 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
                printk(KERN_ERR "KVM: Segment map for 0x%llx (0x%lx) failed\n",
                                vsid, orig_pte->eaddr);
                WARN_ON(true);
-               return -EINVAL;
+               r = -EINVAL;
+               goto out;
        }
 
        vsid = map->host_vsid;
@@ -131,8 +134,10 @@ map_again:
 
        /* In case we tried normal mapping already, let's nuke old entries */
        if (attempt > 1)
-               if (ppc_md.hpte_remove(hpteg) < 0)
-                       return -1;
+               if (ppc_md.hpte_remove(hpteg) < 0) {
+                       r = -1;
+                       goto out;
+               }
 
        ret = ppc_md.hpte_insert(hpteg, va, hpaddr, rflags, vflags, MMU_PAGE_4K, MMU_SEGSIZE_256M);
 
@@ -162,7 +167,8 @@ map_again:
                kvmppc_mmu_hpte_cache_map(vcpu, pte);
        }
 
-       return 0;
+out:
+       return r;
 }
 
 static struct kvmppc_sid_map *create_sid_map(struct kvm_vcpu *vcpu, u64 gvsid)
@@ -207,25 +213,30 @@ static struct kvmppc_sid_map *create_sid_map(struct kvm_vcpu *vcpu, u64 gvsid)
 
 static int kvmppc_mmu_next_segment(struct kvm_vcpu *vcpu, ulong esid)
 {
+       struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
        int i;
        int max_slb_size = 64;
        int found_inval = -1;
        int r;
 
-       if (!to_svcpu(vcpu)->slb_max)
-               to_svcpu(vcpu)->slb_max = 1;
+       if (!svcpu->slb_max)
+               svcpu->slb_max = 1;
 
        /* Are we overwriting? */
-       for (i = 1; i < to_svcpu(vcpu)->slb_max; i++) {
-               if (!(to_svcpu(vcpu)->slb[i].esid & SLB_ESID_V))
+       for (i = 1; i < svcpu->slb_max; i++) {
+               if (!(svcpu->slb[i].esid & SLB_ESID_V))
                        found_inval = i;
-               else if ((to_svcpu(vcpu)->slb[i].esid & ESID_MASK) == esid)
-                       return i;
+               else if ((svcpu->slb[i].esid & ESID_MASK) == esid) {
+                       r = i;
+                       goto out;
+               }
        }
 
        /* Found a spare entry that was invalidated before */
-       if (found_inval > 0)
-               return found_inval;
+       if (found_inval > 0) {
+               r = found_inval;
+               goto out;
+       }
 
        /* No spare invalid entry, so create one */
 
@@ -233,30 +244,35 @@ static int kvmppc_mmu_next_segment(struct kvm_vcpu *vcpu, ulong esid)
                max_slb_size = mmu_slb_size;
 
        /* Overflowing -> purge */
-       if ((to_svcpu(vcpu)->slb_max) == max_slb_size)
+       if ((svcpu->slb_max) == max_slb_size)
                kvmppc_mmu_flush_segments(vcpu);
 
-       r = to_svcpu(vcpu)->slb_max;
-       to_svcpu(vcpu)->slb_max++;
+       r = svcpu->slb_max;
+       svcpu->slb_max++;
 
+out:
+       svcpu_put(svcpu);
        return r;
 }
 
 int kvmppc_mmu_map_segment(struct kvm_vcpu *vcpu, ulong eaddr)
 {
+       struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
        u64 esid = eaddr >> SID_SHIFT;
        u64 slb_esid = (eaddr & ESID_MASK) | SLB_ESID_V;
        u64 slb_vsid = SLB_VSID_USER;
        u64 gvsid;
        int slb_index;
        struct kvmppc_sid_map *map;
+       int r = 0;
 
        slb_index = kvmppc_mmu_next_segment(vcpu, eaddr & ESID_MASK);
 
        if (vcpu->arch.mmu.esid_to_vsid(vcpu, esid, &gvsid)) {
                /* Invalidate an entry */
-               to_svcpu(vcpu)->slb[slb_index].esid = 0;
-               return -ENOENT;
+               svcpu->slb[slb_index].esid = 0;
+               r = -ENOENT;
+               goto out;
        }
 
        map = find_sid_vsid(vcpu, gvsid);
@@ -269,18 +285,22 @@ int kvmppc_mmu_map_segment(struct kvm_vcpu *vcpu, ulong eaddr)
        slb_vsid &= ~SLB_VSID_KP;
        slb_esid |= slb_index;
 
-       to_svcpu(vcpu)->slb[slb_index].esid = slb_esid;
-       to_svcpu(vcpu)->slb[slb_index].vsid = slb_vsid;
+       svcpu->slb[slb_index].esid = slb_esid;
+       svcpu->slb[slb_index].vsid = slb_vsid;
 
        trace_kvm_book3s_slbmte(slb_vsid, slb_esid);
 
-       return 0;
+out:
+       svcpu_put(svcpu);
+       return r;
 }
 
 void kvmppc_mmu_flush_segments(struct kvm_vcpu *vcpu)
 {
-       to_svcpu(vcpu)->slb_max = 1;
-       to_svcpu(vcpu)->slb[0].esid = 0;
+       struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
+       svcpu->slb_max = 1;
+       svcpu->slb[0].esid = 0;
+       svcpu_put(svcpu);
 }
 
 void kvmppc_mmu_destroy(struct kvm_vcpu *vcpu)
index bc3a2ea..ddc485a 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/gfp.h>
 #include <linux/slab.h>
 #include <linux/hugetlb.h>
+#include <linux/vmalloc.h>
 
 #include <asm/tlbflush.h>
 #include <asm/kvm_ppc.h>
 #include <asm/ppc-opcode.h>
 #include <asm/cputable.h>
 
-/* For now use fixed-size 16MB page table */
-#define HPT_ORDER      24
-#define HPT_NPTEG      (1ul << (HPT_ORDER - 7))        /* 128B per pteg */
-#define HPT_HASH_MASK  (HPT_NPTEG - 1)
-
-/* Pages in the VRMA are 16MB pages */
-#define VRMA_PAGE_ORDER        24
-#define VRMA_VSID      0x1ffffffUL     /* 1TB VSID reserved for VRMA */
-
 /* POWER7 has 10-bit LPIDs, PPC970 has 6-bit LPIDs */
 #define MAX_LPID_970   63
 #define NR_LPIDS       (LPID_RSVD + 1)
@@ -51,21 +43,41 @@ long kvmppc_alloc_hpt(struct kvm *kvm)
 {
        unsigned long hpt;
        unsigned long lpid;
+       struct revmap_entry *rev;
+       struct kvmppc_linear_info *li;
+
+       /* Allocate guest's hashed page table */
+       li = kvm_alloc_hpt();
+       if (li) {
+               /* using preallocated memory */
+               hpt = (ulong)li->base_virt;
+               kvm->arch.hpt_li = li;
+       } else {
+               /* using dynamic memory */
+               hpt = __get_free_pages(GFP_KERNEL|__GFP_ZERO|__GFP_REPEAT|
+                                      __GFP_NOWARN, HPT_ORDER - PAGE_SHIFT);
+       }
 
-       hpt = __get_free_pages(GFP_KERNEL|__GFP_ZERO|__GFP_REPEAT|__GFP_NOWARN,
-                              HPT_ORDER - PAGE_SHIFT);
        if (!hpt) {
                pr_err("kvm_alloc_hpt: Couldn't alloc HPT\n");
                return -ENOMEM;
        }
        kvm->arch.hpt_virt = hpt;
 
+       /* Allocate reverse map array */
+       rev = vmalloc(sizeof(struct revmap_entry) * HPT_NPTE);
+       if (!rev) {
+               pr_err("kvmppc_alloc_hpt: Couldn't alloc reverse map array\n");
+               goto out_freehpt;
+       }
+       kvm->arch.revmap = rev;
+
+       /* Allocate the guest's logical partition ID */
        do {
                lpid = find_first_zero_bit(lpid_inuse, NR_LPIDS);
                if (lpid >= NR_LPIDS) {
                        pr_err("kvm_alloc_hpt: No LPIDs free\n");
-                       free_pages(hpt, HPT_ORDER - PAGE_SHIFT);
-                       return -ENOMEM;
+                       goto out_freeboth;
                }
        } while (test_and_set_bit(lpid, lpid_inuse));
 
@@ -74,37 +86,64 @@ long kvmppc_alloc_hpt(struct kvm *kvm)
 
        pr_info("KVM guest htab at %lx, LPID %lx\n", hpt, lpid);
        return 0;
+
+ out_freeboth:
+       vfree(rev);
+ out_freehpt:
+       free_pages(hpt, HPT_ORDER - PAGE_SHIFT);
+       return -ENOMEM;
 }
 
 void kvmppc_free_hpt(struct kvm *kvm)
 {
        clear_bit(kvm->arch.lpid, lpid_inuse);
-       free_pages(kvm->arch.hpt_virt, HPT_ORDER - PAGE_SHIFT);
+       vfree(kvm->arch.revmap);
+       if (kvm->arch.hpt_li)
+               kvm_release_hpt(kvm->arch.hpt_li);
+       else
+               free_pages(kvm->arch.hpt_virt, HPT_ORDER - PAGE_SHIFT);
+}
+
+/* Bits in first HPTE dword for pagesize 4k, 64k or 16M */
+static inline unsigned long hpte0_pgsize_encoding(unsigned long pgsize)
+{
+       return (pgsize > 0x1000) ? HPTE_V_LARGE : 0;
+}
+
+/* Bits in second HPTE dword for pagesize 4k, 64k or 16M */
+static inline unsigned long hpte1_pgsize_encoding(unsigned long pgsize)
+{
+       return (pgsize == 0x10000) ? 0x1000 : 0;
 }
 
-void kvmppc_map_vrma(struct kvm *kvm, struct kvm_userspace_memory_region *mem)
+void kvmppc_map_vrma(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot,
+                    unsigned long porder)
 {
        unsigned long i;
-       unsigned long npages = kvm->arch.ram_npages;
-       unsigned long pfn;
-       unsigned long *hpte;
-       unsigned long hash;
-       struct kvmppc_pginfo *pginfo = kvm->arch.ram_pginfo;
+       unsigned long npages;
+       unsigned long hp_v, hp_r;
+       unsigned long addr, hash;
+       unsigned long psize;
+       unsigned long hp0, hp1;
+       long ret;
 
-       if (!pginfo)
-               return;
+       psize = 1ul << porder;
+       npages = memslot->npages >> (porder - PAGE_SHIFT);
 
        /* VRMA can't be > 1TB */
-       if (npages > 1ul << (40 - kvm->arch.ram_porder))
-               npages = 1ul << (40 - kvm->arch.ram_porder);
+       if (npages > 1ul << (40 - porder))
+               npages = 1ul << (40 - porder);
        /* Can't use more than 1 HPTE per HPTEG */
        if (npages > HPT_NPTEG)
                npages = HPT_NPTEG;
 
+       hp0 = HPTE_V_1TB_SEG | (VRMA_VSID << (40 - 16)) |
+               HPTE_V_BOLTED | hpte0_pgsize_encoding(psize);
+       hp1 = hpte1_pgsize_encoding(psize) |
+               HPTE_R_R | HPTE_R_C | HPTE_R_M | PP_RWXX;
+
        for (i = 0; i < npages; ++i) {
-               pfn = pginfo[i].pfn;
-               if (!pfn)
-                       break;
+               addr = i << porder;
                /* can't use hpt_hash since va > 64 bits */
                hash = (i ^ (VRMA_VSID ^ (VRMA_VSID << 25))) & HPT_HASH_MASK;
                /*
@@ -113,15 +152,15 @@ void kvmppc_map_vrma(struct kvm *kvm, struct kvm_userspace_memory_region *mem)
                 * at most one HPTE per HPTEG, we just assume entry 7
                 * is available and use it.
                 */
-               hpte = (unsigned long *) (kvm->arch.hpt_virt + (hash << 7));
-               hpte += 7 * 2;
-               /* HPTE low word - RPN, protection, etc. */
-               hpte[1] = (pfn << PAGE_SHIFT) | HPTE_R_R | HPTE_R_C |
-                       HPTE_R_M | PP_RWXX;
-               wmb();
-               hpte[0] = HPTE_V_1TB_SEG | (VRMA_VSID << (40 - 16)) |
-                       (i << (VRMA_PAGE_ORDER - 16)) | HPTE_V_BOLTED |
-                       HPTE_V_LARGE | HPTE_V_VALID;
+               hash = (hash << 3) + 7;
+               hp_v = hp0 | ((addr >> 16) & ~0x7fUL);
+               hp_r = hp1 | addr;
+               ret = kvmppc_virtmode_h_enter(vcpu, H_EXACT, hash, hp_v, hp_r);
+               if (ret != H_SUCCESS) {
+                       pr_err("KVM: map_vrma at %lx failed, ret=%ld\n",
+                              addr, ret);
+                       break;
+               }
        }
 }
 
@@ -158,10 +197,814 @@ static void kvmppc_mmu_book3s_64_hv_reset_msr(struct kvm_vcpu *vcpu)
        kvmppc_set_msr(vcpu, MSR_SF | MSR_ME);
 }
 
+/*
+ * This is called to get a reference to a guest page if there isn't
+ * one already in the kvm->arch.slot_phys[][] arrays.
+ */
+static long kvmppc_get_guest_page(struct kvm *kvm, unsigned long gfn,
+                                 struct kvm_memory_slot *memslot,
+                                 unsigned long psize)
+{
+       unsigned long start;
+       long np, err;
+       struct page *page, *hpage, *pages[1];
+       unsigned long s, pgsize;
+       unsigned long *physp;
+       unsigned int is_io, got, pgorder;
+       struct vm_area_struct *vma;
+       unsigned long pfn, i, npages;
+
+       physp = kvm->arch.slot_phys[memslot->id];
+       if (!physp)
+               return -EINVAL;
+       if (physp[gfn - memslot->base_gfn])
+               return 0;
+
+       is_io = 0;
+       got = 0;
+       page = NULL;
+       pgsize = psize;
+       err = -EINVAL;
+       start = gfn_to_hva_memslot(memslot, gfn);
+
+       /* Instantiate and get the page we want access to */
+       np = get_user_pages_fast(start, 1, 1, pages);
+       if (np != 1) {
+               /* Look up the vma for the page */
+               down_read(&current->mm->mmap_sem);
+               vma = find_vma(current->mm, start);
+               if (!vma || vma->vm_start > start ||
+                   start + psize > vma->vm_end ||
+                   !(vma->vm_flags & VM_PFNMAP))
+                       goto up_err;
+               is_io = hpte_cache_bits(pgprot_val(vma->vm_page_prot));
+               pfn = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT);
+               /* check alignment of pfn vs. requested page size */
+               if (psize > PAGE_SIZE && (pfn & ((psize >> PAGE_SHIFT) - 1)))
+                       goto up_err;
+               up_read(&current->mm->mmap_sem);
+
+       } else {
+               page = pages[0];
+               got = KVMPPC_GOT_PAGE;
+
+               /* See if this is a large page */
+               s = PAGE_SIZE;
+               if (PageHuge(page)) {
+                       hpage = compound_head(page);
+                       s <<= compound_order(hpage);
+                       /* Get the whole large page if slot alignment is ok */
+                       if (s > psize && slot_is_aligned(memslot, s) &&
+                           !(memslot->userspace_addr & (s - 1))) {
+                               start &= ~(s - 1);
+                               pgsize = s;
+                               page = hpage;
+                       }
+               }
+               if (s < psize)
+                       goto out;
+               pfn = page_to_pfn(page);
+       }
+
+       npages = pgsize >> PAGE_SHIFT;
+       pgorder = __ilog2(npages);
+       physp += (gfn - memslot->base_gfn) & ~(npages - 1);
+       spin_lock(&kvm->arch.slot_phys_lock);
+       for (i = 0; i < npages; ++i) {
+               if (!physp[i]) {
+                       physp[i] = ((pfn + i) << PAGE_SHIFT) +
+                               got + is_io + pgorder;
+                       got = 0;
+               }
+       }
+       spin_unlock(&kvm->arch.slot_phys_lock);
+       err = 0;
+
+ out:
+       if (got) {
+               if (PageHuge(page))
+                       page = compound_head(page);
+               put_page(page);
+       }
+       return err;
+
+ up_err:
+       up_read(&current->mm->mmap_sem);
+       return err;
+}
+
+/*
+ * We come here on a H_ENTER call from the guest when we are not
+ * using mmu notifiers and we don't have the requested page pinned
+ * already.
+ */
+long kvmppc_virtmode_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
+                       long pte_index, unsigned long pteh, unsigned long ptel)
+{
+       struct kvm *kvm = vcpu->kvm;
+       unsigned long psize, gpa, gfn;
+       struct kvm_memory_slot *memslot;
+       long ret;
+
+       if (kvm->arch.using_mmu_notifiers)
+               goto do_insert;
+
+       psize = hpte_page_size(pteh, ptel);
+       if (!psize)
+               return H_PARAMETER;
+
+       pteh &= ~(HPTE_V_HVLOCK | HPTE_V_ABSENT | HPTE_V_VALID);
+
+       /* Find the memslot (if any) for this address */
+       gpa = (ptel & HPTE_R_RPN) & ~(psize - 1);
+       gfn = gpa >> PAGE_SHIFT;
+       memslot = gfn_to_memslot(kvm, gfn);
+       if (memslot && !(memslot->flags & KVM_MEMSLOT_INVALID)) {
+               if (!slot_is_aligned(memslot, psize))
+                       return H_PARAMETER;
+               if (kvmppc_get_guest_page(kvm, gfn, memslot, psize) < 0)
+                       return H_PARAMETER;
+       }
+
+ do_insert:
+       /* Protect linux PTE lookup from page table destruction */
+       rcu_read_lock_sched();  /* this disables preemption too */
+       vcpu->arch.pgdir = current->mm->pgd;
+       ret = kvmppc_h_enter(vcpu, flags, pte_index, pteh, ptel);
+       rcu_read_unlock_sched();
+       if (ret == H_TOO_HARD) {
+               /* this can't happen */
+               pr_err("KVM: Oops, kvmppc_h_enter returned too hard!\n");
+               ret = H_RESOURCE;       /* or something */
+       }
+       return ret;
+
+}
+
+static struct kvmppc_slb *kvmppc_mmu_book3s_hv_find_slbe(struct kvm_vcpu *vcpu,
+                                                        gva_t eaddr)
+{
+       u64 mask;
+       int i;
+
+       for (i = 0; i < vcpu->arch.slb_nr; i++) {
+               if (!(vcpu->arch.slb[i].orige & SLB_ESID_V))
+                       continue;
+
+               if (vcpu->arch.slb[i].origv & SLB_VSID_B_1T)
+                       mask = ESID_MASK_1T;
+               else
+                       mask = ESID_MASK;
+
+               if (((vcpu->arch.slb[i].orige ^ eaddr) & mask) == 0)
+                       return &vcpu->arch.slb[i];
+       }
+       return NULL;
+}
+
+static unsigned long kvmppc_mmu_get_real_addr(unsigned long v, unsigned long r,
+                       unsigned long ea)
+{
+       unsigned long ra_mask;
+
+       ra_mask = hpte_page_size(v, r) - 1;
+       return (r & HPTE_R_RPN & ~ra_mask) | (ea & ra_mask);
+}
+
 static int kvmppc_mmu_book3s_64_hv_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
-                               struct kvmppc_pte *gpte, bool data)
+                       struct kvmppc_pte *gpte, bool data)
+{
+       struct kvm *kvm = vcpu->kvm;
+       struct kvmppc_slb *slbe;
+       unsigned long slb_v;
+       unsigned long pp, key;
+       unsigned long v, gr;
+       unsigned long *hptep;
+       int index;
+       int virtmode = vcpu->arch.shregs.msr & (data ? MSR_DR : MSR_IR);
+
+       /* Get SLB entry */
+       if (virtmode) {
+               slbe = kvmppc_mmu_book3s_hv_find_slbe(vcpu, eaddr);
+               if (!slbe)
+                       return -EINVAL;
+               slb_v = slbe->origv;
+       } else {
+               /* real mode access */
+               slb_v = vcpu->kvm->arch.vrma_slb_v;
+       }
+
+       /* Find the HPTE in the hash table */
+       index = kvmppc_hv_find_lock_hpte(kvm, eaddr, slb_v,
+                                        HPTE_V_VALID | HPTE_V_ABSENT);
+       if (index < 0)
+               return -ENOENT;
+       hptep = (unsigned long *)(kvm->arch.hpt_virt + (index << 4));
+       v = hptep[0] & ~HPTE_V_HVLOCK;
+       gr = kvm->arch.revmap[index].guest_rpte;
+
+       /* Unlock the HPTE */
+       asm volatile("lwsync" : : : "memory");
+       hptep[0] = v;
+
+       gpte->eaddr = eaddr;
+       gpte->vpage = ((v & HPTE_V_AVPN) << 4) | ((eaddr >> 12) & 0xfff);
+
+       /* Get PP bits and key for permission check */
+       pp = gr & (HPTE_R_PP0 | HPTE_R_PP);
+       key = (vcpu->arch.shregs.msr & MSR_PR) ? SLB_VSID_KP : SLB_VSID_KS;
+       key &= slb_v;
+
+       /* Calculate permissions */
+       gpte->may_read = hpte_read_permission(pp, key);
+       gpte->may_write = hpte_write_permission(pp, key);
+       gpte->may_execute = gpte->may_read && !(gr & (HPTE_R_N | HPTE_R_G));
+
+       /* Storage key permission check for POWER7 */
+       if (data && virtmode && cpu_has_feature(CPU_FTR_ARCH_206)) {
+               int amrfield = hpte_get_skey_perm(gr, vcpu->arch.amr);
+               if (amrfield & 1)
+                       gpte->may_read = 0;
+               if (amrfield & 2)
+                       gpte->may_write = 0;
+       }
+
+       /* Get the guest physical address */
+       gpte->raddr = kvmppc_mmu_get_real_addr(v, gr, eaddr);
+       return 0;
+}
+
+/*
+ * Quick test for whether an instruction is a load or a store.
+ * If the instruction is a load or a store, then this will indicate
+ * which it is, at least on server processors.  (Embedded processors
+ * have some external PID instructions that don't follow the rule
+ * embodied here.)  If the instruction isn't a load or store, then
+ * this doesn't return anything useful.
+ */
+static int instruction_is_store(unsigned int instr)
+{
+       unsigned int mask;
+
+       mask = 0x10000000;
+       if ((instr & 0xfc000000) == 0x7c000000)
+               mask = 0x100;           /* major opcode 31 */
+       return (instr & mask) != 0;
+}
+
+static int kvmppc_hv_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu,
+                                 unsigned long gpa, int is_store)
+{
+       int ret;
+       u32 last_inst;
+       unsigned long srr0 = kvmppc_get_pc(vcpu);
+
+       /* We try to load the last instruction.  We don't let
+        * emulate_instruction do it as it doesn't check what
+        * kvmppc_ld returns.
+        * If we fail, we just return to the guest and try executing it again.
+        */
+       if (vcpu->arch.last_inst == KVM_INST_FETCH_FAILED) {
+               ret = kvmppc_ld(vcpu, &srr0, sizeof(u32), &last_inst, false);
+               if (ret != EMULATE_DONE || last_inst == KVM_INST_FETCH_FAILED)
+                       return RESUME_GUEST;
+               vcpu->arch.last_inst = last_inst;
+       }
+
+       /*
+        * WARNING: We do not know for sure whether the instruction we just
+        * read from memory is the same that caused the fault in the first
+        * place.  If the instruction we read is neither an load or a store,
+        * then it can't access memory, so we don't need to worry about
+        * enforcing access permissions.  So, assuming it is a load or
+        * store, we just check that its direction (load or store) is
+        * consistent with the original fault, since that's what we
+        * checked the access permissions against.  If there is a mismatch
+        * we just return and retry the instruction.
+        */
+
+       if (instruction_is_store(vcpu->arch.last_inst) != !!is_store)
+               return RESUME_GUEST;
+
+       /*
+        * Emulated accesses are emulated by looking at the hash for
+        * translation once, then performing the access later. The
+        * translation could be invalidated in the meantime in which
+        * point performing the subsequent memory access on the old
+        * physical address could possibly be a security hole for the
+        * guest (but not the host).
+        *
+        * This is less of an issue for MMIO stores since they aren't
+        * globally visible. It could be an issue for MMIO loads to
+        * a certain extent but we'll ignore it for now.
+        */
+
+       vcpu->arch.paddr_accessed = gpa;
+       return kvmppc_emulate_mmio(run, vcpu);
+}
+
+int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
+                               unsigned long ea, unsigned long dsisr)
+{
+       struct kvm *kvm = vcpu->kvm;
+       unsigned long *hptep, hpte[3], r;
+       unsigned long mmu_seq, psize, pte_size;
+       unsigned long gfn, hva, pfn;
+       struct kvm_memory_slot *memslot;
+       unsigned long *rmap;
+       struct revmap_entry *rev;
+       struct page *page, *pages[1];
+       long index, ret, npages;
+       unsigned long is_io;
+       unsigned int writing, write_ok;
+       struct vm_area_struct *vma;
+       unsigned long rcbits;
+
+       /*
+        * Real-mode code has already searched the HPT and found the
+        * entry we're interested in.  Lock the entry and check that
+        * it hasn't changed.  If it has, just return and re-execute the
+        * instruction.
+        */
+       if (ea != vcpu->arch.pgfault_addr)
+               return RESUME_GUEST;
+       index = vcpu->arch.pgfault_index;
+       hptep = (unsigned long *)(kvm->arch.hpt_virt + (index << 4));
+       rev = &kvm->arch.revmap[index];
+       preempt_disable();
+       while (!try_lock_hpte(hptep, HPTE_V_HVLOCK))
+               cpu_relax();
+       hpte[0] = hptep[0] & ~HPTE_V_HVLOCK;
+       hpte[1] = hptep[1];
+       hpte[2] = r = rev->guest_rpte;
+       asm volatile("lwsync" : : : "memory");
+       hptep[0] = hpte[0];
+       preempt_enable();
+
+       if (hpte[0] != vcpu->arch.pgfault_hpte[0] ||
+           hpte[1] != vcpu->arch.pgfault_hpte[1])
+               return RESUME_GUEST;
+
+       /* Translate the logical address and get the page */
+       psize = hpte_page_size(hpte[0], r);
+       gfn = hpte_rpn(r, psize);
+       memslot = gfn_to_memslot(kvm, gfn);
+
+       /* No memslot means it's an emulated MMIO region */
+       if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID)) {
+               unsigned long gpa = (gfn << PAGE_SHIFT) | (ea & (psize - 1));
+               return kvmppc_hv_emulate_mmio(run, vcpu, gpa,
+                                             dsisr & DSISR_ISSTORE);
+       }
+
+       if (!kvm->arch.using_mmu_notifiers)
+               return -EFAULT;         /* should never get here */
+
+       /* used to check for invalidations in progress */
+       mmu_seq = kvm->mmu_notifier_seq;
+       smp_rmb();
+
+       is_io = 0;
+       pfn = 0;
+       page = NULL;
+       pte_size = PAGE_SIZE;
+       writing = (dsisr & DSISR_ISSTORE) != 0;
+       /* If writing != 0, then the HPTE must allow writing, if we get here */
+       write_ok = writing;
+       hva = gfn_to_hva_memslot(memslot, gfn);
+       npages = get_user_pages_fast(hva, 1, writing, pages);
+       if (npages < 1) {
+               /* Check if it's an I/O mapping */
+               down_read(&current->mm->mmap_sem);
+               vma = find_vma(current->mm, hva);
+               if (vma && vma->vm_start <= hva && hva + psize <= vma->vm_end &&
+                   (vma->vm_flags & VM_PFNMAP)) {
+                       pfn = vma->vm_pgoff +
+                               ((hva - vma->vm_start) >> PAGE_SHIFT);
+                       pte_size = psize;
+                       is_io = hpte_cache_bits(pgprot_val(vma->vm_page_prot));
+                       write_ok = vma->vm_flags & VM_WRITE;
+               }
+               up_read(&current->mm->mmap_sem);
+               if (!pfn)
+                       return -EFAULT;
+       } else {
+               page = pages[0];
+               if (PageHuge(page)) {
+                       page = compound_head(page);
+                       pte_size <<= compound_order(page);
+               }
+               /* if the guest wants write access, see if that is OK */
+               if (!writing && hpte_is_writable(r)) {
+                       pte_t *ptep, pte;
+
+                       /*
+                        * We need to protect against page table destruction
+                        * while looking up and updating the pte.
+                        */
+                       rcu_read_lock_sched();
+                       ptep = find_linux_pte_or_hugepte(current->mm->pgd,
+                                                        hva, NULL);
+                       if (ptep && pte_present(*ptep)) {
+                               pte = kvmppc_read_update_linux_pte(ptep, 1);
+                               if (pte_write(pte))
+                                       write_ok = 1;
+                       }
+                       rcu_read_unlock_sched();
+               }
+               pfn = page_to_pfn(page);
+       }
+
+       ret = -EFAULT;
+       if (psize > pte_size)
+               goto out_put;
+
+       /* Check WIMG vs. the actual page we're accessing */
+       if (!hpte_cache_flags_ok(r, is_io)) {
+               if (is_io)
+                       return -EFAULT;
+               /*
+                * Allow guest to map emulated device memory as
+                * uncacheable, but actually make it cacheable.
+                */
+               r = (r & ~(HPTE_R_W|HPTE_R_I|HPTE_R_G)) | HPTE_R_M;
+       }
+
+       /* Set the HPTE to point to pfn */
+       r = (r & ~(HPTE_R_PP0 - pte_size)) | (pfn << PAGE_SHIFT);
+       if (hpte_is_writable(r) && !write_ok)
+               r = hpte_make_readonly(r);
+       ret = RESUME_GUEST;
+       preempt_disable();
+       while (!try_lock_hpte(hptep, HPTE_V_HVLOCK))
+               cpu_relax();
+       if ((hptep[0] & ~HPTE_V_HVLOCK) != hpte[0] || hptep[1] != hpte[1] ||
+           rev->guest_rpte != hpte[2])
+               /* HPTE has been changed under us; let the guest retry */
+               goto out_unlock;
+       hpte[0] = (hpte[0] & ~HPTE_V_ABSENT) | HPTE_V_VALID;
+
+       rmap = &memslot->rmap[gfn - memslot->base_gfn];
+       lock_rmap(rmap);
+
+       /* Check if we might have been invalidated; let the guest retry if so */
+       ret = RESUME_GUEST;
+       if (mmu_notifier_retry(vcpu, mmu_seq)) {
+               unlock_rmap(rmap);
+               goto out_unlock;
+       }
+
+       /* Only set R/C in real HPTE if set in both *rmap and guest_rpte */
+       rcbits = *rmap >> KVMPPC_RMAP_RC_SHIFT;
+       r &= rcbits | ~(HPTE_R_R | HPTE_R_C);
+
+       if (hptep[0] & HPTE_V_VALID) {
+               /* HPTE was previously valid, so we need to invalidate it */
+               unlock_rmap(rmap);
+               hptep[0] |= HPTE_V_ABSENT;
+               kvmppc_invalidate_hpte(kvm, hptep, index);
+               /* don't lose previous R and C bits */
+               r |= hptep[1] & (HPTE_R_R | HPTE_R_C);
+       } else {
+               kvmppc_add_revmap_chain(kvm, rev, rmap, index, 0);
+       }
+
+       hptep[1] = r;
+       eieio();
+       hptep[0] = hpte[0];
+       asm volatile("ptesync" : : : "memory");
+       preempt_enable();
+       if (page && hpte_is_writable(r))
+               SetPageDirty(page);
+
+ out_put:
+       if (page)
+               put_page(page);
+       return ret;
+
+ out_unlock:
+       hptep[0] &= ~HPTE_V_HVLOCK;
+       preempt_enable();
+       goto out_put;
+}
+
+static int kvm_handle_hva(struct kvm *kvm, unsigned long hva,
+                         int (*handler)(struct kvm *kvm, unsigned long *rmapp,
+                                        unsigned long gfn))
+{
+       int ret;
+       int retval = 0;
+       struct kvm_memslots *slots;
+       struct kvm_memory_slot *memslot;
+
+       slots = kvm_memslots(kvm);
+       kvm_for_each_memslot(memslot, slots) {
+               unsigned long start = memslot->userspace_addr;
+               unsigned long end;
+
+               end = start + (memslot->npages << PAGE_SHIFT);
+               if (hva >= start && hva < end) {
+                       gfn_t gfn_offset = (hva - start) >> PAGE_SHIFT;
+
+                       ret = handler(kvm, &memslot->rmap[gfn_offset],
+                                     memslot->base_gfn + gfn_offset);
+                       retval |= ret;
+               }
+       }
+
+       return retval;
+}
+
+static int kvm_unmap_rmapp(struct kvm *kvm, unsigned long *rmapp,
+                          unsigned long gfn)
+{
+       struct revmap_entry *rev = kvm->arch.revmap;
+       unsigned long h, i, j;
+       unsigned long *hptep;
+       unsigned long ptel, psize, rcbits;
+
+       for (;;) {
+               lock_rmap(rmapp);
+               if (!(*rmapp & KVMPPC_RMAP_PRESENT)) {
+                       unlock_rmap(rmapp);
+                       break;
+               }
+
+               /*
+                * To avoid an ABBA deadlock with the HPTE lock bit,
+                * we can't spin on the HPTE lock while holding the
+                * rmap chain lock.
+                */
+               i = *rmapp & KVMPPC_RMAP_INDEX;
+               hptep = (unsigned long *) (kvm->arch.hpt_virt + (i << 4));
+               if (!try_lock_hpte(hptep, HPTE_V_HVLOCK)) {
+                       /* unlock rmap before spinning on the HPTE lock */
+                       unlock_rmap(rmapp);
+                       while (hptep[0] & HPTE_V_HVLOCK)
+                               cpu_relax();
+                       continue;
+               }
+               j = rev[i].forw;
+               if (j == i) {
+                       /* chain is now empty */
+                       *rmapp &= ~(KVMPPC_RMAP_PRESENT | KVMPPC_RMAP_INDEX);
+               } else {
+                       /* remove i from chain */
+                       h = rev[i].back;
+                       rev[h].forw = j;
+                       rev[j].back = h;
+                       rev[i].forw = rev[i].back = i;
+                       *rmapp = (*rmapp & ~KVMPPC_RMAP_INDEX) | j;
+               }
+
+               /* Now check and modify the HPTE */
+               ptel = rev[i].guest_rpte;
+               psize = hpte_page_size(hptep[0], ptel);
+               if ((hptep[0] & HPTE_V_VALID) &&
+                   hpte_rpn(ptel, psize) == gfn) {
+                       hptep[0] |= HPTE_V_ABSENT;
+                       kvmppc_invalidate_hpte(kvm, hptep, i);
+                       /* Harvest R and C */
+                       rcbits = hptep[1] & (HPTE_R_R | HPTE_R_C);
+                       *rmapp |= rcbits << KVMPPC_RMAP_RC_SHIFT;
+                       rev[i].guest_rpte = ptel | rcbits;
+               }
+               unlock_rmap(rmapp);
+               hptep[0] &= ~HPTE_V_HVLOCK;
+       }
+       return 0;
+}
+
+int kvm_unmap_hva(struct kvm *kvm, unsigned long hva)
+{
+       if (kvm->arch.using_mmu_notifiers)
+               kvm_handle_hva(kvm, hva, kvm_unmap_rmapp);
+       return 0;
+}
+
+static int kvm_age_rmapp(struct kvm *kvm, unsigned long *rmapp,
+                        unsigned long gfn)
+{
+       struct revmap_entry *rev = kvm->arch.revmap;
+       unsigned long head, i, j;
+       unsigned long *hptep;
+       int ret = 0;
+
+ retry:
+       lock_rmap(rmapp);
+       if (*rmapp & KVMPPC_RMAP_REFERENCED) {
+               *rmapp &= ~KVMPPC_RMAP_REFERENCED;
+               ret = 1;
+       }
+       if (!(*rmapp & KVMPPC_RMAP_PRESENT)) {
+               unlock_rmap(rmapp);
+               return ret;
+       }
+
+       i = head = *rmapp & KVMPPC_RMAP_INDEX;
+       do {
+               hptep = (unsigned long *) (kvm->arch.hpt_virt + (i << 4));
+               j = rev[i].forw;
+
+               /* If this HPTE isn't referenced, ignore it */
+               if (!(hptep[1] & HPTE_R_R))
+                       continue;
+
+               if (!try_lock_hpte(hptep, HPTE_V_HVLOCK)) {
+                       /* unlock rmap before spinning on the HPTE lock */
+                       unlock_rmap(rmapp);
+                       while (hptep[0] & HPTE_V_HVLOCK)
+                               cpu_relax();
+                       goto retry;
+               }
+
+               /* Now check and modify the HPTE */
+               if ((hptep[0] & HPTE_V_VALID) && (hptep[1] & HPTE_R_R)) {
+                       kvmppc_clear_ref_hpte(kvm, hptep, i);
+                       rev[i].guest_rpte |= HPTE_R_R;
+                       ret = 1;
+               }
+               hptep[0] &= ~HPTE_V_HVLOCK;
+       } while ((i = j) != head);
+
+       unlock_rmap(rmapp);
+       return ret;
+}
+
+int kvm_age_hva(struct kvm *kvm, unsigned long hva)
+{
+       if (!kvm->arch.using_mmu_notifiers)
+               return 0;
+       return kvm_handle_hva(kvm, hva, kvm_age_rmapp);
+}
+
+static int kvm_test_age_rmapp(struct kvm *kvm, unsigned long *rmapp,
+                             unsigned long gfn)
+{
+       struct revmap_entry *rev = kvm->arch.revmap;
+       unsigned long head, i, j;
+       unsigned long *hp;
+       int ret = 1;
+
+       if (*rmapp & KVMPPC_RMAP_REFERENCED)
+               return 1;
+
+       lock_rmap(rmapp);
+       if (*rmapp & KVMPPC_RMAP_REFERENCED)
+               goto out;
+
+       if (*rmapp & KVMPPC_RMAP_PRESENT) {
+               i = head = *rmapp & KVMPPC_RMAP_INDEX;
+               do {
+                       hp = (unsigned long *)(kvm->arch.hpt_virt + (i << 4));
+                       j = rev[i].forw;
+                       if (hp[1] & HPTE_R_R)
+                               goto out;
+               } while ((i = j) != head);
+       }
+       ret = 0;
+
+ out:
+       unlock_rmap(rmapp);
+       return ret;
+}
+
+int kvm_test_age_hva(struct kvm *kvm, unsigned long hva)
+{
+       if (!kvm->arch.using_mmu_notifiers)
+               return 0;
+       return kvm_handle_hva(kvm, hva, kvm_test_age_rmapp);
+}
+
+void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte)
 {
-       return -ENOENT;
+       if (!kvm->arch.using_mmu_notifiers)
+               return;
+       kvm_handle_hva(kvm, hva, kvm_unmap_rmapp);
+}
+
+static int kvm_test_clear_dirty(struct kvm *kvm, unsigned long *rmapp)
+{
+       struct revmap_entry *rev = kvm->arch.revmap;
+       unsigned long head, i, j;
+       unsigned long *hptep;
+       int ret = 0;
+
+ retry:
+       lock_rmap(rmapp);
+       if (*rmapp & KVMPPC_RMAP_CHANGED) {
+               *rmapp &= ~KVMPPC_RMAP_CHANGED;
+               ret = 1;
+       }
+       if (!(*rmapp & KVMPPC_RMAP_PRESENT)) {
+               unlock_rmap(rmapp);
+               return ret;
+       }
+
+       i = head = *rmapp & KVMPPC_RMAP_INDEX;
+       do {
+               hptep = (unsigned long *) (kvm->arch.hpt_virt + (i << 4));
+               j = rev[i].forw;
+
+               if (!(hptep[1] & HPTE_R_C))
+                       continue;
+
+               if (!try_lock_hpte(hptep, HPTE_V_HVLOCK)) {
+                       /* unlock rmap before spinning on the HPTE lock */
+                       unlock_rmap(rmapp);
+                       while (hptep[0] & HPTE_V_HVLOCK)
+                               cpu_relax();
+                       goto retry;
+               }
+
+               /* Now check and modify the HPTE */
+               if ((hptep[0] & HPTE_V_VALID) && (hptep[1] & HPTE_R_C)) {
+                       /* need to make it temporarily absent to clear C */
+                       hptep[0] |= HPTE_V_ABSENT;
+                       kvmppc_invalidate_hpte(kvm, hptep, i);
+                       hptep[1] &= ~HPTE_R_C;
+                       eieio();
+                       hptep[0] = (hptep[0] & ~HPTE_V_ABSENT) | HPTE_V_VALID;
+                       rev[i].guest_rpte |= HPTE_R_C;
+                       ret = 1;
+               }
+               hptep[0] &= ~HPTE_V_HVLOCK;
+       } while ((i = j) != head);
+
+       unlock_rmap(rmapp);
+       return ret;
+}
+
+long kvmppc_hv_get_dirty_log(struct kvm *kvm, struct kvm_memory_slot *memslot)
+{
+       unsigned long i;
+       unsigned long *rmapp, *map;
+
+       preempt_disable();
+       rmapp = memslot->rmap;
+       map = memslot->dirty_bitmap;
+       for (i = 0; i < memslot->npages; ++i) {
+               if (kvm_test_clear_dirty(kvm, rmapp))
+                       __set_bit_le(i, map);
+               ++rmapp;
+       }
+       preempt_enable();
+       return 0;
+}
+
+void *kvmppc_pin_guest_page(struct kvm *kvm, unsigned long gpa,
+                           unsigned long *nb_ret)
+{
+       struct kvm_memory_slot *memslot;
+       unsigned long gfn = gpa >> PAGE_SHIFT;
+       struct page *page, *pages[1];
+       int npages;
+       unsigned long hva, psize, offset;
+       unsigned long pa;
+       unsigned long *physp;
+
+       memslot = gfn_to_memslot(kvm, gfn);
+       if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID))
+               return NULL;
+       if (!kvm->arch.using_mmu_notifiers) {
+               physp = kvm->arch.slot_phys[memslot->id];
+               if (!physp)
+                       return NULL;
+               physp += gfn - memslot->base_gfn;
+               pa = *physp;
+               if (!pa) {
+                       if (kvmppc_get_guest_page(kvm, gfn, memslot,
+                                                 PAGE_SIZE) < 0)
+                               return NULL;
+                       pa = *physp;
+               }
+               page = pfn_to_page(pa >> PAGE_SHIFT);
+       } else {
+               hva = gfn_to_hva_memslot(memslot, gfn);
+               npages = get_user_pages_fast(hva, 1, 1, pages);
+               if (npages < 1)
+                       return NULL;
+               page = pages[0];
+       }
+       psize = PAGE_SIZE;
+       if (PageHuge(page)) {
+               page = compound_head(page);
+               psize <<= compound_order(page);
+       }
+       if (!kvm->arch.using_mmu_notifiers)
+               get_page(page);
+       offset = gpa & (psize - 1);
+       if (nb_ret)
+               *nb_ret = psize - offset;
+       return page_address(page) + offset;
+}
+
+void kvmppc_unpin_guest_page(struct kvm *kvm, void *va)
+{
+       struct page *page = virt_to_page(va);
+
+       page = compound_head(page);
+       put_page(page);
 }
 
 void kvmppc_mmu_book3s_hv_init(struct kvm_vcpu *vcpu)
index 0c9dc62..f1950d1 100644 (file)
@@ -230,9 +230,12 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
 
                        r = kvmppc_st(vcpu, &addr, 32, zeros, true);
                        if ((r == -ENOENT) || (r == -EPERM)) {
+                               struct kvmppc_book3s_shadow_vcpu *svcpu;
+
+                               svcpu = svcpu_get(vcpu);
                                *advance = 0;
                                vcpu->arch.shared->dar = vaddr;
-                               to_svcpu(vcpu)->fault_dar = vaddr;
+                               svcpu->fault_dar = vaddr;
 
                                dsisr = DSISR_ISSTORE;
                                if (r == -ENOENT)
@@ -241,7 +244,8 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
                                        dsisr |= DSISR_PROTFAULT;
 
                                vcpu->arch.shared->dsisr = dsisr;
-                               to_svcpu(vcpu)->fault_dsisr = dsisr;
+                               svcpu->fault_dsisr = dsisr;
+                               svcpu_put(svcpu);
 
                                kvmppc_book3s_queue_irqprio(vcpu,
                                        BOOK3S_INTERRUPT_DATA_STORAGE);
index a726716..01294a5 100644 (file)
 #include <asm/cputhreads.h>
 #include <asm/page.h>
 #include <asm/hvcall.h>
+#include <asm/switch_to.h>
 #include <linux/gfp.h>
 #include <linux/vmalloc.h>
 #include <linux/highmem.h>
-
-/*
- * For now, limit memory to 64GB and require it to be large pages.
- * This value is chosen because it makes the ram_pginfo array be
- * 64kB in size, which is about as large as we want to be trying
- * to allocate with kmalloc.
- */
-#define MAX_MEM_ORDER          36
-
-#define LARGE_PAGE_ORDER       24      /* 16MB pages */
+#include <linux/hugetlb.h>
 
 /* #define EXIT_DEBUG */
 /* #define EXIT_DEBUG_SIMPLE */
 /* #define EXIT_DEBUG_INT */
 
 static void kvmppc_end_cede(struct kvm_vcpu *vcpu);
+static int kvmppc_hv_setup_rma(struct kvm_vcpu *vcpu);
 
 void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 {
@@ -146,10 +139,10 @@ static unsigned long do_h_register_vpa(struct kvm_vcpu *vcpu,
                                       unsigned long vcpuid, unsigned long vpa)
 {
        struct kvm *kvm = vcpu->kvm;
-       unsigned long pg_index, ra, len;
-       unsigned long pg_offset;
+       unsigned long len, nb;
        void *va;
        struct kvm_vcpu *tvcpu;
+       int err = H_PARAMETER;
 
        tvcpu = kvmppc_find_vcpu(kvm, vcpuid);
        if (!tvcpu)
@@ -162,45 +155,41 @@ static unsigned long do_h_register_vpa(struct kvm_vcpu *vcpu,
        if (flags < 4) {
                if (vpa & 0x7f)
                        return H_PARAMETER;
+               if (flags >= 2 && !tvcpu->arch.vpa)
+                       return H_RESOURCE;
                /* registering new area; convert logical addr to real */
-               pg_index = vpa >> kvm->arch.ram_porder;
-               pg_offset = vpa & (kvm->arch.ram_psize - 1);
-               if (pg_index >= kvm->arch.ram_npages)
+               va = kvmppc_pin_guest_page(kvm, vpa, &nb);
+               if (va == NULL)
                        return H_PARAMETER;
-               if (kvm->arch.ram_pginfo[pg_index].pfn == 0)
-                       return H_PARAMETER;
-               ra = kvm->arch.ram_pginfo[pg_index].pfn << PAGE_SHIFT;
-               ra |= pg_offset;
-               va = __va(ra);
                if (flags <= 1)
                        len = *(unsigned short *)(va + 4);
                else
                        len = *(unsigned int *)(va + 4);
-               if (pg_offset + len > kvm->arch.ram_psize)
-                       return H_PARAMETER;
+               if (len > nb)
+                       goto out_unpin;
                switch (flags) {
                case 1:         /* register VPA */
                        if (len < 640)
-                               return H_PARAMETER;
+                               goto out_unpin;
+                       if (tvcpu->arch.vpa)
+                               kvmppc_unpin_guest_page(kvm, vcpu->arch.vpa);
                        tvcpu->arch.vpa = va;
                        init_vpa(vcpu, va);
                        break;
                case 2:         /* register DTL */
                        if (len < 48)
-                               return H_PARAMETER;
-                       if (!tvcpu->arch.vpa)
-                               return H_RESOURCE;
+                               goto out_unpin;
                        len -= len % 48;
+                       if (tvcpu->arch.dtl)
+                               kvmppc_unpin_guest_page(kvm, vcpu->arch.dtl);
                        tvcpu->arch.dtl = va;
                        tvcpu->arch.dtl_end = va + len;
                        break;
                case 3:         /* register SLB shadow buffer */
-                       if (len < 8)
-                               return H_PARAMETER;
-                       if (!tvcpu->arch.vpa)
-                               return H_RESOURCE;
-                       tvcpu->arch.slb_shadow = va;
-                       len = (len - 16) / 16;
+                       if (len < 16)
+                               goto out_unpin;
+                       if (tvcpu->arch.slb_shadow)
+                               kvmppc_unpin_guest_page(kvm, vcpu->arch.slb_shadow);
                        tvcpu->arch.slb_shadow = va;
                        break;
                }
@@ -209,17 +198,30 @@ static unsigned long do_h_register_vpa(struct kvm_vcpu *vcpu,
                case 5:         /* unregister VPA */
                        if (tvcpu->arch.slb_shadow || tvcpu->arch.dtl)
                                return H_RESOURCE;
+                       if (!tvcpu->arch.vpa)
+                               break;
+                       kvmppc_unpin_guest_page(kvm, tvcpu->arch.vpa);
                        tvcpu->arch.vpa = NULL;
                        break;
                case 6:         /* unregister DTL */
+                       if (!tvcpu->arch.dtl)
+                               break;
+                       kvmppc_unpin_guest_page(kvm, tvcpu->arch.dtl);
                        tvcpu->arch.dtl = NULL;
                        break;
                case 7:         /* unregister SLB shadow buffer */
+                       if (!tvcpu->arch.slb_shadow)
+                               break;
+                       kvmppc_unpin_guest_page(kvm, tvcpu->arch.slb_shadow);
                        tvcpu->arch.slb_shadow = NULL;
                        break;
                }
        }
        return H_SUCCESS;
+
+ out_unpin:
+       kvmppc_unpin_guest_page(kvm, va);
+       return err;
 }
 
 int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
@@ -229,6 +231,12 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
        struct kvm_vcpu *tvcpu;
 
        switch (req) {
+       case H_ENTER:
+               ret = kvmppc_virtmode_h_enter(vcpu, kvmppc_get_gpr(vcpu, 4),
+                                             kvmppc_get_gpr(vcpu, 5),
+                                             kvmppc_get_gpr(vcpu, 6),
+                                             kvmppc_get_gpr(vcpu, 7));
+               break;
        case H_CEDE:
                break;
        case H_PROD:
@@ -318,20 +326,19 @@ static int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
                break;
        }
        /*
-        * We get these next two if the guest does a bad real-mode access,
-        * as we have enabled VRMA (virtualized real mode area) mode in the
-        * LPCR.  We just generate an appropriate DSI/ISI to the guest.
+        * We get these next two if the guest accesses a page which it thinks
+        * it has mapped but which is not actually present, either because
+        * it is for an emulated I/O device or because the corresonding
+        * host page has been paged out.  Any other HDSI/HISI interrupts
+        * have been handled already.
         */
        case BOOK3S_INTERRUPT_H_DATA_STORAGE:
-               vcpu->arch.shregs.dsisr = vcpu->arch.fault_dsisr;
-               vcpu->arch.shregs.dar = vcpu->arch.fault_dar;
-               kvmppc_inject_interrupt(vcpu, BOOK3S_INTERRUPT_DATA_STORAGE, 0);
-               r = RESUME_GUEST;
+               r = kvmppc_book3s_hv_page_fault(run, vcpu,
+                               vcpu->arch.fault_dar, vcpu->arch.fault_dsisr);
                break;
        case BOOK3S_INTERRUPT_H_INST_STORAGE:
-               kvmppc_inject_interrupt(vcpu, BOOK3S_INTERRUPT_INST_STORAGE,
-                                       0x08000000);
-               r = RESUME_GUEST;
+               r = kvmppc_book3s_hv_page_fault(run, vcpu,
+                               kvmppc_get_pc(vcpu), 0);
                break;
        /*
         * This occurs if the guest executes an illegal instruction.
@@ -391,6 +398,42 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
        return 0;
 }
 
+int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
+{
+       int r = -EINVAL;
+
+       switch (reg->id) {
+       case KVM_REG_PPC_HIOR:
+               r = put_user(0, (u64 __user *)reg->addr);
+               break;
+       default:
+               break;
+       }
+
+       return r;
+}
+
+int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
+{
+       int r = -EINVAL;
+
+       switch (reg->id) {
+       case KVM_REG_PPC_HIOR:
+       {
+               u64 hior;
+               /* Only allow this to be set to zero */
+               r = get_user(hior, (u64 __user *)reg->addr);
+               if (!r && (hior != 0))
+                       r = -EINVAL;
+               break;
+       }
+       default:
+               break;
+       }
+
+       return r;
+}
+
 int kvmppc_core_check_processor_compat(void)
 {
        if (cpu_has_feature(CPU_FTR_HVMODE))
@@ -410,7 +453,7 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id)
                goto out;
 
        err = -ENOMEM;
-       vcpu = kzalloc(sizeof(struct kvm_vcpu), GFP_KERNEL);
+       vcpu = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL);
        if (!vcpu)
                goto out;
 
@@ -462,15 +505,21 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id)
        return vcpu;
 
 free_vcpu:
-       kfree(vcpu);
+       kmem_cache_free(kvm_vcpu_cache, vcpu);
 out:
        return ERR_PTR(err);
 }
 
 void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu)
 {
+       if (vcpu->arch.dtl)
+               kvmppc_unpin_guest_page(vcpu->kvm, vcpu->arch.dtl);
+       if (vcpu->arch.slb_shadow)
+               kvmppc_unpin_guest_page(vcpu->kvm, vcpu->arch.slb_shadow);
+       if (vcpu->arch.vpa)
+               kvmppc_unpin_guest_page(vcpu->kvm, vcpu->arch.vpa);
        kvm_vcpu_uninit(vcpu);
-       kfree(vcpu);
+       kmem_cache_free(kvm_vcpu_cache, vcpu);
 }
 
 static void kvmppc_set_timer(struct kvm_vcpu *vcpu)
@@ -481,7 +530,7 @@ static void kvmppc_set_timer(struct kvm_vcpu *vcpu)
        if (now > vcpu->arch.dec_expires) {
                /* decrementer has already gone negative */
                kvmppc_core_queue_dec(vcpu);
-               kvmppc_core_deliver_interrupts(vcpu);
+               kvmppc_core_prepare_to_enter(vcpu);
                return;
        }
        dec_nsec = (vcpu->arch.dec_expires - now) * NSEC_PER_SEC
@@ -796,7 +845,7 @@ static int kvmppc_run_vcpu(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 
                list_for_each_entry_safe(v, vn, &vc->runnable_threads,
                                         arch.run_list) {
-                       kvmppc_core_deliver_interrupts(v);
+                       kvmppc_core_prepare_to_enter(v);
                        if (signal_pending(v->arch.run_task)) {
                                kvmppc_remove_runnable(vc, v);
                                v->stat.signal_exits++;
@@ -835,20 +884,26 @@ int kvmppc_vcpu_run(struct kvm_run *run, struct kvm_vcpu *vcpu)
                return -EINVAL;
        }
 
+       kvmppc_core_prepare_to_enter(vcpu);
+
        /* No need to go into the guest when all we'll do is come back out */
        if (signal_pending(current)) {
                run->exit_reason = KVM_EXIT_INTR;
                return -EINTR;
        }
 
-       /* On PPC970, check that we have an RMA region */
-       if (!vcpu->kvm->arch.rma && cpu_has_feature(CPU_FTR_ARCH_201))
-               return -EPERM;
+       /* On the first time here, set up VRMA or RMA */
+       if (!vcpu->kvm->arch.rma_setup_done) {
+               r = kvmppc_hv_setup_rma(vcpu);
+               if (r)
+                       return r;
+       }
 
        flush_fp_to_thread(current);
        flush_altivec_to_thread(current);
        flush_vsx_to_thread(current);
        vcpu->arch.wqp = &vcpu->arch.vcore->wq;
+       vcpu->arch.pgdir = current->mm->pgd;
 
        do {
                r = kvmppc_run_vcpu(run, vcpu);
@@ -856,7 +911,7 @@ int kvmppc_vcpu_run(struct kvm_run *run, struct kvm_vcpu *vcpu)
                if (run->exit_reason == KVM_EXIT_PAPR_HCALL &&
                    !(vcpu->arch.shregs.msr & MSR_PR)) {
                        r = kvmppc_pseries_do_hcall(vcpu);
-                       kvmppc_core_deliver_interrupts(vcpu);
+                       kvmppc_core_prepare_to_enter(vcpu);
                }
        } while (r == RESUME_GUEST);
        return r;
@@ -1000,7 +1055,7 @@ static inline int lpcr_rmls(unsigned long rma_size)
 
 static int kvm_rma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
-       struct kvmppc_rma_info *ri = vma->vm_file->private_data;
+       struct kvmppc_linear_info *ri = vma->vm_file->private_data;
        struct page *page;
 
        if (vmf->pgoff >= ri->npages)
@@ -1025,7 +1080,7 @@ static int kvm_rma_mmap(struct file *file, struct vm_area_struct *vma)
 
 static int kvm_rma_release(struct inode *inode, struct file *filp)
 {
-       struct kvmppc_rma_info *ri = filp->private_data;
+       struct kvmppc_linear_info *ri = filp->private_data;
 
        kvm_release_rma(ri);
        return 0;
@@ -1038,7 +1093,7 @@ static struct file_operations kvm_rma_fops = {
 
 long kvm_vm_ioctl_allocate_rma(struct kvm *kvm, struct kvm_allocate_rma *ret)
 {
-       struct kvmppc_rma_info *ri;
+       struct kvmppc_linear_info *ri;
        long fd;
 
        ri = kvm_alloc_rma();
@@ -1053,89 +1108,189 @@ long kvm_vm_ioctl_allocate_rma(struct kvm *kvm, struct kvm_allocate_rma *ret)
        return fd;
 }
 
-static struct page *hva_to_page(unsigned long addr)
+/*
+ * Get (and clear) the dirty memory log for a memory slot.
+ */
+int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log)
 {
-       struct page *page[1];
-       int npages;
+       struct kvm_memory_slot *memslot;
+       int r;
+       unsigned long n;
 
-       might_sleep();
+       mutex_lock(&kvm->slots_lock);
 
-       npages = get_user_pages_fast(addr, 1, 1, page);
+       r = -EINVAL;
+       if (log->slot >= KVM_MEMORY_SLOTS)
+               goto out;
 
-       if (unlikely(npages != 1))
-               return 0;
+       memslot = id_to_memslot(kvm->memslots, log->slot);
+       r = -ENOENT;
+       if (!memslot->dirty_bitmap)
+               goto out;
+
+       n = kvm_dirty_bitmap_bytes(memslot);
+       memset(memslot->dirty_bitmap, 0, n);
+
+       r = kvmppc_hv_get_dirty_log(kvm, memslot);
+       if (r)
+               goto out;
 
-       return page[0];
+       r = -EFAULT;
+       if (copy_to_user(log->dirty_bitmap, memslot->dirty_bitmap, n))
+               goto out;
+
+       r = 0;
+out:
+       mutex_unlock(&kvm->slots_lock);
+       return r;
+}
+
+static unsigned long slb_pgsize_encoding(unsigned long psize)
+{
+       unsigned long senc = 0;
+
+       if (psize > 0x1000) {
+               senc = SLB_VSID_L;
+               if (psize == 0x10000)
+                       senc |= SLB_VSID_LP_01;
+       }
+       return senc;
 }
 
 int kvmppc_core_prepare_memory_region(struct kvm *kvm,
                                struct kvm_userspace_memory_region *mem)
 {
-       unsigned long psize, porder;
-       unsigned long i, npages, totalpages;
-       unsigned long pg_ix;
-       struct kvmppc_pginfo *pginfo;
-       unsigned long hva;
-       struct kvmppc_rma_info *ri = NULL;
+       unsigned long npages;
+       unsigned long *phys;
+
+       /* Allocate a slot_phys array */
+       phys = kvm->arch.slot_phys[mem->slot];
+       if (!kvm->arch.using_mmu_notifiers && !phys) {
+               npages = mem->memory_size >> PAGE_SHIFT;
+               phys = vzalloc(npages * sizeof(unsigned long));
+               if (!phys)
+                       return -ENOMEM;
+               kvm->arch.slot_phys[mem->slot] = phys;
+               kvm->arch.slot_npages[mem->slot] = npages;
+       }
+
+       return 0;
+}
+
+static void unpin_slot(struct kvm *kvm, int slot_id)
+{
+       unsigned long *physp;
+       unsigned long j, npages, pfn;
        struct page *page;
 
-       /* For now, only allow 16MB pages */
-       porder = LARGE_PAGE_ORDER;
-       psize = 1ul << porder;
-       if ((mem->memory_size & (psize - 1)) ||
-           (mem->guest_phys_addr & (psize - 1))) {
-               pr_err("bad memory_size=%llx @ %llx\n",
-                      mem->memory_size, mem->guest_phys_addr);
-               return -EINVAL;
+       physp = kvm->arch.slot_phys[slot_id];
+       npages = kvm->arch.slot_npages[slot_id];
+       if (physp) {
+               spin_lock(&kvm->arch.slot_phys_lock);
+               for (j = 0; j < npages; j++) {
+                       if (!(physp[j] & KVMPPC_GOT_PAGE))
+                               continue;
+                       pfn = physp[j] >> PAGE_SHIFT;
+                       page = pfn_to_page(pfn);
+                       if (PageHuge(page))
+                               page = compound_head(page);
+                       SetPageDirty(page);
+                       put_page(page);
+               }
+               kvm->arch.slot_phys[slot_id] = NULL;
+               spin_unlock(&kvm->arch.slot_phys_lock);
+               vfree(physp);
        }
+}
 
-       npages = mem->memory_size >> porder;
-       totalpages = (mem->guest_phys_addr + mem->memory_size) >> porder;
+void kvmppc_core_commit_memory_region(struct kvm *kvm,
+                               struct kvm_userspace_memory_region *mem)
+{
+}
 
-       /* More memory than we have space to track? */
-       if (totalpages > (1ul << (MAX_MEM_ORDER - LARGE_PAGE_ORDER)))
-               return -EINVAL;
+static int kvmppc_hv_setup_rma(struct kvm_vcpu *vcpu)
+{
+       int err = 0;
+       struct kvm *kvm = vcpu->kvm;
+       struct kvmppc_linear_info *ri = NULL;
+       unsigned long hva;
+       struct kvm_memory_slot *memslot;
+       struct vm_area_struct *vma;
+       unsigned long lpcr, senc;
+       unsigned long psize, porder;
+       unsigned long rma_size;
+       unsigned long rmls;
+       unsigned long *physp;
+       unsigned long i, npages;
 
-       /* Do we already have an RMA registered? */
-       if (mem->guest_phys_addr == 0 && kvm->arch.rma)
-               return -EINVAL;
+       mutex_lock(&kvm->lock);
+       if (kvm->arch.rma_setup_done)
+               goto out;       /* another vcpu beat us to it */
 
-       if (totalpages > kvm->arch.ram_npages)
-               kvm->arch.ram_npages = totalpages;
+       /* Look up the memslot for guest physical address 0 */
+       memslot = gfn_to_memslot(kvm, 0);
+
+       /* We must have some memory at 0 by now */
+       err = -EINVAL;
+       if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID))
+               goto out;
+
+       /* Look up the VMA for the start of this memory slot */
+       hva = memslot->userspace_addr;
+       down_read(&current->mm->mmap_sem);
+       vma = find_vma(current->mm, hva);
+       if (!vma || vma->vm_start > hva || (vma->vm_flags & VM_IO))
+               goto up_out;
+
+       psize = vma_kernel_pagesize(vma);
+       porder = __ilog2(psize);
 
        /* Is this one of our preallocated RMAs? */
-       if (mem->guest_phys_addr == 0) {
-               struct vm_area_struct *vma;
-
-               down_read(&current->mm->mmap_sem);
-               vma = find_vma(current->mm, mem->userspace_addr);
-               if (vma && vma->vm_file &&
-                   vma->vm_file->f_op == &kvm_rma_fops &&
-                   mem->userspace_addr == vma->vm_start)
-                       ri = vma->vm_file->private_data;
-               up_read(&current->mm->mmap_sem);
-               if (!ri && cpu_has_feature(CPU_FTR_ARCH_201)) {
-                       pr_err("CPU requires an RMO\n");
-                       return -EINVAL;
+       if (vma->vm_file && vma->vm_file->f_op == &kvm_rma_fops &&
+           hva == vma->vm_start)
+               ri = vma->vm_file->private_data;
+
+       up_read(&current->mm->mmap_sem);
+
+       if (!ri) {
+               /* On POWER7, use VRMA; on PPC970, give up */
+               err = -EPERM;
+               if (cpu_has_feature(CPU_FTR_ARCH_201)) {
+                       pr_err("KVM: CPU requires an RMO\n");
+                       goto out;
                }
-       }
 
-       if (ri) {
-               unsigned long rma_size;
-               unsigned long lpcr;
-               long rmls;
+               /* We can handle 4k, 64k or 16M pages in the VRMA */
+               err = -EINVAL;
+               if (!(psize == 0x1000 || psize == 0x10000 ||
+                     psize == 0x1000000))
+                       goto out;
+
+               /* Update VRMASD field in the LPCR */
+               senc = slb_pgsize_encoding(psize);
+               kvm->arch.vrma_slb_v = senc | SLB_VSID_B_1T |
+                       (VRMA_VSID << SLB_VSID_SHIFT_1T);
+               lpcr = kvm->arch.lpcr & ~LPCR_VRMASD;
+               lpcr |= senc << (LPCR_VRMASD_SH - 4);
+               kvm->arch.lpcr = lpcr;
 
-               rma_size = ri->npages << PAGE_SHIFT;
-               if (rma_size > mem->memory_size)
-                       rma_size = mem->memory_size;
+               /* Create HPTEs in the hash page table for the VRMA */
+               kvmppc_map_vrma(vcpu, memslot, porder);
+
+       } else {
+               /* Set up to use an RMO region */
+               rma_size = ri->npages;
+               if (rma_size > memslot->npages)
+                       rma_size = memslot->npages;
+               rma_size <<= PAGE_SHIFT;
                rmls = lpcr_rmls(rma_size);
+               err = -EINVAL;
                if (rmls < 0) {
-                       pr_err("Can't use RMA of 0x%lx bytes\n", rma_size);
-                       return -EINVAL;
+                       pr_err("KVM: Can't use RMA of 0x%lx bytes\n", rma_size);
+                       goto out;
                }
                atomic_inc(&ri->use_count);
                kvm->arch.rma = ri;
-               kvm->arch.n_rma_pages = rma_size >> porder;
 
                /* Update LPCR and RMOR */
                lpcr = kvm->arch.lpcr;
@@ -1155,53 +1310,35 @@ int kvmppc_core_prepare_memory_region(struct kvm *kvm,
                        kvm->arch.rmor = kvm->arch.rma->base_pfn << PAGE_SHIFT;
                }
                kvm->arch.lpcr = lpcr;
-               pr_info("Using RMO at %lx size %lx (LPCR = %lx)\n",
+               pr_info("KVM: Using RMO at %lx size %lx (LPCR = %lx)\n",
                        ri->base_pfn << PAGE_SHIFT, rma_size, lpcr);
-       }
 
-       pg_ix = mem->guest_phys_addr >> porder;
-       pginfo = kvm->arch.ram_pginfo + pg_ix;
-       for (i = 0; i < npages; ++i, ++pg_ix) {
-               if (ri && pg_ix < kvm->arch.n_rma_pages) {
-                       pginfo[i].pfn = ri->base_pfn +
-                               (pg_ix << (porder - PAGE_SHIFT));
-                       continue;
-               }
-               hva = mem->userspace_addr + (i << porder);
-               page = hva_to_page(hva);
-               if (!page) {
-                       pr_err("oops, no pfn for hva %lx\n", hva);
-                       goto err;
-               }
-               /* Check it's a 16MB page */
-               if (!PageHead(page) ||
-                   compound_order(page) != (LARGE_PAGE_ORDER - PAGE_SHIFT)) {
-                       pr_err("page at %lx isn't 16MB (o=%d)\n",
-                              hva, compound_order(page));
-                       goto err;
-               }
-               pginfo[i].pfn = page_to_pfn(page);
+               /* Initialize phys addrs of pages in RMO */
+               npages = ri->npages;
+               porder = __ilog2(npages);
+               physp = kvm->arch.slot_phys[memslot->id];
+               spin_lock(&kvm->arch.slot_phys_lock);
+               for (i = 0; i < npages; ++i)
+                       physp[i] = ((ri->base_pfn + i) << PAGE_SHIFT) + porder;
+               spin_unlock(&kvm->arch.slot_phys_lock);
        }
 
-       return 0;
-
- err:
-       return -EINVAL;
-}
+       /* Order updates to kvm->arch.lpcr etc. vs. rma_setup_done */
+       smp_wmb();
+       kvm->arch.rma_setup_done = 1;
+       err = 0;
+ out:
+       mutex_unlock(&kvm->lock);
+       return err;
 
-void kvmppc_core_commit_memory_region(struct kvm *kvm,
-                               struct kvm_userspace_memory_region *mem)
-{
-       if (mem->guest_phys_addr == 0 && mem->memory_size != 0 &&
-           !kvm->arch.rma)
-               kvmppc_map_vrma(kvm, mem);
+ up_out:
+       up_read(&current->mm->mmap_sem);
+       goto out;
 }
 
 int kvmppc_core_init_vm(struct kvm *kvm)
 {
        long r;
-       unsigned long npages = 1ul << (MAX_MEM_ORDER - LARGE_PAGE_ORDER);
-       long err = -ENOMEM;
        unsigned long lpcr;
 
        /* Allocate hashed page table */
@@ -1211,19 +1348,7 @@ int kvmppc_core_init_vm(struct kvm *kvm)
 
        INIT_LIST_HEAD(&kvm->arch.spapr_tce_tables);
 
-       kvm->arch.ram_pginfo = kzalloc(npages * sizeof(struct kvmppc_pginfo),
-                                      GFP_KERNEL);
-       if (!kvm->arch.ram_pginfo) {
-               pr_err("kvmppc_core_init_vm: couldn't alloc %lu bytes\n",
-                      npages * sizeof(struct kvmppc_pginfo));
-               goto out_free;
-       }
-
-       kvm->arch.ram_npages = 0;
-       kvm->arch.ram_psize = 1ul << LARGE_PAGE_ORDER;
-       kvm->arch.ram_porder = LARGE_PAGE_ORDER;
        kvm->arch.rma = NULL;
-       kvm->arch.n_rma_pages = 0;
 
        kvm->arch.host_sdr1 = mfspr(SPRN_SDR1);
 
@@ -1241,30 +1366,25 @@ int kvmppc_core_init_vm(struct kvm *kvm)
                kvm->arch.host_lpcr = lpcr = mfspr(SPRN_LPCR);
                lpcr &= LPCR_PECE | LPCR_LPES;
                lpcr |= (4UL << LPCR_DPFD_SH) | LPCR_HDICE |
-                       LPCR_VPM0 | LPCR_VRMA_L;
+                       LPCR_VPM0 | LPCR_VPM1;
+               kvm->arch.vrma_slb_v = SLB_VSID_B_1T |
+                       (VRMA_VSID << SLB_VSID_SHIFT_1T);
        }
        kvm->arch.lpcr = lpcr;
 
+       kvm->arch.using_mmu_notifiers = !!cpu_has_feature(CPU_FTR_ARCH_206);
+       spin_lock_init(&kvm->arch.slot_phys_lock);
        return 0;
-
- out_free:
-       kvmppc_free_hpt(kvm);
-       return err;
 }
 
 void kvmppc_core_destroy_vm(struct kvm *kvm)
 {
-       struct kvmppc_pginfo *pginfo;
        unsigned long i;
 
-       if (kvm->arch.ram_pginfo) {
-               pginfo = kvm->arch.ram_pginfo;
-               kvm->arch.ram_pginfo = NULL;
-               for (i = kvm->arch.n_rma_pages; i < kvm->arch.ram_npages; ++i)
-                       if (pginfo[i].pfn)
-                               put_page(pfn_to_page(pginfo[i].pfn));
-               kfree(pginfo);
-       }
+       if (!kvm->arch.using_mmu_notifiers)
+               for (i = 0; i < KVM_MEM_SLOTS_NUM; i++)
+                       unpin_slot(kvm, i);
+
        if (kvm->arch.rma) {
                kvm_release_rma(kvm->arch.rma);
                kvm->arch.rma = NULL;
index a795a13..bed1279 100644 (file)
 #include <asm/kvm_ppc.h>
 #include <asm/kvm_book3s.h>
 
+#define KVM_LINEAR_RMA         0
+#define KVM_LINEAR_HPT         1
+
+static void __init kvm_linear_init_one(ulong size, int count, int type);
+static struct kvmppc_linear_info *kvm_alloc_linear(int type);
+static void kvm_release_linear(struct kvmppc_linear_info *ri);
+
+/*************** RMA *************/
+
 /*
  * This maintains a list of RMAs (real mode areas) for KVM guests to use.
  * Each RMA has to be physically contiguous and of a size that the
 static unsigned long kvm_rma_size = 64 << 20;  /* 64MB */
 static unsigned long kvm_rma_count;
 
-static int __init early_parse_rma_size(char *p)
-{
-       if (!p)
-               return 1;
-
-       kvm_rma_size = memparse(p, &p);
-
-       return 0;
-}
-early_param("kvm_rma_size", early_parse_rma_size);
-
-static int __init early_parse_rma_count(char *p)
-{
-       if (!p)
-               return 1;
-
-       kvm_rma_count = simple_strtoul(p, NULL, 0);
-
-       return 0;
-}
-early_param("kvm_rma_count", early_parse_rma_count);
-
-static struct kvmppc_rma_info *rma_info;
-static LIST_HEAD(free_rmas);
-static DEFINE_SPINLOCK(rma_lock);
-
 /* Work out RMLS (real mode limit selector) field value for a given RMA size.
    Assumes POWER7 or PPC970. */
 static inline int lpcr_rmls(unsigned long rma_size)
@@ -81,45 +64,106 @@ static inline int lpcr_rmls(unsigned long rma_size)
        }
 }
 
+static int __init early_parse_rma_size(char *p)
+{
+       if (!p)
+               return 1;
+
+       kvm_rma_size = memparse(p, &p);
+
+       return 0;
+}
+early_param("kvm_rma_size", early_parse_rma_size);
+
+static int __init early_parse_rma_count(char *p)
+{
+       if (!p)
+               return 1;
+
+       kvm_rma_count = simple_strtoul(p, NULL, 0);
+
+       return 0;
+}
+early_param("kvm_rma_count", early_parse_rma_count);
+
+struct kvmppc_linear_info *kvm_alloc_rma(void)
+{
+       return kvm_alloc_linear(KVM_LINEAR_RMA);
+}
+EXPORT_SYMBOL_GPL(kvm_alloc_rma);
+
+void kvm_release_rma(struct kvmppc_linear_info *ri)
+{
+       kvm_release_linear(ri);
+}
+EXPORT_SYMBOL_GPL(kvm_release_rma);
+
+/*************** HPT *************/
+
 /*
- * Called at boot time while the bootmem allocator is active,
- * to allocate contiguous physical memory for the real memory
- * areas for guests.
+ * This maintains a list of big linear HPT tables that contain the GVA->HPA
+ * memory mappings. If we don't reserve those early on, we might not be able
+ * to get a big (usually 16MB) linear memory region from the kernel anymore.
  */
-void __init kvm_rma_init(void)
+
+static unsigned long kvm_hpt_count;
+
+static int __init early_parse_hpt_count(char *p)
+{
+       if (!p)
+               return 1;
+
+       kvm_hpt_count = simple_strtoul(p, NULL, 0);
+
+       return 0;
+}
+early_param("kvm_hpt_count", early_parse_hpt_count);
+
+struct kvmppc_linear_info *kvm_alloc_hpt(void)
+{
+       return kvm_alloc_linear(KVM_LINEAR_HPT);
+}
+EXPORT_SYMBOL_GPL(kvm_alloc_hpt);
+
+void kvm_release_hpt(struct kvmppc_linear_info *li)
+{
+       kvm_release_linear(li);
+}
+EXPORT_SYMBOL_GPL(kvm_release_hpt);
+
+/*************** generic *************/
+
+static LIST_HEAD(free_linears);
+static DEFINE_SPINLOCK(linear_lock);
+
+static void __init kvm_linear_init_one(ulong size, int count, int type)
 {
        unsigned long i;
        unsigned long j, npages;
-       void *rma;
+       void *linear;
        struct page *pg;
+       const char *typestr;
+       struct kvmppc_linear_info *linear_info;
 
-       /* Only do this on PPC970 in HV mode */
-       if (!cpu_has_feature(CPU_FTR_HVMODE) ||
-           !cpu_has_feature(CPU_FTR_ARCH_201))
-               return;
-
-       if (!kvm_rma_size || !kvm_rma_count)
+       if (!count)
                return;
 
-       /* Check that the requested size is one supported in hardware */
-       if (lpcr_rmls(kvm_rma_size) < 0) {
-               pr_err("RMA size of 0x%lx not supported\n", kvm_rma_size);
-               return;
-       }
-
-       npages = kvm_rma_size >> PAGE_SHIFT;
-       rma_info = alloc_bootmem(kvm_rma_count * sizeof(struct kvmppc_rma_info));
-       for (i = 0; i < kvm_rma_count; ++i) {
-               rma = alloc_bootmem_align(kvm_rma_size, kvm_rma_size);
-               pr_info("Allocated KVM RMA at %p (%ld MB)\n", rma,
-                       kvm_rma_size >> 20);
-               rma_info[i].base_virt = rma;
-               rma_info[i].base_pfn = __pa(rma) >> PAGE_SHIFT;
-               rma_info[i].npages = npages;
-               list_add_tail(&rma_info[i].list, &free_rmas);
-               atomic_set(&rma_info[i].use_count, 0);
-
-               pg = pfn_to_page(rma_info[i].base_pfn);
+       typestr = (type == KVM_LINEAR_RMA) ? "RMA" : "HPT";
+
+       npages = size >> PAGE_SHIFT;
+       linear_info = alloc_bootmem(count * sizeof(struct kvmppc_linear_info));
+       for (i = 0; i < count; ++i) {
+               linear = alloc_bootmem_align(size, size);
+               pr_info("Allocated KVM %s at %p (%ld MB)\n", typestr, linear,
+                       size >> 20);
+               linear_info[i].base_virt = linear;
+               linear_info[i].base_pfn = __pa(linear) >> PAGE_SHIFT;
+               linear_info[i].npages = npages;
+               linear_info[i].type = type;
+               list_add_tail(&linear_info[i].list, &free_linears);
+               atomic_set(&linear_info[i].use_count, 0);
+
+               pg = pfn_to_page(linear_info[i].base_pfn);
                for (j = 0; j < npages; ++j) {
                        atomic_inc(&pg->_count);
                        ++pg;
@@ -127,30 +171,59 @@ void __init kvm_rma_init(void)
        }
 }
 
-struct kvmppc_rma_info *kvm_alloc_rma(void)
+static struct kvmppc_linear_info *kvm_alloc_linear(int type)
 {
-       struct kvmppc_rma_info *ri;
+       struct kvmppc_linear_info *ri;
 
        ri = NULL;
-       spin_lock(&rma_lock);
-       if (!list_empty(&free_rmas)) {
-               ri = list_first_entry(&free_rmas, struct kvmppc_rma_info, list);
+       spin_lock(&linear_lock);
+       list_for_each_entry(ri, &free_linears, list) {
+               if (ri->type != type)
+                       continue;
+
                list_del(&ri->list);
                atomic_inc(&ri->use_count);
+               break;
        }
-       spin_unlock(&rma_lock);
+       spin_unlock(&linear_lock);
+       memset(ri->base_virt, 0, ri->npages << PAGE_SHIFT);
        return ri;
 }
-EXPORT_SYMBOL_GPL(kvm_alloc_rma);
 
-void kvm_release_rma(struct kvmppc_rma_info *ri)
+static void kvm_release_linear(struct kvmppc_linear_info *ri)
 {
        if (atomic_dec_and_test(&ri->use_count)) {
-               spin_lock(&rma_lock);
-               list_add_tail(&ri->list, &free_rmas);
-               spin_unlock(&rma_lock);
+               spin_lock(&linear_lock);
+               list_add_tail(&ri->list, &free_linears);
+               spin_unlock(&linear_lock);
 
        }
 }
-EXPORT_SYMBOL_GPL(kvm_release_rma);
 
+/*
+ * Called at boot time while the bootmem allocator is active,
+ * to allocate contiguous physical memory for the hash page
+ * tables for guests.
+ */
+void __init kvm_linear_init(void)
+{
+       /* HPT */
+       kvm_linear_init_one(1 << HPT_ORDER, kvm_hpt_count, KVM_LINEAR_HPT);
+
+       /* RMA */
+       /* Only do this on PPC970 in HV mode */
+       if (!cpu_has_feature(CPU_FTR_HVMODE) ||
+           !cpu_has_feature(CPU_FTR_ARCH_201))
+               return;
+
+       if (!kvm_rma_size || !kvm_rma_count)
+               return;
+
+       /* Check that the requested size is one supported in hardware */
+       if (lpcr_rmls(kvm_rma_size) < 0) {
+               pr_err("RMA size of 0x%lx not supported\n", kvm_rma_size);
+               return;
+       }
+
+       kvm_linear_init_one(kvm_rma_size, kvm_rma_count, KVM_LINEAR_RMA);
+}
index bacb0cf..def880a 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
 #include <linux/hugetlb.h>
+#include <linux/module.h>
 
 #include <asm/tlbflush.h>
 #include <asm/kvm_ppc.h>
 #include <asm/synch.h>
 #include <asm/ppc-opcode.h>
 
-/* For now use fixed-size 16MB page table */
-#define HPT_ORDER      24
-#define HPT_NPTEG      (1ul << (HPT_ORDER - 7))        /* 128B per pteg */
-#define HPT_HASH_MASK  (HPT_NPTEG - 1)
+/* Translate address of a vmalloc'd thing to a linear map address */
+static void *real_vmalloc_addr(void *x)
+{
+       unsigned long addr = (unsigned long) x;
+       pte_t *p;
 
-#define HPTE_V_HVLOCK  0x40UL
+       p = find_linux_pte(swapper_pg_dir, addr);
+       if (!p || !pte_present(*p))
+               return NULL;
+       /* assume we don't have huge pages in vmalloc space... */
+       addr = (pte_pfn(*p) << PAGE_SHIFT) | (addr & ~PAGE_MASK);
+       return __va(addr);
+}
 
-static inline long lock_hpte(unsigned long *hpte, unsigned long bits)
+/*
+ * Add this HPTE into the chain for the real page.
+ * Must be called with the chain locked; it unlocks the chain.
+ */
+void kvmppc_add_revmap_chain(struct kvm *kvm, struct revmap_entry *rev,
+                            unsigned long *rmap, long pte_index, int realmode)
 {
-       unsigned long tmp, old;
+       struct revmap_entry *head, *tail;
+       unsigned long i;
 
-       asm volatile("  ldarx   %0,0,%2\n"
-                    "  and.    %1,%0,%3\n"
-                    "  bne     2f\n"
-                    "  ori     %0,%0,%4\n"
-                    "  stdcx.  %0,0,%2\n"
-                    "  beq+    2f\n"
-                    "  li      %1,%3\n"
-                    "2:        isync"
-                    : "=&r" (tmp), "=&r" (old)
-                    : "r" (hpte), "r" (bits), "i" (HPTE_V_HVLOCK)
-                    : "cc", "memory");
-       return old == 0;
+       if (*rmap & KVMPPC_RMAP_PRESENT) {
+               i = *rmap & KVMPPC_RMAP_INDEX;
+               head = &kvm->arch.revmap[i];
+               if (realmode)
+                       head = real_vmalloc_addr(head);
+               tail = &kvm->arch.revmap[head->back];
+               if (realmode)
+                       tail = real_vmalloc_addr(tail);
+               rev->forw = i;
+               rev->back = head->back;
+               tail->forw = pte_index;
+               head->back = pte_index;
+       } else {
+               rev->forw = rev->back = pte_index;
+               i = pte_index;
+       }
+       smp_wmb();
+       *rmap = i | KVMPPC_RMAP_REFERENCED | KVMPPC_RMAP_PRESENT; /* unlock */
+}
+EXPORT_SYMBOL_GPL(kvmppc_add_revmap_chain);
+
+/* Remove this HPTE from the chain for a real page */
+static void remove_revmap_chain(struct kvm *kvm, long pte_index,
+                               struct revmap_entry *rev,
+                               unsigned long hpte_v, unsigned long hpte_r)
+{
+       struct revmap_entry *next, *prev;
+       unsigned long gfn, ptel, head;
+       struct kvm_memory_slot *memslot;
+       unsigned long *rmap;
+       unsigned long rcbits;
+
+       rcbits = hpte_r & (HPTE_R_R | HPTE_R_C);
+       ptel = rev->guest_rpte |= rcbits;
+       gfn = hpte_rpn(ptel, hpte_page_size(hpte_v, ptel));
+       memslot = __gfn_to_memslot(kvm_memslots(kvm), gfn);
+       if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID))
+               return;
+
+       rmap = real_vmalloc_addr(&memslot->rmap[gfn - memslot->base_gfn]);
+       lock_rmap(rmap);
+
+       head = *rmap & KVMPPC_RMAP_INDEX;
+       next = real_vmalloc_addr(&kvm->arch.revmap[rev->forw]);
+       prev = real_vmalloc_addr(&kvm->arch.revmap[rev->back]);
+       next->back = rev->back;
+       prev->forw = rev->forw;
+       if (head == pte_index) {
+               head = rev->forw;
+               if (head == pte_index)
+                       *rmap &= ~(KVMPPC_RMAP_PRESENT | KVMPPC_RMAP_INDEX);
+               else
+                       *rmap = (*rmap & ~KVMPPC_RMAP_INDEX) | head;
+       }
+       *rmap |= rcbits << KVMPPC_RMAP_RC_SHIFT;
+       unlock_rmap(rmap);
+}
+
+static pte_t lookup_linux_pte(struct kvm_vcpu *vcpu, unsigned long hva,
+                             int writing, unsigned long *pte_sizep)
+{
+       pte_t *ptep;
+       unsigned long ps = *pte_sizep;
+       unsigned int shift;
+
+       ptep = find_linux_pte_or_hugepte(vcpu->arch.pgdir, hva, &shift);
+       if (!ptep)
+               return __pte(0);
+       if (shift)
+               *pte_sizep = 1ul << shift;
+       else
+               *pte_sizep = PAGE_SIZE;
+       if (ps > *pte_sizep)
+               return __pte(0);
+       if (!pte_present(*ptep))
+               return __pte(0);
+       return kvmppc_read_update_linux_pte(ptep, writing);
+}
+
+static inline void unlock_hpte(unsigned long *hpte, unsigned long hpte_v)
+{
+       asm volatile(PPC_RELEASE_BARRIER "" : : : "memory");
+       hpte[0] = hpte_v;
 }
 
 long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
                    long pte_index, unsigned long pteh, unsigned long ptel)
 {
-       unsigned long porder;
        struct kvm *kvm = vcpu->kvm;
-       unsigned long i, lpn, pa;
+       unsigned long i, pa, gpa, gfn, psize;
+       unsigned long slot_fn, hva;
        unsigned long *hpte;
+       struct revmap_entry *rev;
+       unsigned long g_ptel = ptel;
+       struct kvm_memory_slot *memslot;
+       unsigned long *physp, pte_size;
+       unsigned long is_io;
+       unsigned long *rmap;
+       pte_t pte;
+       unsigned int writing;
+       unsigned long mmu_seq;
+       unsigned long rcbits;
+       bool realmode = vcpu->arch.vcore->vcore_state == VCORE_RUNNING;
 
-       /* only handle 4k, 64k and 16M pages for now */
-       porder = 12;
-       if (pteh & HPTE_V_LARGE) {
-               if (cpu_has_feature(CPU_FTR_ARCH_206) &&
-                   (ptel & 0xf000) == 0x1000) {
-                       /* 64k page */
-                       porder = 16;
-               } else if ((ptel & 0xff000) == 0) {
-                       /* 16M page */
-                       porder = 24;
-                       /* lowest AVA bit must be 0 for 16M pages */
-                       if (pteh & 0x80)
-                               return H_PARAMETER;
-               } else
+       psize = hpte_page_size(pteh, ptel);
+       if (!psize)
+               return H_PARAMETER;
+       writing = hpte_is_writable(ptel);
+       pteh &= ~(HPTE_V_HVLOCK | HPTE_V_ABSENT | HPTE_V_VALID);
+
+       /* used later to detect if we might have been invalidated */
+       mmu_seq = kvm->mmu_notifier_seq;
+       smp_rmb();
+
+       /* Find the memslot (if any) for this address */
+       gpa = (ptel & HPTE_R_RPN) & ~(psize - 1);
+       gfn = gpa >> PAGE_SHIFT;
+       memslot = __gfn_to_memslot(kvm_memslots(kvm), gfn);
+       pa = 0;
+       is_io = ~0ul;
+       rmap = NULL;
+       if (!(memslot && !(memslot->flags & KVM_MEMSLOT_INVALID))) {
+               /* PPC970 can't do emulated MMIO */
+               if (!cpu_has_feature(CPU_FTR_ARCH_206))
                        return H_PARAMETER;
+               /* Emulated MMIO - mark this with key=31 */
+               pteh |= HPTE_V_ABSENT;
+               ptel |= HPTE_R_KEY_HI | HPTE_R_KEY_LO;
+               goto do_insert;
        }
-       lpn = (ptel & HPTE_R_RPN) >> kvm->arch.ram_porder;
-       if (lpn >= kvm->arch.ram_npages || porder > kvm->arch.ram_porder)
-               return H_PARAMETER;
-       pa = kvm->arch.ram_pginfo[lpn].pfn << PAGE_SHIFT;
-       if (!pa)
+
+       /* Check if the requested page fits entirely in the memslot. */
+       if (!slot_is_aligned(memslot, psize))
                return H_PARAMETER;
-       /* Check WIMG */
-       if ((ptel & HPTE_R_WIMG) != HPTE_R_M &&
-           (ptel & HPTE_R_WIMG) != (HPTE_R_W | HPTE_R_I | HPTE_R_M))
+       slot_fn = gfn - memslot->base_gfn;
+       rmap = &memslot->rmap[slot_fn];
+
+       if (!kvm->arch.using_mmu_notifiers) {
+               physp = kvm->arch.slot_phys[memslot->id];
+               if (!physp)
+                       return H_PARAMETER;
+               physp += slot_fn;
+               if (realmode)
+                       physp = real_vmalloc_addr(physp);
+               pa = *physp;
+               if (!pa)
+                       return H_TOO_HARD;
+               is_io = pa & (HPTE_R_I | HPTE_R_W);
+               pte_size = PAGE_SIZE << (pa & KVMPPC_PAGE_ORDER_MASK);
+               pa &= PAGE_MASK;
+       } else {
+               /* Translate to host virtual address */
+               hva = gfn_to_hva_memslot(memslot, gfn);
+
+               /* Look up the Linux PTE for the backing page */
+               pte_size = psize;
+               pte = lookup_linux_pte(vcpu, hva, writing, &pte_size);
+               if (pte_present(pte)) {
+                       if (writing && !pte_write(pte))
+                               /* make the actual HPTE be read-only */
+                               ptel = hpte_make_readonly(ptel);
+                       is_io = hpte_cache_bits(pte_val(pte));
+                       pa = pte_pfn(pte) << PAGE_SHIFT;
+               }
+       }
+       if (pte_size < psize)
                return H_PARAMETER;
-       pteh &= ~0x60UL;
-       ptel &= ~(HPTE_R_PP0 - kvm->arch.ram_psize);
+       if (pa && pte_size > psize)
+               pa |= gpa & (pte_size - 1);
+
+       ptel &= ~(HPTE_R_PP0 - psize);
        ptel |= pa;
-       if (pte_index >= (HPT_NPTEG << 3))
+
+       if (pa)
+               pteh |= HPTE_V_VALID;
+       else
+               pteh |= HPTE_V_ABSENT;
+
+       /* Check WIMG */
+       if (is_io != ~0ul && !hpte_cache_flags_ok(ptel, is_io)) {
+               if (is_io)
+                       return H_PARAMETER;
+               /*
+                * Allow guest to map emulated device memory as
+                * uncacheable, but actually make it cacheable.
+                */
+               ptel &= ~(HPTE_R_W|HPTE_R_I|HPTE_R_G);
+               ptel |= HPTE_R_M;
+       }
+
+       /* Find and lock the HPTEG slot to use */
+ do_insert:
+       if (pte_index >= HPT_NPTE)
                return H_PARAMETER;
        if (likely((flags & H_EXACT) == 0)) {
                pte_index &= ~7UL;
                hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
-               for (i = 0; ; ++i) {
-                       if (i == 8)
-                               return H_PTEG_FULL;
+               for (i = 0; i < 8; ++i) {
                        if ((*hpte & HPTE_V_VALID) == 0 &&
-                           lock_hpte(hpte, HPTE_V_HVLOCK | HPTE_V_VALID))
+                           try_lock_hpte(hpte, HPTE_V_HVLOCK | HPTE_V_VALID |
+                                         HPTE_V_ABSENT))
                                break;
                        hpte += 2;
                }
+               if (i == 8) {
+                       /*
+                        * Since try_lock_hpte doesn't retry (not even stdcx.
+                        * failures), it could be that there is a free slot
+                        * but we transiently failed to lock it.  Try again,
+                        * actually locking each slot and checking it.
+                        */
+                       hpte -= 16;
+                       for (i = 0; i < 8; ++i) {
+                               while (!try_lock_hpte(hpte, HPTE_V_HVLOCK))
+                                       cpu_relax();
+                               if (!(*hpte & (HPTE_V_VALID | HPTE_V_ABSENT)))
+                                       break;
+                               *hpte &= ~HPTE_V_HVLOCK;
+                               hpte += 2;
+                       }
+                       if (i == 8)
+                               return H_PTEG_FULL;
+               }
+               pte_index += i;
        } else {
-               i = 0;
                hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
-               if (!lock_hpte(hpte, HPTE_V_HVLOCK | HPTE_V_VALID))
-                       return H_PTEG_FULL;
+               if (!try_lock_hpte(hpte, HPTE_V_HVLOCK | HPTE_V_VALID |
+                                  HPTE_V_ABSENT)) {
+                       /* Lock the slot and check again */
+                       while (!try_lock_hpte(hpte, HPTE_V_HVLOCK))
+                               cpu_relax();
+                       if (*hpte & (HPTE_V_VALID | HPTE_V_ABSENT)) {
+                               *hpte &= ~HPTE_V_HVLOCK;
+                               return H_PTEG_FULL;
+                       }
+               }
        }
+
+       /* Save away the guest's idea of the second HPTE dword */
+       rev = &kvm->arch.revmap[pte_index];
+       if (realmode)
+               rev = real_vmalloc_addr(rev);
+       if (rev)
+               rev->guest_rpte = g_ptel;
+
+       /* Link HPTE into reverse-map chain */
+       if (pteh & HPTE_V_VALID) {
+               if (realmode)
+                       rmap = real_vmalloc_addr(rmap);
+               lock_rmap(rmap);
+               /* Check for pending invalidations under the rmap chain lock */
+               if (kvm->arch.using_mmu_notifiers &&
+                   mmu_notifier_retry(vcpu, mmu_seq)) {
+                       /* inval in progress, write a non-present HPTE */
+                       pteh |= HPTE_V_ABSENT;
+                       pteh &= ~HPTE_V_VALID;
+                       unlock_rmap(rmap);
+               } else {
+                       kvmppc_add_revmap_chain(kvm, rev, rmap, pte_index,
+                                               realmode);
+                       /* Only set R/C in real HPTE if already set in *rmap */
+                       rcbits = *rmap >> KVMPPC_RMAP_RC_SHIFT;
+                       ptel &= rcbits | ~(HPTE_R_R | HPTE_R_C);
+               }
+       }
+
        hpte[1] = ptel;
+
+       /* Write the first HPTE dword, unlocking the HPTE and making it valid */
        eieio();
        hpte[0] = pteh;
        asm volatile("ptesync" : : : "memory");
-       atomic_inc(&kvm->arch.ram_pginfo[lpn].refcnt);
-       vcpu->arch.gpr[4] = pte_index + i;
+
+       vcpu->arch.gpr[4] = pte_index;
        return H_SUCCESS;
 }
+EXPORT_SYMBOL_GPL(kvmppc_h_enter);
 
 #define LOCK_TOKEN     (*(u32 *)(&get_paca()->lock_token))
 
@@ -137,37 +350,46 @@ long kvmppc_h_remove(struct kvm_vcpu *vcpu, unsigned long flags,
        struct kvm *kvm = vcpu->kvm;
        unsigned long *hpte;
        unsigned long v, r, rb;
+       struct revmap_entry *rev;
 
-       if (pte_index >= (HPT_NPTEG << 3))
+       if (pte_index >= HPT_NPTE)
                return H_PARAMETER;
        hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
-       while (!lock_hpte(hpte, HPTE_V_HVLOCK))
+       while (!try_lock_hpte(hpte, HPTE_V_HVLOCK))
                cpu_relax();
-       if ((hpte[0] & HPTE_V_VALID) == 0 ||
+       if ((hpte[0] & (HPTE_V_ABSENT | HPTE_V_VALID)) == 0 ||
            ((flags & H_AVPN) && (hpte[0] & ~0x7fUL) != avpn) ||
            ((flags & H_ANDCOND) && (hpte[0] & avpn) != 0)) {
                hpte[0] &= ~HPTE_V_HVLOCK;
                return H_NOT_FOUND;
        }
-       if (atomic_read(&kvm->online_vcpus) == 1)
-               flags |= H_LOCAL;
-       vcpu->arch.gpr[4] = v = hpte[0] & ~HPTE_V_HVLOCK;
-       vcpu->arch.gpr[5] = r = hpte[1];
-       rb = compute_tlbie_rb(v, r, pte_index);
-       hpte[0] = 0;
-       if (!(flags & H_LOCAL)) {
-               while(!try_lock_tlbie(&kvm->arch.tlbie_lock))
-                       cpu_relax();
-               asm volatile("ptesync" : : : "memory");
-               asm volatile(PPC_TLBIE(%1,%0)"; eieio; tlbsync"
-                            : : "r" (rb), "r" (kvm->arch.lpid));
-               asm volatile("ptesync" : : : "memory");
-               kvm->arch.tlbie_lock = 0;
-       } else {
-               asm volatile("ptesync" : : : "memory");
-               asm volatile("tlbiel %0" : : "r" (rb));
-               asm volatile("ptesync" : : : "memory");
+
+       rev = real_vmalloc_addr(&kvm->arch.revmap[pte_index]);
+       v = hpte[0] & ~HPTE_V_HVLOCK;
+       if (v & HPTE_V_VALID) {
+               hpte[0] &= ~HPTE_V_VALID;
+               rb = compute_tlbie_rb(v, hpte[1], pte_index);
+               if (!(flags & H_LOCAL) && atomic_read(&kvm->online_vcpus) > 1) {
+                       while (!try_lock_tlbie(&kvm->arch.tlbie_lock))
+                               cpu_relax();
+                       asm volatile("ptesync" : : : "memory");
+                       asm volatile(PPC_TLBIE(%1,%0)"; eieio; tlbsync"
+                                    : : "r" (rb), "r" (kvm->arch.lpid));
+                       asm volatile("ptesync" : : : "memory");
+                       kvm->arch.tlbie_lock = 0;
+               } else {
+                       asm volatile("ptesync" : : : "memory");
+                       asm volatile("tlbiel %0" : : "r" (rb));
+                       asm volatile("ptesync" : : : "memory");
+               }
+               /* Read PTE low word after tlbie to get final R/C values */
+               remove_revmap_chain(kvm, pte_index, rev, v, hpte[1]);
        }
+       r = rev->guest_rpte;
+       unlock_hpte(hpte, 0);
+
+       vcpu->arch.gpr[4] = v;
+       vcpu->arch.gpr[5] = r;
        return H_SUCCESS;
 }
 
@@ -175,78 +397,117 @@ long kvmppc_h_bulk_remove(struct kvm_vcpu *vcpu)
 {
        struct kvm *kvm = vcpu->kvm;
        unsigned long *args = &vcpu->arch.gpr[4];
-       unsigned long *hp, tlbrb[4];
-       long int i, found;
-       long int n_inval = 0;
-       unsigned long flags, req, pte_index;
+       unsigned long *hp, *hptes[4], tlbrb[4];
+       long int i, j, k, n, found, indexes[4];
+       unsigned long flags, req, pte_index, rcbits;
        long int local = 0;
        long int ret = H_SUCCESS;
+       struct revmap_entry *rev, *revs[4];
 
        if (atomic_read(&kvm->online_vcpus) == 1)
                local = 1;
-       for (i = 0; i < 4; ++i) {
-               pte_index = args[i * 2];
-               flags = pte_index >> 56;
-               pte_index &= ((1ul << 56) - 1);
-               req = flags >> 6;
-               flags &= 3;
-               if (req == 3)
-                       break;
-               if (req != 1 || flags == 3 ||
-                   pte_index >= (HPT_NPTEG << 3)) {
-                       /* parameter error */
-                       args[i * 2] = ((0xa0 | flags) << 56) + pte_index;
-                       ret = H_PARAMETER;
-                       break;
-               }
-               hp = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
-               while (!lock_hpte(hp, HPTE_V_HVLOCK))
-                       cpu_relax();
-               found = 0;
-               if (hp[0] & HPTE_V_VALID) {
-                       switch (flags & 3) {
-                       case 0:         /* absolute */
-                               found = 1;
+       for (i = 0; i < 4 && ret == H_SUCCESS; ) {
+               n = 0;
+               for (; i < 4; ++i) {
+                       j = i * 2;
+                       pte_index = args[j];
+                       flags = pte_index >> 56;
+                       pte_index &= ((1ul << 56) - 1);
+                       req = flags >> 6;
+                       flags &= 3;
+                       if (req == 3) {         /* no more requests */
+                               i = 4;
                                break;
-                       case 1:         /* andcond */
-                               if (!(hp[0] & args[i * 2 + 1]))
-                                       found = 1;
+                       }
+                       if (req != 1 || flags == 3 || pte_index >= HPT_NPTE) {
+                               /* parameter error */
+                               args[j] = ((0xa0 | flags) << 56) + pte_index;
+                               ret = H_PARAMETER;
                                break;
-                       case 2:         /* AVPN */
-                               if ((hp[0] & ~0x7fUL) == args[i * 2 + 1])
+                       }
+                       hp = (unsigned long *)
+                               (kvm->arch.hpt_virt + (pte_index << 4));
+                       /* to avoid deadlock, don't spin except for first */
+                       if (!try_lock_hpte(hp, HPTE_V_HVLOCK)) {
+                               if (n)
+                                       break;
+                               while (!try_lock_hpte(hp, HPTE_V_HVLOCK))
+                                       cpu_relax();
+                       }
+                       found = 0;
+                       if (hp[0] & (HPTE_V_ABSENT | HPTE_V_VALID)) {
+                               switch (flags & 3) {
+                               case 0:         /* absolute */
                                        found = 1;
-                               break;
+                                       break;
+                               case 1:         /* andcond */
+                                       if (!(hp[0] & args[j + 1]))
+                                               found = 1;
+                                       break;
+                               case 2:         /* AVPN */
+                                       if ((hp[0] & ~0x7fUL) == args[j + 1])
+                                               found = 1;
+                                       break;
+                               }
+                       }
+                       if (!found) {
+                               hp[0] &= ~HPTE_V_HVLOCK;
+                               args[j] = ((0x90 | flags) << 56) + pte_index;
+                               continue;
                        }
+
+                       args[j] = ((0x80 | flags) << 56) + pte_index;
+                       rev = real_vmalloc_addr(&kvm->arch.revmap[pte_index]);
+
+                       if (!(hp[0] & HPTE_V_VALID)) {
+                               /* insert R and C bits from PTE */
+                               rcbits = rev->guest_rpte & (HPTE_R_R|HPTE_R_C);
+                               args[j] |= rcbits << (56 - 5);
+                               continue;
+                       }
+
+                       hp[0] &= ~HPTE_V_VALID;         /* leave it locked */
+                       tlbrb[n] = compute_tlbie_rb(hp[0], hp[1], pte_index);
+                       indexes[n] = j;
+                       hptes[n] = hp;
+                       revs[n] = rev;
+                       ++n;
+               }
+
+               if (!n)
+                       break;
+
+               /* Now that we've collected a batch, do the tlbies */
+               if (!local) {
+                       while(!try_lock_tlbie(&kvm->arch.tlbie_lock))
+                               cpu_relax();
+                       asm volatile("ptesync" : : : "memory");
+                       for (k = 0; k < n; ++k)
+                               asm volatile(PPC_TLBIE(%1,%0) : :
+                                            "r" (tlbrb[k]),
+                                            "r" (kvm->arch.lpid));
+                       asm volatile("eieio; tlbsync; ptesync" : : : "memory");
+                       kvm->arch.tlbie_lock = 0;
+               } else {
+                       asm volatile("ptesync" : : : "memory");
+                       for (k = 0; k < n; ++k)
+                               asm volatile("tlbiel %0" : : "r" (tlbrb[k]));
+                       asm volatile("ptesync" : : : "memory");
                }
-               if (!found) {
-                       hp[0] &= ~HPTE_V_HVLOCK;
-                       args[i * 2] = ((0x90 | flags) << 56) + pte_index;
-                       continue;
+
+               /* Read PTE low words after tlbie to get final R/C values */
+               for (k = 0; k < n; ++k) {
+                       j = indexes[k];
+                       pte_index = args[j] & ((1ul << 56) - 1);
+                       hp = hptes[k];
+                       rev = revs[k];
+                       remove_revmap_chain(kvm, pte_index, rev, hp[0], hp[1]);
+                       rcbits = rev->guest_rpte & (HPTE_R_R|HPTE_R_C);
+                       args[j] |= rcbits << (56 - 5);
+                       hp[0] = 0;
                }
-               /* insert R and C bits from PTE */
-               flags |= (hp[1] >> 5) & 0x0c;
-               args[i * 2] = ((0x80 | flags) << 56) + pte_index;
-               tlbrb[n_inval++] = compute_tlbie_rb(hp[0], hp[1], pte_index);
-               hp[0] = 0;
-       }
-       if (n_inval == 0)
-               return ret;
-
-       if (!local) {
-               while(!try_lock_tlbie(&kvm->arch.tlbie_lock))
-                       cpu_relax();
-               asm volatile("ptesync" : : : "memory");
-               for (i = 0; i < n_inval; ++i)
-                       asm volatile(PPC_TLBIE(%1,%0)
-                                    : : "r" (tlbrb[i]), "r" (kvm->arch.lpid));
-               asm volatile("eieio; tlbsync; ptesync" : : : "memory");
-               kvm->arch.tlbie_lock = 0;
-       } else {
-               asm volatile("ptesync" : : : "memory");
-               for (i = 0; i < n_inval; ++i)
-                       asm volatile("tlbiel %0" : : "r" (tlbrb[i]));
-               asm volatile("ptesync" : : : "memory");
        }
+
        return ret;
 }
 
@@ -256,40 +517,55 @@ long kvmppc_h_protect(struct kvm_vcpu *vcpu, unsigned long flags,
 {
        struct kvm *kvm = vcpu->kvm;
        unsigned long *hpte;
-       unsigned long v, r, rb;
+       struct revmap_entry *rev;
+       unsigned long v, r, rb, mask, bits;
 
-       if (pte_index >= (HPT_NPTEG << 3))
+       if (pte_index >= HPT_NPTE)
                return H_PARAMETER;
+
        hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
-       while (!lock_hpte(hpte, HPTE_V_HVLOCK))
+       while (!try_lock_hpte(hpte, HPTE_V_HVLOCK))
                cpu_relax();
-       if ((hpte[0] & HPTE_V_VALID) == 0 ||
+       if ((hpte[0] & (HPTE_V_ABSENT | HPTE_V_VALID)) == 0 ||
            ((flags & H_AVPN) && (hpte[0] & ~0x7fUL) != avpn)) {
                hpte[0] &= ~HPTE_V_HVLOCK;
                return H_NOT_FOUND;
        }
+
        if (atomic_read(&kvm->online_vcpus) == 1)
                flags |= H_LOCAL;
        v = hpte[0];
-       r = hpte[1] & ~(HPTE_R_PP0 | HPTE_R_PP | HPTE_R_N |
-                       HPTE_R_KEY_HI | HPTE_R_KEY_LO);
-       r |= (flags << 55) & HPTE_R_PP0;
-       r |= (flags << 48) & HPTE_R_KEY_HI;
-       r |= flags & (HPTE_R_PP | HPTE_R_N | HPTE_R_KEY_LO);
-       rb = compute_tlbie_rb(v, r, pte_index);
-       hpte[0] = v & ~HPTE_V_VALID;
-       if (!(flags & H_LOCAL)) {
-               while(!try_lock_tlbie(&kvm->arch.tlbie_lock))
-                       cpu_relax();
-               asm volatile("ptesync" : : : "memory");
-               asm volatile(PPC_TLBIE(%1,%0)"; eieio; tlbsync"
-                            : : "r" (rb), "r" (kvm->arch.lpid));
-               asm volatile("ptesync" : : : "memory");
-               kvm->arch.tlbie_lock = 0;
-       } else {
-               asm volatile("ptesync" : : : "memory");
-               asm volatile("tlbiel %0" : : "r" (rb));
-               asm volatile("ptesync" : : : "memory");
+       bits = (flags << 55) & HPTE_R_PP0;
+       bits |= (flags << 48) & HPTE_R_KEY_HI;
+       bits |= flags & (HPTE_R_PP | HPTE_R_N | HPTE_R_KEY_LO);
+
+       /* Update guest view of 2nd HPTE dword */
+       mask = HPTE_R_PP0 | HPTE_R_PP | HPTE_R_N |
+               HPTE_R_KEY_HI | HPTE_R_KEY_LO;
+       rev = real_vmalloc_addr(&kvm->arch.revmap[pte_index]);
+       if (rev) {
+               r = (rev->guest_rpte & ~mask) | bits;
+               rev->guest_rpte = r;
+       }
+       r = (hpte[1] & ~mask) | bits;
+
+       /* Update HPTE */
+       if (v & HPTE_V_VALID) {
+               rb = compute_tlbie_rb(v, r, pte_index);
+               hpte[0] = v & ~HPTE_V_VALID;
+               if (!(flags & H_LOCAL)) {
+                       while(!try_lock_tlbie(&kvm->arch.tlbie_lock))
+                               cpu_relax();
+                       asm volatile("ptesync" : : : "memory");
+                       asm volatile(PPC_TLBIE(%1,%0)"; eieio; tlbsync"
+                                    : : "r" (rb), "r" (kvm->arch.lpid));
+                       asm volatile("ptesync" : : : "memory");
+                       kvm->arch.tlbie_lock = 0;
+               } else {
+                       asm volatile("ptesync" : : : "memory");
+                       asm volatile("tlbiel %0" : : "r" (rb));
+                       asm volatile("ptesync" : : : "memory");
+               }
        }
        hpte[1] = r;
        eieio();
@@ -298,40 +574,243 @@ long kvmppc_h_protect(struct kvm_vcpu *vcpu, unsigned long flags,
        return H_SUCCESS;
 }
 
-static unsigned long reverse_xlate(struct kvm *kvm, unsigned long realaddr)
-{
-       long int i;
-       unsigned long offset, rpn;
-
-       offset = realaddr & (kvm->arch.ram_psize - 1);
-       rpn = (realaddr - offset) >> PAGE_SHIFT;
-       for (i = 0; i < kvm->arch.ram_npages; ++i)
-               if (rpn == kvm->arch.ram_pginfo[i].pfn)
-                       return (i << PAGE_SHIFT) + offset;
-       return HPTE_R_RPN;      /* all 1s in the RPN field */
-}
-
 long kvmppc_h_read(struct kvm_vcpu *vcpu, unsigned long flags,
                   unsigned long pte_index)
 {
        struct kvm *kvm = vcpu->kvm;
-       unsigned long *hpte, r;
+       unsigned long *hpte, v, r;
        int i, n = 1;
+       struct revmap_entry *rev = NULL;
 
-       if (pte_index >= (HPT_NPTEG << 3))
+       if (pte_index >= HPT_NPTE)
                return H_PARAMETER;
        if (flags & H_READ_4) {
                pte_index &= ~3;
                n = 4;
        }
+       rev = real_vmalloc_addr(&kvm->arch.revmap[pte_index]);
        for (i = 0; i < n; ++i, ++pte_index) {
                hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
+               v = hpte[0] & ~HPTE_V_HVLOCK;
                r = hpte[1];
-               if ((flags & H_R_XLATE) && (hpte[0] & HPTE_V_VALID))
-                       r = reverse_xlate(kvm, r & HPTE_R_RPN) |
-                               (r & ~HPTE_R_RPN);
-               vcpu->arch.gpr[4 + i * 2] = hpte[0];
+               if (v & HPTE_V_ABSENT) {
+                       v &= ~HPTE_V_ABSENT;
+                       v |= HPTE_V_VALID;
+               }
+               if (v & HPTE_V_VALID)
+                       r = rev[i].guest_rpte | (r & (HPTE_R_R | HPTE_R_C));
+               vcpu->arch.gpr[4 + i * 2] = v;
                vcpu->arch.gpr[5 + i * 2] = r;
        }
        return H_SUCCESS;
 }
+
+void kvmppc_invalidate_hpte(struct kvm *kvm, unsigned long *hptep,
+                       unsigned long pte_index)
+{
+       unsigned long rb;
+
+       hptep[0] &= ~HPTE_V_VALID;
+       rb = compute_tlbie_rb(hptep[0], hptep[1], pte_index);
+       while (!try_lock_tlbie(&kvm->arch.tlbie_lock))
+               cpu_relax();
+       asm volatile("ptesync" : : : "memory");
+       asm volatile(PPC_TLBIE(%1,%0)"; eieio; tlbsync"
+                    : : "r" (rb), "r" (kvm->arch.lpid));
+       asm volatile("ptesync" : : : "memory");
+       kvm->arch.tlbie_lock = 0;
+}
+EXPORT_SYMBOL_GPL(kvmppc_invalidate_hpte);
+
+void kvmppc_clear_ref_hpte(struct kvm *kvm, unsigned long *hptep,
+                          unsigned long pte_index)
+{
+       unsigned long rb;
+       unsigned char rbyte;
+
+       rb = compute_tlbie_rb(hptep[0], hptep[1], pte_index);
+       rbyte = (hptep[1] & ~HPTE_R_R) >> 8;
+       /* modify only the second-last byte, which contains the ref bit */
+       *((char *)hptep + 14) = rbyte;
+       while (!try_lock_tlbie(&kvm->arch.tlbie_lock))
+               cpu_relax();
+       asm volatile(PPC_TLBIE(%1,%0)"; eieio; tlbsync"
+                    : : "r" (rb), "r" (kvm->arch.lpid));
+       asm volatile("ptesync" : : : "memory");
+       kvm->arch.tlbie_lock = 0;
+}
+EXPORT_SYMBOL_GPL(kvmppc_clear_ref_hpte);
+
+static int slb_base_page_shift[4] = {
+       24,     /* 16M */
+       16,     /* 64k */
+       34,     /* 16G */
+       20,     /* 1M, unsupported */
+};
+
+long kvmppc_hv_find_lock_hpte(struct kvm *kvm, gva_t eaddr, unsigned long slb_v,
+                             unsigned long valid)
+{
+       unsigned int i;
+       unsigned int pshift;
+       unsigned long somask;
+       unsigned long vsid, hash;
+       unsigned long avpn;
+       unsigned long *hpte;
+       unsigned long mask, val;
+       unsigned long v, r;
+
+       /* Get page shift, work out hash and AVPN etc. */
+       mask = SLB_VSID_B | HPTE_V_AVPN | HPTE_V_SECONDARY;
+       val = 0;
+       pshift = 12;
+       if (slb_v & SLB_VSID_L) {
+               mask |= HPTE_V_LARGE;
+               val |= HPTE_V_LARGE;
+               pshift = slb_base_page_shift[(slb_v & SLB_VSID_LP) >> 4];
+       }
+       if (slb_v & SLB_VSID_B_1T) {
+               somask = (1UL << 40) - 1;
+               vsid = (slb_v & ~SLB_VSID_B) >> SLB_VSID_SHIFT_1T;
+               vsid ^= vsid << 25;
+       } else {
+               somask = (1UL << 28) - 1;
+               vsid = (slb_v & ~SLB_VSID_B) >> SLB_VSID_SHIFT;
+       }
+       hash = (vsid ^ ((eaddr & somask) >> pshift)) & HPT_HASH_MASK;
+       avpn = slb_v & ~(somask >> 16); /* also includes B */
+       avpn |= (eaddr & somask) >> 16;
+
+       if (pshift >= 24)
+               avpn &= ~((1UL << (pshift - 16)) - 1);
+       else
+               avpn &= ~0x7fUL;
+       val |= avpn;
+
+       for (;;) {
+               hpte = (unsigned long *)(kvm->arch.hpt_virt + (hash << 7));
+
+               for (i = 0; i < 16; i += 2) {
+                       /* Read the PTE racily */
+                       v = hpte[i] & ~HPTE_V_HVLOCK;
+
+                       /* Check valid/absent, hash, segment size and AVPN */
+                       if (!(v & valid) || (v & mask) != val)
+                               continue;
+
+                       /* Lock the PTE and read it under the lock */
+                       while (!try_lock_hpte(&hpte[i], HPTE_V_HVLOCK))
+                               cpu_relax();
+                       v = hpte[i] & ~HPTE_V_HVLOCK;
+                       r = hpte[i+1];
+
+                       /*
+                        * Check the HPTE again, including large page size
+                        * Since we don't currently allow any MPSS (mixed
+                        * page-size segment) page sizes, it is sufficient
+                        * to check against the actual page size.
+                        */
+                       if ((v & valid) && (v & mask) == val &&
+                           hpte_page_size(v, r) == (1ul << pshift))
+                               /* Return with the HPTE still locked */
+                               return (hash << 3) + (i >> 1);
+
+                       /* Unlock and move on */
+                       hpte[i] = v;
+               }
+
+               if (val & HPTE_V_SECONDARY)
+                       break;
+               val |= HPTE_V_SECONDARY;
+               hash = hash ^ HPT_HASH_MASK;
+       }
+       return -1;
+}
+EXPORT_SYMBOL(kvmppc_hv_find_lock_hpte);
+
+/*
+ * Called in real mode to check whether an HPTE not found fault
+ * is due to accessing a paged-out page or an emulated MMIO page,
+ * or if a protection fault is due to accessing a page that the
+ * guest wanted read/write access to but which we made read-only.
+ * Returns a possibly modified status (DSISR) value if not
+ * (i.e. pass the interrupt to the guest),
+ * -1 to pass the fault up to host kernel mode code, -2 to do that
+ * and also load the instruction word (for MMIO emulation),
+ * or 0 if we should make the guest retry the access.
+ */
+long kvmppc_hpte_hv_fault(struct kvm_vcpu *vcpu, unsigned long addr,
+                         unsigned long slb_v, unsigned int status, bool data)
+{
+       struct kvm *kvm = vcpu->kvm;
+       long int index;
+       unsigned long v, r, gr;
+       unsigned long *hpte;
+       unsigned long valid;
+       struct revmap_entry *rev;
+       unsigned long pp, key;
+
+       /* For protection fault, expect to find a valid HPTE */
+       valid = HPTE_V_VALID;
+       if (status & DSISR_NOHPTE)
+               valid |= HPTE_V_ABSENT;
+
+       index = kvmppc_hv_find_lock_hpte(kvm, addr, slb_v, valid);
+       if (index < 0) {
+               if (status & DSISR_NOHPTE)
+                       return status;  /* there really was no HPTE */
+               return 0;               /* for prot fault, HPTE disappeared */
+       }
+       hpte = (unsigned long *)(kvm->arch.hpt_virt + (index << 4));
+       v = hpte[0] & ~HPTE_V_HVLOCK;
+       r = hpte[1];
+       rev = real_vmalloc_addr(&kvm->arch.revmap[index]);
+       gr = rev->guest_rpte;
+
+       unlock_hpte(hpte, v);
+
+       /* For not found, if the HPTE is valid by now, retry the instruction */
+       if ((status & DSISR_NOHPTE) && (v & HPTE_V_VALID))
+               return 0;
+
+       /* Check access permissions to the page */
+       pp = gr & (HPTE_R_PP0 | HPTE_R_PP);
+       key = (vcpu->arch.shregs.msr & MSR_PR) ? SLB_VSID_KP : SLB_VSID_KS;
+       status &= ~DSISR_NOHPTE;        /* DSISR_NOHPTE == SRR1_ISI_NOPT */
+       if (!data) {
+               if (gr & (HPTE_R_N | HPTE_R_G))
+                       return status | SRR1_ISI_N_OR_G;
+               if (!hpte_read_permission(pp, slb_v & key))
+                       return status | SRR1_ISI_PROT;
+       } else if (status & DSISR_ISSTORE) {
+               /* check write permission */
+               if (!hpte_write_permission(pp, slb_v & key))
+                       return status | DSISR_PROTFAULT;
+       } else {
+               if (!hpte_read_permission(pp, slb_v & key))
+                       return status | DSISR_PROTFAULT;
+       }
+
+       /* Check storage key, if applicable */
+       if (data && (vcpu->arch.shregs.msr & MSR_DR)) {
+               unsigned int perm = hpte_get_skey_perm(gr, vcpu->arch.amr);
+               if (status & DSISR_ISSTORE)
+                       perm >>= 1;
+               if (perm & 1)
+                       return status | DSISR_KEYFAULT;
+       }
+
+       /* Save HPTE info for virtual-mode handler */
+       vcpu->arch.pgfault_addr = addr;
+       vcpu->arch.pgfault_index = index;
+       vcpu->arch.pgfault_hpte[0] = v;
+       vcpu->arch.pgfault_hpte[1] = r;
+
+       /* Check the storage key to see if it is possibly emulated MMIO */
+       if (data && (vcpu->arch.shregs.msr & MSR_IR) &&
+           (r & (HPTE_R_KEY_HI | HPTE_R_KEY_LO)) ==
+           (HPTE_R_KEY_HI | HPTE_R_KEY_LO))
+               return -2;      /* MMIO emulation - load instr word */
+
+       return -1;              /* send fault up to host kernel mode */
+}
index 5c8b261..b70bf22 100644 (file)
@@ -601,6 +601,30 @@ kvmppc_interrupt:
 
        stw     r12,VCPU_TRAP(r9)
 
+       /* Save HEIR (HV emulation assist reg) in last_inst
+          if this is an HEI (HV emulation interrupt, e40) */
+       li      r3,KVM_INST_FETCH_FAILED
+BEGIN_FTR_SECTION
+       cmpwi   r12,BOOK3S_INTERRUPT_H_EMUL_ASSIST
+       bne     11f
+       mfspr   r3,SPRN_HEIR
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
+11:    stw     r3,VCPU_LAST_INST(r9)
+
+       /* these are volatile across C function calls */
+       mfctr   r3
+       mfxer   r4
+       std     r3, VCPU_CTR(r9)
+       stw     r4, VCPU_XER(r9)
+
+BEGIN_FTR_SECTION
+       /* If this is a page table miss then see if it's theirs or ours */
+       cmpwi   r12, BOOK3S_INTERRUPT_H_DATA_STORAGE
+       beq     kvmppc_hdsi
+       cmpwi   r12, BOOK3S_INTERRUPT_H_INST_STORAGE
+       beq     kvmppc_hisi
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
+
        /* See if this is a leftover HDEC interrupt */
        cmpwi   r12,BOOK3S_INTERRUPT_HV_DECREMENTER
        bne     2f
@@ -608,7 +632,7 @@ kvmppc_interrupt:
        cmpwi   r3,0
        bge     ignore_hdec
 2:
-       /* See if this is something we can handle in real mode */
+       /* See if this is an hcall we can handle in real mode */
        cmpwi   r12,BOOK3S_INTERRUPT_SYSCALL
        beq     hcall_try_real_mode
 
@@ -624,6 +648,7 @@ BEGIN_FTR_SECTION
 1:
 END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
 
+nohpte_cont:
 hcall_real_cont:               /* r9 = vcpu, r12 = trap, r13 = paca */
        /* Save DEC */
        mfspr   r5,SPRN_DEC
@@ -632,36 +657,21 @@ hcall_real_cont:          /* r9 = vcpu, r12 = trap, r13 = paca */
        add     r5,r5,r6
        std     r5,VCPU_DEC_EXPIRES(r9)
 
-       /* Save HEIR (HV emulation assist reg) in last_inst
-          if this is an HEI (HV emulation interrupt, e40) */
-       li      r3,-1
-BEGIN_FTR_SECTION
-       cmpwi   r12,BOOK3S_INTERRUPT_H_EMUL_ASSIST
-       bne     11f
-       mfspr   r3,SPRN_HEIR
-END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
-11:    stw     r3,VCPU_LAST_INST(r9)
-
        /* Save more register state  */
-       mfxer   r5
        mfdar   r6
        mfdsisr r7
-       mfctr   r8
-
-       stw     r5, VCPU_XER(r9)
        std     r6, VCPU_DAR(r9)
        stw     r7, VCPU_DSISR(r9)
-       std     r8, VCPU_CTR(r9)
-       /* grab HDAR & HDSISR if HV data storage interrupt (HDSI) */
 BEGIN_FTR_SECTION
+       /* don't overwrite fault_dar/fault_dsisr if HDSI */
        cmpwi   r12,BOOK3S_INTERRUPT_H_DATA_STORAGE
        beq     6f
 END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
-7:     std     r6, VCPU_FAULT_DAR(r9)
+       std     r6, VCPU_FAULT_DAR(r9)
        stw     r7, VCPU_FAULT_DSISR(r9)
 
        /* Save guest CTRL register, set runlatch to 1 */
-       mfspr   r6,SPRN_CTRLF
+6:     mfspr   r6,SPRN_CTRLF
        stw     r6,VCPU_CTRL(r9)
        andi.   r0,r6,1
        bne     4f
@@ -1094,9 +1104,131 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
        mtspr   SPRN_HSRR1, r7
        ba      0x500
 
-6:     mfspr   r6,SPRN_HDAR
-       mfspr   r7,SPRN_HDSISR
-       b       7b
+/*
+ * Check whether an HDSI is an HPTE not found fault or something else.
+ * If it is an HPTE not found fault that is due to the guest accessing
+ * a page that they have mapped but which we have paged out, then
+ * we continue on with the guest exit path.  In all other cases,
+ * reflect the HDSI to the guest as a DSI.
+ */
+kvmppc_hdsi:
+       mfspr   r4, SPRN_HDAR
+       mfspr   r6, SPRN_HDSISR
+       /* HPTE not found fault or protection fault? */
+       andis.  r0, r6, (DSISR_NOHPTE | DSISR_PROTFAULT)@h
+       beq     1f                      /* if not, send it to the guest */
+       andi.   r0, r11, MSR_DR         /* data relocation enabled? */
+       beq     3f
+       clrrdi  r0, r4, 28
+       PPC_SLBFEE_DOT(r5, r0)          /* if so, look up SLB */
+       bne     1f                      /* if no SLB entry found */
+4:     std     r4, VCPU_FAULT_DAR(r9)
+       stw     r6, VCPU_FAULT_DSISR(r9)
+
+       /* Search the hash table. */
+       mr      r3, r9                  /* vcpu pointer */
+       li      r7, 1                   /* data fault */
+       bl      .kvmppc_hpte_hv_fault
+       ld      r9, HSTATE_KVM_VCPU(r13)
+       ld      r10, VCPU_PC(r9)
+       ld      r11, VCPU_MSR(r9)
+       li      r12, BOOK3S_INTERRUPT_H_DATA_STORAGE
+       cmpdi   r3, 0                   /* retry the instruction */
+       beq     6f
+       cmpdi   r3, -1                  /* handle in kernel mode */
+       beq     nohpte_cont
+       cmpdi   r3, -2                  /* MMIO emulation; need instr word */
+       beq     2f
+
+       /* Synthesize a DSI for the guest */
+       ld      r4, VCPU_FAULT_DAR(r9)
+       mr      r6, r3
+1:     mtspr   SPRN_DAR, r4
+       mtspr   SPRN_DSISR, r6
+       mtspr   SPRN_SRR0, r10
+       mtspr   SPRN_SRR1, r11
+       li      r10, BOOK3S_INTERRUPT_DATA_STORAGE
+       li      r11, (MSR_ME << 1) | 1  /* synthesize MSR_SF | MSR_ME */
+       rotldi  r11, r11, 63
+6:     ld      r7, VCPU_CTR(r9)
+       lwz     r8, VCPU_XER(r9)
+       mtctr   r7
+       mtxer   r8
+       mr      r4, r9
+       b       fast_guest_return
+
+3:     ld      r5, VCPU_KVM(r9)        /* not relocated, use VRMA */
+       ld      r5, KVM_VRMA_SLB_V(r5)
+       b       4b
+
+       /* If this is for emulated MMIO, load the instruction word */
+2:     li      r8, KVM_INST_FETCH_FAILED       /* In case lwz faults */
+
+       /* Set guest mode to 'jump over instruction' so if lwz faults
+        * we'll just continue at the next IP. */
+       li      r0, KVM_GUEST_MODE_SKIP
+       stb     r0, HSTATE_IN_GUEST(r13)
+
+       /* Do the access with MSR:DR enabled */
+       mfmsr   r3
+       ori     r4, r3, MSR_DR          /* Enable paging for data */
+       mtmsrd  r4
+       lwz     r8, 0(r10)
+       mtmsrd  r3
+
+       /* Store the result */
+       stw     r8, VCPU_LAST_INST(r9)
+
+       /* Unset guest mode. */
+       li      r0, KVM_GUEST_MODE_NONE
+       stb     r0, HSTATE_IN_GUEST(r13)
+       b       nohpte_cont
+
+/*
+ * Similarly for an HISI, reflect it to the guest as an ISI unless
+ * it is an HPTE not found fault for a page that we have paged out.
+ */
+kvmppc_hisi:
+       andis.  r0, r11, SRR1_ISI_NOPT@h
+       beq     1f
+       andi.   r0, r11, MSR_IR         /* instruction relocation enabled? */
+       beq     3f
+       clrrdi  r0, r10, 28
+       PPC_SLBFEE_DOT(r5, r0)          /* if so, look up SLB */
+       bne     1f                      /* if no SLB entry found */
+4:
+       /* Search the hash table. */
+       mr      r3, r9                  /* vcpu pointer */
+       mr      r4, r10
+       mr      r6, r11
+       li      r7, 0                   /* instruction fault */
+       bl      .kvmppc_hpte_hv_fault
+       ld      r9, HSTATE_KVM_VCPU(r13)
+       ld      r10, VCPU_PC(r9)
+       ld      r11, VCPU_MSR(r9)
+       li      r12, BOOK3S_INTERRUPT_H_INST_STORAGE
+       cmpdi   r3, 0                   /* retry the instruction */
+       beq     6f
+       cmpdi   r3, -1                  /* handle in kernel mode */
+       beq     nohpte_cont
+
+       /* Synthesize an ISI for the guest */
+       mr      r11, r3
+1:     mtspr   SPRN_SRR0, r10
+       mtspr   SPRN_SRR1, r11
+       li      r10, BOOK3S_INTERRUPT_INST_STORAGE
+       li      r11, (MSR_ME << 1) | 1  /* synthesize MSR_SF | MSR_ME */
+       rotldi  r11, r11, 63
+6:     ld      r7, VCPU_CTR(r9)
+       lwz     r8, VCPU_XER(r9)
+       mtctr   r7
+       mtxer   r8
+       mr      r4, r9
+       b       fast_guest_return
+
+3:     ld      r6, VCPU_KVM(r9)        /* not relocated, use VRMA */
+       ld      r5, KVM_VRMA_SLB_V(r6)
+       b       4b
 
 /*
  * Try to handle an hcall in real mode.
index 7b0ee96..e70ef2d 100644 (file)
@@ -196,7 +196,8 @@ static int kvmppc_emulate_fpr_load(struct kvm_run *run, struct kvm_vcpu *vcpu,
                kvmppc_inject_pf(vcpu, addr, false);
                goto done_load;
        } else if (r == EMULATE_DO_MMIO) {
-               emulated = kvmppc_handle_load(run, vcpu, KVM_REG_FPR | rs, len, 1);
+               emulated = kvmppc_handle_load(run, vcpu, KVM_MMIO_REG_FPR | rs,
+                                             len, 1);
                goto done_load;
        }
 
@@ -286,11 +287,13 @@ static int kvmppc_emulate_psq_load(struct kvm_run *run, struct kvm_vcpu *vcpu,
                kvmppc_inject_pf(vcpu, addr, false);
                goto done_load;
        } else if ((r == EMULATE_DO_MMIO) && w) {
-               emulated = kvmppc_handle_load(run, vcpu, KVM_REG_FPR | rs, 4, 1);
+               emulated = kvmppc_handle_load(run, vcpu, KVM_MMIO_REG_FPR | rs,
+                                             4, 1);
                vcpu->arch.qpr[rs] = tmp[1];
                goto done_load;
        } else if (r == EMULATE_DO_MMIO) {
-               emulated = kvmppc_handle_load(run, vcpu, KVM_REG_FQPR | rs, 8, 1);
+               emulated = kvmppc_handle_load(run, vcpu, KVM_MMIO_REG_FQPR | rs,
+                                             8, 1);
                goto done_load;
        }
 
index 220fcdf..7340e10 100644 (file)
@@ -51,15 +51,19 @@ static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr,
 #define MSR_USER32 MSR_USER
 #define MSR_USER64 MSR_USER
 #define HW_PAGE_SIZE PAGE_SIZE
+#define __hard_irq_disable local_irq_disable
+#define __hard_irq_enable local_irq_enable
 #endif
 
 void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 {
 #ifdef CONFIG_PPC_BOOK3S_64
-       memcpy(to_svcpu(vcpu)->slb, to_book3s(vcpu)->slb_shadow, sizeof(to_svcpu(vcpu)->slb));
+       struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
+       memcpy(svcpu->slb, to_book3s(vcpu)->slb_shadow, sizeof(svcpu->slb));
        memcpy(&get_paca()->shadow_vcpu, to_book3s(vcpu)->shadow_vcpu,
               sizeof(get_paca()->shadow_vcpu));
-       to_svcpu(vcpu)->slb_max = to_book3s(vcpu)->slb_shadow_max;
+       svcpu->slb_max = to_book3s(vcpu)->slb_shadow_max;
+       svcpu_put(svcpu);
 #endif
 
 #ifdef CONFIG_PPC_BOOK3S_32
@@ -70,10 +74,12 @@ void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu)
 {
 #ifdef CONFIG_PPC_BOOK3S_64
-       memcpy(to_book3s(vcpu)->slb_shadow, to_svcpu(vcpu)->slb, sizeof(to_svcpu(vcpu)->slb));
+       struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
+       memcpy(to_book3s(vcpu)->slb_shadow, svcpu->slb, sizeof(svcpu->slb));
        memcpy(to_book3s(vcpu)->shadow_vcpu, &get_paca()->shadow_vcpu,
               sizeof(get_paca()->shadow_vcpu));
-       to_book3s(vcpu)->slb_shadow_max = to_svcpu(vcpu)->slb_max;
+       to_book3s(vcpu)->slb_shadow_max = svcpu->slb_max;
+       svcpu_put(svcpu);
 #endif
 
        kvmppc_giveup_ext(vcpu, MSR_FP);
@@ -151,14 +157,16 @@ void kvmppc_set_pvr(struct kvm_vcpu *vcpu, u32 pvr)
 #ifdef CONFIG_PPC_BOOK3S_64
        if ((pvr >= 0x330000) && (pvr < 0x70330000)) {
                kvmppc_mmu_book3s_64_init(vcpu);
-               to_book3s(vcpu)->hior = 0xfff00000;
+               if (!to_book3s(vcpu)->hior_explicit)
+                       to_book3s(vcpu)->hior = 0xfff00000;
                to_book3s(vcpu)->msr_mask = 0xffffffffffffffffULL;
                vcpu->arch.cpu_type = KVM_CPU_3S_64;
        } else
 #endif
        {
                kvmppc_mmu_book3s_32_init(vcpu);
-               to_book3s(vcpu)->hior = 0;
+               if (!to_book3s(vcpu)->hior_explicit)
+                       to_book3s(vcpu)->hior = 0;
                to_book3s(vcpu)->msr_mask = 0xffffffffULL;
                vcpu->arch.cpu_type = KVM_CPU_3S_32;
        }
@@ -308,19 +316,22 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,
 
        if (page_found == -ENOENT) {
                /* Page not found in guest PTE entries */
+               struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
                vcpu->arch.shared->dar = kvmppc_get_fault_dar(vcpu);
-               vcpu->arch.shared->dsisr = to_svcpu(vcpu)->fault_dsisr;
+               vcpu->arch.shared->dsisr = svcpu->fault_dsisr;
                vcpu->arch.shared->msr |=
-                       (to_svcpu(vcpu)->shadow_srr1 & 0x00000000f8000000ULL);
+                       (svcpu->shadow_srr1 & 0x00000000f8000000ULL);
+               svcpu_put(svcpu);
                kvmppc_book3s_queue_irqprio(vcpu, vec);
        } else if (page_found == -EPERM) {
                /* Storage protection */
+               struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
                vcpu->arch.shared->dar = kvmppc_get_fault_dar(vcpu);
-               vcpu->arch.shared->dsisr =
-                       to_svcpu(vcpu)->fault_dsisr & ~DSISR_NOHPTE;
+               vcpu->arch.shared->dsisr = svcpu->fault_dsisr & ~DSISR_NOHPTE;
                vcpu->arch.shared->dsisr |= DSISR_PROTFAULT;
                vcpu->arch.shared->msr |=
-                       (to_svcpu(vcpu)->shadow_srr1 & 0x00000000f8000000ULL);
+                       svcpu->shadow_srr1 & 0x00000000f8000000ULL;
+               svcpu_put(svcpu);
                kvmppc_book3s_queue_irqprio(vcpu, vec);
        } else if (page_found == -EINVAL) {
                /* Page not found in guest SLB */
@@ -517,24 +528,29 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
        run->ready_for_interrupt_injection = 1;
 
        trace_kvm_book3s_exit(exit_nr, vcpu);
+       preempt_enable();
        kvm_resched(vcpu);
        switch (exit_nr) {
        case BOOK3S_INTERRUPT_INST_STORAGE:
+       {
+               struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
+               ulong shadow_srr1 = svcpu->shadow_srr1;
                vcpu->stat.pf_instruc++;
 
 #ifdef CONFIG_PPC_BOOK3S_32
                /* We set segments as unused segments when invalidating them. So
                 * treat the respective fault as segment fault. */
-               if (to_svcpu(vcpu)->sr[kvmppc_get_pc(vcpu) >> SID_SHIFT]
-                   == SR_INVALID) {
+               if (svcpu->sr[kvmppc_get_pc(vcpu) >> SID_SHIFT] == SR_INVALID) {
                        kvmppc_mmu_map_segment(vcpu, kvmppc_get_pc(vcpu));
                        r = RESUME_GUEST;
+                       svcpu_put(svcpu);
                        break;
                }
 #endif
+               svcpu_put(svcpu);
 
                /* only care about PTEG not found errors, but leave NX alone */
-               if (to_svcpu(vcpu)->shadow_srr1 & 0x40000000) {
+               if (shadow_srr1 & 0x40000000) {
                        r = kvmppc_handle_pagefault(run, vcpu, kvmppc_get_pc(vcpu), exit_nr);
                        vcpu->stat.sp_instruc++;
                } else if (vcpu->arch.mmu.is_dcbz32(vcpu) &&
@@ -547,33 +563,37 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
                        kvmppc_mmu_pte_flush(vcpu, kvmppc_get_pc(vcpu), ~0xFFFUL);
                        r = RESUME_GUEST;
                } else {
-                       vcpu->arch.shared->msr |=
-                               to_svcpu(vcpu)->shadow_srr1 & 0x58000000;
+                       vcpu->arch.shared->msr |= shadow_srr1 & 0x58000000;
                        kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
                        r = RESUME_GUEST;
                }
                break;
+       }
        case BOOK3S_INTERRUPT_DATA_STORAGE:
        {
                ulong dar = kvmppc_get_fault_dar(vcpu);
+               struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
+               u32 fault_dsisr = svcpu->fault_dsisr;
                vcpu->stat.pf_storage++;
 
 #ifdef CONFIG_PPC_BOOK3S_32
                /* We set segments as unused segments when invalidating them. So
                 * treat the respective fault as segment fault. */
-               if ((to_svcpu(vcpu)->sr[dar >> SID_SHIFT]) == SR_INVALID) {
+               if ((svcpu->sr[dar >> SID_SHIFT]) == SR_INVALID) {
                        kvmppc_mmu_map_segment(vcpu, dar);
                        r = RESUME_GUEST;
+                       svcpu_put(svcpu);
                        break;
                }
 #endif
+               svcpu_put(svcpu);
 
                /* The only case we need to handle is missing shadow PTEs */
-               if (to_svcpu(vcpu)->fault_dsisr & DSISR_NOHPTE) {
+               if (fault_dsisr & DSISR_NOHPTE) {
                        r = kvmppc_handle_pagefault(run, vcpu, dar, exit_nr);
                } else {
                        vcpu->arch.shared->dar = dar;
-                       vcpu->arch.shared->dsisr = to_svcpu(vcpu)->fault_dsisr;
+                       vcpu->arch.shared->dsisr = fault_dsisr;
                        kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
                        r = RESUME_GUEST;
                }
@@ -609,10 +629,13 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
        case BOOK3S_INTERRUPT_PROGRAM:
        {
                enum emulation_result er;
+               struct kvmppc_book3s_shadow_vcpu *svcpu;
                ulong flags;
 
 program_interrupt:
-               flags = to_svcpu(vcpu)->shadow_srr1 & 0x1f0000ull;
+               svcpu = svcpu_get(vcpu);
+               flags = svcpu->shadow_srr1 & 0x1f0000ull;
+               svcpu_put(svcpu);
 
                if (vcpu->arch.shared->msr & MSR_PR) {
 #ifdef EXIT_DEBUG
@@ -740,20 +763,33 @@ program_interrupt:
                r = RESUME_GUEST;
                break;
        default:
+       {
+               struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
+               ulong shadow_srr1 = svcpu->shadow_srr1;
+               svcpu_put(svcpu);
                /* Ugh - bork here! What did we get? */
                printk(KERN_EMERG "exit_nr=0x%x | pc=0x%lx | msr=0x%lx\n",
-                       exit_nr, kvmppc_get_pc(vcpu), to_svcpu(vcpu)->shadow_srr1);
+                       exit_nr, kvmppc_get_pc(vcpu), shadow_srr1);
                r = RESUME_HOST;
                BUG();
                break;
        }
-
+       }
 
        if (!(r & RESUME_HOST)) {
                /* To avoid clobbering exit_reason, only check for signals if
                 * we aren't already exiting to userspace for some other
                 * reason. */
+
+               /*
+                * Interrupts could be timers for the guest which we have to
+                * inject again, so let's postpone them until we're in the guest
+                * and if we really did time things so badly, then we just exit
+                * again due to a host external interrupt.
+                */
+               __hard_irq_disable();
                if (signal_pending(current)) {
+                       __hard_irq_enable();
 #ifdef EXIT_DEBUG
                        printk(KERN_EMERG "KVM: Going back to host\n");
 #endif
@@ -761,10 +797,12 @@ program_interrupt:
                        run->exit_reason = KVM_EXIT_INTR;
                        r = -EINTR;
                } else {
+                       preempt_disable();
+
                        /* In case an interrupt came in that was triggered
                         * from userspace (like DEC), we need to check what
                         * to inject now! */
-                       kvmppc_core_deliver_interrupts(vcpu);
+                       kvmppc_core_prepare_to_enter(vcpu);
                }
        }
 
@@ -836,6 +874,38 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
        return 0;
 }
 
+int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
+{
+       int r = -EINVAL;
+
+       switch (reg->id) {
+       case KVM_REG_PPC_HIOR:
+               r = put_user(to_book3s(vcpu)->hior, (u64 __user *)reg->addr);
+               break;
+       default:
+               break;
+       }
+
+       return r;
+}
+
+int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
+{
+       int r = -EINVAL;
+
+       switch (reg->id) {
+       case KVM_REG_PPC_HIOR:
+               r = get_user(to_book3s(vcpu)->hior, (u64 __user *)reg->addr);
+               if (!r)
+                       to_book3s(vcpu)->hior_explicit = true;
+               break;
+       default:
+               break;
+       }
+
+       return r;
+}
+
 int kvmppc_core_check_processor_compat(void)
 {
        return 0;
@@ -923,16 +993,31 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 #endif
        ulong ext_msr;
 
+       preempt_disable();
+
        /* Check if we can run the vcpu at all */
        if (!vcpu->arch.sane) {
                kvm_run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
-               return -EINVAL;
+               ret = -EINVAL;
+               goto out;
        }
 
+       kvmppc_core_prepare_to_enter(vcpu);
+
+       /*
+        * Interrupts could be timers for the guest which we have to inject
+        * again, so let's postpone them until we're in the guest and if we
+        * really did time things so badly, then we just exit again due to
+        * a host external interrupt.
+        */
+       __hard_irq_disable();
+
        /* No need to go into the guest when all we do is going out */
        if (signal_pending(current)) {
+               __hard_irq_enable();
                kvm_run->exit_reason = KVM_EXIT_INTR;
-               return -EINTR;
+               ret = -EINTR;
+               goto out;
        }
 
        /* Save FPU state in stack */
@@ -974,8 +1059,6 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 
        kvm_guest_exit();
 
-       local_irq_disable();
-
        current->thread.regs->msr = ext_msr;
 
        /* Make sure we save the guest FPU/Altivec/VSX state */
@@ -1002,9 +1085,50 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
        current->thread.used_vsr = used_vsr;
 #endif
 
+out:
+       preempt_enable();
        return ret;
 }
 
+/*
+ * Get (and clear) the dirty memory log for a memory slot.
+ */
+int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
+                                     struct kvm_dirty_log *log)
+{
+       struct kvm_memory_slot *memslot;
+       struct kvm_vcpu *vcpu;
+       ulong ga, ga_end;
+       int is_dirty = 0;
+       int r;
+       unsigned long n;
+
+       mutex_lock(&kvm->slots_lock);
+
+       r = kvm_get_dirty_log(kvm, log, &is_dirty);
+       if (r)
+               goto out;
+
+       /* If nothing is dirty, don't bother messing with page tables. */
+       if (is_dirty) {
+               memslot = id_to_memslot(kvm->memslots, log->slot);
+
+               ga = memslot->base_gfn << PAGE_SHIFT;
+               ga_end = ga + (memslot->npages << PAGE_SHIFT);
+
+               kvm_for_each_vcpu(n, vcpu, kvm)
+                       kvmppc_mmu_pte_pflush(vcpu, ga, ga_end);
+
+               n = kvm_dirty_bitmap_bytes(memslot);
+               memset(memslot->dirty_bitmap, 0, n);
+       }
+
+       r = 0;
+out:
+       mutex_unlock(&kvm->slots_lock);
+       return r;
+}
+
 int kvmppc_core_prepare_memory_region(struct kvm *kvm,
                                      struct kvm_userspace_memory_region *mem)
 {
index bb6c988..ee9e1ee 100644 (file)
@@ -124,12 +124,6 @@ void kvmppc_set_msr(struct kvm_vcpu *vcpu, u32 new_msr)
        vcpu->arch.shared->msr = new_msr;
 
        kvmppc_mmu_msr_notify(vcpu, old_msr);
-
-       if (vcpu->arch.shared->msr & MSR_WE) {
-               kvm_vcpu_block(vcpu);
-               kvmppc_set_exit_type(vcpu, EMULATED_MTMSRWE_EXITS);
-       };
-
        kvmppc_vcpu_sync_spe(vcpu);
 }
 
@@ -258,9 +252,11 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
                allowed = vcpu->arch.shared->msr & MSR_ME;
                msr_mask = 0;
                break;
-       case BOOKE_IRQPRIO_EXTERNAL:
        case BOOKE_IRQPRIO_DECREMENTER:
        case BOOKE_IRQPRIO_FIT:
+               keep_irq = true;
+               /* fall through */
+       case BOOKE_IRQPRIO_EXTERNAL:
                allowed = vcpu->arch.shared->msr & MSR_EE;
                allowed = allowed && !crit;
                msr_mask = MSR_CE|MSR_ME|MSR_DE;
@@ -276,7 +272,7 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
                vcpu->arch.shared->srr1 = vcpu->arch.shared->msr;
                vcpu->arch.pc = vcpu->arch.ivpr | vcpu->arch.ivor[priority];
                if (update_esr == true)
-                       vcpu->arch.esr = vcpu->arch.queued_esr;
+                       vcpu->arch.shared->esr = vcpu->arch.queued_esr;
                if (update_dear == true)
                        vcpu->arch.shared->dar = vcpu->arch.queued_dear;
                kvmppc_set_msr(vcpu, vcpu->arch.shared->msr & msr_mask);
@@ -288,13 +284,26 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
        return allowed;
 }
 
-/* Check pending exceptions and deliver one, if possible. */
-void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu)
+static void update_timer_ints(struct kvm_vcpu *vcpu)
+{
+       if ((vcpu->arch.tcr & TCR_DIE) && (vcpu->arch.tsr & TSR_DIS))
+               kvmppc_core_queue_dec(vcpu);
+       else
+               kvmppc_core_dequeue_dec(vcpu);
+}
+
+static void kvmppc_core_check_exceptions(struct kvm_vcpu *vcpu)
 {
        unsigned long *pending = &vcpu->arch.pending_exceptions;
-       unsigned long old_pending = vcpu->arch.pending_exceptions;
        unsigned int priority;
 
+       if (vcpu->requests) {
+               if (kvm_check_request(KVM_REQ_PENDING_TIMER, vcpu)) {
+                       smp_mb();
+                       update_timer_ints(vcpu);
+               }
+       }
+
        priority = __ffs(*pending);
        while (priority <= BOOKE_IRQPRIO_MAX) {
                if (kvmppc_booke_irqprio_deliver(vcpu, priority))
@@ -306,10 +315,24 @@ void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu)
        }
 
        /* Tell the guest about our interrupt status */
-       if (*pending)
-               vcpu->arch.shared->int_pending = 1;
-       else if (old_pending)
-               vcpu->arch.shared->int_pending = 0;
+       vcpu->arch.shared->int_pending = !!*pending;
+}
+
+/* Check pending exceptions and deliver one, if possible. */
+void kvmppc_core_prepare_to_enter(struct kvm_vcpu *vcpu)
+{
+       WARN_ON_ONCE(!irqs_disabled());
+
+       kvmppc_core_check_exceptions(vcpu);
+
+       if (vcpu->arch.shared->msr & MSR_WE) {
+               local_irq_enable();
+               kvm_vcpu_block(vcpu);
+               local_irq_disable();
+
+               kvmppc_set_exit_type(vcpu, EMULATED_MTMSRWE_EXITS);
+               kvmppc_core_check_exceptions(vcpu);
+       };
 }
 
 int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
@@ -322,11 +345,21 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
        }
 
        local_irq_disable();
+
+       kvmppc_core_prepare_to_enter(vcpu);
+
+       if (signal_pending(current)) {
+               kvm_run->exit_reason = KVM_EXIT_INTR;
+               ret = -EINTR;
+               goto out;
+       }
+
        kvm_guest_enter();
        ret = __kvmppc_vcpu_run(kvm_run, vcpu);
        kvm_guest_exit();
-       local_irq_enable();
 
+out:
+       local_irq_enable();
        return ret;
 }
 
@@ -603,7 +636,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
 
        local_irq_disable();
 
-       kvmppc_core_deliver_interrupts(vcpu);
+       kvmppc_core_prepare_to_enter(vcpu);
 
        if (!(r & RESUME_HOST)) {
                /* To avoid clobbering exit_reason, only check for signals if
@@ -628,6 +661,7 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
        vcpu->arch.pc = 0;
        vcpu->arch.shared->msr = 0;
        vcpu->arch.shadow_msr = MSR_USER | MSR_DE | MSR_IS | MSR_DS;
+       vcpu->arch.shared->pir = vcpu->vcpu_id;
        kvmppc_set_gpr(vcpu, 1, (16<<20) - 8); /* -8 for the callee-save LR slot */
 
        vcpu->arch.shadow_pid = 1;
@@ -662,10 +696,10 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
        regs->sprg1 = vcpu->arch.shared->sprg1;
        regs->sprg2 = vcpu->arch.shared->sprg2;
        regs->sprg3 = vcpu->arch.shared->sprg3;
-       regs->sprg4 = vcpu->arch.sprg4;
-       regs->sprg5 = vcpu->arch.sprg5;
-       regs->sprg6 = vcpu->arch.sprg6;
-       regs->sprg7 = vcpu->arch.sprg7;
+       regs->sprg4 = vcpu->arch.shared->sprg4;
+       regs->sprg5 = vcpu->arch.shared->sprg5;
+       regs->sprg6 = vcpu->arch.shared->sprg6;
+       regs->sprg7 = vcpu->arch.shared->sprg7;
 
        for (i = 0; i < ARRAY_SIZE(regs->gpr); i++)
                regs->gpr[i] = kvmppc_get_gpr(vcpu, i);
@@ -690,10 +724,10 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
        vcpu->arch.shared->sprg1 = regs->sprg1;
        vcpu->arch.shared->sprg2 = regs->sprg2;
        vcpu->arch.shared->sprg3 = regs->sprg3;
-       vcpu->arch.sprg4 = regs->sprg4;
-       vcpu->arch.sprg5 = regs->sprg5;
-       vcpu->arch.sprg6 = regs->sprg6;
-       vcpu->arch.sprg7 = regs->sprg7;
+       vcpu->arch.shared->sprg4 = regs->sprg4;
+       vcpu->arch.shared->sprg5 = regs->sprg5;
+       vcpu->arch.shared->sprg6 = regs->sprg6;
+       vcpu->arch.shared->sprg7 = regs->sprg7;
 
        for (i = 0; i < ARRAY_SIZE(regs->gpr); i++)
                kvmppc_set_gpr(vcpu, i, regs->gpr[i]);
@@ -711,7 +745,7 @@ static void get_sregs_base(struct kvm_vcpu *vcpu,
        sregs->u.e.csrr0 = vcpu->arch.csrr0;
        sregs->u.e.csrr1 = vcpu->arch.csrr1;
        sregs->u.e.mcsr = vcpu->arch.mcsr;
-       sregs->u.e.esr = vcpu->arch.esr;
+       sregs->u.e.esr = vcpu->arch.shared->esr;
        sregs->u.e.dear = vcpu->arch.shared->dar;
        sregs->u.e.tsr = vcpu->arch.tsr;
        sregs->u.e.tcr = vcpu->arch.tcr;
@@ -729,28 +763,19 @@ static int set_sregs_base(struct kvm_vcpu *vcpu,
        vcpu->arch.csrr0 = sregs->u.e.csrr0;
        vcpu->arch.csrr1 = sregs->u.e.csrr1;
        vcpu->arch.mcsr = sregs->u.e.mcsr;
-       vcpu->arch.esr = sregs->u.e.esr;
+       vcpu->arch.shared->esr = sregs->u.e.esr;
        vcpu->arch.shared->dar = sregs->u.e.dear;
        vcpu->arch.vrsave = sregs->u.e.vrsave;
-       vcpu->arch.tcr = sregs->u.e.tcr;
+       kvmppc_set_tcr(vcpu, sregs->u.e.tcr);
 
-       if (sregs->u.e.update_special & KVM_SREGS_E_UPDATE_DEC)
+       if (sregs->u.e.update_special & KVM_SREGS_E_UPDATE_DEC) {
                vcpu->arch.dec = sregs->u.e.dec;
-
-       kvmppc_emulate_dec(vcpu);
+               kvmppc_emulate_dec(vcpu);
+       }
 
        if (sregs->u.e.update_special & KVM_SREGS_E_UPDATE_TSR) {
-               /*
-                * FIXME: existing KVM timer handling is incomplete.
-                * TSR cannot be read by the guest, and its value in
-                * vcpu->arch is always zero.  For now, just handle
-                * the case where the caller is trying to inject a
-                * decrementer interrupt.
-                */
-
-               if ((sregs->u.e.tsr & TSR_DIS) &&
-                   (vcpu->arch.tcr & TCR_DIE))
-                       kvmppc_core_queue_dec(vcpu);
+               vcpu->arch.tsr = sregs->u.e.tsr;
+               update_timer_ints(vcpu);
        }
 
        return 0;
@@ -761,7 +786,7 @@ static void get_sregs_arch206(struct kvm_vcpu *vcpu,
 {
        sregs->u.e.features |= KVM_SREGS_E_ARCH206;
 
-       sregs->u.e.pir = 0;
+       sregs->u.e.pir = vcpu->vcpu_id;
        sregs->u.e.mcsrr0 = vcpu->arch.mcsrr0;
        sregs->u.e.mcsrr1 = vcpu->arch.mcsrr1;
        sregs->u.e.decar = vcpu->arch.decar;
@@ -774,7 +799,7 @@ static int set_sregs_arch206(struct kvm_vcpu *vcpu,
        if (!(sregs->u.e.features & KVM_SREGS_E_ARCH206))
                return 0;
 
-       if (sregs->u.e.pir != 0)
+       if (sregs->u.e.pir != vcpu->vcpu_id)
                return -EINVAL;
 
        vcpu->arch.mcsrr0 = sregs->u.e.mcsrr0;
@@ -862,6 +887,16 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
        return kvmppc_core_set_sregs(vcpu, sregs);
 }
 
+int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
+{
+       return -EINVAL;
+}
+
+int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
+{
+       return -EINVAL;
+}
+
 int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
 {
        return -ENOTSUPP;
@@ -906,6 +941,33 @@ void kvmppc_core_destroy_vm(struct kvm *kvm)
 {
 }
 
+void kvmppc_set_tcr(struct kvm_vcpu *vcpu, u32 new_tcr)
+{
+       vcpu->arch.tcr = new_tcr;
+       update_timer_ints(vcpu);
+}
+
+void kvmppc_set_tsr_bits(struct kvm_vcpu *vcpu, u32 tsr_bits)
+{
+       set_bits(tsr_bits, &vcpu->arch.tsr);
+       smp_wmb();
+       kvm_make_request(KVM_REQ_PENDING_TIMER, vcpu);
+       kvm_vcpu_kick(vcpu);
+}
+
+void kvmppc_clr_tsr_bits(struct kvm_vcpu *vcpu, u32 tsr_bits)
+{
+       clear_bits(tsr_bits, &vcpu->arch.tsr);
+       update_timer_ints(vcpu);
+}
+
+void kvmppc_decrementer_func(unsigned long data)
+{
+       struct kvm_vcpu *vcpu = (struct kvm_vcpu *)data;
+
+       kvmppc_set_tsr_bits(vcpu, TSR_DIS);
+}
+
 int __init kvmppc_booke_init(void)
 {
        unsigned long ivor[16];
index 8e1fe33..2fe2027 100644 (file)
@@ -55,6 +55,10 @@ extern unsigned long kvmppc_booke_handlers;
 void kvmppc_set_msr(struct kvm_vcpu *vcpu, u32 new_msr);
 void kvmppc_mmu_msr_notify(struct kvm_vcpu *vcpu, u32 old_msr);
 
+void kvmppc_set_tcr(struct kvm_vcpu *vcpu, u32 new_tcr);
+void kvmppc_set_tsr_bits(struct kvm_vcpu *vcpu, u32 tsr_bits);
+void kvmppc_clr_tsr_bits(struct kvm_vcpu *vcpu, u32 tsr_bits);
+
 int kvmppc_booke_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
                             unsigned int inst, int *advance);
 int kvmppc_booke_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt);
index 1260f5f..3e652da 100644 (file)
@@ -13,6 +13,7 @@
  * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *
  * Copyright IBM Corp. 2008
+ * Copyright 2011 Freescale Semiconductor, Inc.
  *
  * Authors: Hollis Blanchard <hollisb@us.ibm.com>
  */
@@ -107,7 +108,7 @@ int kvmppc_booke_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
        case SPRN_DEAR:
                vcpu->arch.shared->dar = spr_val; break;
        case SPRN_ESR:
-               vcpu->arch.esr = spr_val; break;
+               vcpu->arch.shared->esr = spr_val; break;
        case SPRN_DBCR0:
                vcpu->arch.dbcr0 = spr_val; break;
        case SPRN_DBCR1:
@@ -115,23 +116,23 @@ int kvmppc_booke_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
        case SPRN_DBSR:
                vcpu->arch.dbsr &= ~spr_val; break;
        case SPRN_TSR:
-               vcpu->arch.tsr &= ~spr_val; break;
+               kvmppc_clr_tsr_bits(vcpu, spr_val);
+               break;
        case SPRN_TCR:
-               vcpu->arch.tcr = spr_val;
-               kvmppc_emulate_dec(vcpu);
+               kvmppc_set_tcr(vcpu, spr_val);
                break;
 
        /* Note: SPRG4-7 are user-readable. These values are
         * loaded into the real SPRGs when resuming the
         * guest. */
        case SPRN_SPRG4:
-               vcpu->arch.sprg4 = spr_val; break;
+               vcpu->arch.shared->sprg4 = spr_val; break;
        case SPRN_SPRG5:
-               vcpu->arch.sprg5 = spr_val; break;
+               vcpu->arch.shared->sprg5 = spr_val; break;
        case SPRN_SPRG6:
-               vcpu->arch.sprg6 = spr_val; break;
+               vcpu->arch.shared->sprg6 = spr_val; break;
        case SPRN_SPRG7:
-               vcpu->arch.sprg7 = spr_val; break;
+               vcpu->arch.shared->sprg7 = spr_val; break;
 
        case SPRN_IVPR:
                vcpu->arch.ivpr = spr_val;
@@ -202,13 +203,17 @@ int kvmppc_booke_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)
        case SPRN_DEAR:
                kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->dar); break;
        case SPRN_ESR:
-               kvmppc_set_gpr(vcpu, rt, vcpu->arch.esr); break;
+               kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->esr); break;
        case SPRN_DBCR0:
                kvmppc_set_gpr(vcpu, rt, vcpu->arch.dbcr0); break;
        case SPRN_DBCR1:
                kvmppc_set_gpr(vcpu, rt, vcpu->arch.dbcr1); break;
        case SPRN_DBSR:
                kvmppc_set_gpr(vcpu, rt, vcpu->arch.dbsr); break;
+       case SPRN_TSR:
+               kvmppc_set_gpr(vcpu, rt, vcpu->arch.tsr); break;
+       case SPRN_TCR:
+               kvmppc_set_gpr(vcpu, rt, vcpu->arch.tcr); break;
 
        case SPRN_IVOR0:
                kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_CRITICAL]);
index 42f2fb1..10d8ef6 100644 (file)
@@ -402,19 +402,25 @@ lightweight_exit:
        /* Save vcpu pointer for the exception handlers. */
        mtspr   SPRN_SPRG_WVCPU, r4
 
+       lwz     r5, VCPU_SHARED(r4)
+
        /* Can't switch the stack pointer until after IVPR is switched,
         * because host interrupt handlers would get confused. */
        lwz     r1, VCPU_GPR(r1)(r4)
 
-       /* Host interrupt handlers may have clobbered these guest-readable
-        * SPRGs, so we need to reload them here with the guest's values. */
-       lwz     r3, VCPU_SPRG4(r4)
+       /*
+        * Host interrupt handlers may have clobbered these
+        * guest-readable SPRGs, or the guest kernel may have
+        * written directly to the shared area, so we
+        * need to reload them here with the guest's values.
+        */
+       lwz     r3, VCPU_SHARED_SPRG4(r5)
        mtspr   SPRN_SPRG4W, r3
-       lwz     r3, VCPU_SPRG5(r4)
+       lwz     r3, VCPU_SHARED_SPRG5(r5)
        mtspr   SPRN_SPRG5W, r3
-       lwz     r3, VCPU_SPRG6(r4)
+       lwz     r3, VCPU_SHARED_SPRG6(r5)
        mtspr   SPRN_SPRG6W, r3
-       lwz     r3, VCPU_SPRG7(r4)
+       lwz     r3, VCPU_SHARED_SPRG7(r5)
        mtspr   SPRN_SPRG7W, r3
 
 #ifdef CONFIG_KVM_EXIT_TIMING
index 8c0d45a..ddcd896 100644 (file)
@@ -71,9 +71,6 @@ int kvmppc_core_vcpu_setup(struct kvm_vcpu *vcpu)
        vcpu->arch.pvr = mfspr(SPRN_PVR);
        vcpu_e500->svr = mfspr(SPRN_SVR);
 
-       /* Since booke kvm only support one core, update all vcpus' PIR to 0 */
-       vcpu->vcpu_id = 0;
-
        vcpu->arch.cpu_type = KVM_CPU_E500V2;
 
        return 0;
@@ -118,12 +115,12 @@ void kvmppc_core_get_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs)
        sregs->u.e.impl.fsl.hid0 = vcpu_e500->hid0;
        sregs->u.e.impl.fsl.mcar = vcpu_e500->mcar;
 
-       sregs->u.e.mas0 = vcpu_e500->mas0;
-       sregs->u.e.mas1 = vcpu_e500->mas1;
-       sregs->u.e.mas2 = vcpu_e500->mas2;
-       sregs->u.e.mas7_3 = ((u64)vcpu_e500->mas7 << 32) | vcpu_e500->mas3;
-       sregs->u.e.mas4 = vcpu_e500->mas4;
-       sregs->u.e.mas6 = vcpu_e500->mas6;
+       sregs->u.e.mas0 = vcpu->arch.shared->mas0;
+       sregs->u.e.mas1 = vcpu->arch.shared->mas1;
+       sregs->u.e.mas2 = vcpu->arch.shared->mas2;
+       sregs->u.e.mas7_3 = vcpu->arch.shared->mas7_3;
+       sregs->u.e.mas4 = vcpu->arch.shared->mas4;
+       sregs->u.e.mas6 = vcpu->arch.shared->mas6;
 
        sregs->u.e.mmucfg = mfspr(SPRN_MMUCFG);
        sregs->u.e.tlbcfg[0] = vcpu_e500->tlb0cfg;
@@ -151,13 +148,12 @@ int kvmppc_core_set_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs)
        }
 
        if (sregs->u.e.features & KVM_SREGS_E_ARCH206_MMU) {
-               vcpu_e500->mas0 = sregs->u.e.mas0;
-               vcpu_e500->mas1 = sregs->u.e.mas1;
-               vcpu_e500->mas2 = sregs->u.e.mas2;
-               vcpu_e500->mas7 = sregs->u.e.mas7_3 >> 32;
-               vcpu_e500->mas3 = (u32)sregs->u.e.mas7_3;
-               vcpu_e500->mas4 = sregs->u.e.mas4;
-               vcpu_e500->mas6 = sregs->u.e.mas6;
+               vcpu->arch.shared->mas0 = sregs->u.e.mas0;
+               vcpu->arch.shared->mas1 = sregs->u.e.mas1;
+               vcpu->arch.shared->mas2 = sregs->u.e.mas2;
+               vcpu->arch.shared->mas7_3 = sregs->u.e.mas7_3;
+               vcpu->arch.shared->mas4 = sregs->u.e.mas4;
+               vcpu->arch.shared->mas6 = sregs->u.e.mas6;
        }
 
        if (!(sregs->u.e.features & KVM_SREGS_E_IVOR))
@@ -233,6 +229,10 @@ static int __init kvmppc_e500_init(void)
        unsigned long ivor[3];
        unsigned long max_ivor = 0;
 
+       r = kvmppc_core_check_processor_compat();
+       if (r)
+               return r;
+
        r = kvmppc_booke_init();
        if (r)
                return r;
index d48ae39..6d0b2bd 100644 (file)
@@ -89,19 +89,23 @@ int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
                        return EMULATE_FAIL;
                vcpu_e500->pid[2] = spr_val; break;
        case SPRN_MAS0:
-               vcpu_e500->mas0 = spr_val; break;
+               vcpu->arch.shared->mas0 = spr_val; break;
        case SPRN_MAS1:
-               vcpu_e500->mas1 = spr_val; break;
+               vcpu->arch.shared->mas1 = spr_val; break;
        case SPRN_MAS2:
-               vcpu_e500->mas2 = spr_val; break;
+               vcpu->arch.shared->mas2 = spr_val; break;
        case SPRN_MAS3:
-               vcpu_e500->mas3 = spr_val; break;
+               vcpu->arch.shared->mas7_3 &= ~(u64)0xffffffff;
+               vcpu->arch.shared->mas7_3 |= spr_val;
+               break;
        case SPRN_MAS4:
-               vcpu_e500->mas4 = spr_val; break;
+               vcpu->arch.shared->mas4 = spr_val; break;
        case SPRN_MAS6:
-               vcpu_e500->mas6 = spr_val; break;
+               vcpu->arch.shared->mas6 = spr_val; break;
        case SPRN_MAS7:
-               vcpu_e500->mas7 = spr_val; break;
+               vcpu->arch.shared->mas7_3 &= (u64)0xffffffff;
+               vcpu->arch.shared->mas7_3 |= (u64)spr_val << 32;
+               break;
        case SPRN_L1CSR0:
                vcpu_e500->l1csr0 = spr_val;
                vcpu_e500->l1csr0 &= ~(L1CSR0_DCFI | L1CSR0_CLFC);
@@ -143,6 +147,7 @@ int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)
 {
        struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
        int emulated = EMULATE_DONE;
+       unsigned long val;
 
        switch (sprn) {
        case SPRN_PID:
@@ -152,20 +157,23 @@ int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)
        case SPRN_PID2:
                kvmppc_set_gpr(vcpu, rt, vcpu_e500->pid[2]); break;
        case SPRN_MAS0:
-               kvmppc_set_gpr(vcpu, rt, vcpu_e500->mas0); break;
+               kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->mas0); break;
        case SPRN_MAS1:
-               kvmppc_set_gpr(vcpu, rt, vcpu_e500->mas1); break;
+               kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->mas1); break;
        case SPRN_MAS2:
-               kvmppc_set_gpr(vcpu, rt, vcpu_e500->mas2); break;
+               kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->mas2); break;
        case SPRN_MAS3:
-               kvmppc_set_gpr(vcpu, rt, vcpu_e500->mas3); break;
+               val = (u32)vcpu->arch.shared->mas7_3;
+               kvmppc_set_gpr(vcpu, rt, val);
+               break;
        case SPRN_MAS4:
-               kvmppc_set_gpr(vcpu, rt, vcpu_e500->mas4); break;
+               kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->mas4); break;
        case SPRN_MAS6:
-               kvmppc_set_gpr(vcpu, rt, vcpu_e500->mas6); break;
+               kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->mas6); break;
        case SPRN_MAS7:
-               kvmppc_set_gpr(vcpu, rt, vcpu_e500->mas7); break;
-
+               val = vcpu->arch.shared->mas7_3 >> 32;
+               kvmppc_set_gpr(vcpu, rt, val);
+               break;
        case SPRN_TLB0CFG:
                kvmppc_set_gpr(vcpu, rt, vcpu_e500->tlb0cfg); break;
        case SPRN_TLB1CFG:
index 13c432e..6e53e41 100644 (file)
  * published by the Free Software Foundation.
  */
 
+#include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
 #include <linux/highmem.h>
+#include <linux/log2.h>
+#include <linux/uaccess.h>
+#include <linux/sched.h>
+#include <linux/rwsem.h>
+#include <linux/vmalloc.h>
+#include <linux/hugetlb.h>
 #include <asm/kvm_ppc.h>
 #include <asm/kvm_e500.h>
 
@@ -26,7 +33,7 @@
 #include "trace.h"
 #include "timing.h"
 
-#define to_htlb1_esel(esel) (tlb1_entry_num - (esel) - 1)
+#define to_htlb1_esel(esel) (host_tlb_params[1].entries - (esel) - 1)
 
 struct id {
        unsigned long val;
@@ -63,7 +70,14 @@ static DEFINE_PER_CPU(struct pcpu_id_table, pcpu_sids);
  * The valid range of shadow ID is [1..255] */
 static DEFINE_PER_CPU(unsigned long, pcpu_last_used_sid);
 
-static unsigned int tlb1_entry_num;
+static struct kvmppc_e500_tlb_params host_tlb_params[E500_TLB_NUM];
+
+static struct kvm_book3e_206_tlb_entry *get_entry(
+       struct kvmppc_vcpu_e500 *vcpu_e500, int tlbsel, int entry)
+{
+       int offset = vcpu_e500->gtlb_offset[tlbsel];
+       return &vcpu_e500->gtlb_arch[offset + entry];
+}
 
 /*
  * Allocate a free shadow id and setup a valid sid mapping in given entry.
@@ -116,13 +130,11 @@ static inline int local_sid_lookup(struct id *entry)
        return -1;
 }
 
-/* Invalidate all id mappings on local core */
+/* Invalidate all id mappings on local core -- call with preempt disabled */
 static inline void local_sid_destroy_all(void)
 {
-       preempt_disable();
        __get_cpu_var(pcpu_last_used_sid) = 0;
        memset(&__get_cpu_var(pcpu_sids), 0, sizeof(__get_cpu_var(pcpu_sids)));
-       preempt_enable();
 }
 
 static void *kvmppc_e500_id_table_alloc(struct kvmppc_vcpu_e500 *vcpu_e500)
@@ -218,34 +230,13 @@ void kvmppc_e500_recalc_shadow_pid(struct kvmppc_vcpu_e500 *vcpu_e500)
        preempt_enable();
 }
 
-void kvmppc_dump_tlbs(struct kvm_vcpu *vcpu)
-{
-       struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
-       struct tlbe *tlbe;
-       int i, tlbsel;
-
-       printk("| %8s | %8s | %8s | %8s | %8s |\n",
-                       "nr", "mas1", "mas2", "mas3", "mas7");
-
-       for (tlbsel = 0; tlbsel < 2; tlbsel++) {
-               printk("Guest TLB%d:\n", tlbsel);
-               for (i = 0; i < vcpu_e500->gtlb_size[tlbsel]; i++) {
-                       tlbe = &vcpu_e500->gtlb_arch[tlbsel][i];
-                       if (tlbe->mas1 & MAS1_VALID)
-                               printk(" G[%d][%3d] |  %08X | %08X | %08X | %08X |\n",
-                                       tlbsel, i, tlbe->mas1, tlbe->mas2,
-                                       tlbe->mas3, tlbe->mas7);
-               }
-       }
-}
-
-static inline unsigned int tlb0_get_next_victim(
+static inline unsigned int gtlb0_get_next_victim(
                struct kvmppc_vcpu_e500 *vcpu_e500)
 {
        unsigned int victim;
 
        victim = vcpu_e500->gtlb_nv[0]++;
-       if (unlikely(vcpu_e500->gtlb_nv[0] >= KVM_E500_TLB0_WAY_NUM))
+       if (unlikely(vcpu_e500->gtlb_nv[0] >= vcpu_e500->gtlb_params[0].ways))
                vcpu_e500->gtlb_nv[0] = 0;
 
        return victim;
@@ -254,12 +245,12 @@ static inline unsigned int tlb0_get_next_victim(
 static inline unsigned int tlb1_max_shadow_size(void)
 {
        /* reserve one entry for magic page */
-       return tlb1_entry_num - tlbcam_index - 1;
+       return host_tlb_params[1].entries - tlbcam_index - 1;
 }
 
-static inline int tlbe_is_writable(struct tlbe *tlbe)
+static inline int tlbe_is_writable(struct kvm_book3e_206_tlb_entry *tlbe)
 {
-       return tlbe->mas3 & (MAS3_SW|MAS3_UW);
+       return tlbe->mas7_3 & (MAS3_SW|MAS3_UW);
 }
 
 static inline u32 e500_shadow_mas3_attrib(u32 mas3, int usermode)
@@ -290,40 +281,66 @@ static inline u32 e500_shadow_mas2_attrib(u32 mas2, int usermode)
 /*
  * writing shadow tlb entry to host TLB
  */
-static inline void __write_host_tlbe(struct tlbe *stlbe, uint32_t mas0)
+static inline void __write_host_tlbe(struct kvm_book3e_206_tlb_entry *stlbe,
+                                    uint32_t mas0)
 {
        unsigned long flags;
 
        local_irq_save(flags);
        mtspr(SPRN_MAS0, mas0);
        mtspr(SPRN_MAS1, stlbe->mas1);
-       mtspr(SPRN_MAS2, stlbe->mas2);
-       mtspr(SPRN_MAS3, stlbe->mas3);
-       mtspr(SPRN_MAS7, stlbe->mas7);
+       mtspr(SPRN_MAS2, (unsigned long)stlbe->mas2);
+       mtspr(SPRN_MAS3, (u32)stlbe->mas7_3);
+       mtspr(SPRN_MAS7, (u32)(stlbe->mas7_3 >> 32));
        asm volatile("isync; tlbwe" : : : "memory");
        local_irq_restore(flags);
+
+       trace_kvm_booke206_stlb_write(mas0, stlbe->mas8, stlbe->mas1,
+                                     stlbe->mas2, stlbe->mas7_3);
+}
+
+/*
+ * Acquire a mas0 with victim hint, as if we just took a TLB miss.
+ *
+ * We don't care about the address we're searching for, other than that it's
+ * in the right set and is not present in the TLB.  Using a zero PID and a
+ * userspace address means we don't have to set and then restore MAS5, or
+ * calculate a proper MAS6 value.
+ */
+static u32 get_host_mas0(unsigned long eaddr)
+{
+       unsigned long flags;
+       u32 mas0;
+
+       local_irq_save(flags);
+       mtspr(SPRN_MAS6, 0);
+       asm volatile("tlbsx 0, %0" : : "b" (eaddr & ~CONFIG_PAGE_OFFSET));
+       mas0 = mfspr(SPRN_MAS0);
+       local_irq_restore(flags);
+
+       return mas0;
 }
 
+/* sesel is for tlb1 only */
 static inline void write_host_tlbe(struct kvmppc_vcpu_e500 *vcpu_e500,
-               int tlbsel, int esel, struct tlbe *stlbe)
+               int tlbsel, int sesel, struct kvm_book3e_206_tlb_entry *stlbe)
 {
+       u32 mas0;
+
        if (tlbsel == 0) {
-               __write_host_tlbe(stlbe,
-                                 MAS0_TLBSEL(0) |
-                                 MAS0_ESEL(esel & (KVM_E500_TLB0_WAY_NUM - 1)));
+               mas0 = get_host_mas0(stlbe->mas2);
+               __write_host_tlbe(stlbe, mas0);
        } else {
                __write_host_tlbe(stlbe,
                                  MAS0_TLBSEL(1) |
-                                 MAS0_ESEL(to_htlb1_esel(esel)));
+                                 MAS0_ESEL(to_htlb1_esel(sesel)));
        }
-       trace_kvm_stlb_write(index_of(tlbsel, esel), stlbe->mas1, stlbe->mas2,
-                            stlbe->mas3, stlbe->mas7);
 }
 
 void kvmppc_map_magic(struct kvm_vcpu *vcpu)
 {
        struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
-       struct tlbe magic;
+       struct kvm_book3e_206_tlb_entry magic;
        ulong shared_page = ((ulong)vcpu->arch.shared) & PAGE_MASK;
        unsigned int stid;
        pfn_t pfn;
@@ -337,9 +354,9 @@ void kvmppc_map_magic(struct kvm_vcpu *vcpu)
        magic.mas1 = MAS1_VALID | MAS1_TS | MAS1_TID(stid) |
                     MAS1_TSIZE(BOOK3E_PAGESZ_4K);
        magic.mas2 = vcpu->arch.magic_page_ea | MAS2_M;
-       magic.mas3 = (pfn << PAGE_SHIFT) |
-                    MAS3_SW | MAS3_SR | MAS3_UW | MAS3_UR;
-       magic.mas7 = pfn >> (32 - PAGE_SHIFT);
+       magic.mas7_3 = ((u64)pfn << PAGE_SHIFT) |
+                      MAS3_SW | MAS3_SR | MAS3_UW | MAS3_UR;
+       magic.mas8 = 0;
 
        __write_host_tlbe(&magic, MAS0_TLBSEL(1) | MAS0_ESEL(tlbcam_index));
        preempt_enable();
@@ -357,10 +374,11 @@ void kvmppc_e500_tlb_put(struct kvm_vcpu *vcpu)
 {
 }
 
-static void kvmppc_e500_stlbe_invalidate(struct kvmppc_vcpu_e500 *vcpu_e500,
-                                        int tlbsel, int esel)
+static void inval_gtlbe_on_host(struct kvmppc_vcpu_e500 *vcpu_e500,
+                               int tlbsel, int esel)
 {
-       struct tlbe *gtlbe = &vcpu_e500->gtlb_arch[tlbsel][esel];
+       struct kvm_book3e_206_tlb_entry *gtlbe =
+               get_entry(vcpu_e500, tlbsel, esel);
        struct vcpu_id_table *idt = vcpu_e500->idt;
        unsigned int pr, tid, ts, pid;
        u32 val, eaddr;
@@ -414,25 +432,57 @@ static void kvmppc_e500_stlbe_invalidate(struct kvmppc_vcpu_e500 *vcpu_e500,
        preempt_enable();
 }
 
+static int tlb0_set_base(gva_t addr, int sets, int ways)
+{
+       int set_base;
+
+       set_base = (addr >> PAGE_SHIFT) & (sets - 1);
+       set_base *= ways;
+
+       return set_base;
+}
+
+static int gtlb0_set_base(struct kvmppc_vcpu_e500 *vcpu_e500, gva_t addr)
+{
+       return tlb0_set_base(addr, vcpu_e500->gtlb_params[0].sets,
+                            vcpu_e500->gtlb_params[0].ways);
+}
+
+static unsigned int get_tlb_esel(struct kvm_vcpu *vcpu, int tlbsel)
+{
+       struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
+       int esel = get_tlb_esel_bit(vcpu);
+
+       if (tlbsel == 0) {
+               esel &= vcpu_e500->gtlb_params[0].ways - 1;
+               esel += gtlb0_set_base(vcpu_e500, vcpu->arch.shared->mas2);
+       } else {
+               esel &= vcpu_e500->gtlb_params[tlbsel].entries - 1;
+       }
+
+       return esel;
+}
+
 /* Search the guest TLB for a matching entry. */
 static int kvmppc_e500_tlb_index(struct kvmppc_vcpu_e500 *vcpu_e500,
                gva_t eaddr, int tlbsel, unsigned int pid, int as)
 {
-       int size = vcpu_e500->gtlb_size[tlbsel];
-       int set_base;
+       int size = vcpu_e500->gtlb_params[tlbsel].entries;
+       unsigned int set_base, offset;
        int i;
 
        if (tlbsel == 0) {
-               int mask = size / KVM_E500_TLB0_WAY_NUM - 1;
-               set_base = (eaddr >> PAGE_SHIFT) & mask;
-               set_base *= KVM_E500_TLB0_WAY_NUM;
-               size = KVM_E500_TLB0_WAY_NUM;
+               set_base = gtlb0_set_base(vcpu_e500, eaddr);
+               size = vcpu_e500->gtlb_params[0].ways;
        } else {
                set_base = 0;
        }
 
+       offset = vcpu_e500->gtlb_offset[tlbsel];
+
        for (i = 0; i < size; i++) {
-               struct tlbe *tlbe = &vcpu_e500->gtlb_arch[tlbsel][set_base + i];
+               struct kvm_book3e_206_tlb_entry *tlbe =
+                       &vcpu_e500->gtlb_arch[offset + set_base + i];
                unsigned int tid;
 
                if (eaddr < get_tlb_eaddr(tlbe))
@@ -457,27 +507,55 @@ static int kvmppc_e500_tlb_index(struct kvmppc_vcpu_e500 *vcpu_e500,
        return -1;
 }
 
-static inline void kvmppc_e500_priv_setup(struct tlbe_priv *priv,
-                                         struct tlbe *gtlbe,
-                                         pfn_t pfn)
+static inline void kvmppc_e500_ref_setup(struct tlbe_ref *ref,
+                                        struct kvm_book3e_206_tlb_entry *gtlbe,
+                                        pfn_t pfn)
 {
-       priv->pfn = pfn;
-       priv->flags = E500_TLB_VALID;
+       ref->pfn = pfn;
+       ref->flags = E500_TLB_VALID;
 
        if (tlbe_is_writable(gtlbe))
-               priv->flags |= E500_TLB_DIRTY;
+               ref->flags |= E500_TLB_DIRTY;
 }
 
-static inline void kvmppc_e500_priv_release(struct tlbe_priv *priv)
+static inline void kvmppc_e500_ref_release(struct tlbe_ref *ref)
 {
-       if (priv->flags & E500_TLB_VALID) {
-               if (priv->flags & E500_TLB_DIRTY)
-                       kvm_release_pfn_dirty(priv->pfn);
+       if (ref->flags & E500_TLB_VALID) {
+               if (ref->flags & E500_TLB_DIRTY)
+                       kvm_release_pfn_dirty(ref->pfn);
                else
-                       kvm_release_pfn_clean(priv->pfn);
+                       kvm_release_pfn_clean(ref->pfn);
+
+               ref->flags = 0;
+       }
+}
+
+static void clear_tlb_privs(struct kvmppc_vcpu_e500 *vcpu_e500)
+{
+       int tlbsel = 0;
+       int i;
+
+       for (i = 0; i < vcpu_e500->gtlb_params[tlbsel].entries; i++) {
+               struct tlbe_ref *ref =
+                       &vcpu_e500->gtlb_priv[tlbsel][i].ref;
+               kvmppc_e500_ref_release(ref);
+       }
+}
+
+static void clear_tlb_refs(struct kvmppc_vcpu_e500 *vcpu_e500)
+{
+       int stlbsel = 1;
+       int i;
+
+       kvmppc_e500_id_table_reset_all(vcpu_e500);
 
-               priv->flags = 0;
+       for (i = 0; i < host_tlb_params[stlbsel].entries; i++) {
+               struct tlbe_ref *ref =
+                       &vcpu_e500->tlb_refs[stlbsel][i];
+               kvmppc_e500_ref_release(ref);
        }
+
+       clear_tlb_privs(vcpu_e500);
 }
 
 static inline void kvmppc_e500_deliver_tlb_miss(struct kvm_vcpu *vcpu,
@@ -488,59 +566,54 @@ static inline void kvmppc_e500_deliver_tlb_miss(struct kvm_vcpu *vcpu,
        int tlbsel;
 
        /* since we only have two TLBs, only lower bit is used. */
-       tlbsel = (vcpu_e500->mas4 >> 28) & 0x1;
-       victim = (tlbsel == 0) ? tlb0_get_next_victim(vcpu_e500) : 0;
-       pidsel = (vcpu_e500->mas4 >> 16) & 0xf;
-       tsized = (vcpu_e500->mas4 >> 7) & 0x1f;
+       tlbsel = (vcpu->arch.shared->mas4 >> 28) & 0x1;
+       victim = (tlbsel == 0) ? gtlb0_get_next_victim(vcpu_e500) : 0;
+       pidsel = (vcpu->arch.shared->mas4 >> 16) & 0xf;
+       tsized = (vcpu->arch.shared->mas4 >> 7) & 0x1f;
 
-       vcpu_e500->mas0 = MAS0_TLBSEL(tlbsel) | MAS0_ESEL(victim)
+       vcpu->arch.shared->mas0 = MAS0_TLBSEL(tlbsel) | MAS0_ESEL(victim)
                | MAS0_NV(vcpu_e500->gtlb_nv[tlbsel]);
-       vcpu_e500->mas1 = MAS1_VALID | (as ? MAS1_TS : 0)
+       vcpu->arch.shared->mas1 = MAS1_VALID | (as ? MAS1_TS : 0)
                | MAS1_TID(vcpu_e500->pid[pidsel])
                | MAS1_TSIZE(tsized);
-       vcpu_e500->mas2 = (eaddr & MAS2_EPN)
-               | (vcpu_e500->mas4 & MAS2_ATTRIB_MASK);
-       vcpu_e500->mas3 &= MAS3_U0 | MAS3_U1 | MAS3_U2 | MAS3_U3;
-       vcpu_e500->mas6 = (vcpu_e500->mas6 & MAS6_SPID1)
+       vcpu->arch.shared->mas2 = (eaddr & MAS2_EPN)
+               | (vcpu->arch.shared->mas4 & MAS2_ATTRIB_MASK);
+       vcpu->arch.shared->mas7_3 &= MAS3_U0 | MAS3_U1 | MAS3_U2 | MAS3_U3;
+       vcpu->arch.shared->mas6 = (vcpu->arch.shared->mas6 & MAS6_SPID1)
                | (get_cur_pid(vcpu) << 16)
                | (as ? MAS6_SAS : 0);
-       vcpu_e500->mas7 = 0;
 }
 
-static inline void kvmppc_e500_setup_stlbe(struct kvmppc_vcpu_e500 *vcpu_e500,
-                                          struct tlbe *gtlbe, int tsize,
-                                          struct tlbe_priv *priv,
-                                          u64 gvaddr, struct tlbe *stlbe)
+/* TID must be supplied by the caller */
+static inline void kvmppc_e500_setup_stlbe(
+       struct kvmppc_vcpu_e500 *vcpu_e500,
+       struct kvm_book3e_206_tlb_entry *gtlbe,
+       int tsize, struct tlbe_ref *ref, u64 gvaddr,
+       struct kvm_book3e_206_tlb_entry *stlbe)
 {
-       pfn_t pfn = priv->pfn;
-       unsigned int stid;
+       pfn_t pfn = ref->pfn;
 
-       stid = kvmppc_e500_get_sid(vcpu_e500, get_tlb_ts(gtlbe),
-                                  get_tlb_tid(gtlbe),
-                                  get_cur_pr(&vcpu_e500->vcpu), 0);
+       BUG_ON(!(ref->flags & E500_TLB_VALID));
 
        /* Force TS=1 IPROT=0 for all guest mappings. */
-       stlbe->mas1 = MAS1_TSIZE(tsize)
-               | MAS1_TID(stid) | MAS1_TS | MAS1_VALID;
+       stlbe->mas1 = MAS1_TSIZE(tsize) | MAS1_TS | MAS1_VALID;
        stlbe->mas2 = (gvaddr & MAS2_EPN)
                | e500_shadow_mas2_attrib(gtlbe->mas2,
                                vcpu_e500->vcpu.arch.shared->msr & MSR_PR);
-       stlbe->mas3 = ((pfn << PAGE_SHIFT) & MAS3_RPN)
-               | e500_shadow_mas3_attrib(gtlbe->mas3,
+       stlbe->mas7_3 = ((u64)pfn << PAGE_SHIFT)
+               | e500_shadow_mas3_attrib(gtlbe->mas7_3,
                                vcpu_e500->vcpu.arch.shared->msr & MSR_PR);
-       stlbe->mas7 = (pfn >> (32 - PAGE_SHIFT)) & MAS7_RPN;
 }
 
-
 static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
-       u64 gvaddr, gfn_t gfn, struct tlbe *gtlbe, int tlbsel, int esel,
-       struct tlbe *stlbe)
+       u64 gvaddr, gfn_t gfn, struct kvm_book3e_206_tlb_entry *gtlbe,
+       int tlbsel, struct kvm_book3e_206_tlb_entry *stlbe,
+       struct tlbe_ref *ref)
 {
        struct kvm_memory_slot *slot;
        unsigned long pfn, hva;
        int pfnmap = 0;
        int tsize = BOOK3E_PAGESZ_4K;
-       struct tlbe_priv *priv;
 
        /*
         * Translate guest physical to true physical, acquiring
@@ -621,12 +694,31 @@ static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
                                pfn &= ~(tsize_pages - 1);
                                break;
                        }
+               } else if (vma && hva >= vma->vm_start &&
+                          (vma->vm_flags & VM_HUGETLB)) {
+                       unsigned long psize = vma_kernel_pagesize(vma);
+
+                       tsize = (gtlbe->mas1 & MAS1_TSIZE_MASK) >>
+                               MAS1_TSIZE_SHIFT;
+
+                       /*
+                        * Take the largest page size that satisfies both host
+                        * and guest mapping
+                        */
+                       tsize = min(__ilog2(psize) - 10, tsize);
+
+                       /*
+                        * e500 doesn't implement the lowest tsize bit,
+                        * or 1K pages.
+                        */
+                       tsize = max(BOOK3E_PAGESZ_4K, tsize & ~1);
                }
 
                up_read(&current->mm->mmap_sem);
        }
 
        if (likely(!pfnmap)) {
+               unsigned long tsize_pages = 1 << (tsize + 10 - PAGE_SHIFT);
                pfn = gfn_to_pfn_memslot(vcpu_e500->vcpu.kvm, slot, gfn);
                if (is_error_pfn(pfn)) {
                        printk(KERN_ERR "Couldn't get real page for gfn %lx!\n",
@@ -634,45 +726,52 @@ static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
                        kvm_release_pfn_clean(pfn);
                        return;
                }
+
+               /* Align guest and physical address to page map boundaries */
+               pfn &= ~(tsize_pages - 1);
+               gvaddr &= ~((tsize_pages << PAGE_SHIFT) - 1);
        }
 
-       /* Drop old priv and setup new one. */
-       priv = &vcpu_e500->gtlb_priv[tlbsel][esel];
-       kvmppc_e500_priv_release(priv);
-       kvmppc_e500_priv_setup(priv, gtlbe, pfn);
+       /* Drop old ref and setup new one. */
+       kvmppc_e500_ref_release(ref);
+       kvmppc_e500_ref_setup(ref, gtlbe, pfn);
 
-       kvmppc_e500_setup_stlbe(vcpu_e500, gtlbe, tsize, priv, gvaddr, stlbe);
+       kvmppc_e500_setup_stlbe(vcpu_e500, gtlbe, tsize, ref, gvaddr, stlbe);
 }
 
 /* XXX only map the one-one case, for now use TLB0 */
-static int kvmppc_e500_tlb0_map(struct kvmppc_vcpu_e500 *vcpu_e500,
-                               int esel, struct tlbe *stlbe)
+static void kvmppc_e500_tlb0_map(struct kvmppc_vcpu_e500 *vcpu_e500,
+                                int esel,
+                                struct kvm_book3e_206_tlb_entry *stlbe)
 {
-       struct tlbe *gtlbe;
+       struct kvm_book3e_206_tlb_entry *gtlbe;
+       struct tlbe_ref *ref;
 
-       gtlbe = &vcpu_e500->gtlb_arch[0][esel];
+       gtlbe = get_entry(vcpu_e500, 0, esel);
+       ref = &vcpu_e500->gtlb_priv[0][esel].ref;
 
        kvmppc_e500_shadow_map(vcpu_e500, get_tlb_eaddr(gtlbe),
                        get_tlb_raddr(gtlbe) >> PAGE_SHIFT,
-                       gtlbe, 0, esel, stlbe);
-
-       return esel;
+                       gtlbe, 0, stlbe, ref);
 }
 
 /* Caller must ensure that the specified guest TLB entry is safe to insert into
  * the shadow TLB. */
 /* XXX for both one-one and one-to-many , for now use TLB1 */
 static int kvmppc_e500_tlb1_map(struct kvmppc_vcpu_e500 *vcpu_e500,
-               u64 gvaddr, gfn_t gfn, struct tlbe *gtlbe, struct tlbe *stlbe)
+               u64 gvaddr, gfn_t gfn, struct kvm_book3e_206_tlb_entry *gtlbe,
+               struct kvm_book3e_206_tlb_entry *stlbe)
 {
+       struct tlbe_ref *ref;
        unsigned int victim;
 
-       victim = vcpu_e500->gtlb_nv[1]++;
+       victim = vcpu_e500->host_tlb1_nv++;
 
-       if (unlikely(vcpu_e500->gtlb_nv[1] >= tlb1_max_shadow_size()))
-               vcpu_e500->gtlb_nv[1] = 0;
+       if (unlikely(vcpu_e500->host_tlb1_nv >= tlb1_max_shadow_size()))
+               vcpu_e500->host_tlb1_nv = 0;
 
-       kvmppc_e500_shadow_map(vcpu_e500, gvaddr, gfn, gtlbe, 1, victim, stlbe);
+       ref = &vcpu_e500->tlb_refs[1][victim];
+       kvmppc_e500_shadow_map(vcpu_e500, gvaddr, gfn, gtlbe, 1, stlbe, ref);
 
        return victim;
 }
@@ -689,7 +788,8 @@ static inline int kvmppc_e500_gtlbe_invalidate(
                                struct kvmppc_vcpu_e500 *vcpu_e500,
                                int tlbsel, int esel)
 {
-       struct tlbe *gtlbe = &vcpu_e500->gtlb_arch[tlbsel][esel];
+       struct kvm_book3e_206_tlb_entry *gtlbe =
+               get_entry(vcpu_e500, tlbsel, esel);
 
        if (unlikely(get_tlb_iprot(gtlbe)))
                return -1;
@@ -704,10 +804,10 @@ int kvmppc_e500_emul_mt_mmucsr0(struct kvmppc_vcpu_e500 *vcpu_e500, ulong value)
        int esel;
 
        if (value & MMUCSR0_TLB0FI)
-               for (esel = 0; esel < vcpu_e500->gtlb_size[0]; esel++)
+               for (esel = 0; esel < vcpu_e500->gtlb_params[0].entries; esel++)
                        kvmppc_e500_gtlbe_invalidate(vcpu_e500, 0, esel);
        if (value & MMUCSR0_TLB1FI)
-               for (esel = 0; esel < vcpu_e500->gtlb_size[1]; esel++)
+               for (esel = 0; esel < vcpu_e500->gtlb_params[1].entries; esel++)
                        kvmppc_e500_gtlbe_invalidate(vcpu_e500, 1, esel);
 
        /* Invalidate all vcpu id mappings */
@@ -732,7 +832,8 @@ int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, int ra, int rb)
 
        if (ia) {
                /* invalidate all entries */
-               for (esel = 0; esel < vcpu_e500->gtlb_size[tlbsel]; esel++)
+               for (esel = 0; esel < vcpu_e500->gtlb_params[tlbsel].entries;
+                    esel++)
                        kvmppc_e500_gtlbe_invalidate(vcpu_e500, tlbsel, esel);
        } else {
                ea &= 0xfffff000;
@@ -752,18 +853,17 @@ int kvmppc_e500_emul_tlbre(struct kvm_vcpu *vcpu)
 {
        struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
        int tlbsel, esel;
-       struct tlbe *gtlbe;
+       struct kvm_book3e_206_tlb_entry *gtlbe;
 
-       tlbsel = get_tlb_tlbsel(vcpu_e500);
-       esel = get_tlb_esel(vcpu_e500, tlbsel);
+       tlbsel = get_tlb_tlbsel(vcpu);
+       esel = get_tlb_esel(vcpu, tlbsel);
 
-       gtlbe = &vcpu_e500->gtlb_arch[tlbsel][esel];
-       vcpu_e500->mas0 &= ~MAS0_NV(~0);
-       vcpu_e500->mas0 |= MAS0_NV(vcpu_e500->gtlb_nv[tlbsel]);
-       vcpu_e500->mas1 = gtlbe->mas1;
-       vcpu_e500->mas2 = gtlbe->mas2;
-       vcpu_e500->mas3 = gtlbe->mas3;
-       vcpu_e500->mas7 = gtlbe->mas7;
+       gtlbe = get_entry(vcpu_e500, tlbsel, esel);
+       vcpu->arch.shared->mas0 &= ~MAS0_NV(~0);
+       vcpu->arch.shared->mas0 |= MAS0_NV(vcpu_e500->gtlb_nv[tlbsel]);
+       vcpu->arch.shared->mas1 = gtlbe->mas1;
+       vcpu->arch.shared->mas2 = gtlbe->mas2;
+       vcpu->arch.shared->mas7_3 = gtlbe->mas7_3;
 
        return EMULATE_DONE;
 }
@@ -771,10 +871,10 @@ int kvmppc_e500_emul_tlbre(struct kvm_vcpu *vcpu)
 int kvmppc_e500_emul_tlbsx(struct kvm_vcpu *vcpu, int rb)
 {
        struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
-       int as = !!get_cur_sas(vcpu_e500);
-       unsigned int pid = get_cur_spid(vcpu_e500);
+       int as = !!get_cur_sas(vcpu);
+       unsigned int pid = get_cur_spid(vcpu);
        int esel, tlbsel;
-       struct tlbe *gtlbe = NULL;
+       struct kvm_book3e_206_tlb_entry *gtlbe = NULL;
        gva_t ea;
 
        ea = kvmppc_get_gpr(vcpu, rb);
@@ -782,70 +882,90 @@ int kvmppc_e500_emul_tlbsx(struct kvm_vcpu *vcpu, int rb)
        for (tlbsel = 0; tlbsel < 2; tlbsel++) {
                esel = kvmppc_e500_tlb_index(vcpu_e500, ea, tlbsel, pid, as);
                if (esel >= 0) {
-                       gtlbe = &vcpu_e500->gtlb_arch[tlbsel][esel];
+                       gtlbe = get_entry(vcpu_e500, tlbsel, esel);
                        break;
                }
        }
 
        if (gtlbe) {
-               vcpu_e500->mas0 = MAS0_TLBSEL(tlbsel) | MAS0_ESEL(esel)
+               esel &= vcpu_e500->gtlb_params[tlbsel].ways - 1;
+
+               vcpu->arch.shared->mas0 = MAS0_TLBSEL(tlbsel) | MAS0_ESEL(esel)
                        | MAS0_NV(vcpu_e500->gtlb_nv[tlbsel]);
-               vcpu_e500->mas1 = gtlbe->mas1;
-               vcpu_e500->mas2 = gtlbe->mas2;
-               vcpu_e500->mas3 = gtlbe->mas3;
-               vcpu_e500->mas7 = gtlbe->mas7;
+               vcpu->arch.shared->mas1 = gtlbe->mas1;
+               vcpu->arch.shared->mas2 = gtlbe->mas2;
+               vcpu->arch.shared->mas7_3 = gtlbe->mas7_3;
        } else {
                int victim;
 
                /* since we only have two TLBs, only lower bit is used. */
-               tlbsel = vcpu_e500->mas4 >> 28 & 0x1;
-               victim = (tlbsel == 0) ? tlb0_get_next_victim(vcpu_e500) : 0;
+               tlbsel = vcpu->arch.shared->mas4 >> 28 & 0x1;
+               victim = (tlbsel == 0) ? gtlb0_get_next_victim(vcpu_e500) : 0;
 
-               vcpu_e500->mas0 = MAS0_TLBSEL(tlbsel) | MAS0_ESEL(victim)
+               vcpu->arch.shared->mas0 = MAS0_TLBSEL(tlbsel)
+                       | MAS0_ESEL(victim)
                        | MAS0_NV(vcpu_e500->gtlb_nv[tlbsel]);
-               vcpu_e500->mas1 = (vcpu_e500->mas6 & MAS6_SPID0)
-                       | (vcpu_e500->mas6 & (MAS6_SAS ? MAS1_TS : 0))
-                       | (vcpu_e500->mas4 & MAS4_TSIZED(~0));
-               vcpu_e500->mas2 &= MAS2_EPN;
-               vcpu_e500->mas2 |= vcpu_e500->mas4 & MAS2_ATTRIB_MASK;
-               vcpu_e500->mas3 &= MAS3_U0 | MAS3_U1 | MAS3_U2 | MAS3_U3;
-               vcpu_e500->mas7 = 0;
+               vcpu->arch.shared->mas1 =
+                         (vcpu->arch.shared->mas6 & MAS6_SPID0)
+                       | (vcpu->arch.shared->mas6 & (MAS6_SAS ? MAS1_TS : 0))
+                       | (vcpu->arch.shared->mas4 & MAS4_TSIZED(~0));
+               vcpu->arch.shared->mas2 &= MAS2_EPN;
+               vcpu->arch.shared->mas2 |= vcpu->arch.shared->mas4 &
+                                          MAS2_ATTRIB_MASK;
+               vcpu->arch.shared->mas7_3 &= MAS3_U0 | MAS3_U1 |
+                                            MAS3_U2 | MAS3_U3;
        }
 
        kvmppc_set_exit_type(vcpu, EMULATED_TLBSX_EXITS);
        return EMULATE_DONE;
 }
 
+/* sesel is for tlb1 only */
+static void write_stlbe(struct kvmppc_vcpu_e500 *vcpu_e500,
+                       struct kvm_book3e_206_tlb_entry *gtlbe,
+                       struct kvm_book3e_206_tlb_entry *stlbe,
+                       int stlbsel, int sesel)
+{
+       int stid;
+
+       preempt_disable();
+       stid = kvmppc_e500_get_sid(vcpu_e500, get_tlb_ts(gtlbe),
+                                  get_tlb_tid(gtlbe),
+                                  get_cur_pr(&vcpu_e500->vcpu), 0);
+
+       stlbe->mas1 |= MAS1_TID(stid);
+       write_host_tlbe(vcpu_e500, stlbsel, sesel, stlbe);
+       preempt_enable();
+}
+
 int kvmppc_e500_emul_tlbwe(struct kvm_vcpu *vcpu)
 {
        struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
-       struct tlbe *gtlbe;
+       struct kvm_book3e_206_tlb_entry *gtlbe;
        int tlbsel, esel;
 
-       tlbsel = get_tlb_tlbsel(vcpu_e500);
-       esel = get_tlb_esel(vcpu_e500, tlbsel);
+       tlbsel = get_tlb_tlbsel(vcpu);
+       esel = get_tlb_esel(vcpu, tlbsel);
 
-       gtlbe = &vcpu_e500->gtlb_arch[tlbsel][esel];
+       gtlbe = get_entry(vcpu_e500, tlbsel, esel);
 
        if (get_tlb_v(gtlbe))
-               kvmppc_e500_stlbe_invalidate(vcpu_e500, tlbsel, esel);
+               inval_gtlbe_on_host(vcpu_e500, tlbsel, esel);
 
-       gtlbe->mas1 = vcpu_e500->mas1;
-       gtlbe->mas2 = vcpu_e500->mas2;
-       gtlbe->mas3 = vcpu_e500->mas3;
-       gtlbe->mas7 = vcpu_e500->mas7;
+       gtlbe->mas1 = vcpu->arch.shared->mas1;
+       gtlbe->mas2 = vcpu->arch.shared->mas2;
+       gtlbe->mas7_3 = vcpu->arch.shared->mas7_3;
 
-       trace_kvm_gtlb_write(vcpu_e500->mas0, gtlbe->mas1, gtlbe->mas2,
-                            gtlbe->mas3, gtlbe->mas7);
+       trace_kvm_booke206_gtlb_write(vcpu->arch.shared->mas0, gtlbe->mas1,
+                                     gtlbe->mas2, gtlbe->mas7_3);
 
        /* Invalidate shadow mappings for the about-to-be-clobbered TLBE. */
        if (tlbe_is_host_safe(vcpu, gtlbe)) {
-               struct tlbe stlbe;
+               struct kvm_book3e_206_tlb_entry stlbe;
                int stlbsel, sesel;
                u64 eaddr;
                u64 raddr;
 
-               preempt_disable();
                switch (tlbsel) {
                case 0:
                        /* TLB0 */
@@ -853,7 +973,8 @@ int kvmppc_e500_emul_tlbwe(struct kvm_vcpu *vcpu)
                        gtlbe->mas1 |= MAS1_TSIZE(BOOK3E_PAGESZ_4K);
 
                        stlbsel = 0;
-                       sesel = kvmppc_e500_tlb0_map(vcpu_e500, esel, &stlbe);
+                       kvmppc_e500_tlb0_map(vcpu_e500, esel, &stlbe);
+                       sesel = 0; /* unused */
 
                        break;
 
@@ -874,8 +995,8 @@ int kvmppc_e500_emul_tlbwe(struct kvm_vcpu *vcpu)
                default:
                        BUG();
                }
-               write_host_tlbe(vcpu_e500, stlbsel, sesel, &stlbe);
-               preempt_enable();
+
+               write_stlbe(vcpu_e500, gtlbe, &stlbe, stlbsel, sesel);
        }
 
        kvmppc_set_exit_type(vcpu, EMULATED_TLBWE_EXITS);
@@ -914,9 +1035,11 @@ gpa_t kvmppc_mmu_xlate(struct kvm_vcpu *vcpu, unsigned int index,
                        gva_t eaddr)
 {
        struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
-       struct tlbe *gtlbe =
-               &vcpu_e500->gtlb_arch[tlbsel_of(index)][esel_of(index)];
-       u64 pgmask = get_tlb_bytes(gtlbe) - 1;
+       struct kvm_book3e_206_tlb_entry *gtlbe;
+       u64 pgmask;
+
+       gtlbe = get_entry(vcpu_e500, tlbsel_of(index), esel_of(index));
+       pgmask = get_tlb_bytes(gtlbe) - 1;
 
        return get_tlb_raddr(gtlbe) | (eaddr & pgmask);
 }
@@ -930,22 +1053,21 @@ void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 eaddr, gpa_t gpaddr,
 {
        struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
        struct tlbe_priv *priv;
-       struct tlbe *gtlbe, stlbe;
+       struct kvm_book3e_206_tlb_entry *gtlbe, stlbe;
        int tlbsel = tlbsel_of(index);
        int esel = esel_of(index);
        int stlbsel, sesel;
 
-       gtlbe = &vcpu_e500->gtlb_arch[tlbsel][esel];
+       gtlbe = get_entry(vcpu_e500, tlbsel, esel);
 
-       preempt_disable();
        switch (tlbsel) {
        case 0:
                stlbsel = 0;
-               sesel = esel;
-               priv = &vcpu_e500->gtlb_priv[stlbsel][sesel];
+               sesel = 0; /* unused */
+               priv = &vcpu_e500->gtlb_priv[tlbsel][esel];
 
                kvmppc_e500_setup_stlbe(vcpu_e500, gtlbe, BOOK3E_PAGESZ_4K,
-                                       priv, eaddr, &stlbe);
+                                       &priv->ref, eaddr, &stlbe);
                break;
 
        case 1: {
@@ -962,8 +1084,7 @@ void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 eaddr, gpa_t gpaddr,
                break;
        }
 
-       write_host_tlbe(vcpu_e500, stlbsel, sesel, &stlbe);
-       preempt_enable();
+       write_stlbe(vcpu_e500, gtlbe, &stlbe, stlbsel, sesel);
 }
 
 int kvmppc_e500_tlb_search(struct kvm_vcpu *vcpu,
@@ -993,85 +1114,279 @@ void kvmppc_set_pid(struct kvm_vcpu *vcpu, u32 pid)
 
 void kvmppc_e500_tlb_setup(struct kvmppc_vcpu_e500 *vcpu_e500)
 {
-       struct tlbe *tlbe;
+       struct kvm_book3e_206_tlb_entry *tlbe;
 
        /* Insert large initial mapping for guest. */
-       tlbe = &vcpu_e500->gtlb_arch[1][0];
+       tlbe = get_entry(vcpu_e500, 1, 0);
        tlbe->mas1 = MAS1_VALID | MAS1_TSIZE(BOOK3E_PAGESZ_256M);
        tlbe->mas2 = 0;
-       tlbe->mas3 = E500_TLB_SUPER_PERM_MASK;
-       tlbe->mas7 = 0;
+       tlbe->mas7_3 = E500_TLB_SUPER_PERM_MASK;
 
        /* 4K map for serial output. Used by kernel wrapper. */
-       tlbe = &vcpu_e500->gtlb_arch[1][1];
+       tlbe = get_entry(vcpu_e500, 1, 1);
        tlbe->mas1 = MAS1_VALID | MAS1_TSIZE(BOOK3E_PAGESZ_4K);
        tlbe->mas2 = (0xe0004500 & 0xFFFFF000) | MAS2_I | MAS2_G;
-       tlbe->mas3 = (0xe0004500 & 0xFFFFF000) | E500_TLB_SUPER_PERM_MASK;
-       tlbe->mas7 = 0;
+       tlbe->mas7_3 = (0xe0004500 & 0xFFFFF000) | E500_TLB_SUPER_PERM_MASK;
+}
+
+static void free_gtlb(struct kvmppc_vcpu_e500 *vcpu_e500)
+{
+       int i;
+
+       clear_tlb_refs(vcpu_e500);
+       kfree(vcpu_e500->gtlb_priv[0]);
+       kfree(vcpu_e500->gtlb_priv[1]);
+
+       if (vcpu_e500->shared_tlb_pages) {
+               vfree((void *)(round_down((uintptr_t)vcpu_e500->gtlb_arch,
+                                         PAGE_SIZE)));
+
+               for (i = 0; i < vcpu_e500->num_shared_tlb_pages; i++) {
+                       set_page_dirty_lock(vcpu_e500->shared_tlb_pages[i]);
+                       put_page(vcpu_e500->shared_tlb_pages[i]);
+               }
+
+               vcpu_e500->num_shared_tlb_pages = 0;
+               vcpu_e500->shared_tlb_pages = NULL;
+       } else {
+               kfree(vcpu_e500->gtlb_arch);
+       }
+
+       vcpu_e500->gtlb_arch = NULL;
+}
+
+int kvm_vcpu_ioctl_config_tlb(struct kvm_vcpu *vcpu,
+                             struct kvm_config_tlb *cfg)
+{
+       struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
+       struct kvm_book3e_206_tlb_params params;
+       char *virt;
+       struct page **pages;
+       struct tlbe_priv *privs[2] = {};
+       size_t array_len;
+       u32 sets;
+       int num_pages, ret, i;
+
+       if (cfg->mmu_type != KVM_MMU_FSL_BOOKE_NOHV)
+               return -EINVAL;
+
+       if (copy_from_user(&params, (void __user *)(uintptr_t)cfg->params,
+                          sizeof(params)))
+               return -EFAULT;
+
+       if (params.tlb_sizes[1] > 64)
+               return -EINVAL;
+       if (params.tlb_ways[1] != params.tlb_sizes[1])
+               return -EINVAL;
+       if (params.tlb_sizes[2] != 0 || params.tlb_sizes[3] != 0)
+               return -EINVAL;
+       if (params.tlb_ways[2] != 0 || params.tlb_ways[3] != 0)
+               return -EINVAL;
+
+       if (!is_power_of_2(params.tlb_ways[0]))
+               return -EINVAL;
+
+       sets = params.tlb_sizes[0] >> ilog2(params.tlb_ways[0]);
+       if (!is_power_of_2(sets))
+               return -EINVAL;
+
+       array_len = params.tlb_sizes[0] + params.tlb_sizes[1];
+       array_len *= sizeof(struct kvm_book3e_206_tlb_entry);
+
+       if (cfg->array_len < array_len)
+               return -EINVAL;
+
+       num_pages = DIV_ROUND_UP(cfg->array + array_len - 1, PAGE_SIZE) -
+                   cfg->array / PAGE_SIZE;
+       pages = kmalloc(sizeof(struct page *) * num_pages, GFP_KERNEL);
+       if (!pages)
+               return -ENOMEM;
+
+       ret = get_user_pages_fast(cfg->array, num_pages, 1, pages);
+       if (ret < 0)
+               goto err_pages;
+
+       if (ret != num_pages) {
+               num_pages = ret;
+               ret = -EFAULT;
+               goto err_put_page;
+       }
+
+       virt = vmap(pages, num_pages, VM_MAP, PAGE_KERNEL);
+       if (!virt)
+               goto err_put_page;
+
+       privs[0] = kzalloc(sizeof(struct tlbe_priv) * params.tlb_sizes[0],
+                          GFP_KERNEL);
+       privs[1] = kzalloc(sizeof(struct tlbe_priv) * params.tlb_sizes[1],
+                          GFP_KERNEL);
+
+       if (!privs[0] || !privs[1])
+               goto err_put_page;
+
+       free_gtlb(vcpu_e500);
+
+       vcpu_e500->gtlb_priv[0] = privs[0];
+       vcpu_e500->gtlb_priv[1] = privs[1];
+
+       vcpu_e500->gtlb_arch = (struct kvm_book3e_206_tlb_entry *)
+               (virt + (cfg->array & (PAGE_SIZE - 1)));
+
+       vcpu_e500->gtlb_params[0].entries = params.tlb_sizes[0];
+       vcpu_e500->gtlb_params[1].entries = params.tlb_sizes[1];
+
+       vcpu_e500->gtlb_offset[0] = 0;
+       vcpu_e500->gtlb_offset[1] = params.tlb_sizes[0];
+
+       vcpu_e500->tlb0cfg &= ~(TLBnCFG_N_ENTRY | TLBnCFG_ASSOC);
+       if (params.tlb_sizes[0] <= 2048)
+               vcpu_e500->tlb0cfg |= params.tlb_sizes[0];
+       vcpu_e500->tlb0cfg |= params.tlb_ways[0] << TLBnCFG_ASSOC_SHIFT;
+
+       vcpu_e500->tlb1cfg &= ~(TLBnCFG_N_ENTRY | TLBnCFG_ASSOC);
+       vcpu_e500->tlb1cfg |= params.tlb_sizes[1];
+       vcpu_e500->tlb1cfg |= params.tlb_ways[1] << TLBnCFG_ASSOC_SHIFT;
+
+       vcpu_e500->shared_tlb_pages = pages;
+       vcpu_e500->num_shared_tlb_pages = num_pages;
+
+       vcpu_e500->gtlb_params[0].ways = params.tlb_ways[0];
+       vcpu_e500->gtlb_params[0].sets = sets;
+
+       vcpu_e500->gtlb_params[1].ways = params.tlb_sizes[1];
+       vcpu_e500->gtlb_params[1].sets = 1;
+
+       return 0;
+
+err_put_page:
+       kfree(privs[0]);
+       kfree(privs[1]);
+
+       for (i = 0; i < num_pages; i++)
+               put_page(pages[i]);
+
+err_pages:
+       kfree(pages);
+       return ret;
+}
+
+int kvm_vcpu_ioctl_dirty_tlb(struct kvm_vcpu *vcpu,
+                            struct kvm_dirty_tlb *dirty)
+{
+       struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
+
+       clear_tlb_refs(vcpu_e500);
+       return 0;
 }
 
 int kvmppc_e500_tlb_init(struct kvmppc_vcpu_e500 *vcpu_e500)
 {
-       tlb1_entry_num = mfspr(SPRN_TLB1CFG) & 0xFFF;
-
-       vcpu_e500->gtlb_size[0] = KVM_E500_TLB0_SIZE;
-       vcpu_e500->gtlb_arch[0] =
-               kzalloc(sizeof(struct tlbe) * KVM_E500_TLB0_SIZE, GFP_KERNEL);
-       if (vcpu_e500->gtlb_arch[0] == NULL)
-               goto err_out;
-
-       vcpu_e500->gtlb_size[1] = KVM_E500_TLB1_SIZE;
-       vcpu_e500->gtlb_arch[1] =
-               kzalloc(sizeof(struct tlbe) * KVM_E500_TLB1_SIZE, GFP_KERNEL);
-       if (vcpu_e500->gtlb_arch[1] == NULL)
-               goto err_out_guest0;
-
-       vcpu_e500->gtlb_priv[0] = (struct tlbe_priv *)
-               kzalloc(sizeof(struct tlbe_priv) * KVM_E500_TLB0_SIZE, GFP_KERNEL);
-       if (vcpu_e500->gtlb_priv[0] == NULL)
-               goto err_out_guest1;
-       vcpu_e500->gtlb_priv[1] = (struct tlbe_priv *)
-               kzalloc(sizeof(struct tlbe_priv) * KVM_E500_TLB1_SIZE, GFP_KERNEL);
-
-       if (vcpu_e500->gtlb_priv[1] == NULL)
-               goto err_out_priv0;
+       int entry_size = sizeof(struct kvm_book3e_206_tlb_entry);
+       int entries = KVM_E500_TLB0_SIZE + KVM_E500_TLB1_SIZE;
+
+       host_tlb_params[0].entries = mfspr(SPRN_TLB0CFG) & TLBnCFG_N_ENTRY;
+       host_tlb_params[1].entries = mfspr(SPRN_TLB1CFG) & TLBnCFG_N_ENTRY;
+
+       /*
+        * This should never happen on real e500 hardware, but is
+        * architecturally possible -- e.g. in some weird nested
+        * virtualization case.
+        */
+       if (host_tlb_params[0].entries == 0 ||
+           host_tlb_params[1].entries == 0) {
+               pr_err("%s: need to know host tlb size\n", __func__);
+               return -ENODEV;
+       }
+
+       host_tlb_params[0].ways = (mfspr(SPRN_TLB0CFG) & TLBnCFG_ASSOC) >>
+                                 TLBnCFG_ASSOC_SHIFT;
+       host_tlb_params[1].ways = host_tlb_params[1].entries;
+
+       if (!is_power_of_2(host_tlb_params[0].entries) ||
+           !is_power_of_2(host_tlb_params[0].ways) ||
+           host_tlb_params[0].entries < host_tlb_params[0].ways ||
+           host_tlb_params[0].ways == 0) {
+               pr_err("%s: bad tlb0 host config: %u entries %u ways\n",
+                      __func__, host_tlb_params[0].entries,
+                      host_tlb_params[0].ways);
+               return -ENODEV;
+       }
+
+       host_tlb_params[0].sets =
+               host_tlb_params[0].entries / host_tlb_params[0].ways;
+       host_tlb_params[1].sets = 1;
+
+       vcpu_e500->gtlb_params[0].entries = KVM_E500_TLB0_SIZE;
+       vcpu_e500->gtlb_params[1].entries = KVM_E500_TLB1_SIZE;
+
+       vcpu_e500->gtlb_params[0].ways = KVM_E500_TLB0_WAY_NUM;
+       vcpu_e500->gtlb_params[0].sets =
+               KVM_E500_TLB0_SIZE / KVM_E500_TLB0_WAY_NUM;
+
+       vcpu_e500->gtlb_params[1].ways = KVM_E500_TLB1_SIZE;
+       vcpu_e500->gtlb_params[1].sets = 1;
+
+       vcpu_e500->gtlb_arch = kmalloc(entries * entry_size, GFP_KERNEL);
+       if (!vcpu_e500->gtlb_arch)
+               return -ENOMEM;
+
+       vcpu_e500->gtlb_offset[0] = 0;
+       vcpu_e500->gtlb_offset[1] = KVM_E500_TLB0_SIZE;
+
+       vcpu_e500->tlb_refs[0] =
+               kzalloc(sizeof(struct tlbe_ref) * host_tlb_params[0].entries,
+                       GFP_KERNEL);
+       if (!vcpu_e500->tlb_refs[0])
+               goto err;
+
+       vcpu_e500->tlb_refs[1] =
+               kzalloc(sizeof(struct tlbe_ref) * host_tlb_params[1].entries,
+                       GFP_KERNEL);
+       if (!vcpu_e500->tlb_refs[1])
+               goto err;
+
+       vcpu_e500->gtlb_priv[0] = kzalloc(sizeof(struct tlbe_ref) *
+                                         vcpu_e500->gtlb_params[0].entries,
+                                         GFP_KERNEL);
+       if (!vcpu_e500->gtlb_priv[0])
+               goto err;
+
+       vcpu_e500->gtlb_priv[1] = kzalloc(sizeof(struct tlbe_ref) *
+                                         vcpu_e500->gtlb_params[1].entries,
+                                         GFP_KERNEL);
+       if (!vcpu_e500->gtlb_priv[1])
+               goto err;
 
        if (kvmppc_e500_id_table_alloc(vcpu_e500) == NULL)
-               goto err_out_priv1;
+               goto err;
 
        /* Init TLB configuration register */
-       vcpu_e500->tlb0cfg = mfspr(SPRN_TLB0CFG) & ~0xfffUL;
-       vcpu_e500->tlb0cfg |= vcpu_e500->gtlb_size[0];
-       vcpu_e500->tlb1cfg = mfspr(SPRN_TLB1CFG) & ~0xfffUL;
-       vcpu_e500->tlb1cfg |= vcpu_e500->gtlb_size[1];
+       vcpu_e500->tlb0cfg = mfspr(SPRN_TLB0CFG) &
+                            ~(TLBnCFG_N_ENTRY | TLBnCFG_ASSOC);
+       vcpu_e500->tlb0cfg |= vcpu_e500->gtlb_params[0].entries;
+       vcpu_e500->tlb0cfg |=
+               vcpu_e500->gtlb_params[0].ways << TLBnCFG_ASSOC_SHIFT;
+
+       vcpu_e500->tlb1cfg = mfspr(SPRN_TLB1CFG) &
+                            ~(TLBnCFG_N_ENTRY | TLBnCFG_ASSOC);
+       vcpu_e500->tlb0cfg |= vcpu_e500->gtlb_params[1].entries;
+       vcpu_e500->tlb0cfg |=
+               vcpu_e500->gtlb_params[1].ways << TLBnCFG_ASSOC_SHIFT;
 
        return 0;
 
-err_out_priv1:
-       kfree(vcpu_e500->gtlb_priv[1]);
-err_out_priv0:
-       kfree(vcpu_e500->gtlb_priv[0]);
-err_out_guest1:
-       kfree(vcpu_e500->gtlb_arch[1]);
-err_out_guest0:
-       kfree(vcpu_e500->gtlb_arch[0]);
-err_out:
+err:
+       free_gtlb(vcpu_e500);
+       kfree(vcpu_e500->tlb_refs[0]);
+       kfree(vcpu_e500->tlb_refs[1]);
        return -1;
 }
 
 void kvmppc_e500_tlb_uninit(struct kvmppc_vcpu_e500 *vcpu_e500)
 {
-       int stlbsel, i;
-
-       /* release all privs */
-       for (stlbsel = 0; stlbsel < 2; stlbsel++)
-               for (i = 0; i < vcpu_e500->gtlb_size[stlbsel]; i++) {
-                       struct tlbe_priv *priv =
-                               &vcpu_e500->gtlb_priv[stlbsel][i];
-                       kvmppc_e500_priv_release(priv);
-               }
-
+       free_gtlb(vcpu_e500);
        kvmppc_e500_id_table_free(vcpu_e500);
-       kfree(vcpu_e500->gtlb_arch[1]);
-       kfree(vcpu_e500->gtlb_arch[0]);
+
+       kfree(vcpu_e500->tlb_refs[0]);
+       kfree(vcpu_e500->tlb_refs[1]);
 }
index 59b88e9..5c6d2d7 100644 (file)
 #include <asm/tlb.h>
 #include <asm/kvm_e500.h>
 
-#define KVM_E500_TLB0_WAY_SIZE_BIT     7       /* Fixed */
-#define KVM_E500_TLB0_WAY_SIZE         (1UL << KVM_E500_TLB0_WAY_SIZE_BIT)
-#define KVM_E500_TLB0_WAY_SIZE_MASK    (KVM_E500_TLB0_WAY_SIZE - 1)
-
-#define KVM_E500_TLB0_WAY_NUM_BIT      1       /* No greater than 7 */
-#define KVM_E500_TLB0_WAY_NUM          (1UL << KVM_E500_TLB0_WAY_NUM_BIT)
-#define KVM_E500_TLB0_WAY_NUM_MASK     (KVM_E500_TLB0_WAY_NUM - 1)
+/* This geometry is the legacy default -- can be overridden by userspace */
+#define KVM_E500_TLB0_WAY_SIZE         128
+#define KVM_E500_TLB0_WAY_NUM          2
 
 #define KVM_E500_TLB0_SIZE  (KVM_E500_TLB0_WAY_SIZE * KVM_E500_TLB0_WAY_NUM)
 #define KVM_E500_TLB1_SIZE  16
@@ -58,50 +54,54 @@ extern void kvmppc_e500_tlb_setup(struct kvmppc_vcpu_e500 *);
 extern void kvmppc_e500_recalc_shadow_pid(struct kvmppc_vcpu_e500 *);
 
 /* TLB helper functions */
-static inline unsigned int get_tlb_size(const struct tlbe *tlbe)
+static inline unsigned int
+get_tlb_size(const struct kvm_book3e_206_tlb_entry *tlbe)
 {
        return (tlbe->mas1 >> 7) & 0x1f;
 }
 
-static inline gva_t get_tlb_eaddr(const struct tlbe *tlbe)
+static inline gva_t get_tlb_eaddr(const struct kvm_book3e_206_tlb_entry *tlbe)
 {
        return tlbe->mas2 & 0xfffff000;
 }
 
-static inline u64 get_tlb_bytes(const struct tlbe *tlbe)
+static inline u64 get_tlb_bytes(const struct kvm_book3e_206_tlb_entry *tlbe)
 {
        unsigned int pgsize = get_tlb_size(tlbe);
        return 1ULL << 10 << pgsize;
 }
 
-static inline gva_t get_tlb_end(const struct tlbe *tlbe)
+static inline gva_t get_tlb_end(const struct kvm_book3e_206_tlb_entry *tlbe)
 {
        u64 bytes = get_tlb_bytes(tlbe);
        return get_tlb_eaddr(tlbe) + bytes - 1;
 }
 
-static inline u64 get_tlb_raddr(const struct tlbe *tlbe)
+static inline u64 get_tlb_raddr(const struct kvm_book3e_206_tlb_entry *tlbe)
 {
-       u64 rpn = tlbe->mas7;
-       return (rpn << 32) | (tlbe->mas3 & 0xfffff000);
+       return tlbe->mas7_3 & ~0xfffULL;
 }
 
-static inline unsigned int get_tlb_tid(const struct tlbe *tlbe)
+static inline unsigned int
+get_tlb_tid(const struct kvm_book3e_206_tlb_entry *tlbe)
 {
        return (tlbe->mas1 >> 16) & 0xff;
 }
 
-static inline unsigned int get_tlb_ts(const struct tlbe *tlbe)
+static inline unsigned int
+get_tlb_ts(const struct kvm_book3e_206_tlb_entry *tlbe)
 {
        return (tlbe->mas1 >> 12) & 0x1;
 }
 
-static inline unsigned int get_tlb_v(const struct tlbe *tlbe)
+static inline unsigned int
+get_tlb_v(const struct kvm_book3e_206_tlb_entry *tlbe)
 {
        return (tlbe->mas1 >> 31) & 0x1;
 }
 
-static inline unsigned int get_tlb_iprot(const struct tlbe *tlbe)
+static inline unsigned int
+get_tlb_iprot(const struct kvm_book3e_206_tlb_entry *tlbe)
 {
        return (tlbe->mas1 >> 30) & 0x1;
 }
@@ -121,59 +121,37 @@ static inline unsigned int get_cur_pr(struct kvm_vcpu *vcpu)
        return !!(vcpu->arch.shared->msr & MSR_PR);
 }
 
-static inline unsigned int get_cur_spid(
-               const struct kvmppc_vcpu_e500 *vcpu_e500)
+static inline unsigned int get_cur_spid(const struct kvm_vcpu *vcpu)
 {
-       return (vcpu_e500->mas6 >> 16) & 0xff;
+       return (vcpu->arch.shared->mas6 >> 16) & 0xff;
 }
 
-static inline unsigned int get_cur_sas(
-               const struct kvmppc_vcpu_e500 *vcpu_e500)
+static inline unsigned int get_cur_sas(const struct kvm_vcpu *vcpu)
 {
-       return vcpu_e500->mas6 & 0x1;
+       return vcpu->arch.shared->mas6 & 0x1;
 }
 
-static inline unsigned int get_tlb_tlbsel(
-               const struct kvmppc_vcpu_e500 *vcpu_e500)
+static inline unsigned int get_tlb_tlbsel(const struct kvm_vcpu *vcpu)
 {
        /*
         * Manual says that tlbsel has 2 bits wide.
         * Since we only have two TLBs, only lower bit is used.
         */
-       return (vcpu_e500->mas0 >> 28) & 0x1;
-}
-
-static inline unsigned int get_tlb_nv_bit(
-               const struct kvmppc_vcpu_e500 *vcpu_e500)
-{
-       return vcpu_e500->mas0 & 0xfff;
+       return (vcpu->arch.shared->mas0 >> 28) & 0x1;
 }
 
-static inline unsigned int get_tlb_esel_bit(
-               const struct kvmppc_vcpu_e500 *vcpu_e500)
+static inline unsigned int get_tlb_nv_bit(const struct kvm_vcpu *vcpu)
 {
-       return (vcpu_e500->mas0 >> 16) & 0xfff;
+       return vcpu->arch.shared->mas0 & 0xfff;
 }
 
-static inline unsigned int get_tlb_esel(
-               const struct kvmppc_vcpu_e500 *vcpu_e500,
-               int tlbsel)
+static inline unsigned int get_tlb_esel_bit(const struct kvm_vcpu *vcpu)
 {
-       unsigned int esel = get_tlb_esel_bit(vcpu_e500);
-
-       if (tlbsel == 0) {
-               esel &= KVM_E500_TLB0_WAY_NUM_MASK;
-               esel |= ((vcpu_e500->mas2 >> 12) & KVM_E500_TLB0_WAY_SIZE_MASK)
-                               << KVM_E500_TLB0_WAY_NUM_BIT;
-       } else {
-               esel &= KVM_E500_TLB1_SIZE - 1;
-       }
-
-       return esel;
+       return (vcpu->arch.shared->mas0 >> 16) & 0xfff;
 }
 
 static inline int tlbe_is_host_safe(const struct kvm_vcpu *vcpu,
-                       const struct tlbe *tlbe)
+                       const struct kvm_book3e_206_tlb_entry *tlbe)
 {
        gpa_t gpa;
 
index 141dce3..968f401 100644 (file)
@@ -13,6 +13,7 @@
  * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *
  * Copyright IBM Corp. 2007
+ * Copyright 2011 Freescale Semiconductor, Inc.
  *
  * Authors: Hollis Blanchard <hollisb@us.ibm.com>
  */
 #define OP_STH  44
 #define OP_STHU 45
 
-#ifdef CONFIG_PPC_BOOK3S
-static int kvmppc_dec_enabled(struct kvm_vcpu *vcpu)
-{
-       return 1;
-}
-#else
-static int kvmppc_dec_enabled(struct kvm_vcpu *vcpu)
-{
-       return vcpu->arch.tcr & TCR_DIE;
-}
-#endif
-
 void kvmppc_emulate_dec(struct kvm_vcpu *vcpu)
 {
        unsigned long dec_nsec;
+       unsigned long long dec_time;
 
        pr_debug("mtDEC: %x\n", vcpu->arch.dec);
+       hrtimer_try_to_cancel(&vcpu->arch.dec_timer);
+
 #ifdef CONFIG_PPC_BOOK3S
        /* mtdec lowers the interrupt line when positive. */
        kvmppc_core_dequeue_dec(vcpu);
 
        /* POWER4+ triggers a dec interrupt if the value is < 0 */
        if (vcpu->arch.dec & 0x80000000) {
-               hrtimer_try_to_cancel(&vcpu->arch.dec_timer);
                kvmppc_core_queue_dec(vcpu);
                return;
        }
 #endif
-       if (kvmppc_dec_enabled(vcpu)) {
-               /* The decrementer ticks at the same rate as the timebase, so
-                * that's how we convert the guest DEC value to the number of
-                * host ticks. */
-
-               hrtimer_try_to_cancel(&vcpu->arch.dec_timer);
-               dec_nsec = vcpu->arch.dec;
-               dec_nsec *= 1000;
-               dec_nsec /= tb_ticks_per_usec;
-               hrtimer_start(&vcpu->arch.dec_timer, ktime_set(0, dec_nsec),
-                             HRTIMER_MODE_REL);
-               vcpu->arch.dec_jiffies = get_tb();
-       } else {
-               hrtimer_try_to_cancel(&vcpu->arch.dec_timer);
-       }
+
+#ifdef CONFIG_BOOKE
+       /* On BOOKE, DEC = 0 is as good as decrementer not enabled */
+       if (vcpu->arch.dec == 0)
+               return;
+#endif
+
+       /*
+        * The decrementer ticks at the same rate as the timebase, so
+        * that's how we convert the guest DEC value to the number of
+        * host ticks.
+        */
+
+       dec_time = vcpu->arch.dec;
+       dec_time *= 1000;
+       do_div(dec_time, tb_ticks_per_usec);
+       dec_nsec = do_div(dec_time, NSEC_PER_SEC);
+       hrtimer_start(&vcpu->arch.dec_timer,
+               ktime_set(dec_time, dec_nsec), HRTIMER_MODE_REL);
+       vcpu->arch.dec_jiffies = get_tb();
 }
 
 u32 kvmppc_get_dec(struct kvm_vcpu *vcpu, u64 tb)
 {
        u64 jd = tb - vcpu->arch.dec_jiffies;
+
+#ifdef CONFIG_BOOKE
+       if (vcpu->arch.dec < jd)
+               return 0;
+#endif
+
        return vcpu->arch.dec - jd;
 }
 
@@ -159,7 +161,8 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
        case OP_TRAP_64:
                kvmppc_core_queue_program(vcpu, SRR1_PROGTRAP);
 #else
-               kvmppc_core_queue_program(vcpu, vcpu->arch.esr | ESR_PTR);
+               kvmppc_core_queue_program(vcpu,
+                                         vcpu->arch.shared->esr | ESR_PTR);
 #endif
                advance = 0;
                break;
index 607fbdf..00d7e34 100644 (file)
@@ -39,7 +39,8 @@
 int kvm_arch_vcpu_runnable(struct kvm_vcpu *v)
 {
        return !(v->arch.shared->msr & MSR_WE) ||
-              !!(v->arch.pending_exceptions);
+              !!(v->arch.pending_exceptions) ||
+              v->requests;
 }
 
 int kvmppc_kvm_pv(struct kvm_vcpu *vcpu)
@@ -66,7 +67,7 @@ int kvmppc_kvm_pv(struct kvm_vcpu *vcpu)
                vcpu->arch.magic_page_pa = param1;
                vcpu->arch.magic_page_ea = param2;
 
-               r2 = KVM_MAGIC_FEAT_SR;
+               r2 = KVM_MAGIC_FEAT_SR | KVM_MAGIC_FEAT_MAS0_TO_SPRG7;
 
                r = HC_EV_SUCCESS;
                break;
@@ -171,8 +172,11 @@ void kvm_arch_check_processor_compat(void *rtn)
        *(int *)rtn = kvmppc_core_check_processor_compat();
 }
 
-int kvm_arch_init_vm(struct kvm *kvm)
+int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
 {
+       if (type)
+               return -EINVAL;
+
        return kvmppc_core_init_vm(kvm);
 }
 
@@ -208,17 +212,22 @@ int kvm_dev_ioctl_check_extension(long ext)
        case KVM_CAP_PPC_BOOKE_SREGS:
 #else
        case KVM_CAP_PPC_SEGSTATE:
+       case KVM_CAP_PPC_HIOR:
        case KVM_CAP_PPC_PAPR:
 #endif
        case KVM_CAP_PPC_UNSET_IRQ:
        case KVM_CAP_PPC_IRQ_LEVEL:
        case KVM_CAP_ENABLE_CAP:
+       case KVM_CAP_ONE_REG:
                r = 1;
                break;
 #ifndef CONFIG_KVM_BOOK3S_64_HV
        case KVM_CAP_PPC_PAIRED_SINGLES:
        case KVM_CAP_PPC_OSI:
        case KVM_CAP_PPC_GET_PVINFO:
+#ifdef CONFIG_KVM_E500
+       case KVM_CAP_SW_TLB:
+#endif
                r = 1;
                break;
        case KVM_CAP_COALESCED_MMIO:
@@ -238,7 +247,26 @@ int kvm_dev_ioctl_check_extension(long ext)
                if (cpu_has_feature(CPU_FTR_ARCH_201))
                        r = 2;
                break;
+       case KVM_CAP_SYNC_MMU:
+               r = cpu_has_feature(CPU_FTR_ARCH_206) ? 1 : 0;
+               break;
 #endif
+       case KVM_CAP_NR_VCPUS:
+               /*
+                * Recommending a number of CPUs is somewhat arbitrary; we
+                * return the number of present CPUs for -HV (since a host
+                * will have secondary threads "offline"), and for other KVM
+                * implementations just count online CPUs.
+                */
+#ifdef CONFIG_KVM_BOOK3S_64_HV
+               r = num_present_cpus();
+#else
+               r = num_online_cpus();
+#endif
+               break;
+       case KVM_CAP_MAX_VCPUS:
+               r = KVM_MAX_VCPUS;
+               break;
        default:
                r = 0;
                break;
@@ -253,6 +281,16 @@ long kvm_arch_dev_ioctl(struct file *filp,
        return -EINVAL;
 }
 
+void kvm_arch_free_memslot(struct kvm_memory_slot *free,
+                          struct kvm_memory_slot *dont)
+{
+}
+
+int kvm_arch_create_memslot(struct kvm_memory_slot *slot, unsigned long npages)
+{
+       return 0;
+}
+
 int kvm_arch_prepare_memory_region(struct kvm *kvm,
                                    struct kvm_memory_slot *memslot,
                                    struct kvm_memory_slot old,
@@ -279,9 +317,10 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
 {
        struct kvm_vcpu *vcpu;
        vcpu = kvmppc_core_vcpu_create(kvm, id);
-       vcpu->arch.wqp = &vcpu->wq;
-       if (!IS_ERR(vcpu))
+       if (!IS_ERR(vcpu)) {
+               vcpu->arch.wqp = &vcpu->wq;
                kvmppc_create_vcpu_debugfs(vcpu, id);
+       }
        return vcpu;
 }
 
@@ -305,18 +344,6 @@ int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
        return kvmppc_core_pending_dec(vcpu);
 }
 
-static void kvmppc_decrementer_func(unsigned long data)
-{
-       struct kvm_vcpu *vcpu = (struct kvm_vcpu *)data;
-
-       kvmppc_core_queue_dec(vcpu);
-
-       if (waitqueue_active(vcpu->arch.wqp)) {
-               wake_up_interruptible(vcpu->arch.wqp);
-               vcpu->stat.halt_wakeup++;
-       }
-}
-
 /*
  * low level hrtimer wake routine. Because this runs in hardirq context
  * we schedule a tasklet to do the real work.
@@ -431,20 +458,20 @@ static void kvmppc_complete_mmio_load(struct kvm_vcpu *vcpu,
 
        kvmppc_set_gpr(vcpu, vcpu->arch.io_gpr, gpr);
 
-       switch (vcpu->arch.io_gpr & KVM_REG_EXT_MASK) {
-       case KVM_REG_GPR:
+       switch (vcpu->arch.io_gpr & KVM_MMIO_REG_EXT_MASK) {
+       case KVM_MMIO_REG_GPR:
                kvmppc_set_gpr(vcpu, vcpu->arch.io_gpr, gpr);
                break;
-       case KVM_REG_FPR:
-               vcpu->arch.fpr[vcpu->arch.io_gpr & KVM_REG_MASK] = gpr;
+       case KVM_MMIO_REG_FPR:
+               vcpu->arch.fpr[vcpu->arch.io_gpr & KVM_MMIO_REG_MASK] = gpr;
                break;
 #ifdef CONFIG_PPC_BOOK3S
-       case KVM_REG_QPR:
-               vcpu->arch.qpr[vcpu->arch.io_gpr & KVM_REG_MASK] = gpr;
+       case KVM_MMIO_REG_QPR:
+               vcpu->arch.qpr[vcpu->arch.io_gpr & KVM_MMIO_REG_MASK] = gpr;
                break;
-       case KVM_REG_FQPR:
-               vcpu->arch.fpr[vcpu->arch.io_gpr & KVM_REG_MASK] = gpr;
-               vcpu->arch.qpr[vcpu->arch.io_gpr & KVM_REG_MASK] = gpr;
+       case KVM_MMIO_REG_FQPR:
+               vcpu->arch.fpr[vcpu->arch.io_gpr & KVM_MMIO_REG_MASK] = gpr;
+               vcpu->arch.qpr[vcpu->arch.io_gpr & KVM_MMIO_REG_MASK] = gpr;
                break;
 #endif
        default:
@@ -553,8 +580,6 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
                vcpu->arch.hcall_needed = 0;
        }
 
-       kvmppc_core_deliver_interrupts(vcpu);
-
        r = kvmppc_vcpu_run(run, vcpu);
 
        if (vcpu->sigset_active)
@@ -563,6 +588,21 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
        return r;
 }
 
+void kvm_vcpu_kick(struct kvm_vcpu *vcpu)
+{
+       int me;
+       int cpu = vcpu->cpu;
+
+       me = get_cpu();
+       if (waitqueue_active(vcpu->arch.wqp)) {
+               wake_up_interruptible(vcpu->arch.wqp);
+               vcpu->stat.halt_wakeup++;
+       } else if (cpu != me && cpu != -1) {
+               smp_send_reschedule(vcpu->cpu);
+       }
+       put_cpu();
+}
+
 int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, struct kvm_interrupt *irq)
 {
        if (irq->irq == KVM_INTERRUPT_UNSET) {
@@ -571,13 +611,7 @@ int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, struct kvm_interrupt *irq)
        }
 
        kvmppc_core_queue_external(vcpu, irq);
-
-       if (waitqueue_active(vcpu->arch.wqp)) {
-               wake_up_interruptible(vcpu->arch.wqp);
-               vcpu->stat.halt_wakeup++;
-       } else if (vcpu->cpu != -1) {
-               smp_send_reschedule(vcpu->cpu);
-       }
+       kvm_vcpu_kick(vcpu);
 
        return 0;
 }
@@ -599,6 +633,19 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
                r = 0;
                vcpu->arch.papr_enabled = true;
                break;
+#ifdef CONFIG_KVM_E500
+       case KVM_CAP_SW_TLB: {
+               struct kvm_config_tlb cfg;
+               void __user *user_ptr = (void __user *)(uintptr_t)cap->args[0];
+
+               r = -EFAULT;
+               if (copy_from_user(&cfg, user_ptr, sizeof(cfg)))
+                       break;
+
+               r = kvm_vcpu_ioctl_config_tlb(vcpu, &cfg);
+               break;
+       }
+#endif
        default:
                r = -EINVAL;
                break;
@@ -648,6 +695,32 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
                r = kvm_vcpu_ioctl_enable_cap(vcpu, &cap);
                break;
        }
+
+       case KVM_SET_ONE_REG:
+       case KVM_GET_ONE_REG:
+       {
+               struct kvm_one_reg reg;
+               r = -EFAULT;
+               if (copy_from_user(&reg, argp, sizeof(reg)))
+                       goto out;
+               if (ioctl == KVM_SET_ONE_REG)
+                       r = kvm_vcpu_ioctl_set_one_reg(vcpu, &reg);
+               else
+                       r = kvm_vcpu_ioctl_get_one_reg(vcpu, &reg);
+               break;
+       }
+
+#ifdef CONFIG_KVM_E500
+       case KVM_DIRTY_TLB: {
+               struct kvm_dirty_tlb dirty;
+               r = -EFAULT;
+               if (copy_from_user(&dirty, argp, sizeof(dirty)))
+                       goto out;
+               r = kvm_vcpu_ioctl_dirty_tlb(vcpu, &dirty);
+               break;
+       }
+#endif
+
        default:
                r = -EINVAL;
        }
@@ -656,6 +729,11 @@ out:
        return r;
 }
 
+int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf)
+{
+       return VM_FAULT_SIGBUS;
+}
+
 static int kvm_vm_ioctl_get_pvinfo(struct kvm_ppc_pvinfo *pvinfo)
 {
        u32 inst_lis = 0x3c000000;
index b135d3d..877186b 100644 (file)
@@ -118,11 +118,14 @@ TRACE_EVENT(kvm_book3s_exit,
        ),
 
        TP_fast_assign(
+               struct kvmppc_book3s_shadow_vcpu *svcpu;
                __entry->exit_nr        = exit_nr;
                __entry->pc             = kvmppc_get_pc(vcpu);
                __entry->dar            = kvmppc_get_fault_dar(vcpu);
                __entry->msr            = vcpu->arch.shared->msr;
-               __entry->srr1           = to_svcpu(vcpu)->shadow_srr1;
+               svcpu = svcpu_get(vcpu);
+               __entry->srr1           = svcpu->shadow_srr1;
+               svcpu_put(svcpu);
        ),
 
        TP_printk("exit=0x%x | pc=0x%lx | msr=0x%lx | dar=0x%lx | srr1=0x%lx",
@@ -337,6 +340,63 @@ TRACE_EVENT(kvm_book3s_slbmte,
 
 #endif /* CONFIG_PPC_BOOK3S */
 
+
+/*************************************************************************
+ *                         Book3E trace points                           *
+ *************************************************************************/
+
+#ifdef CONFIG_BOOKE
+
+TRACE_EVENT(kvm_booke206_stlb_write,
+       TP_PROTO(__u32 mas0, __u32 mas8, __u32 mas1, __u64 mas2, __u64 mas7_3),
+       TP_ARGS(mas0, mas8, mas1, mas2, mas7_3),
+
+       TP_STRUCT__entry(
+               __field(        __u32,  mas0            )
+               __field(        __u32,  mas8            )
+               __field(        __u32,  mas1            )
+               __field(        __u64,  mas2            )
+               __field(        __u64,  mas7_3          )
+       ),
+
+       TP_fast_assign(
+               __entry->mas0           = mas0;
+               __entry->mas8           = mas8;
+               __entry->mas1           = mas1;
+               __entry->mas2           = mas2;
+               __entry->mas7_3         = mas7_3;
+       ),
+
+       TP_printk("mas0=%x mas8=%x mas1=%x mas2=%llx mas7_3=%llx",
+               __entry->mas0, __entry->mas8, __entry->mas1,
+               __entry->mas2, __entry->mas7_3)
+);
+
+TRACE_EVENT(kvm_booke206_gtlb_write,
+       TP_PROTO(__u32 mas0, __u32 mas1, __u64 mas2, __u64 mas7_3),
+       TP_ARGS(mas0, mas1, mas2, mas7_3),
+
+       TP_STRUCT__entry(
+               __field(        __u32,  mas0            )
+               __field(        __u32,  mas1            )
+               __field(        __u64,  mas2            )
+               __field(        __u64,  mas7_3          )
+       ),
+
+       TP_fast_assign(
+               __entry->mas0           = mas0;
+               __entry->mas1           = mas1;
+               __entry->mas2           = mas2;
+               __entry->mas7_3         = mas7_3;
+       ),
+
+       TP_printk("mas0=%x mas1=%x mas2=%llx mas7_3=%llx",
+               __entry->mas0, __entry->mas1,
+               __entry->mas2, __entry->mas7_3)
+);
+
+#endif
+
 #endif /* _TRACE_KVM_H */
 
 /* This part must be outside protection */
index 13b676c..da22c84 100644 (file)
@@ -3,8 +3,8 @@
 #include <linux/slab.h>
 #include <linux/bootmem.h>
 #include <linux/string.h>
+#include <asm/setup.h>
 
-#include <asm/system.h>
 
 void * __init_refok zalloc_maybe_bootmem(size_t size, gfp_t mask)
 {
index 6e1efad..bf2654f 100644 (file)
@@ -20,6 +20,7 @@
  */
 #include <linux/uaccess.h>
 #include <linux/hardirq.h>
+#include <asm/switch_to.h>
 
 int enter_vmx_copy(void)
 {
index 388b95e..2c9441e 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/memblock.h>
 
 #include <asm/mmu.h>
-#include <asm/system.h>
 #include <asm/page.h>
 #include <asm/cacheflush.h>
 
index 19f2f94..08ffcf5 100644 (file)
 #include <asm/pgtable.h>
 #include <asm/mmu.h>
 #include <asm/mmu_context.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/tlbflush.h>
 #include <asm/siginfo.h>
+#include <asm/debug.h>
 #include <mm/mmu_decl.h>
 
 #include "icswx.h"
index 3e8c37a..377e5cb 100644 (file)
@@ -40,7 +40,6 @@
 #include <asm/mmu_context.h>
 #include <asm/page.h>
 #include <asm/types.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/machdep.h>
 #include <asm/prom.h>
index 57c7465..fb05b12 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/io.h>
 #include <linux/slab.h>
 #include <linux/hugetlb.h>
+#include <linux/export.h>
 #include <linux/of_fdt.h>
 #include <linux/memblock.h>
 #include <linux/bootmem.h>
@@ -103,6 +104,7 @@ pte_t *find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea, unsigned *shift
                *shift = hugepd_shift(*hpdp);
        return hugepte_offset(hpdp, ea, pdshift);
 }
+EXPORT_SYMBOL_GPL(find_linux_pte_or_hugepte);
 
 pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
 {
@@ -310,7 +312,8 @@ void __init reserve_hugetlb_gpages(void)
        int i;
 
        strlcpy(cmdline, boot_command_line, COMMAND_LINE_SIZE);
-       parse_args("hugetlb gpages", cmdline, NULL, 0, &do_gpage_early_setup);
+       parse_args("hugetlb gpages", cmdline, NULL, 0, 0, 0,
+                       &do_gpage_early_setup);
 
        /*
         * Walk gpage list in reverse, allocating larger page sizes first.
index 6157be2..01e2db9 100644 (file)
@@ -45,7 +45,6 @@
 #include <asm/btext.h>
 #include <asm/tlb.h>
 #include <asm/sections.h>
-#include <asm/system.h>
 #include <asm/hugetlb.h>
 
 #include "mmu_decl.h"
index e94b57f..620b7ac 100644 (file)
@@ -61,7 +61,6 @@
 #include <asm/mmzone.h>
 #include <asm/cputable.h>
 #include <asm/sections.h>
-#include <asm/system.h>
 #include <asm/iommu.h>
 #include <asm/abs_addr.h>
 #include <asm/vdso.h>
index 3feefc3..b6edbb3 100644 (file)
 #include <linux/node.h>
 #include <asm/sparsemem.h>
 #include <asm/prom.h>
-#include <asm/system.h>
 #include <asm/smp.h>
 #include <asm/firmware.h>
 #include <asm/paca.h>
 #include <asm/hvcall.h>
+#include <asm/setup.h>
 
 static int numa_enabled = 1;
 
index 0907f92..6c856fb 100644 (file)
@@ -33,6 +33,7 @@
 #include <asm/pgalloc.h>
 #include <asm/fixmap.h>
 #include <asm/io.h>
+#include <asm/setup.h>
 
 #include "mmu_decl.h"
 
index ad36ede..249a063 100644 (file)
@@ -51,7 +51,6 @@
 #include <asm/processor.h>
 #include <asm/cputable.h>
 #include <asm/sections.h>
-#include <asm/system.h>
 #include <asm/abs_addr.h>
 #include <asm/firmware.h>
 
index 6f01624..4f51025 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/smp.h>
 #include <linux/errno.h>
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/pmc.h>
 #include <asm/cputable.h>
 #include <asm/oprofile_impl.h>
index f8d36f9..ff61724 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/init.h>
 #include <linux/smp.h>
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/processor.h>
 #include <asm/cputable.h>
 #include <asm/page.h>
index cb515cf..b9589c1 100644 (file)
@@ -34,7 +34,6 @@
 #include <asm/ptrace.h>
 #include <asm/reg.h>
 #include <asm/rtas.h>
-#include <asm/system.h>
 #include <asm/cell-regs.h>
 
 #include "../platforms/cell/interrupt.h"
index d4e6507..ccc1daa 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/init.h>
 #include <linux/smp.h>
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/processor.h>
 #include <asm/cputable.h>
 #include <asm/reg_fsl_emb.h>
index e6bec74..95ae77d 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/smp.h>
 #include <asm/firmware.h>
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/processor.h>
 #include <asm/cputable.h>
 #include <asm/rtas.h>
index a20afe4..9b801b8 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/init.h>
 #include <linux/smp.h>
 #include <asm/ptrace.h>
-#include <asm/system.h>
 #include <asm/processor.h>
 #include <asm/cputable.h>
 #include <asm/oprofile_impl.h>
index c2e27ed..02aee03 100644 (file)
@@ -116,14 +116,45 @@ static inline void perf_get_data_addr(struct pt_regs *regs, u64 *addrp)
                *addrp = mfspr(SPRN_SDAR);
 }
 
+static inline u32 perf_flags_from_msr(struct pt_regs *regs)
+{
+       if (regs->msr & MSR_PR)
+               return PERF_RECORD_MISC_USER;
+       if ((regs->msr & MSR_HV) && freeze_events_kernel != MMCR0_FCHV)
+               return PERF_RECORD_MISC_HYPERVISOR;
+       return PERF_RECORD_MISC_KERNEL;
+}
+
 static inline u32 perf_get_misc_flags(struct pt_regs *regs)
 {
        unsigned long mmcra = regs->dsisr;
        unsigned long sihv = MMCRA_SIHV;
        unsigned long sipr = MMCRA_SIPR;
 
+       /* Not a PMU interrupt: Make up flags from regs->msr */
        if (TRAP(regs) != 0xf00)
-               return 0;       /* not a PMU interrupt */
+               return perf_flags_from_msr(regs);
+
+       /*
+        * If we don't support continuous sampling and this
+        * is not a marked event, same deal
+        */
+       if ((ppmu->flags & PPMU_NO_CONT_SAMPLING) &&
+           !(mmcra & MMCRA_SAMPLE_ENABLE))
+               return perf_flags_from_msr(regs);
+
+       /*
+        * If we don't have flags in MMCRA, rather than using
+        * the MSR, we intuit the flags from the address in
+        * SIAR which should give slightly more reliable
+        * results
+        */
+       if (ppmu->flags & PPMU_NO_SIPR) {
+               unsigned long siar = mfspr(SPRN_SIAR);
+               if (siar >= PAGE_OFFSET)
+                       return PERF_RECORD_MISC_KERNEL;
+               return PERF_RECORD_MISC_USER;
+       }
 
        if (ppmu->flags & PPMU_ALT_SIPR) {
                sihv = POWER6_MMCRA_SIHV;
@@ -1299,13 +1330,18 @@ unsigned long perf_misc_flags(struct pt_regs *regs)
  */
 unsigned long perf_instruction_pointer(struct pt_regs *regs)
 {
-       unsigned long ip;
+       unsigned long mmcra = regs->dsisr;
 
+       /* Not a PMU interrupt */
        if (TRAP(regs) != 0xf00)
-               return regs->nip;       /* not a PMU interrupt */
+               return regs->nip;
+
+       /* Processor doesn't support sampling non marked events */
+       if ((ppmu->flags & PPMU_NO_CONT_SAMPLING) &&
+           !(mmcra & MMCRA_SAMPLE_ENABLE))
+               return regs->nip;
 
-       ip = mfspr(SPRN_SIAR) + perf_ip_adjust(regs);
-       return ip;
+       return mfspr(SPRN_SIAR) + perf_ip_adjust(regs);
 }
 
 static bool pmc_overflow(unsigned long val)
index b4f1dda..9103a1d 100644 (file)
@@ -607,6 +607,7 @@ static struct power_pmu power4_pmu = {
        .n_generic              = ARRAY_SIZE(p4_generic_events),
        .generic_events         = p4_generic_events,
        .cache_events           = &power4_cache_events,
+       .flags                  = PPMU_NO_SIPR | PPMU_NO_CONT_SAMPLING,
 };
 
 static int __init init_power4_pmu(void)
index 111eb25..20139ce 100644 (file)
@@ -487,6 +487,7 @@ static struct power_pmu ppc970_pmu = {
        .n_generic              = ARRAY_SIZE(ppc970_generic_events),
        .generic_events         = ppc970_generic_events,
        .cache_events           = &ppc970_cache_events,
+       .flags                  = PPMU_NO_SIPR | PPMU_NO_CONT_SAMPLING,
 };
 
 static int __init init_ppc970_pmu(void)
index eda0fc2..870b70f 100644 (file)
@@ -3,6 +3,7 @@
 #include <asm/io.h>
 #include <asm/time.h>
 #include <asm/mpc52xx.h>
+#include <asm/switch_to.h>
 
 /* defined in lite5200_sleep.S and only used here */
 extern void lite5200_low_power(void __iomem *sram, void __iomem *mbar);
index d111b02..fb94d10 100644 (file)
@@ -17,7 +17,6 @@
 #include <asm/cpm2.h>
 #include <asm/io.h>
 #include <asm/pci-bridge.h>
-#include <asm/system.h>
 
 #include <platforms/82xx/pq2.h>
 
index 65eb792..a266ba8 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/of_platform.h>
 #include <linux/of_device.h>
 
-#include <asm/system.h>
 #include <linux/atomic.h>
 #include <asm/time.h>
 #include <asm/io.h>
index e36bc61..d440435 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/of_platform.h>
 #include <linux/of_device.h>
 
-#include <asm/system.h>
 #include <linux/atomic.h>
 #include <asm/time.h>
 #include <asm/io.h>
index 39849dd..a494fa5 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/root_dev.h>
 #include <linux/of_platform.h>
 
-#include <asm/system.h>
 #include <linux/atomic.h>
 #include <asm/time.h>
 #include <asm/io.h>
index 5828d8e..553e793 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/root_dev.h>
 #include <linux/of_platform.h>
 
-#include <asm/system.h>
 #include <linux/atomic.h>
 #include <asm/time.h>
 #include <asm/io.h>
index ad8e4bc..1b1f6c8 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/of_platform.h>
 #include <linux/of_device.h>
 
-#include <asm/system.h>
 #include <linux/atomic.h>
 #include <asm/time.h>
 #include <asm/io.h>
index 8a81d76..26cb3e9 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/root_dev.h>
 #include <linux/of_platform.h>
 
-#include <asm/system.h>
 #include <linux/atomic.h>
 #include <asm/time.h>
 #include <asm/io.h>
index edf6687..1a04671 100644 (file)
@@ -27,6 +27,7 @@
 #include <asm/io.h>
 #include <asm/time.h>
 #include <asm/mpc6xx.h>
+#include <asm/switch_to.h>
 
 #include <sysdev/fsl_soc.h>
 
index df69e99..dd3617c 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/interrupt.h>
 #include <linux/memblock.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
index d50056f..1801462 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/of_platform.h>
 #include <linux/memblock.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
index 60120e5..3dc1bda 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/seq_file.h>
 #include <linux/of_platform.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
index f588726..585bd22 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/of_platform.h>
 #include <linux/memblock.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
index d19f675..29ee8fc 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/seq_file.h>
 #include <linux/of_platform.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
index ab5f0bf..11156fb 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/fsl_devices.h>
 #include <linux/of_platform.h>
 
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
 #include <linux/atomic.h>
index 6e23e3e..1fd91e9 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/of_platform.h>
 #include <linux/memblock.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
index f33662b..3754ddc 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/phy.h>
 #include <linux/memblock.h>
 
-#include <asm/system.h>
 #include <linux/atomic.h>
 #include <asm/time.h>
 #include <asm/io.h>
index db214cd..9848f9e 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/interrupt.h>
 #include <linux/of_platform.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
index d8bd656..dbaf443 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/interrupt.h>
 #include <linux/of_platform.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
index 6b07398..2990e8b 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/of_platform.h>
 #include <linux/of_device.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
index eda6ed5..6541fa2 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/interrupt.h>
 #include <linux/phy.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
index 96d99a3..f238efa 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/interrupt.h>
 #include <linux/phy.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
index d1b21d7..c92417d 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
index e8cba50..17bef15 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/interrupt.h>
 #include <linux/phy.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
index 1677b8a..cd3a66b 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/fsl_devices.h>
 #include <linux/of_platform.h>
 
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
 #include <linux/atomic.h>
index 3c3bbcc..b1be632 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/seq_file.h>
 #include <linux/of_platform.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
index b719192..b9c6daa 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/seq_file.h>
 #include <linux/of_platform.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
index 27ca3a7..e050800 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/seq_file.h>
 #include <linux/of_platform.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
index d7504ce..4d786c2 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/seq_file.h>
 #include <linux/of_platform.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
index 503c215..41c6875 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/interrupt.h>
 #include <linux/of_platform.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
index ed58b6c..1fca663 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/seq_file.h>
 #include <linux/of_platform.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
index 710db69..14e0e57 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/seq_file.h>
 #include <linux/of_platform.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
index 4a13d2f..1638f43 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/seq_file.h>
 #include <linux/of_platform.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
index 13fa9a6..bbc6152 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/seq_file.h>
 #include <linux/of.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
index 569262c..3755e61 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/of_platform.h>
 #include <linux/memblock.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
index 22cc357..9982f57 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/interrupt.h>
 #include <linux/of_platform.h>
 
-#include <asm/system.h>
 #include <asm/mpic.h>
 #include <asm/i8259.h>
 
index 51c8f33..e7007d0 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/seq_file.h>
 #include <linux/of_platform.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
index caaec29..866feff 100644 (file)
@@ -19,7 +19,6 @@
 
 #include <asm/io.h>
 #include <asm/machdep.h>
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/8xx_immap.h>
 #include <asm/cpm1.h>
index 45ed6cd..5d98398 100644 (file)
@@ -32,7 +32,6 @@
 #include <asm/machdep.h>
 #include <asm/page.h>
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/mpc8xx.h>
 #include <asm/8xx_immap.h>
index 528e00d..8d21ab7 100644 (file)
@@ -35,7 +35,6 @@
 #include <asm/machdep.h>
 #include <asm/page.h>
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/mpc8xx.h>
 #include <asm/8xx_immap.h>
index 2516c1c..943c9d3 100644 (file)
@@ -95,7 +95,6 @@ static long beat_lpar_hpte_insert(unsigned long hpte_group,
        unsigned long lpar_rc;
        u64 hpte_v, hpte_r, slot;
 
-       /* same as iseries */
        if (vflags & HPTE_V_SECONDARY)
                return -1;
 
@@ -319,7 +318,6 @@ static long beat_lpar_hpte_insert_v3(unsigned long hpte_group,
        unsigned long lpar_rc;
        u64 hpte_v, hpte_r, slot;
 
-       /* same as iseries */
        if (vflags & HPTE_V_SECONDARY)
                return -1;
 
index 4a255cf..49a65e2 100644 (file)
@@ -38,7 +38,6 @@
 #include <asm/machdep.h>
 #include <asm/cputable.h>
 #include <asm/firmware.h>
-#include <asm/system.h>
 #include <asm/rtas.h>
 #include <asm/cputhreads.h>
 
index 8cab573..ebd3963 100644 (file)
@@ -23,7 +23,6 @@
 
 #include <asm/machdep.h>
 #include <asm/prom.h>
-#include <asm/system.h>
 #include <asm/time.h>
 
 #include <mm/mmu_decl.h>
index ab51b21..8c305c7 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/of_platform.h>
 #include <linux/module.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/prom.h>
index 74ccce3..beeaf4a 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/tty.h>
 #include <linux/serial_core.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/prom.h>
index 670035f..d455f08 100644 (file)
@@ -17,7 +17,6 @@
 
 #include <asm/machdep.h>
 #include <asm/prom.h>
-#include <asm/system.h>
 #include <asm/time.h>
 
 #include <mm/mmu_decl.h>
index e0ed3c7..c458b60 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/initrd.h>
 #include <linux/of_platform.h>
 
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/prom.h>
 #include <asm/mpic.h>
index 8b0c208..64fde05 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/interrupt.h>
 #include <linux/mc146818rtc.h>
 
-#include <asm/system.h>
 #include <asm/pci-bridge.h>
 
 #define ULI_PIRQA      0x08
index 3b7545a..cb1b0b3 100644 (file)
@@ -47,7 +47,6 @@
 #include <asm/processor.h>
 #include <asm/sections.h>
 #include <asm/prom.h>
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
 #include <asm/pci-bridge.h>
index eac569d..b4a369d 100644 (file)
@@ -27,7 +27,6 @@
 
 #include <asm/sections.h>
 #include <asm/prom.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/machdep.h>
index e777ad4..2ed9212 100644 (file)
 #include <linux/gfp.h>
 
 #include <asm/prom.h>
-#include <asm/system.h>
 #include <asm/iommu.h>
 #include <asm/machdep.h>
 #include <asm/mpic.h>
 #include <asm/smp.h>
 #include <asm/time.h>
 #include <asm/mmu.h>
+#include <asm/debug.h>
 
 #include <pcmcia/ss.h>
 #include <pcmcia/cistpl.h>
index 84d7fd9..3e91ef5 100644 (file)
@@ -19,6 +19,7 @@
 #include <asm/bootx.h>
 #include <asm/btext.h>
 #include <asm/io.h>
+#include <asm/setup.h>
 
 #undef DEBUG
 #define SET_BOOT_BAT
index 1fc386a..6417119 100644 (file)
@@ -33,9 +33,9 @@
 #include <asm/sections.h>
 #include <asm/cputable.h>
 #include <asm/time.h>
-#include <asm/system.h>
 #include <asm/mpic.h>
 #include <asm/keylargo.h>
+#include <asm/switch_to.h>
 
 /* WARNING !!! This will cause calibrate_delay() to be called,
  * but this is an __init function ! So you MUST go edit
index da18b26..014d06e 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/spinlock.h>
 #include <asm/sections.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/nvram.h>
index 970ea1d..141f889 100644 (file)
@@ -57,7 +57,6 @@
 #include <asm/reg.h>
 #include <asm/sections.h>
 #include <asm/prom.h>
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
 #include <asm/pci-bridge.h>
index 11c9fce..8680bb6 100644 (file)
@@ -26,7 +26,6 @@
 
 #include <asm/sections.h>
 #include <asm/prom.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/machdep.h>
index 17210c5..3ef4625 100644 (file)
@@ -25,7 +25,6 @@
 #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>
index 8bd6ba5..de2aea4 100644 (file)
@@ -29,6 +29,7 @@
 #include <asm/prom.h>
 #include <asm/udbg.h>
 #include <asm/lv1call.h>
+#include <asm/setup.h>
 
 #include "platform.h"
 
index 0e86563..a764854 100644 (file)
 #include <linux/debugfs.h>
 #include <linux/spinlock.h>
 #include <asm/smp.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/firmware.h>
 #include <asm/lppaca.h>
+#include <asm/debug.h>
 
 #include "plpar_wrappers.h"
 
index 8011088..309d38e 100644 (file)
@@ -984,7 +984,8 @@ int __exit eeh_ops_unregister(const char *name)
  */
 void __init eeh_init(void)
 {
-       struct device_node *phb, *np;
+       struct pci_controller *hose, *tmp;
+       struct device_node *phb;
        int ret;
 
        /* call platform initialization function */
@@ -1000,19 +1001,9 @@ void __init eeh_init(void)
 
        raw_spin_lock_init(&confirm_error_lock);
 
-       np = of_find_node_by_path("/rtas");
-       if (np == NULL)
-               return;
-
-       /* Enable EEH for all adapters.  Note that eeh requires buid's */
-       for (phb = of_find_node_by_name(NULL, "pci"); phb;
-            phb = of_find_node_by_name(phb, "pci")) {
-               unsigned long buid;
-
-               buid = get_phb_buid(phb);
-               if (buid == 0 || !of_node_to_eeh_dev(phb))
-                       continue;
-
+       /* Enable EEH for all adapters */
+       list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
+               phb = hose->dn;
                traverse_pci_devices(phb, eeh_early_enable, NULL);
        }
 
index f3aed7d..c4507d0 100644 (file)
@@ -62,7 +62,7 @@ void * __devinit eeh_dev_init(struct device_node *dn, void *data)
        }
 
        /* Associate EEH device with OF node */
-       dn->edev  = edev;
+       PCI_DN(dn)->edev = edev;
        edev->dn  = dn;
        edev->phb = phb;
 
index c986d08..64c97d8 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/delay.h>
 #include <linux/sched.h>       /* for idle_task_exit */
 #include <linux/cpu.h>
-#include <asm/system.h>
 #include <asm/prom.h>
 #include <asm/rtas.h>
 #include <asm/firmware.h>
index 1a709bc..ef9d9d8 100644 (file)
@@ -63,73 +63,9 @@ EXPORT_SYMBOL_GPL(pseries_ioei_notifier_list);
 
 static int ioei_check_exception_token;
 
-/* pSeries event log format */
-
-/* Two bytes ASCII section IDs */
-#define PSERIES_ELOG_SECT_ID_PRIV_HDR          (('P' << 8) | 'H')
-#define PSERIES_ELOG_SECT_ID_USER_HDR          (('U' << 8) | 'H')
-#define PSERIES_ELOG_SECT_ID_PRIMARY_SRC       (('P' << 8) | 'S')
-#define PSERIES_ELOG_SECT_ID_EXTENDED_UH       (('E' << 8) | 'H')
-#define PSERIES_ELOG_SECT_ID_FAILING_MTMS      (('M' << 8) | 'T')
-#define PSERIES_ELOG_SECT_ID_SECONDARY_SRC     (('S' << 8) | 'S')
-#define PSERIES_ELOG_SECT_ID_DUMP_LOCATOR      (('D' << 8) | 'H')
-#define PSERIES_ELOG_SECT_ID_FW_ERROR          (('S' << 8) | 'W')
-#define PSERIES_ELOG_SECT_ID_IMPACT_PART_ID    (('L' << 8) | 'P')
-#define PSERIES_ELOG_SECT_ID_LOGIC_RESOURCE_ID (('L' << 8) | 'R')
-#define PSERIES_ELOG_SECT_ID_HMC_ID            (('H' << 8) | 'M')
-#define PSERIES_ELOG_SECT_ID_EPOW              (('E' << 8) | 'P')
-#define PSERIES_ELOG_SECT_ID_IO_EVENT          (('I' << 8) | 'E')
-#define PSERIES_ELOG_SECT_ID_MANUFACT_INFO     (('M' << 8) | 'I')
-#define PSERIES_ELOG_SECT_ID_CALL_HOME         (('C' << 8) | 'H')
-#define PSERIES_ELOG_SECT_ID_USER_DEF          (('U' << 8) | 'D')
-
-/* Vendor specific Platform Event Log Format, Version 6, section header */
-struct pseries_elog_section {
-       uint16_t id;                    /* 0x00 2-byte ASCII section ID */
-       uint16_t length;                /* 0x02 Section length in bytes */
-       uint8_t version;                /* 0x04 Section version         */
-       uint8_t subtype;                /* 0x05 Section subtype         */
-       uint16_t creator_component;     /* 0x06 Creator component ID    */
-       uint8_t data[];                 /* 0x08 Start of section data   */
-};
-
 static char ioei_rtas_buf[RTAS_DATA_BUF_SIZE] __cacheline_aligned;
 
 /**
- * Find data portion of a specific section in RTAS extended event log.
- * @elog: RTAS error/event log.
- * @sect_id: secsion ID.
- *
- * Return:
- *     pointer to the section data of the specified section
- *     NULL if not found
- */
-static struct pseries_elog_section *find_xelog_section(struct rtas_error_log *elog,
-                                                      uint16_t sect_id)
-{
-       struct rtas_ext_event_log_v6 *xelog =
-               (struct rtas_ext_event_log_v6 *) elog->buffer;
-       struct pseries_elog_section *sect;
-       unsigned char *p, *log_end;
-
-       /* Check that we understand the format */
-       if (elog->extended_log_length < sizeof(struct rtas_ext_event_log_v6) ||
-           xelog->log_format != RTAS_V6EXT_LOG_FORMAT_EVENT_LOG ||
-           xelog->company_id != RTAS_V6EXT_COMPANY_ID_IBM)
-               return NULL;
-
-       log_end = elog->buffer + elog->extended_log_length;
-       p = xelog->vendor_log;
-       while (p < log_end) {
-               sect = (struct pseries_elog_section *)p;
-               if (sect->id == sect_id)
-                       return sect;
-               p += sect->length;
-       }
-       return NULL;
-}
-
-/**
  * Find the data portion of an IO Event section from event log.
  * @elog: RTAS error/event log.
  *
@@ -138,7 +74,7 @@ static struct pseries_elog_section *find_xelog_section(struct rtas_error_log *el
  */
 static struct pseries_io_event * ioei_find_event(struct rtas_error_log *elog)
 {
-       struct pseries_elog_section *sect;
+       struct pseries_errorlog *sect;
 
        /* We should only ever get called for io-event interrupts, but if
         * we do get called for another type then something went wrong so
@@ -152,7 +88,7 @@ static struct pseries_io_event * ioei_find_event(struct rtas_error_log *elog)
                return NULL;
        }
 
-       sect = find_xelog_section(elog, PSERIES_ELOG_SECT_ID_IO_EVENT);
+       sect = get_pseries_errorlog(elog, PSERIES_ELOG_SECT_ID_IO_EVENT);
        if (unlikely(!sect)) {
                printk_once(KERN_WARNING "io_event_irq: RTAS extended event "
                            "log does not contain an IO Event section. "
index c442f2b..0915b1a 100644 (file)
@@ -809,8 +809,7 @@ machine_arch_initcall(pseries, find_existing_ddw_windows);
 static int query_ddw(struct pci_dev *dev, const u32 *ddw_avail,
                        struct ddw_query_response *query)
 {
-       struct device_node *dn;
-       struct pci_dn *pcidn;
+       struct eeh_dev *edev;
        u32 cfg_addr;
        u64 buid;
        int ret;
@@ -821,12 +820,12 @@ static int query_ddw(struct pci_dev *dev, const u32 *ddw_avail,
         * Retrieve them from the pci device, not the node with the
         * dma-window property
         */
-       dn = pci_device_to_OF_node(dev);
-       pcidn = PCI_DN(dn);
-       cfg_addr = pcidn->eeh_config_addr;
-       if (pcidn->eeh_pe_config_addr)
-               cfg_addr = pcidn->eeh_pe_config_addr;
-       buid = pcidn->phb->buid;
+       edev = pci_dev_to_eeh_dev(dev);
+       cfg_addr = edev->config_addr;
+       if (edev->pe_config_addr)
+               cfg_addr = edev->pe_config_addr;
+       buid = edev->phb->buid;
+
        ret = rtas_call(ddw_avail[0], 3, 5, (u32 *)query,
                  cfg_addr, BUID_HI(buid), BUID_LO(buid));
        dev_info(&dev->dev, "ibm,query-pe-dma-windows(%x) %x %x %x"
@@ -839,8 +838,7 @@ static int create_ddw(struct pci_dev *dev, const u32 *ddw_avail,
                        struct ddw_create_response *create, int page_shift,
                        int window_shift)
 {
-       struct device_node *dn;
-       struct pci_dn *pcidn;
+       struct eeh_dev *edev;
        u32 cfg_addr;
        u64 buid;
        int ret;
@@ -851,12 +849,11 @@ static int create_ddw(struct pci_dev *dev, const u32 *ddw_avail,
         * Retrieve them from the pci device, not the node with the
         * dma-window property
         */
-       dn = pci_device_to_OF_node(dev);
-       pcidn = PCI_DN(dn);
-       cfg_addr = pcidn->eeh_config_addr;
-       if (pcidn->eeh_pe_config_addr)
-               cfg_addr = pcidn->eeh_pe_config_addr;
-       buid = pcidn->phb->buid;
+       edev = pci_dev_to_eeh_dev(dev);
+       cfg_addr = edev->config_addr;
+       if (edev->pe_config_addr)
+               cfg_addr = edev->pe_config_addr;
+       buid = edev->phb->buid;
 
        do {
                /* extra outputs are LIOBN and dma-addr (hi, lo) */
index a12e95a..41a34bc 100644 (file)
@@ -14,9 +14,9 @@
 
 #include <asm/paca.h>
 #include <asm/reg.h>
-#include <asm/system.h>
 #include <asm/machdep.h>
 #include <asm/firmware.h>
+#include <asm/runlatch.h>
 
 #include "plpar_wrappers.h"
 #include "pseries.h"
index 086d2ae..c4dfccd 100644 (file)
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
 
-/* Change Activity:
- * 2001/09/21 : engebret : Created with minimal EPOW and HW exception support.
- * End Change Activity
- */
-
-#include <linux/errno.h>
-#include <linux/threads.h>
-#include <linux/kernel_stat.h>
-#include <linux/signal.h>
 #include <linux/sched.h>
-#include <linux/ioport.h>
 #include <linux/interrupt.h>
-#include <linux/timex.h>
-#include <linux/init.h>
-#include <linux/delay.h>
 #include <linux/irq.h>
-#include <linux/random.h>
-#include <linux/sysrq.h>
-#include <linux/bitops.h>
-
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/irq.h>
-#include <asm/cache.h>
-#include <asm/prom.h>
-#include <asm/ptrace.h>
+#include <linux/of.h>
+#include <linux/fs.h>
+#include <linux/reboot.h>
+
 #include <asm/machdep.h>
 #include <asm/rtas.h>
-#include <asm/udbg.h>
 #include <asm/firmware.h>
 
 #include "pseries.h"
@@ -57,7 +35,6 @@ static DEFINE_SPINLOCK(ras_log_buf_lock);
 static char global_mce_data_buf[RTAS_ERROR_LOG_MAX];
 static DEFINE_PER_CPU(__u64, mce_data_buf);
 
-static int ras_get_sensor_state_token;
 static int ras_check_exception_token;
 
 #define EPOW_SENSOR_TOKEN      9
@@ -75,7 +52,6 @@ static int __init init_ras_IRQ(void)
 {
        struct device_node *np;
 
-       ras_get_sensor_state_token = rtas_token("get-sensor-state");
        ras_check_exception_token = rtas_token("check-exception");
 
        /* Internal Errors */
@@ -95,26 +71,126 @@ static int __init init_ras_IRQ(void)
 
        return 0;
 }
-__initcall(init_ras_IRQ);
+subsys_initcall(init_ras_IRQ);
 
-/*
- * Handle power subsystem events (EPOW).
- *
- * Presently we just log the event has occurred.  This should be fixed
- * to examine the type of power failure and take appropriate action where
- * the time horizon permits something useful to be done.
- */
+#define EPOW_SHUTDOWN_NORMAL                           1
+#define EPOW_SHUTDOWN_ON_UPS                           2
+#define EPOW_SHUTDOWN_LOSS_OF_CRITICAL_FUNCTIONS       3
+#define EPOW_SHUTDOWN_AMBIENT_TEMPERATURE_TOO_HIGH     4
+
+static void handle_system_shutdown(char event_modifier)
+{
+       switch (event_modifier) {
+       case EPOW_SHUTDOWN_NORMAL:
+               pr_emerg("Firmware initiated power off");
+               orderly_poweroff(1);
+               break;
+
+       case EPOW_SHUTDOWN_ON_UPS:
+               pr_emerg("Loss of power reported by firmware, system is "
+                       "running on UPS/battery");
+               break;
+
+       case EPOW_SHUTDOWN_LOSS_OF_CRITICAL_FUNCTIONS:
+               pr_emerg("Loss of system critical functions reported by "
+                       "firmware");
+               pr_emerg("Check RTAS error log for details");
+               orderly_poweroff(1);
+               break;
+
+       case EPOW_SHUTDOWN_AMBIENT_TEMPERATURE_TOO_HIGH:
+               pr_emerg("Ambient temperature too high reported by firmware");
+               pr_emerg("Check RTAS error log for details");
+               orderly_poweroff(1);
+               break;
+
+       default:
+               pr_err("Unknown power/cooling shutdown event (modifier %d)",
+                       event_modifier);
+       }
+}
+
+struct epow_errorlog {
+       unsigned char sensor_value;
+       unsigned char event_modifier;
+       unsigned char extended_modifier;
+       unsigned char reserved;
+       unsigned char platform_reason;
+};
+
+#define EPOW_RESET                     0
+#define EPOW_WARN_COOLING              1
+#define EPOW_WARN_POWER                        2
+#define EPOW_SYSTEM_SHUTDOWN           3
+#define EPOW_SYSTEM_HALT               4
+#define EPOW_MAIN_ENCLOSURE            5
+#define EPOW_POWER_OFF                 7
+
+void rtas_parse_epow_errlog(struct rtas_error_log *log)
+{
+       struct pseries_errorlog *pseries_log;
+       struct epow_errorlog *epow_log;
+       char action_code;
+       char modifier;
+
+       pseries_log = get_pseries_errorlog(log, PSERIES_ELOG_SECT_ID_EPOW);
+       if (pseries_log == NULL)
+               return;
+
+       epow_log = (struct epow_errorlog *)pseries_log->data;
+       action_code = epow_log->sensor_value & 0xF;     /* bottom 4 bits */
+       modifier = epow_log->event_modifier & 0xF;      /* bottom 4 bits */
+
+       switch (action_code) {
+       case EPOW_RESET:
+               pr_err("Non critical power or cooling issue cleared");
+               break;
+
+       case EPOW_WARN_COOLING:
+               pr_err("Non critical cooling issue reported by firmware");
+               pr_err("Check RTAS error log for details");
+               break;
+
+       case EPOW_WARN_POWER:
+               pr_err("Non critical power issue reported by firmware");
+               pr_err("Check RTAS error log for details");
+               break;
+
+       case EPOW_SYSTEM_SHUTDOWN:
+               handle_system_shutdown(epow_log->event_modifier);
+               break;
+
+       case EPOW_SYSTEM_HALT:
+               pr_emerg("Firmware initiated power off");
+               orderly_poweroff(1);
+               break;
+
+       case EPOW_MAIN_ENCLOSURE:
+       case EPOW_POWER_OFF:
+               pr_emerg("Critical power/cooling issue reported by firmware");
+               pr_emerg("Check RTAS error log for details");
+               pr_emerg("Immediate power off");
+               emergency_sync();
+               kernel_power_off();
+               break;
+
+       default:
+               pr_err("Unknown power/cooling event (action code %d)",
+                       action_code);
+       }
+}
+
+/* Handle environmental and power warning (EPOW) interrupts. */
 static irqreturn_t ras_epow_interrupt(int irq, void *dev_id)
 {
-       int status = 0xdeadbeef;
-       int state = 0;
+       int status;
+       int state;
        int critical;
 
-       status = rtas_call(ras_get_sensor_state_token, 2, 2, &state,
-                          EPOW_SENSOR_TOKEN, EPOW_SENSOR_INDEX);
+       status = rtas_get_sensor(EPOW_SENSOR_TOKEN, EPOW_SENSOR_INDEX, &state);
 
        if (state > 3)
-               critical = 1;  /* Time Critical */
+               critical = 1;           /* Time Critical */
        else
                critical = 0;
 
@@ -123,18 +199,14 @@ static irqreturn_t ras_epow_interrupt(int irq, void *dev_id)
        status = rtas_call(ras_check_exception_token, 6, 1, NULL,
                           RTAS_VECTOR_EXTERNAL_INTERRUPT,
                           virq_to_hw(irq),
-                          RTAS_EPOW_WARNING | RTAS_POWERMGM_EVENTS,
+                          RTAS_EPOW_WARNING,
                           critical, __pa(&ras_log_buf),
                                rtas_get_error_log_max());
 
-       udbg_printf("EPOW <0x%lx 0x%x 0x%x>\n",
-                   *((unsigned long *)&ras_log_buf), status, state);
-       printk(KERN_WARNING "EPOW <0x%lx 0x%x 0x%x>\n",
-              *((unsigned long *)&ras_log_buf), status, state);
-
-       /* format and print the extended information */
        log_error(ras_log_buf, ERR_TYPE_RTAS_LOG, 0);
 
+       rtas_parse_epow_errlog((struct rtas_error_log *)ras_log_buf);
+
        spin_unlock(&ras_log_buf_lock);
        return IRQ_HANDLED;
 }
@@ -150,7 +222,7 @@ static irqreturn_t ras_epow_interrupt(int irq, void *dev_id)
 static irqreturn_t ras_error_interrupt(int irq, void *dev_id)
 {
        struct rtas_error_log *rtas_elog;
-       int status = 0xdeadbeef;
+       int status;
        int fatal;
 
        spin_lock(&ras_log_buf_lock);
@@ -158,7 +230,7 @@ static irqreturn_t ras_error_interrupt(int irq, void *dev_id)
        status = rtas_call(ras_check_exception_token, 6, 1, NULL,
                           RTAS_VECTOR_EXTERNAL_INTERRUPT,
                           virq_to_hw(irq),
-                          RTAS_INTERNAL_ERROR, 1 /*Time Critical */,
+                          RTAS_INTERNAL_ERROR, 1 /* Time Critical */,
                           __pa(&ras_log_buf),
                                rtas_get_error_log_max());
 
@@ -173,24 +245,13 @@ static irqreturn_t ras_error_interrupt(int irq, void *dev_id)
        log_error(ras_log_buf, ERR_TYPE_RTAS_LOG, fatal);
 
        if (fatal) {
-               udbg_printf("Fatal HW Error <0x%lx 0x%x>\n",
-                           *((unsigned long *)&ras_log_buf), status);
-               printk(KERN_EMERG "Error: Fatal hardware error <0x%lx 0x%x>\n",
-                      *((unsigned long *)&ras_log_buf), status);
-
-#ifndef DEBUG_RTAS_POWER_OFF
-               /* Don't actually power off when debugging so we can test
-                * without actually failing while injecting errors.
-                * Error data will not be logged to syslog.
-                */
-               ppc_md.power_off();
-#endif
+               pr_emerg("Fatal hardware error reported by firmware");
+               pr_emerg("Check RTAS error log for details");
+               pr_emerg("Immediate power off");
+               emergency_sync();
+               kernel_power_off();
        } else {
-               udbg_printf("Recoverable HW Error <0x%lx 0x%x>\n",
-                           *((unsigned long *)&ras_log_buf), status);
-               printk(KERN_WARNING
-                      "Warning: Recoverable hardware error <0x%lx 0x%x>\n",
-                      *((unsigned long *)&ras_log_buf), status);
+               pr_err("Recoverable hardware error reported by firmware");
        }
 
        spin_unlock(&ras_log_buf_lock);
index eadba95..e16bb8d 100644 (file)
@@ -37,7 +37,6 @@
 #include <asm/machdep.h>
 #include <asm/cputable.h>
 #include <asm/firmware.h>
-#include <asm/system.h>
 #include <asm/rtas.h>
 #include <asm/pSeries_reconfig.h>
 #include <asm/mpic.h>
index ca6fa26..8ef53bc 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/time.h>
 
 #include <asm/machdep.h>
-#include <asm/system.h>
 #include <asm/udbg.h>
 
 #include "ics.h"
index 0c1ae06..508ec82 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/time.h>
 
 #include <asm/machdep.h>
-#include <asm/system.h>
 #include <asm/udbg.h>
 
 #include "ics.h"
index 763014c..1526551 100644 (file)
@@ -27,6 +27,7 @@
 #include <asm/ppc-pci.h>
 #include <asm/iommu.h>
 #include <asm/io-workarounds.h>
+#include <asm/debug.h>
 
 #include "wsp.h"
 #include "wsp_pci.h"
index bf6c7cc..4dd5341 100644 (file)
@@ -26,7 +26,6 @@
 
 #include <asm/udbg.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/rheap.h>
 #include <asm/cpm.h>
 
index e8f385f..c449dbd 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/fs_enet_pd.h>
 #include <linux/fs_uart_pd.h>
 
-#include <asm/system.h>
 #include <linux/atomic.h>
 #include <asm/io.h>
 #include <asm/irq.h>
index 5287e95..0968b66 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/kernel.h>
 #include <linux/bitmap.h>
 #include <asm/msi_bitmap.h>
+#include <asm/setup.h>
 
 int msi_bitmap_alloc_hwirqs(struct msi_bitmap *bmp, int num)
 {
index 2370e1c..1fd0717 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/of_net.h>
 #include <asm/tsi108.h>
 
-#include <asm/system.h>
 #include <linux/atomic.h>
 #include <asm/io.h>
 #include <asm/irq.h>
index 68a9cbb..0f3ab06 100644 (file)
@@ -41,6 +41,7 @@
 #include <asm/spu_priv1.h>
 #include <asm/setjmp.h>
 #include <asm/reg.h>
+#include <asm/debug.h>
 
 #ifdef CONFIG_PPC64
 #include <asm/hvcall.h>
index ffd1ac2..9178db6 100644 (file)
@@ -17,6 +17,7 @@
 #define _CRYPTO_ARCH_S390_CRYPT_S390_H
 
 #include <asm/errno.h>
+#include <asm/facility.h>
 
 #define CRYPT_S390_OP_MASK 0xFF00
 #define CRYPT_S390_FUNC_MASK 0x00FF
index 8517d2a..748347b 100644 (file)
@@ -15,7 +15,7 @@
 
 #include <linux/compiler.h>
 #include <linux/types.h>
-#include <asm/system.h>
+#include <asm/cmpxchg.h>
 
 #define ATOMIC_INIT(i)  { (i) }
 
diff --git a/arch/s390/include/asm/barrier.h b/arch/s390/include/asm/barrier.h
new file mode 100644 (file)
index 0000000..451273a
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright IBM Corp. 1999, 2009
+ *
+ * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
+ */
+
+#ifndef __ASM_BARRIER_H
+#define __ASM_BARRIER_H
+
+/*
+ * Force strict CPU ordering.
+ * And yes, this is required on UP too when we're talking
+ * to devices.
+ *
+ * This is very similar to the ppc eieio/sync instruction in that is
+ * does a checkpoint syncronisation & makes sure that 
+ * all memory ops have completed wrt other CPU's ( see 7-15 POP  DJB ).
+ */
+
+#define eieio()        asm volatile("bcr 15,0" : : : "memory")
+#define SYNC_OTHER_CORES(x)   eieio()
+#define mb()    eieio()
+#define rmb()   eieio()
+#define wmb()   eieio()
+#define read_barrier_depends() do { } while(0)
+#define smp_mb()       mb()
+#define smp_rmb()      rmb()
+#define smp_wmb()      wmb()
+#define smp_read_barrier_depends()    read_barrier_depends()
+#define smp_mb__before_clear_bit()     smp_mb()
+#define smp_mb__after_clear_bit()      smp_mb()
+
+#define set_mb(var, value)      do { var = value; mb(); } while (0)
+
+#endif /* __ASM_BARRIER_H */
diff --git a/arch/s390/include/asm/ctl_reg.h b/arch/s390/include/asm/ctl_reg.h
new file mode 100644 (file)
index 0000000..ecde941
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright IBM Corp. 1999, 2009
+ *
+ * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
+ */
+
+#ifndef __ASM_CTL_REG_H
+#define __ASM_CTL_REG_H
+
+#ifdef __s390x__
+
+#define __ctl_load(array, low, high) ({                                \
+       typedef struct { char _[sizeof(array)]; } addrtype;     \
+       asm volatile(                                           \
+               "       lctlg   %1,%2,%0\n"                     \
+               : : "Q" (*(addrtype *)(&array)),                \
+                   "i" (low), "i" (high));                     \
+       })
+
+#define __ctl_store(array, low, high) ({                       \
+       typedef struct { char _[sizeof(array)]; } addrtype;     \
+       asm volatile(                                           \
+               "       stctg   %1,%2,%0\n"                     \
+               : "=Q" (*(addrtype *)(&array))                  \
+               : "i" (low), "i" (high));                       \
+       })
+
+#else /* __s390x__ */
+
+#define __ctl_load(array, low, high) ({                                \
+       typedef struct { char _[sizeof(array)]; } addrtype;     \
+       asm volatile(                                           \
+               "       lctl    %1,%2,%0\n"                     \
+               : : "Q" (*(addrtype *)(&array)),                \
+                   "i" (low), "i" (high));                     \
+})
+
+#define __ctl_store(array, low, high) ({                       \
+       typedef struct { char _[sizeof(array)]; } addrtype;     \
+       asm volatile(                                           \
+               "       stctl   %1,%2,%0\n"                     \
+               : "=Q" (*(addrtype *)(&array))                  \
+               : "i" (low), "i" (high));                       \
+       })
+
+#endif /* __s390x__ */
+
+#define __ctl_set_bit(cr, bit) ({      \
+       unsigned long __dummy;          \
+       __ctl_store(__dummy, cr, cr);   \
+       __dummy |= 1UL << (bit);        \
+       __ctl_load(__dummy, cr, cr);    \
+})
+
+#define __ctl_clear_bit(cr, bit) ({    \
+       unsigned long __dummy;          \
+       __ctl_store(__dummy, cr, cr);   \
+       __dummy &= ~(1UL << (bit));     \
+       __ctl_load(__dummy, cr, cr);    \
+})
+
+#ifdef CONFIG_SMP
+
+extern void smp_ctl_set_bit(int cr, int bit);
+extern void smp_ctl_clear_bit(int cr, int bit);
+#define ctl_set_bit(cr, bit) smp_ctl_set_bit(cr, bit)
+#define ctl_clear_bit(cr, bit) smp_ctl_clear_bit(cr, bit)
+
+#else
+
+#define ctl_set_bit(cr, bit) __ctl_set_bit(cr, bit)
+#define ctl_clear_bit(cr, bit) __ctl_clear_bit(cr, bit)
+
+#endif /* CONFIG_SMP */
+
+#endif /* __ASM_CTL_REG_H */
index 547f1a6..c4ee39f 100644 (file)
@@ -129,7 +129,6 @@ typedef s390_fp_regs compat_elf_fpregset_t;
 typedef s390_compat_regs compat_elf_gregset_t;
 
 #include <linux/sched.h>       /* for task_struct */
-#include <asm/system.h>                /* for save_access_regs */
 #include <asm/mmu_context.h>
 
 #include <asm/vdso.h>
diff --git a/arch/s390/include/asm/exec.h b/arch/s390/include/asm/exec.h
new file mode 100644 (file)
index 0000000..c4a93d6
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * Copyright IBM Corp. 1999, 2009
+ *
+ * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
+ */
+
+#ifndef __ASM_EXEC_H
+#define __ASM_EXEC_H
+
+extern unsigned long arch_align_stack(unsigned long sp);
+
+#endif /* __ASM_EXEC_H */
diff --git a/arch/s390/include/asm/facility.h b/arch/s390/include/asm/facility.h
new file mode 100644 (file)
index 0000000..1e5b27e
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright IBM Corp. 1999, 2009
+ *
+ * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
+ */
+
+#ifndef __ASM_FACILITY_H
+#define __ASM_FACILITY_H
+
+#include <linux/string.h>
+#include <linux/preempt.h>
+#include <asm/lowcore.h>
+
+#define MAX_FACILITY_BIT (256*8)       /* stfle_fac_list has 256 bytes */
+
+/*
+ * The test_facility function uses the bit odering where the MSB is bit 0.
+ * That makes it easier to query facility bits with the bit number as
+ * documented in the Principles of Operation.
+ */
+static inline int test_facility(unsigned long nr)
+{
+       unsigned char *ptr;
+
+       if (nr >= MAX_FACILITY_BIT)
+               return 0;
+       ptr = (unsigned char *) &S390_lowcore.stfle_fac_list + (nr >> 3);
+       return (*ptr & (0x80 >> (nr & 7))) != 0;
+}
+
+/**
+ * stfle - Store facility list extended
+ * @stfle_fac_list: array where facility list can be stored
+ * @size: size of passed in array in double words
+ */
+static inline void stfle(u64 *stfle_fac_list, int size)
+{
+       unsigned long nr;
+
+       preempt_disable();
+       S390_lowcore.stfl_fac_list = 0;
+       asm volatile(
+               "       .insn s,0xb2b10000,0(0)\n" /* stfl */
+               "0:\n"
+               EX_TABLE(0b, 0b)
+               : "=m" (S390_lowcore.stfl_fac_list));
+       nr = 4; /* bytes stored by stfl */
+       memcpy(stfle_fac_list, &S390_lowcore.stfl_fac_list, 4);
+       if (S390_lowcore.stfl_fac_list & 0x01000000) {
+               /* More facility bits available with stfle */
+               register unsigned long reg0 asm("0") = size - 1;
+
+               asm volatile(".insn s,0xb2b00000,0(%1)" /* stfle */
+                            : "+d" (reg0)
+                            : "a" (stfle_fac_list)
+                            : "memory", "cc");
+               nr = (reg0 + 1) * 8; /* # bytes stored by stfle */
+       }
+       memset((char *) stfle_fac_list + nr, 0, size * 8 - nr);
+       preempt_enable();
+}
+
+#endif /* __ASM_FACILITY_H */
index 82b32a1..9607667 100644 (file)
@@ -41,4 +41,15 @@ struct kvm_debug_exit_arch {
 struct kvm_guest_debug_arch {
 };
 
+#define KVM_SYNC_PREFIX (1UL << 0)
+#define KVM_SYNC_GPRS   (1UL << 1)
+#define KVM_SYNC_ACRS   (1UL << 2)
+#define KVM_SYNC_CRS    (1UL << 3)
+/* definition of registers in kvm_run */
+struct kvm_sync_regs {
+       __u64 prefix;   /* prefix register */
+       __u64 gprs[16]; /* general purpose registers */
+       __u32 acrs[16]; /* access registers */
+       __u64 crs[16];  /* control registers */
+};
 #endif
index b0c235c..7343872 100644 (file)
@@ -220,18 +220,17 @@ struct kvm_s390_float_interrupt {
        struct list_head list;
        atomic_t active;
        int next_rr_cpu;
-       unsigned long idle_mask [(64 + sizeof(long) - 1) / sizeof(long)];
-       struct kvm_s390_local_interrupt *local_int[64];
+       unsigned long idle_mask[(KVM_MAX_VCPUS + sizeof(long) - 1)
+                               / sizeof(long)];
+       struct kvm_s390_local_interrupt *local_int[KVM_MAX_VCPUS];
 };
 
 
 struct kvm_vcpu_arch {
        struct kvm_s390_sie_block *sie_block;
-       unsigned long     guest_gprs[16];
        s390_fp_regs      host_fpregs;
        unsigned int      host_acrs[NUM_ACRS];
        s390_fp_regs      guest_fpregs;
-       unsigned int      guest_acrs[NUM_ACRS];
        struct kvm_s390_local_interrupt local_int;
        struct hrtimer    ckc_timer;
        struct tasklet_struct tasklet;
@@ -246,6 +245,9 @@ struct kvm_vm_stat {
        u32 remote_tlb_flush;
 };
 
+struct kvm_arch_memory_slot {
+};
+
 struct kvm_arch{
        struct sca_block *sca;
        debug_info_t *dbf;
@@ -253,5 +255,5 @@ struct kvm_arch{
        struct gmap *gmap;
 };
 
-extern int sie64a(struct kvm_s390_sie_block *, unsigned long *);
+extern int sie64a(struct kvm_s390_sie_block *, u64 *);
 #endif
index 4506791..1c7d6ce 100644 (file)
@@ -21,4 +21,18 @@ typedef struct {
        .context.pgtable_list = LIST_HEAD_INIT(name.context.pgtable_list),    \
        .context.gmap_list = LIST_HEAD_INIT(name.context.gmap_list),
 
+static inline int tprot(unsigned long addr)
+{
+       int rc = -EFAULT;
+
+       asm volatile(
+               "       tprot   0(%1),0\n"
+               "0:     ipm     %0\n"
+               "       srl     %0,28\n"
+               "1:\n"
+               EX_TABLE(0b,1b)
+               : "+d" (rc) : "a" (addr) : "cc");
+       return rc;
+}
+
 #endif
index 5682f16..5d09e40 100644 (file)
@@ -12,6 +12,7 @@
 #include <asm/pgalloc.h>
 #include <asm/uaccess.h>
 #include <asm/tlbflush.h>
+#include <asm/ctl_reg.h>
 #include <asm-generic/mm_hooks.h>
 
 static inline int init_new_context(struct task_struct *tsk,
index d25843a..d499b30 100644 (file)
@@ -14,6 +14,7 @@
 #define __ASM_S390_PROCESSOR_H
 
 #include <linux/linkage.h>
+#include <linux/irqflags.h>
 #include <asm/cpu.h>
 #include <asm/page.h>
 #include <asm/ptrace.h>
@@ -156,6 +157,14 @@ unsigned long get_wchan(struct task_struct *p);
 #define KSTK_EIP(tsk)  (task_pt_regs(tsk)->psw.addr)
 #define KSTK_ESP(tsk)  (task_pt_regs(tsk)->gprs[15])
 
+static inline unsigned short stap(void)
+{
+       unsigned short cpu_address;
+
+       asm volatile("stap %0" : "=m" (cpu_address));
+       return cpu_address;
+}
+
 /*
  * Give up the time slice of the virtual PU.
  */
@@ -304,6 +313,21 @@ static inline void __noreturn disabled_wait(unsigned long code)
 }
 
 /*
+ * Use to set psw mask except for the first byte which
+ * won't be changed by this function.
+ */
+static inline void
+__set_psw_mask(unsigned long mask)
+{
+       __load_psw_mask(mask | (arch_local_save_flags() & ~(-1UL >> 8)));
+}
+
+#define local_mcck_enable() \
+       __set_psw_mask(psw_kernel_bits | PSW_MASK_DAT | PSW_MASK_MCHECK)
+#define local_mcck_disable() \
+       __set_psw_mask(psw_kernel_bits | PSW_MASK_DAT)
+
+/*
  * Basic Machine Check/Program Check Handler.
  */
 
index 097183c..b21e46e 100644 (file)
@@ -140,6 +140,20 @@ extern char vmpoff_cmd[];
 #define NSS_NAME_SIZE  8
 extern char kernel_nss_name[];
 
+#ifdef CONFIG_PFAULT
+extern int pfault_init(void);
+extern void pfault_fini(void);
+#else /* CONFIG_PFAULT */
+#define pfault_init()          ({-1;})
+#define pfault_fini()          do { } while (0)
+#endif /* CONFIG_PFAULT */
+
+extern void cmma_init(void);
+
+extern void (*_machine_restart)(char *command);
+extern void (*_machine_halt)(void);
+extern void (*_machine_power_off)(void);
+
 #else /* __ASSEMBLY__ */
 
 #ifndef __s390x__
index 797f787..c77c6de 100644 (file)
@@ -9,7 +9,7 @@
 
 #ifdef CONFIG_SMP
 
-#include <asm/system.h>
+#include <asm/lowcore.h>
 
 #define raw_smp_processor_id() (S390_lowcore.cpu_nr)
 
diff --git a/arch/s390/include/asm/switch_to.h b/arch/s390/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..f223068
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright IBM Corp. 1999, 2009
+ *
+ * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
+ */
+
+#ifndef __ASM_SWITCH_TO_H
+#define __ASM_SWITCH_TO_H
+
+#include <linux/thread_info.h>
+
+extern struct task_struct *__switch_to(void *, void *);
+extern void update_per_regs(struct task_struct *task);
+
+static inline void save_fp_regs(s390_fp_regs *fpregs)
+{
+       asm volatile(
+               "       std     0,%O0+8(%R0)\n"
+               "       std     2,%O0+24(%R0)\n"
+               "       std     4,%O0+40(%R0)\n"
+               "       std     6,%O0+56(%R0)"
+               : "=Q" (*fpregs) : "Q" (*fpregs));
+       if (!MACHINE_HAS_IEEE)
+               return;
+       asm volatile(
+               "       stfpc   %0\n"
+               "       std     1,%O0+16(%R0)\n"
+               "       std     3,%O0+32(%R0)\n"
+               "       std     5,%O0+48(%R0)\n"
+               "       std     7,%O0+64(%R0)\n"
+               "       std     8,%O0+72(%R0)\n"
+               "       std     9,%O0+80(%R0)\n"
+               "       std     10,%O0+88(%R0)\n"
+               "       std     11,%O0+96(%R0)\n"
+               "       std     12,%O0+104(%R0)\n"
+               "       std     13,%O0+112(%R0)\n"
+               "       std     14,%O0+120(%R0)\n"
+               "       std     15,%O0+128(%R0)\n"
+               : "=Q" (*fpregs) : "Q" (*fpregs));
+}
+
+static inline void restore_fp_regs(s390_fp_regs *fpregs)
+{
+       asm volatile(
+               "       ld      0,%O0+8(%R0)\n"
+               "       ld      2,%O0+24(%R0)\n"
+               "       ld      4,%O0+40(%R0)\n"
+               "       ld      6,%O0+56(%R0)"
+               : : "Q" (*fpregs));
+       if (!MACHINE_HAS_IEEE)
+               return;
+       asm volatile(
+               "       lfpc    %0\n"
+               "       ld      1,%O0+16(%R0)\n"
+               "       ld      3,%O0+32(%R0)\n"
+               "       ld      5,%O0+48(%R0)\n"
+               "       ld      7,%O0+64(%R0)\n"
+               "       ld      8,%O0+72(%R0)\n"
+               "       ld      9,%O0+80(%R0)\n"
+               "       ld      10,%O0+88(%R0)\n"
+               "       ld      11,%O0+96(%R0)\n"
+               "       ld      12,%O0+104(%R0)\n"
+               "       ld      13,%O0+112(%R0)\n"
+               "       ld      14,%O0+120(%R0)\n"
+               "       ld      15,%O0+128(%R0)\n"
+               : : "Q" (*fpregs));
+}
+
+static inline void save_access_regs(unsigned int *acrs)
+{
+       asm volatile("stam 0,15,%0" : "=Q" (*acrs));
+}
+
+static inline void restore_access_regs(unsigned int *acrs)
+{
+       asm volatile("lam 0,15,%0" : : "Q" (*acrs));
+}
+
+#define switch_to(prev,next,last) do {                                 \
+       if (prev->mm) {                                                 \
+               save_fp_regs(&prev->thread.fp_regs);                    \
+               save_access_regs(&prev->thread.acrs[0]);                \
+       }                                                               \
+       if (next->mm) {                                                 \
+               restore_fp_regs(&next->thread.fp_regs);                 \
+               restore_access_regs(&next->thread.acrs[0]);             \
+               update_per_regs(next);                                  \
+       }                                                               \
+       prev = __switch_to(prev,next);                                  \
+} while (0)
+
+extern void account_vtime(struct task_struct *, struct task_struct *);
+extern void account_tick_vtime(struct task_struct *);
+
+#define finish_arch_switch(prev) do {                                       \
+       set_fs(current->thread.mm_segment);                                  \
+       account_vtime(prev, current);                                        \
+} while (0)
+
+#endif /* __ASM_SWITCH_TO_H */
diff --git a/arch/s390/include/asm/system.h b/arch/s390/include/asm/system.h
deleted file mode 100644 (file)
index 2e0bb7f..0000000
+++ /dev/null
@@ -1,315 +0,0 @@
-/*
- * Copyright IBM Corp. 1999, 2009
- *
- * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
- */
-
-#ifndef __ASM_SYSTEM_H
-#define __ASM_SYSTEM_H
-
-#include <linux/preempt.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <asm/types.h>
-#include <asm/ptrace.h>
-#include <asm/setup.h>
-#include <asm/processor.h>
-#include <asm/lowcore.h>
-#include <asm/cmpxchg.h>
-
-#ifdef __KERNEL__
-
-struct task_struct;
-
-extern struct task_struct *__switch_to(void *, void *);
-extern void update_per_regs(struct task_struct *task);
-
-static inline void save_fp_regs(s390_fp_regs *fpregs)
-{
-       asm volatile(
-               "       std     0,%O0+8(%R0)\n"
-               "       std     2,%O0+24(%R0)\n"
-               "       std     4,%O0+40(%R0)\n"
-               "       std     6,%O0+56(%R0)"
-               : "=Q" (*fpregs) : "Q" (*fpregs));
-       if (!MACHINE_HAS_IEEE)
-               return;
-       asm volatile(
-               "       stfpc   %0\n"
-               "       std     1,%O0+16(%R0)\n"
-               "       std     3,%O0+32(%R0)\n"
-               "       std     5,%O0+48(%R0)\n"
-               "       std     7,%O0+64(%R0)\n"
-               "       std     8,%O0+72(%R0)\n"
-               "       std     9,%O0+80(%R0)\n"
-               "       std     10,%O0+88(%R0)\n"
-               "       std     11,%O0+96(%R0)\n"
-               "       std     12,%O0+104(%R0)\n"
-               "       std     13,%O0+112(%R0)\n"
-               "       std     14,%O0+120(%R0)\n"
-               "       std     15,%O0+128(%R0)\n"
-               : "=Q" (*fpregs) : "Q" (*fpregs));
-}
-
-static inline void restore_fp_regs(s390_fp_regs *fpregs)
-{
-       asm volatile(
-               "       ld      0,%O0+8(%R0)\n"
-               "       ld      2,%O0+24(%R0)\n"
-               "       ld      4,%O0+40(%R0)\n"
-               "       ld      6,%O0+56(%R0)"
-               : : "Q" (*fpregs));
-       if (!MACHINE_HAS_IEEE)
-               return;
-       asm volatile(
-               "       lfpc    %0\n"
-               "       ld      1,%O0+16(%R0)\n"
-               "       ld      3,%O0+32(%R0)\n"
-               "       ld      5,%O0+48(%R0)\n"
-               "       ld      7,%O0+64(%R0)\n"
-               "       ld      8,%O0+72(%R0)\n"
-               "       ld      9,%O0+80(%R0)\n"
-               "       ld      10,%O0+88(%R0)\n"
-               "       ld      11,%O0+96(%R0)\n"
-               "       ld      12,%O0+104(%R0)\n"
-               "       ld      13,%O0+112(%R0)\n"
-               "       ld      14,%O0+120(%R0)\n"
-               "       ld      15,%O0+128(%R0)\n"
-               : : "Q" (*fpregs));
-}
-
-static inline void save_access_regs(unsigned int *acrs)
-{
-       asm volatile("stam 0,15,%0" : "=Q" (*acrs));
-}
-
-static inline void restore_access_regs(unsigned int *acrs)
-{
-       asm volatile("lam 0,15,%0" : : "Q" (*acrs));
-}
-
-#define switch_to(prev,next,last) do {                                 \
-       if (prev->mm) {                                                 \
-               save_fp_regs(&prev->thread.fp_regs);                    \
-               save_access_regs(&prev->thread.acrs[0]);                \
-       }                                                               \
-       if (next->mm) {                                                 \
-               restore_fp_regs(&next->thread.fp_regs);                 \
-               restore_access_regs(&next->thread.acrs[0]);             \
-               update_per_regs(next);                                  \
-       }                                                               \
-       prev = __switch_to(prev,next);                                  \
-} while (0)
-
-extern void account_vtime(struct task_struct *, struct task_struct *);
-extern void account_tick_vtime(struct task_struct *);
-
-#ifdef CONFIG_PFAULT
-extern int pfault_init(void);
-extern void pfault_fini(void);
-#else /* CONFIG_PFAULT */
-#define pfault_init()          ({-1;})
-#define pfault_fini()          do { } while (0)
-#endif /* CONFIG_PFAULT */
-
-extern void cmma_init(void);
-extern int memcpy_real(void *, void *, size_t);
-extern void copy_to_absolute_zero(void *dest, void *src, size_t count);
-extern int copy_to_user_real(void __user *dest, void *src, size_t count);
-extern int copy_from_user_real(void *dest, void __user *src, size_t count);
-
-#define finish_arch_switch(prev) do {                                       \
-       set_fs(current->thread.mm_segment);                                  \
-       account_vtime(prev, current);                                        \
-} while (0)
-
-#define nop() asm volatile("nop")
-
-/*
- * Force strict CPU ordering.
- * And yes, this is required on UP too when we're talking
- * to devices.
- *
- * This is very similar to the ppc eieio/sync instruction in that is
- * does a checkpoint syncronisation & makes sure that 
- * all memory ops have completed wrt other CPU's ( see 7-15 POP  DJB ).
- */
-
-#define eieio()        asm volatile("bcr 15,0" : : : "memory")
-#define SYNC_OTHER_CORES(x)   eieio()
-#define mb()    eieio()
-#define rmb()   eieio()
-#define wmb()   eieio()
-#define read_barrier_depends() do { } while(0)
-#define smp_mb()       mb()
-#define smp_rmb()      rmb()
-#define smp_wmb()      wmb()
-#define smp_read_barrier_depends()    read_barrier_depends()
-#define smp_mb__before_clear_bit()     smp_mb()
-#define smp_mb__after_clear_bit()      smp_mb()
-
-
-#define set_mb(var, value)      do { var = value; mb(); } while (0)
-
-#ifdef __s390x__
-
-#define __ctl_load(array, low, high) ({                                \
-       typedef struct { char _[sizeof(array)]; } addrtype;     \
-       asm volatile(                                           \
-               "       lctlg   %1,%2,%0\n"                     \
-               : : "Q" (*(addrtype *)(&array)),                \
-                   "i" (low), "i" (high));                     \
-       })
-
-#define __ctl_store(array, low, high) ({                       \
-       typedef struct { char _[sizeof(array)]; } addrtype;     \
-       asm volatile(                                           \
-               "       stctg   %1,%2,%0\n"                     \
-               : "=Q" (*(addrtype *)(&array))                  \
-               : "i" (low), "i" (high));                       \
-       })
-
-#else /* __s390x__ */
-
-#define __ctl_load(array, low, high) ({                                \
-       typedef struct { char _[sizeof(array)]; } addrtype;     \
-       asm volatile(                                           \
-               "       lctl    %1,%2,%0\n"                     \
-               : : "Q" (*(addrtype *)(&array)),                \
-                   "i" (low), "i" (high));                     \
-})
-
-#define __ctl_store(array, low, high) ({                       \
-       typedef struct { char _[sizeof(array)]; } addrtype;     \
-       asm volatile(                                           \
-               "       stctl   %1,%2,%0\n"                     \
-               : "=Q" (*(addrtype *)(&array))                  \
-               : "i" (low), "i" (high));                       \
-       })
-
-#endif /* __s390x__ */
-
-#define __ctl_set_bit(cr, bit) ({      \
-       unsigned long __dummy;          \
-       __ctl_store(__dummy, cr, cr);   \
-       __dummy |= 1UL << (bit);        \
-       __ctl_load(__dummy, cr, cr);    \
-})
-
-#define __ctl_clear_bit(cr, bit) ({    \
-       unsigned long __dummy;          \
-       __ctl_store(__dummy, cr, cr);   \
-       __dummy &= ~(1UL << (bit));     \
-       __ctl_load(__dummy, cr, cr);    \
-})
-
-/*
- * Use to set psw mask except for the first byte which
- * won't be changed by this function.
- */
-static inline void
-__set_psw_mask(unsigned long mask)
-{
-       __load_psw_mask(mask | (arch_local_save_flags() & ~(-1UL >> 8)));
-}
-
-#define local_mcck_enable() \
-       __set_psw_mask(psw_kernel_bits | PSW_MASK_DAT | PSW_MASK_MCHECK)
-#define local_mcck_disable() \
-       __set_psw_mask(psw_kernel_bits | PSW_MASK_DAT)
-
-#ifdef CONFIG_SMP
-
-extern void smp_ctl_set_bit(int cr, int bit);
-extern void smp_ctl_clear_bit(int cr, int bit);
-#define ctl_set_bit(cr, bit) smp_ctl_set_bit(cr, bit)
-#define ctl_clear_bit(cr, bit) smp_ctl_clear_bit(cr, bit)
-
-#else
-
-#define ctl_set_bit(cr, bit) __ctl_set_bit(cr, bit)
-#define ctl_clear_bit(cr, bit) __ctl_clear_bit(cr, bit)
-
-#endif /* CONFIG_SMP */
-
-#define MAX_FACILITY_BIT (256*8)       /* stfle_fac_list has 256 bytes */
-
-/*
- * The test_facility function uses the bit odering where the MSB is bit 0.
- * That makes it easier to query facility bits with the bit number as
- * documented in the Principles of Operation.
- */
-static inline int test_facility(unsigned long nr)
-{
-       unsigned char *ptr;
-
-       if (nr >= MAX_FACILITY_BIT)
-               return 0;
-       ptr = (unsigned char *) &S390_lowcore.stfle_fac_list + (nr >> 3);
-       return (*ptr & (0x80 >> (nr & 7))) != 0;
-}
-
-/**
- * stfle - Store facility list extended
- * @stfle_fac_list: array where facility list can be stored
- * @size: size of passed in array in double words
- */
-static inline void stfle(u64 *stfle_fac_list, int size)
-{
-       unsigned long nr;
-
-       preempt_disable();
-       S390_lowcore.stfl_fac_list = 0;
-       asm volatile(
-               "       .insn s,0xb2b10000,0(0)\n" /* stfl */
-               "0:\n"
-               EX_TABLE(0b, 0b)
-               : "=m" (S390_lowcore.stfl_fac_list));
-       nr = 4; /* bytes stored by stfl */
-       memcpy(stfle_fac_list, &S390_lowcore.stfl_fac_list, 4);
-       if (S390_lowcore.stfl_fac_list & 0x01000000) {
-               /* More facility bits available with stfle */
-               register unsigned long reg0 asm("0") = size - 1;
-
-               asm volatile(".insn s,0xb2b00000,0(%1)" /* stfle */
-                            : "+d" (reg0)
-                            : "a" (stfle_fac_list)
-                            : "memory", "cc");
-               nr = (reg0 + 1) * 8; /* # bytes stored by stfle */
-       }
-       memset((char *) stfle_fac_list + nr, 0, size * 8 - nr);
-       preempt_enable();
-}
-
-static inline unsigned short stap(void)
-{
-       unsigned short cpu_address;
-
-       asm volatile("stap %0" : "=m" (cpu_address));
-       return cpu_address;
-}
-
-extern void (*_machine_restart)(char *command);
-extern void (*_machine_halt)(void);
-extern void (*_machine_power_off)(void);
-
-extern unsigned long arch_align_stack(unsigned long sp);
-
-static inline int tprot(unsigned long addr)
-{
-       int rc = -EFAULT;
-
-       asm volatile(
-               "       tprot   0(%1),0\n"
-               "0:     ipm     %0\n"
-               "       srl     %0,28\n"
-               "1:\n"
-               EX_TABLE(0b,1b)
-               : "+d" (rc) : "a" (addr) : "cc");
-       return rc;
-}
-
-#endif /* __KERNEL__ */
-
-#endif
index 2b23885..8f2cada 100644 (file)
@@ -16,6 +16,7 @@
  */
 #include <linux/sched.h>
 #include <linux/errno.h>
+#include <asm/ctl_reg.h>
 
 #define VERIFY_READ     0
 #define VERIFY_WRITE    1
@@ -375,4 +376,9 @@ clear_user(void __user *to, unsigned long n)
        return n;
 }
 
+extern int memcpy_real(void *, void *, size_t);
+extern void copy_to_absolute_zero(void *dest, void *src, size_t count);
+extern int copy_to_user_real(void __user *dest, void *src, size_t count);
+extern int copy_from_user_real(void *dest, void __user *src, size_t count);
+
 #endif /* __S390_UACCESS_H */
index ed8c913..83e6edf 100644 (file)
@@ -12,7 +12,6 @@
 #include <asm/timer.h>
 #include <asm/vdso.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 
 /*
  * Make sure that the compiler is new enough. We want a compiler that
index 53a82c8..28040fd 100644 (file)
@@ -27,6 +27,7 @@
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
 #include <asm/lowcore.h>
+#include <asm/switch_to.h>
 #include "compat_linux.h"
 #include "compat_ptrace.h"
 #include "entry.h"
index 3e8b881..e3dd886 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/string.h>
 #include <asm/ebcdic.h>
 #include <asm/cpcmd.h>
-#include <asm/system.h>
 #include <asm/io.h>
 
 static DEFINE_SPINLOCK(cpcmd_lock);
index e2f8475..3221c6f 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/kprobes.h>
 #include <linux/kdebug.h>
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <linux/atomic.h>
index 578eb4e..9475e68 100644 (file)
@@ -29,7 +29,7 @@
 #include <asm/sysinfo.h>
 #include <asm/cpcmd.h>
 #include <asm/sclp.h>
-#include <asm/system.h>
+#include <asm/facility.h>
 #include "entry.h"
 
 /*
index 8431b92..ac39e7a 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/slab.h>
 #include <asm/sysinfo.h>
 #include <asm/ebcdic.h>
-#include <asm/system.h>
 #include <asm/debug.h>
 #include <asm/ipl.h>
 
index 0f8cdf1..bdad47d 100644 (file)
@@ -19,7 +19,6 @@
 #include <asm/setup.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
-#include <asm/system.h>
 #include <asm/smp.h>
 #include <asm/reset.h>
 #include <asm/ipl.h>
index bbe5226..e8d6c21 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/kernel.h>
 #include <asm/checksum.h>
 #include <asm/lowcore.h>
-#include <asm/system.h>
 #include <asm/os_info.h>
 
 /*
index 3732e4c..60055ce 100644 (file)
 #include <linux/kprobes.h>
 #include <linux/random.h>
 #include <linux/module.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/processor.h>
 #include <asm/irq.h>
 #include <asm/timer.h>
 #include <asm/nmi.h>
 #include <asm/smp.h>
+#include <asm/switch_to.h>
 #include "entry.h"
 
 asmlinkage void ret_from_fork(void) asm ("ret_from_fork");
index 61f9548..02f300f 100644 (file)
@@ -26,9 +26,9 @@
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
+#include <asm/switch_to.h>
 #include "entry.h"
 
 #ifdef CONFIG_COMPAT
index 38e7512..1581ea2 100644 (file)
@@ -50,7 +50,6 @@
 
 #include <asm/ipl.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/smp.h>
 #include <asm/mmu_context.h>
 #include <asm/cpcmd.h>
index f29f5ef..f7582b2 100644 (file)
@@ -30,6 +30,7 @@
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
 #include <asm/lowcore.h>
+#include <asm/switch_to.h>
 #include "entry.h"
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
index 47df775..aa1494d 100644 (file)
@@ -9,7 +9,7 @@
 #include <linux/pfn.h>
 #include <linux/suspend.h>
 #include <linux/mm.h>
-#include <asm/system.h>
+#include <asm/ctl_reg.h>
 
 /*
  * References to section boundaries
index cd6ebe1..77cdf42 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/kprobes.h>
 #include <linux/bug.h>
 #include <linux/utsname.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <linux/atomic.h>
index 9c80138..ea5590f 100644 (file)
 #include <linux/compat.h>
 #include <asm/asm-offsets.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/processor.h>
 #include <asm/mmu.h>
 #include <asm/mmu_context.h>
 #include <asm/sections.h>
 #include <asm/vdso.h>
+#include <asm/facility.h>
 
 #if defined(CONFIG_32BIT) || defined(CONFIG_COMPAT)
 extern char vdso32_start, vdso32_end;
index a216341..78eb984 100644 (file)
@@ -34,6 +34,15 @@ config KVM
 
          If unsure, say N.
 
+config KVM_S390_UCONTROL
+       bool "Userspace controlled virtual machines"
+       depends on KVM
+       ---help---
+         Allow CAP_SYS_ADMIN users to create KVM virtual machines that are
+         controlled by userspace.
+
+         If unsure, say N.
+
 # OK, it's a little counter-intuitive to do this, but it puts it neatly under
 # the virtualization menu.
 source drivers/vhost/Kconfig
index 8943e82..a353f0e 100644 (file)
@@ -20,8 +20,8 @@ static int diag_release_pages(struct kvm_vcpu *vcpu)
        unsigned long start, end;
        unsigned long prefix  = vcpu->arch.sie_block->prefix;
 
-       start = vcpu->arch.guest_gprs[(vcpu->arch.sie_block->ipa & 0xf0) >> 4];
-       end = vcpu->arch.guest_gprs[vcpu->arch.sie_block->ipa & 0xf] + 4096;
+       start = vcpu->run->s.regs.gprs[(vcpu->arch.sie_block->ipa & 0xf0) >> 4];
+       end = vcpu->run->s.regs.gprs[vcpu->arch.sie_block->ipa & 0xf] + 4096;
 
        if (start & ~PAGE_MASK || end & ~PAGE_MASK || start > end
            || start < 2 * PAGE_SIZE)
@@ -56,7 +56,7 @@ static int __diag_time_slice_end(struct kvm_vcpu *vcpu)
 static int __diag_ipl_functions(struct kvm_vcpu *vcpu)
 {
        unsigned int reg = vcpu->arch.sie_block->ipa & 0xf;
-       unsigned long subcode = vcpu->arch.guest_gprs[reg] & 0xffff;
+       unsigned long subcode = vcpu->run->s.regs.gprs[reg] & 0xffff;
 
        VCPU_EVENT(vcpu, 5, "diag ipl functions, subcode %lx", subcode);
        switch (subcode) {
index 0243454..3614565 100644 (file)
@@ -36,7 +36,7 @@ static int handle_lctlg(struct kvm_vcpu *vcpu)
 
        useraddr = disp2;
        if (base2)
-               useraddr += vcpu->arch.guest_gprs[base2];
+               useraddr += vcpu->run->s.regs.gprs[base2];
 
        if (useraddr & 7)
                return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
@@ -75,7 +75,7 @@ static int handle_lctl(struct kvm_vcpu *vcpu)
 
        useraddr = disp2;
        if (base2)
-               useraddr += vcpu->arch.guest_gprs[base2];
+               useraddr += vcpu->run->s.regs.gprs[base2];
 
        if (useraddr & 3)
                return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
@@ -133,13 +133,6 @@ static int handle_stop(struct kvm_vcpu *vcpu)
 
        vcpu->stat.exit_stop_request++;
        spin_lock_bh(&vcpu->arch.local_int.lock);
-       if (vcpu->arch.local_int.action_bits & ACTION_STORE_ON_STOP) {
-               vcpu->arch.local_int.action_bits &= ~ACTION_STORE_ON_STOP;
-               rc = kvm_s390_vcpu_store_status(vcpu,
-                                                 KVM_S390_STORE_STATUS_NOADDR);
-               if (rc >= 0)
-                       rc = -EOPNOTSUPP;
-       }
 
        if (vcpu->arch.local_int.action_bits & ACTION_RELOADVCPU_ON_STOP) {
                vcpu->arch.local_int.action_bits &= ~ACTION_RELOADVCPU_ON_STOP;
@@ -155,7 +148,18 @@ static int handle_stop(struct kvm_vcpu *vcpu)
                rc = -EOPNOTSUPP;
        }
 
-       spin_unlock_bh(&vcpu->arch.local_int.lock);
+       if (vcpu->arch.local_int.action_bits & ACTION_STORE_ON_STOP) {
+               vcpu->arch.local_int.action_bits &= ~ACTION_STORE_ON_STOP;
+               /* store status must be called unlocked. Since local_int.lock
+                * only protects local_int.* and not guest memory we can give
+                * up the lock here */
+               spin_unlock_bh(&vcpu->arch.local_int.lock);
+               rc = kvm_s390_vcpu_store_status(vcpu,
+                                               KVM_S390_STORE_STATUS_NOADDR);
+               if (rc >= 0)
+                       rc = -EOPNOTSUPP;
+       } else
+               spin_unlock_bh(&vcpu->arch.local_int.lock);
        return rc;
 }
 
index f0647ce..2d9f9a7 100644 (file)
@@ -236,8 +236,7 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
                VCPU_EVENT(vcpu, 4, "interrupt: set prefix to %x",
                           inti->prefix.address);
                vcpu->stat.deliver_prefix_signal++;
-               vcpu->arch.sie_block->prefix = inti->prefix.address;
-               vcpu->arch.sie_block->ihcpu = 0xffff;
+               kvm_s390_set_prefix(vcpu, inti->prefix.address);
                break;
 
        case KVM_S390_RESTART:
index d1c4457..217ce44 100644 (file)
@@ -27,7 +27,7 @@
 #include <asm/lowcore.h>
 #include <asm/pgtable.h>
 #include <asm/nmi.h>
-#include <asm/system.h>
+#include <asm/switch_to.h>
 #include "kvm-s390.h"
 #include "gaccess.h"
 
@@ -129,6 +129,10 @@ int kvm_dev_ioctl_check_extension(long ext)
        case KVM_CAP_S390_PSW:
        case KVM_CAP_S390_GMAP:
        case KVM_CAP_SYNC_MMU:
+#ifdef CONFIG_KVM_S390_UCONTROL
+       case KVM_CAP_S390_UCONTROL:
+#endif
+       case KVM_CAP_SYNC_REGS:
                r = 1;
                break;
        default:
@@ -171,11 +175,22 @@ long kvm_arch_vm_ioctl(struct file *filp,
        return r;
 }
 
-int kvm_arch_init_vm(struct kvm *kvm)
+int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
 {
        int rc;
        char debug_name[16];
 
+       rc = -EINVAL;
+#ifdef CONFIG_KVM_S390_UCONTROL
+       if (type & ~KVM_VM_S390_UCONTROL)
+               goto out_err;
+       if ((type & KVM_VM_S390_UCONTROL) && (!capable(CAP_SYS_ADMIN)))
+               goto out_err;
+#else
+       if (type)
+               goto out_err;
+#endif
+
        rc = s390_enable_sie();
        if (rc)
                goto out_err;
@@ -198,10 +213,13 @@ int kvm_arch_init_vm(struct kvm *kvm)
        debug_register_view(kvm->arch.dbf, &debug_sprintf_view);
        VM_EVENT(kvm, 3, "%s", "vm created");
 
-       kvm->arch.gmap = gmap_alloc(current->mm);
-       if (!kvm->arch.gmap)
-               goto out_nogmap;
-
+       if (type & KVM_VM_S390_UCONTROL) {
+               kvm->arch.gmap = NULL;
+       } else {
+               kvm->arch.gmap = gmap_alloc(current->mm);
+               if (!kvm->arch.gmap)
+                       goto out_nogmap;
+       }
        return 0;
 out_nogmap:
        debug_unregister(kvm->arch.dbf);
@@ -214,11 +232,18 @@ out_err:
 void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
 {
        VCPU_EVENT(vcpu, 3, "%s", "free cpu");
-       clear_bit(63 - vcpu->vcpu_id, (unsigned long *) &vcpu->kvm->arch.sca->mcn);
-       if (vcpu->kvm->arch.sca->cpu[vcpu->vcpu_id].sda ==
-               (__u64) vcpu->arch.sie_block)
-               vcpu->kvm->arch.sca->cpu[vcpu->vcpu_id].sda = 0;
+       if (!kvm_is_ucontrol(vcpu->kvm)) {
+               clear_bit(63 - vcpu->vcpu_id,
+                         (unsigned long *) &vcpu->kvm->arch.sca->mcn);
+               if (vcpu->kvm->arch.sca->cpu[vcpu->vcpu_id].sda ==
+                   (__u64) vcpu->arch.sie_block)
+                       vcpu->kvm->arch.sca->cpu[vcpu->vcpu_id].sda = 0;
+       }
        smp_mb();
+
+       if (kvm_is_ucontrol(vcpu->kvm))
+               gmap_free(vcpu->arch.gmap);
+
        free_page((unsigned long)(vcpu->arch.sie_block));
        kvm_vcpu_uninit(vcpu);
        kfree(vcpu);
@@ -249,13 +274,25 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
        kvm_free_vcpus(kvm);
        free_page((unsigned long)(kvm->arch.sca));
        debug_unregister(kvm->arch.dbf);
-       gmap_free(kvm->arch.gmap);
+       if (!kvm_is_ucontrol(kvm))
+               gmap_free(kvm->arch.gmap);
 }
 
 /* Section: vcpu related */
 int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
 {
+       if (kvm_is_ucontrol(vcpu->kvm)) {
+               vcpu->arch.gmap = gmap_alloc(current->mm);
+               if (!vcpu->arch.gmap)
+                       return -ENOMEM;
+               return 0;
+       }
+
        vcpu->arch.gmap = vcpu->kvm->arch.gmap;
+       vcpu->run->kvm_valid_regs = KVM_SYNC_PREFIX |
+                                   KVM_SYNC_GPRS |
+                                   KVM_SYNC_ACRS |
+                                   KVM_SYNC_CRS;
        return 0;
 }
 
@@ -270,7 +307,7 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
        save_access_regs(vcpu->arch.host_acrs);
        vcpu->arch.guest_fpregs.fpc &= FPC_VALID_MASK;
        restore_fp_regs(&vcpu->arch.guest_fpregs);
-       restore_access_regs(vcpu->arch.guest_acrs);
+       restore_access_regs(vcpu->run->s.regs.acrs);
        gmap_enable(vcpu->arch.gmap);
        atomic_set_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
 }
@@ -280,7 +317,7 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
        atomic_clear_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
        gmap_disable(vcpu->arch.gmap);
        save_fp_regs(&vcpu->arch.guest_fpregs);
-       save_access_regs(vcpu->arch.guest_acrs);
+       save_access_regs(vcpu->run->s.regs.acrs);
        restore_fp_regs(&vcpu->arch.host_fpregs);
        restore_access_regs(vcpu->arch.host_acrs);
 }
@@ -290,8 +327,7 @@ static void kvm_s390_vcpu_initial_reset(struct kvm_vcpu *vcpu)
        /* this equals initial cpu reset in pop, but we don't switch to ESA */
        vcpu->arch.sie_block->gpsw.mask = 0UL;
        vcpu->arch.sie_block->gpsw.addr = 0UL;
-       vcpu->arch.sie_block->prefix    = 0UL;
-       vcpu->arch.sie_block->ihcpu     = 0xffff;
+       kvm_s390_set_prefix(vcpu, 0);
        vcpu->arch.sie_block->cputm     = 0UL;
        vcpu->arch.sie_block->ckc       = 0UL;
        vcpu->arch.sie_block->todpr     = 0;
@@ -342,12 +378,19 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
                goto out_free_cpu;
 
        vcpu->arch.sie_block->icpua = id;
-       BUG_ON(!kvm->arch.sca);
-       if (!kvm->arch.sca->cpu[id].sda)
-               kvm->arch.sca->cpu[id].sda = (__u64) vcpu->arch.sie_block;
-       vcpu->arch.sie_block->scaoh = (__u32)(((__u64)kvm->arch.sca) >> 32);
-       vcpu->arch.sie_block->scaol = (__u32)(__u64)kvm->arch.sca;
-       set_bit(63 - id, (unsigned long *) &kvm->arch.sca->mcn);
+       if (!kvm_is_ucontrol(kvm)) {
+               if (!kvm->arch.sca) {
+                       WARN_ON_ONCE(1);
+                       goto out_free_cpu;
+               }
+               if (!kvm->arch.sca->cpu[id].sda)
+                       kvm->arch.sca->cpu[id].sda =
+                               (__u64) vcpu->arch.sie_block;
+               vcpu->arch.sie_block->scaoh =
+                       (__u32)(((__u64)kvm->arch.sca) >> 32);
+               vcpu->arch.sie_block->scaol = (__u32)(__u64)kvm->arch.sca;
+               set_bit(63 - id, (unsigned long *) &kvm->arch.sca->mcn);
+       }
 
        spin_lock_init(&vcpu->arch.local_int.lock);
        INIT_LIST_HEAD(&vcpu->arch.local_int.list);
@@ -388,29 +431,29 @@ static int kvm_arch_vcpu_ioctl_initial_reset(struct kvm_vcpu *vcpu)
 
 int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
 {
-       memcpy(&vcpu->arch.guest_gprs, &regs->gprs, sizeof(regs->gprs));
+       memcpy(&vcpu->run->s.regs.gprs, &regs->gprs, sizeof(regs->gprs));
        return 0;
 }
 
 int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
 {
-       memcpy(&regs->gprs, &vcpu->arch.guest_gprs, sizeof(regs->gprs));
+       memcpy(&regs->gprs, &vcpu->run->s.regs.gprs, sizeof(regs->gprs));
        return 0;
 }
 
 int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
                                  struct kvm_sregs *sregs)
 {
-       memcpy(&vcpu->arch.guest_acrs, &sregs->acrs, sizeof(sregs->acrs));
+       memcpy(&vcpu->run->s.regs.acrs, &sregs->acrs, sizeof(sregs->acrs));
        memcpy(&vcpu->arch.sie_block->gcr, &sregs->crs, sizeof(sregs->crs));
-       restore_access_regs(vcpu->arch.guest_acrs);
+       restore_access_regs(vcpu->run->s.regs.acrs);
        return 0;
 }
 
 int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
                                  struct kvm_sregs *sregs)
 {
-       memcpy(&sregs->acrs, &vcpu->arch.guest_acrs, sizeof(sregs->acrs));
+       memcpy(&sregs->acrs, &vcpu->run->s.regs.acrs, sizeof(sregs->acrs));
        memcpy(&sregs->crs, &vcpu->arch.sie_block->gcr, sizeof(sregs->crs));
        return 0;
 }
@@ -418,7 +461,7 @@ int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
 int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
 {
        memcpy(&vcpu->arch.guest_fpregs.fprs, &fpu->fprs, sizeof(fpu->fprs));
-       vcpu->arch.guest_fpregs.fpc = fpu->fpc;
+       vcpu->arch.guest_fpregs.fpc = fpu->fpc & FPC_VALID_MASK;
        restore_fp_regs(&vcpu->arch.guest_fpregs);
        return 0;
 }
@@ -467,9 +510,11 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
        return -EINVAL; /* not implemented yet */
 }
 
-static void __vcpu_run(struct kvm_vcpu *vcpu)
+static int __vcpu_run(struct kvm_vcpu *vcpu)
 {
-       memcpy(&vcpu->arch.sie_block->gg14, &vcpu->arch.guest_gprs[14], 16);
+       int rc;
+
+       memcpy(&vcpu->arch.sie_block->gg14, &vcpu->run->s.regs.gprs[14], 16);
 
        if (need_resched())
                schedule();
@@ -477,7 +522,8 @@ static void __vcpu_run(struct kvm_vcpu *vcpu)
        if (test_thread_flag(TIF_MCCK_PENDING))
                s390_handle_mcck();
 
-       kvm_s390_deliver_pending_interrupts(vcpu);
+       if (!kvm_is_ucontrol(vcpu->kvm))
+               kvm_s390_deliver_pending_interrupts(vcpu);
 
        vcpu->arch.sie_block->icptcode = 0;
        local_irq_disable();
@@ -485,9 +531,15 @@ static void __vcpu_run(struct kvm_vcpu *vcpu)
        local_irq_enable();
        VCPU_EVENT(vcpu, 6, "entering sie flags %x",
                   atomic_read(&vcpu->arch.sie_block->cpuflags));
-       if (sie64a(vcpu->arch.sie_block, vcpu->arch.guest_gprs)) {
-               VCPU_EVENT(vcpu, 3, "%s", "fault in sie instruction");
-               kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
+       rc = sie64a(vcpu->arch.sie_block, vcpu->run->s.regs.gprs);
+       if (rc) {
+               if (kvm_is_ucontrol(vcpu->kvm)) {
+                       rc = SIE_INTERCEPT_UCONTROL;
+               } else {
+                       VCPU_EVENT(vcpu, 3, "%s", "fault in sie instruction");
+                       kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
+                       rc = 0;
+               }
        }
        VCPU_EVENT(vcpu, 6, "exit sie icptcode %d",
                   vcpu->arch.sie_block->icptcode);
@@ -495,7 +547,8 @@ static void __vcpu_run(struct kvm_vcpu *vcpu)
        kvm_guest_exit();
        local_irq_enable();
 
-       memcpy(&vcpu->arch.guest_gprs[14], &vcpu->arch.sie_block->gg14, 16);
+       memcpy(&vcpu->run->s.regs.gprs[14], &vcpu->arch.sie_block->gg14, 16);
+       return rc;
 }
 
 int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
@@ -516,6 +569,7 @@ rerun_vcpu:
        case KVM_EXIT_UNKNOWN:
        case KVM_EXIT_INTR:
        case KVM_EXIT_S390_RESET:
+       case KVM_EXIT_S390_UCONTROL:
                break;
        default:
                BUG();
@@ -523,12 +577,26 @@ rerun_vcpu:
 
        vcpu->arch.sie_block->gpsw.mask = kvm_run->psw_mask;
        vcpu->arch.sie_block->gpsw.addr = kvm_run->psw_addr;
+       if (kvm_run->kvm_dirty_regs & KVM_SYNC_PREFIX) {
+               kvm_run->kvm_dirty_regs &= ~KVM_SYNC_PREFIX;
+               kvm_s390_set_prefix(vcpu, kvm_run->s.regs.prefix);
+       }
+       if (kvm_run->kvm_dirty_regs & KVM_SYNC_CRS) {
+               kvm_run->kvm_dirty_regs &= ~KVM_SYNC_CRS;
+               memcpy(&vcpu->arch.sie_block->gcr, &kvm_run->s.regs.crs, 128);
+               kvm_s390_set_prefix(vcpu, kvm_run->s.regs.prefix);
+       }
 
        might_fault();
 
        do {
-               __vcpu_run(vcpu);
-               rc = kvm_handle_sie_intercept(vcpu);
+               rc = __vcpu_run(vcpu);
+               if (rc)
+                       break;
+               if (kvm_is_ucontrol(vcpu->kvm))
+                       rc = -EOPNOTSUPP;
+               else
+                       rc = kvm_handle_sie_intercept(vcpu);
        } while (!signal_pending(current) && !rc);
 
        if (rc == SIE_INTERCEPT_RERUNVCPU)
@@ -539,6 +607,16 @@ rerun_vcpu:
                rc = -EINTR;
        }
 
+#ifdef CONFIG_KVM_S390_UCONTROL
+       if (rc == SIE_INTERCEPT_UCONTROL) {
+               kvm_run->exit_reason = KVM_EXIT_S390_UCONTROL;
+               kvm_run->s390_ucontrol.trans_exc_code =
+                       current->thread.gmap_addr;
+               kvm_run->s390_ucontrol.pgm_code = 0x10;
+               rc = 0;
+       }
+#endif
+
        if (rc == -EOPNOTSUPP) {
                /* intercept cannot be handled in-kernel, prepare kvm-run */
                kvm_run->exit_reason         = KVM_EXIT_S390_SIEIC;
@@ -556,6 +634,8 @@ rerun_vcpu:
 
        kvm_run->psw_mask     = vcpu->arch.sie_block->gpsw.mask;
        kvm_run->psw_addr     = vcpu->arch.sie_block->gpsw.addr;
+       kvm_run->s.regs.prefix = vcpu->arch.sie_block->prefix;
+       memcpy(&kvm_run->s.regs.crs, &vcpu->arch.sie_block->gcr, 128);
 
        if (vcpu->sigset_active)
                sigprocmask(SIG_SETMASK, &sigsaved, NULL);
@@ -602,7 +682,7 @@ int kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr)
                return -EFAULT;
 
        if (__guestcopy(vcpu, addr + offsetof(struct save_area, gp_regs),
-                       vcpu->arch.guest_gprs, 128, prefix))
+                       vcpu->run->s.regs.gprs, 128, prefix))
                return -EFAULT;
 
        if (__guestcopy(vcpu, addr + offsetof(struct save_area, psw),
@@ -631,7 +711,7 @@ int kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr)
                return -EFAULT;
 
        if (__guestcopy(vcpu, addr + offsetof(struct save_area, acc_regs),
-                       &vcpu->arch.guest_acrs, 64, prefix))
+                       &vcpu->run->s.regs.acrs, 64, prefix))
                return -EFAULT;
 
        if (__guestcopy(vcpu,
@@ -673,12 +753,77 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
        case KVM_S390_INITIAL_RESET:
                r = kvm_arch_vcpu_ioctl_initial_reset(vcpu);
                break;
+#ifdef CONFIG_KVM_S390_UCONTROL
+       case KVM_S390_UCAS_MAP: {
+               struct kvm_s390_ucas_mapping ucasmap;
+
+               if (copy_from_user(&ucasmap, argp, sizeof(ucasmap))) {
+                       r = -EFAULT;
+                       break;
+               }
+
+               if (!kvm_is_ucontrol(vcpu->kvm)) {
+                       r = -EINVAL;
+                       break;
+               }
+
+               r = gmap_map_segment(vcpu->arch.gmap, ucasmap.user_addr,
+                                    ucasmap.vcpu_addr, ucasmap.length);
+               break;
+       }
+       case KVM_S390_UCAS_UNMAP: {
+               struct kvm_s390_ucas_mapping ucasmap;
+
+               if (copy_from_user(&ucasmap, argp, sizeof(ucasmap))) {
+                       r = -EFAULT;
+                       break;
+               }
+
+               if (!kvm_is_ucontrol(vcpu->kvm)) {
+                       r = -EINVAL;
+                       break;
+               }
+
+               r = gmap_unmap_segment(vcpu->arch.gmap, ucasmap.vcpu_addr,
+                       ucasmap.length);
+               break;
+       }
+#endif
+       case KVM_S390_VCPU_FAULT: {
+               r = gmap_fault(arg, vcpu->arch.gmap);
+               if (!IS_ERR_VALUE(r))
+                       r = 0;
+               break;
+       }
        default:
-               r = -EINVAL;
+               r = -ENOTTY;
        }
        return r;
 }
 
+int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf)
+{
+#ifdef CONFIG_KVM_S390_UCONTROL
+       if ((vmf->pgoff == KVM_S390_SIE_PAGE_OFFSET)
+                && (kvm_is_ucontrol(vcpu->kvm))) {
+               vmf->page = virt_to_page(vcpu->arch.sie_block);
+               get_page(vmf->page);
+               return 0;
+       }
+#endif
+       return VM_FAULT_SIGBUS;
+}
+
+void kvm_arch_free_memslot(struct kvm_memory_slot *free,
+                          struct kvm_memory_slot *dont)
+{
+}
+
+int kvm_arch_create_memslot(struct kvm_memory_slot *slot, unsigned long npages)
+{
+       return 0;
+}
+
 /* Section: memory related */
 int kvm_arch_prepare_memory_region(struct kvm *kvm,
                                   struct kvm_memory_slot *memslot,
index 99b0b75..ff28f9d 100644 (file)
@@ -26,6 +26,7 @@ typedef int (*intercept_handler_t)(struct kvm_vcpu *vcpu);
 
 /* negativ values are error codes, positive values for internal conditions */
 #define SIE_INTERCEPT_RERUNVCPU                (1<<0)
+#define SIE_INTERCEPT_UCONTROL         (1<<1)
 int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu);
 
 #define VM_EVENT(d_kvm, d_loglevel, d_string, d_args...)\
@@ -47,6 +48,23 @@ static inline int __cpu_is_stopped(struct kvm_vcpu *vcpu)
        return atomic_read(&vcpu->arch.sie_block->cpuflags) & CPUSTAT_STOP_INT;
 }
 
+static inline int kvm_is_ucontrol(struct kvm *kvm)
+{
+#ifdef CONFIG_KVM_S390_UCONTROL
+       if (kvm->arch.gmap)
+               return 0;
+       return 1;
+#else
+       return 0;
+#endif
+}
+
+static inline void kvm_s390_set_prefix(struct kvm_vcpu *vcpu, u32 prefix)
+{
+       vcpu->arch.sie_block->prefix = prefix & 0x7fffe000u;
+       vcpu->arch.sie_block->ihcpu  = 0xffff;
+}
+
 int kvm_s390_handle_wait(struct kvm_vcpu *vcpu);
 enum hrtimer_restart kvm_s390_idle_wakeup(struct hrtimer *timer);
 void kvm_s390_tasklet(unsigned long parm);
index d026389..e5a45db 100644 (file)
@@ -33,7 +33,7 @@ static int handle_set_prefix(struct kvm_vcpu *vcpu)
 
        operand2 = disp2;
        if (base2)
-               operand2 += vcpu->arch.guest_gprs[base2];
+               operand2 += vcpu->run->s.regs.gprs[base2];
 
        /* must be word boundary */
        if (operand2 & 3) {
@@ -56,8 +56,7 @@ static int handle_set_prefix(struct kvm_vcpu *vcpu)
                goto out;
        }
 
-       vcpu->arch.sie_block->prefix = address;
-       vcpu->arch.sie_block->ihcpu = 0xffff;
+       kvm_s390_set_prefix(vcpu, address);
 
        VCPU_EVENT(vcpu, 5, "setting prefix to %x", address);
 out:
@@ -74,7 +73,7 @@ static int handle_store_prefix(struct kvm_vcpu *vcpu)
        vcpu->stat.instruction_stpx++;
        operand2 = disp2;
        if (base2)
-               operand2 += vcpu->arch.guest_gprs[base2];
+               operand2 += vcpu->run->s.regs.gprs[base2];
 
        /* must be word boundary */
        if (operand2 & 3) {
@@ -106,7 +105,7 @@ static int handle_store_cpu_address(struct kvm_vcpu *vcpu)
        vcpu->stat.instruction_stap++;
        useraddr = disp2;
        if (base2)
-               useraddr += vcpu->arch.guest_gprs[base2];
+               useraddr += vcpu->run->s.regs.gprs[base2];
 
        if (useraddr & 1) {
                kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
@@ -181,7 +180,7 @@ static int handle_stidp(struct kvm_vcpu *vcpu)
        vcpu->stat.instruction_stidp++;
        operand2 = disp2;
        if (base2)
-               operand2 += vcpu->arch.guest_gprs[base2];
+               operand2 += vcpu->run->s.regs.gprs[base2];
 
        if (operand2 & 7) {
                kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
@@ -232,9 +231,9 @@ static void handle_stsi_3_2_2(struct kvm_vcpu *vcpu, struct sysinfo_3_2_2 *mem)
 
 static int handle_stsi(struct kvm_vcpu *vcpu)
 {
-       int fc = (vcpu->arch.guest_gprs[0] & 0xf0000000) >> 28;
-       int sel1 = vcpu->arch.guest_gprs[0] & 0xff;
-       int sel2 = vcpu->arch.guest_gprs[1] & 0xffff;
+       int fc = (vcpu->run->s.regs.gprs[0] & 0xf0000000) >> 28;
+       int sel1 = vcpu->run->s.regs.gprs[0] & 0xff;
+       int sel2 = vcpu->run->s.regs.gprs[1] & 0xffff;
        int base2 = vcpu->arch.sie_block->ipb >> 28;
        int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16);
        u64 operand2;
@@ -245,14 +244,14 @@ static int handle_stsi(struct kvm_vcpu *vcpu)
 
        operand2 = disp2;
        if (base2)
-               operand2 += vcpu->arch.guest_gprs[base2];
+               operand2 += vcpu->run->s.regs.gprs[base2];
 
        if (operand2 & 0xfff && fc > 0)
                return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
 
        switch (fc) {
        case 0:
-               vcpu->arch.guest_gprs[0] = 3 << 28;
+               vcpu->run->s.regs.gprs[0] = 3 << 28;
                vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44);
                return 0;
        case 1: /* same handling for 1 and 2 */
@@ -281,7 +280,7 @@ static int handle_stsi(struct kvm_vcpu *vcpu)
        }
        free_page(mem);
        vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44);
-       vcpu->arch.guest_gprs[0] = 0;
+       vcpu->run->s.regs.gprs[0] = 0;
        return 0;
 out_mem:
        free_page(mem);
@@ -333,8 +332,8 @@ static int handle_tprot(struct kvm_vcpu *vcpu)
        int disp1 = (vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16;
        int base2 = (vcpu->arch.sie_block->ipb & 0xf000) >> 12;
        int disp2 = vcpu->arch.sie_block->ipb & 0x0fff;
-       u64 address1 = disp1 + base1 ? vcpu->arch.guest_gprs[base1] : 0;
-       u64 address2 = disp2 + base2 ? vcpu->arch.guest_gprs[base2] : 0;
+       u64 address1 = disp1 + base1 ? vcpu->run->s.regs.gprs[base1] : 0;
+       u64 address2 = disp2 + base2 ? vcpu->run->s.regs.gprs[base2] : 0;
        struct vm_area_struct *vma;
        unsigned long user_address;
 
index 0a7941d..0ad4cf2 100644 (file)
@@ -48,7 +48,7 @@
 
 
 static int __sigp_sense(struct kvm_vcpu *vcpu, u16 cpu_addr,
-                       unsigned long *reg)
+                       u64 *reg)
 {
        struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
        int rc;
@@ -160,12 +160,15 @@ static int __inject_sigp_stop(struct kvm_s390_local_interrupt *li, int action)
        inti->type = KVM_S390_SIGP_STOP;
 
        spin_lock_bh(&li->lock);
+       if ((atomic_read(li->cpuflags) & CPUSTAT_STOPPED))
+               goto out;
        list_add_tail(&inti->list, &li->list);
        atomic_set(&li->active, 1);
        atomic_set_mask(CPUSTAT_STOP_INT, li->cpuflags);
        li->action_bits |= action;
        if (waitqueue_active(&li->wq))
                wake_up_interruptible(&li->wq);
+out:
        spin_unlock_bh(&li->lock);
 
        return 0; /* order accepted */
@@ -220,7 +223,7 @@ static int __sigp_set_arch(struct kvm_vcpu *vcpu, u32 parameter)
 }
 
 static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address,
-                            unsigned long *reg)
+                            u64 *reg)
 {
        struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
        struct kvm_s390_local_interrupt *li = NULL;
@@ -278,7 +281,7 @@ out_fi:
 }
 
 static int __sigp_sense_running(struct kvm_vcpu *vcpu, u16 cpu_addr,
-                               unsigned long *reg)
+                               u64 *reg)
 {
        int rc;
        struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
@@ -309,6 +312,34 @@ static int __sigp_sense_running(struct kvm_vcpu *vcpu, u16 cpu_addr,
        return rc;
 }
 
+static int __sigp_restart(struct kvm_vcpu *vcpu, u16 cpu_addr)
+{
+       int rc = 0;
+       struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
+       struct kvm_s390_local_interrupt *li;
+
+       if (cpu_addr >= KVM_MAX_VCPUS)
+               return 3; /* not operational */
+
+       spin_lock(&fi->lock);
+       li = fi->local_int[cpu_addr];
+       if (li == NULL) {
+               rc = 3; /* not operational */
+               goto out;
+       }
+
+       spin_lock_bh(&li->lock);
+       if (li->action_bits & ACTION_STOP_ON_STOP)
+               rc = 2; /* busy */
+       else
+               VCPU_EVENT(vcpu, 4, "sigp restart %x to handle userspace",
+                       cpu_addr);
+       spin_unlock_bh(&li->lock);
+out:
+       spin_unlock(&fi->lock);
+       return rc;
+}
+
 int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
 {
        int r1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4;
@@ -316,7 +347,7 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
        int base2 = vcpu->arch.sie_block->ipb >> 28;
        int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16);
        u32 parameter;
-       u16 cpu_addr = vcpu->arch.guest_gprs[r3];
+       u16 cpu_addr = vcpu->run->s.regs.gprs[r3];
        u8 order_code;
        int rc;
 
@@ -327,18 +358,18 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
 
        order_code = disp2;
        if (base2)
-               order_code += vcpu->arch.guest_gprs[base2];
+               order_code += vcpu->run->s.regs.gprs[base2];
 
        if (r1 % 2)
-               parameter = vcpu->arch.guest_gprs[r1];
+               parameter = vcpu->run->s.regs.gprs[r1];
        else
-               parameter = vcpu->arch.guest_gprs[r1 + 1];
+               parameter = vcpu->run->s.regs.gprs[r1 + 1];
 
        switch (order_code) {
        case SIGP_SENSE:
                vcpu->stat.instruction_sigp_sense++;
                rc = __sigp_sense(vcpu, cpu_addr,
-                                 &vcpu->arch.guest_gprs[r1]);
+                                 &vcpu->run->s.regs.gprs[r1]);
                break;
        case SIGP_EXTERNAL_CALL:
                vcpu->stat.instruction_sigp_external_call++;
@@ -354,7 +385,8 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
                break;
        case SIGP_STOP_STORE_STATUS:
                vcpu->stat.instruction_sigp_stop++;
-               rc = __sigp_stop(vcpu, cpu_addr, ACTION_STORE_ON_STOP);
+               rc = __sigp_stop(vcpu, cpu_addr, ACTION_STORE_ON_STOP |
+                                                ACTION_STOP_ON_STOP);
                break;
        case SIGP_SET_ARCH:
                vcpu->stat.instruction_sigp_arch++;
@@ -363,15 +395,18 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
        case SIGP_SET_PREFIX:
                vcpu->stat.instruction_sigp_prefix++;
                rc = __sigp_set_prefix(vcpu, cpu_addr, parameter,
-                                      &vcpu->arch.guest_gprs[r1]);
+                                      &vcpu->run->s.regs.gprs[r1]);
                break;
        case SIGP_SENSE_RUNNING:
                vcpu->stat.instruction_sigp_sense_running++;
                rc = __sigp_sense_running(vcpu, cpu_addr,
-                                         &vcpu->arch.guest_gprs[r1]);
+                                         &vcpu->run->s.regs.gprs[r1]);
                break;
        case SIGP_RESTART:
                vcpu->stat.instruction_sigp_restart++;
+               rc = __sigp_restart(vcpu, cpu_addr);
+               if (rc == 2) /* busy */
+                       break;
                /* user space must know about restart */
        default:
                return -EOPNOTSUPP;
index b17c42d..46ef3fd 100644 (file)
 #include <linux/uaccess.h>
 #include <linux/hugetlb.h>
 #include <asm/asm-offsets.h>
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/irq.h>
 #include <asm/mmu_context.h>
+#include <asm/facility.h>
 #include "../kernel/entry.h"
 
 #ifndef CONFIG_64BIT
index 5023661..2bea060 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/export.h>
 #include <linux/gfp.h>
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
@@ -38,6 +37,7 @@
 #include <asm/tlb.h>
 #include <asm/tlbflush.h>
 #include <asm/sections.h>
+#include <asm/ctl_reg.h>
 
 pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((__aligned__(PAGE_SIZE)));
 
index 1cb8427..7bb15fc 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/gfp.h>
-#include <asm/system.h>
+#include <asm/ctl_reg.h>
 
 /*
  * This function writes to kernel memory bypassing DAT and possible
index 51b0738..373adf6 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/rcupdate.h>
 #include <linux/slab.h>
 
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
 #include <asm/tlb.h>
index f097d51..c6646de 100644 (file)
@@ -17,6 +17,8 @@
 #include <linux/semaphore.h>
 #include <linux/oom.h>
 #include <linux/oprofile.h>
+
+#include <asm/facility.h>
 #include <asm/cpu_mf.h>
 #include <asm/irq.h>
 
index 84eb8dd..edf33db 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef _ASM_SCORE_ATOMIC_H
 #define _ASM_SCORE_ATOMIC_H
 
+#include <asm/cmpxchg.h>
 #include <asm-generic/atomic.h>
 
 #endif /* _ASM_SCORE_ATOMIC_H */
diff --git a/arch/score/include/asm/barrier.h b/arch/score/include/asm/barrier.h
new file mode 100644 (file)
index 0000000..0eacb64
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef _ASM_SCORE_BARRIER_H
+#define _ASM_SCORE_BARRIER_H
+
+#define mb()           barrier()
+#define rmb()          barrier()
+#define wmb()          barrier()
+#define smp_mb()       barrier()
+#define smp_rmb()      barrier()
+#define smp_wmb()      barrier()
+
+#define read_barrier_depends()         do {} while (0)
+#define smp_read_barrier_depends()     do {} while (0)
+
+#define set_mb(var, value)             do {var = value; wmb(); } while (0)
+
+#endif /* _ASM_SCORE_BARRIER_H */
index 2763b05..a304096 100644 (file)
@@ -2,7 +2,6 @@
 #define _ASM_SCORE_BITOPS_H
 
 #include <asm/byteorder.h> /* swab32 */
-#include <asm/system.h> /* save_flags */
 
 /*
  * clear_bit() doesn't provide any barrier for the compiler.
index bb76a33..fd7164a 100644 (file)
@@ -3,4 +3,15 @@
 
 #include <asm-generic/bug.h>
 
+struct pt_regs;
+extern void __die(const char *, struct pt_regs *, const char *,
+       const char *, unsigned long) __attribute__((noreturn));
+extern void __die_if_kernel(const char *, struct pt_regs *, const char *,
+       const char *, unsigned long);
+
+#define die(msg, regs)                                                 \
+       __die(msg, regs, __FILE__ ":", __func__, __LINE__)
+#define die_if_kernel(msg, regs)                                       \
+       __die_if_kernel(msg, regs, __FILE__ ":", __func__, __LINE__)
+
 #endif /* _ASM_SCORE_BUG_H */
diff --git a/arch/score/include/asm/cmpxchg.h b/arch/score/include/asm/cmpxchg.h
new file mode 100644 (file)
index 0000000..f384839
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef _ASM_SCORE_CMPXCHG_H
+#define _ASM_SCORE_CMPXCHG_H
+
+#include <linux/irqflags.h>
+
+struct __xchg_dummy { unsigned long a[100]; };
+#define __xg(x) ((struct __xchg_dummy *)(x))
+
+static inline
+unsigned long __xchg(volatile unsigned long *m, unsigned long val)
+{
+       unsigned long retval;
+       unsigned long flags;
+
+       local_irq_save(flags);
+       retval = *m;
+       *m = val;
+       local_irq_restore(flags);
+       return retval;
+}
+
+#define xchg(ptr, v)                                           \
+       ((__typeof__(*(ptr))) __xchg((unsigned long *)(ptr),    \
+                                       (unsigned long)(v)))
+
+static inline unsigned long __cmpxchg(volatile unsigned long *m,
+                               unsigned long old, unsigned long new)
+{
+       unsigned long retval;
+       unsigned long flags;
+
+       local_irq_save(flags);
+       retval = *m;
+       if (retval == old)
+               *m = new;
+       local_irq_restore(flags);
+       return retval;
+}
+
+#define cmpxchg(ptr, o, n)                                     \
+       ((__typeof__(*(ptr))) __cmpxchg((unsigned long *)(ptr), \
+                                       (unsigned long)(o),     \
+                                       (unsigned long)(n)))
+
+#define __HAVE_ARCH_CMPXCHG    1
+
+#include <asm-generic/cmpxchg-local.h>
+
+#endif /* _ASM_SCORE_CMPXCHG_H */
diff --git a/arch/score/include/asm/exec.h b/arch/score/include/asm/exec.h
new file mode 100644 (file)
index 0000000..f9f3cd5
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _ASM_SCORE_EXEC_H
+#define _ASM_SCORE_EXEC_H
+
+extern unsigned long arch_align_stack(unsigned long sp);
+
+#endif /* _ASM_SCORE_EXEC_H */
diff --git a/arch/score/include/asm/switch_to.h b/arch/score/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..031756b
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef _ASM_SCORE_SWITCH_TO_H
+#define _ASM_SCORE_SWITCH_TO_H
+
+extern void *resume(void *last, void *next, void *next_ti);
+
+#define switch_to(prev, next, last)                            \
+do {                                                           \
+       (last) = resume(prev, next, task_thread_info(next));    \
+} while (0)
+
+#define finish_arch_switch(prev)       do {} while (0)
+
+#endif /* _ASM_SCORE_SWITCH_TO_H */
diff --git a/arch/score/include/asm/system.h b/arch/score/include/asm/system.h
deleted file mode 100644 (file)
index 589d5c7..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-#ifndef _ASM_SCORE_SYSTEM_H
-#define _ASM_SCORE_SYSTEM_H
-
-#include <linux/types.h>
-#include <linux/irqflags.h>
-
-struct pt_regs;
-struct task_struct;
-
-extern void *resume(void *last, void *next, void *next_ti);
-
-#define switch_to(prev, next, last)                            \
-do {                                                           \
-       (last) = resume(prev, next, task_thread_info(next));    \
-} while (0)
-
-#define finish_arch_switch(prev)       do {} while (0)
-
-typedef void (*vi_handler_t)(void);
-extern unsigned long arch_align_stack(unsigned long sp);
-
-#define mb()           barrier()
-#define rmb()          barrier()
-#define wmb()          barrier()
-#define smp_mb()       barrier()
-#define smp_rmb()      barrier()
-#define smp_wmb()      barrier()
-
-#define read_barrier_depends()         do {} while (0)
-#define smp_read_barrier_depends()     do {} while (0)
-
-#define set_mb(var, value)             do {var = value; wmb(); } while (0)
-
-#define __HAVE_ARCH_CMPXCHG    1
-
-#include <asm-generic/cmpxchg-local.h>
-
-#ifndef __ASSEMBLY__
-
-struct __xchg_dummy { unsigned long a[100]; };
-#define __xg(x) ((struct __xchg_dummy *)(x))
-
-static inline
-unsigned long __xchg(volatile unsigned long *m, unsigned long val)
-{
-       unsigned long retval;
-       unsigned long flags;
-
-       local_irq_save(flags);
-       retval = *m;
-       *m = val;
-       local_irq_restore(flags);
-       return retval;
-}
-
-#define xchg(ptr, v)                                           \
-       ((__typeof__(*(ptr))) __xchg((unsigned long *)(ptr),    \
-                                       (unsigned long)(v)))
-
-static inline unsigned long __cmpxchg(volatile unsigned long *m,
-                               unsigned long old, unsigned long new)
-{
-       unsigned long retval;
-       unsigned long flags;
-
-       local_irq_save(flags);
-       retval = *m;
-       if (retval == old)
-               *m = new;
-       local_irq_restore(flags);
-       return retval;
-}
-
-#define cmpxchg(ptr, o, n)                                     \
-       ((__typeof__(*(ptr))) __cmpxchg((unsigned long *)(ptr), \
-                                       (unsigned long)(o),     \
-                                       (unsigned long)(n)))
-
-extern void __die(const char *, struct pt_regs *, const char *,
-       const char *, unsigned long) __attribute__((noreturn));
-extern void __die_if_kernel(const char *, struct pt_regs *, const char *,
-       const char *, unsigned long);
-
-#define die(msg, regs)                                                 \
-       __die(msg, regs, __FILE__ ":", __func__, __LINE__)
-#define die_if_kernel(msg, regs)                                       \
-       __die_if_kernel(msg, regs, __FILE__ ":", __func__, __LINE__)
-
-#endif /* !__ASSEMBLY__ */
-#endif /* _ASM_SCORE_SYSTEM_H */
index 4fb0036..9a8aff3 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <mach/microdev.h>
 
index 467d941..9f7c566 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef __ASM_SH_ATOMIC_IRQ_H
 #define __ASM_SH_ATOMIC_IRQ_H
 
+#include <linux/irqflags.h>
+
 /*
  * To get proper branch prediction for the main line, we must branch
  * forward to code at the end of this object's .text section, then
index 63a27db..37f2f4a 100644 (file)
@@ -9,7 +9,7 @@
 
 #include <linux/compiler.h>
 #include <linux/types.h>
-#include <asm/system.h>
+#include <asm/cmpxchg.h>
 
 #define ATOMIC_INIT(i) ( (atomic_t) { (i) } )
 
index 483effd..8bcc51a 100644 (file)
@@ -33,4 +33,6 @@
 #define AT_L1D_CACHESHAPE      35
 #define AT_L2_CACHESHAPE       36
 
+#define AT_VECTOR_SIZE_ARCH 5 /* entries in ARCH_DLINFO */
+
 #endif /* __ASM_SH_AUXVEC_H */
diff --git a/arch/sh/include/asm/barrier.h b/arch/sh/include/asm/barrier.h
new file mode 100644 (file)
index 0000000..72c103d
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 1999, 2000  Niibe Yutaka  &  Kaz Kojima
+ * Copyright (C) 2002 Paul Mundt
+ */
+#ifndef __ASM_SH_BARRIER_H
+#define __ASM_SH_BARRIER_H
+
+#if defined(CONFIG_CPU_SH4A) || defined(CONFIG_CPU_SH5)
+#include <asm/cache_insns.h>
+#endif
+
+/*
+ * A brief note on ctrl_barrier(), the control register write barrier.
+ *
+ * Legacy SH cores typically require a sequence of 8 nops after
+ * modification of a control register in order for the changes to take
+ * effect. On newer cores (like the sh4a and sh5) this is accomplished
+ * with icbi.
+ *
+ * Also note that on sh4a in the icbi case we can forego a synco for the
+ * write barrier, as it's not necessary for control registers.
+ *
+ * Historically we have only done this type of barrier for the MMUCR, but
+ * it's also necessary for the CCR, so we make it generic here instead.
+ */
+#if defined(CONFIG_CPU_SH4A) || defined(CONFIG_CPU_SH5)
+#define mb()           __asm__ __volatile__ ("synco": : :"memory")
+#define rmb()          mb()
+#define wmb()          __asm__ __volatile__ ("synco": : :"memory")
+#define ctrl_barrier() __icbi(PAGE_OFFSET)
+#define read_barrier_depends() do { } while(0)
+#else
+#define mb()           __asm__ __volatile__ ("": : :"memory")
+#define rmb()          mb()
+#define wmb()          __asm__ __volatile__ ("": : :"memory")
+#define ctrl_barrier() __asm__ __volatile__ ("nop;nop;nop;nop;nop;nop;nop;nop")
+#define read_barrier_depends() do { } while(0)
+#endif
+
+#ifdef CONFIG_SMP
+#define smp_mb()       mb()
+#define smp_rmb()      rmb()
+#define smp_wmb()      wmb()
+#define smp_read_barrier_depends()     read_barrier_depends()
+#else
+#define smp_mb()       barrier()
+#define smp_rmb()      barrier()
+#define smp_wmb()      barrier()
+#define smp_read_barrier_depends()     do { } while(0)
+#endif
+
+#define set_mb(var, value) do { (void)xchg(&var, value); } while (0)
+
+#endif /* __ASM_SH_BARRIER_H */
index 90fa3e4..ea8706d 100644 (file)
@@ -7,7 +7,6 @@
 #error only <linux/bitops.h> can be included directly
 #endif
 
-#include <asm/system.h>
 /* For __swab32 */
 #include <asm/byteorder.h>
 
diff --git a/arch/sh/include/asm/bl_bit.h b/arch/sh/include/asm/bl_bit.h
new file mode 100644 (file)
index 0000000..45e6b9f
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef __ASM_SH_BL_BIT_H
+#define __ASM_SH_BL_BIT_H
+
+#ifdef CONFIG_SUPERH32
+# include "bl_bit_32.h"
+#else
+# include "bl_bit_64.h"
+#endif
+
+#endif /* __ASM_SH_BL_BIT_H */
diff --git a/arch/sh/include/asm/bl_bit_32.h b/arch/sh/include/asm/bl_bit_32.h
new file mode 100644 (file)
index 0000000..fd21eee
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef __ASM_SH_BL_BIT_32_H
+#define __ASM_SH_BL_BIT_32_H
+
+static inline void set_bl_bit(void)
+{
+       unsigned long __dummy0, __dummy1;
+
+       __asm__ __volatile__ (
+               "stc    sr, %0\n\t"
+               "or     %2, %0\n\t"
+               "and    %3, %0\n\t"
+               "ldc    %0, sr\n\t"
+               : "=&r" (__dummy0), "=r" (__dummy1)
+               : "r" (0x10000000), "r" (0xffffff0f)
+               : "memory"
+       );
+}
+
+static inline void clear_bl_bit(void)
+{
+       unsigned long __dummy0, __dummy1;
+
+       __asm__ __volatile__ (
+               "stc    sr, %0\n\t"
+               "and    %2, %0\n\t"
+               "ldc    %0, sr\n\t"
+               : "=&r" (__dummy0), "=r" (__dummy1)
+               : "1" (~0x10000000)
+               : "memory"
+       );
+}
+
+#endif /* __ASM_SH_BL_BIT_32_H */
diff --git a/arch/sh/include/asm/bl_bit_64.h b/arch/sh/include/asm/bl_bit_64.h
new file mode 100644 (file)
index 0000000..6cc8711
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2000, 2001  Paolo Alberelli
+ * Copyright (C) 2003  Paul Mundt
+ * Copyright (C) 2004  Richard Curnow
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#ifndef __ASM_SH_BL_BIT_64_H
+#define __ASM_SH_BL_BIT_64_H
+
+#include <asm/processor.h>
+
+#define SR_BL_LL       0x0000000010000000LL
+
+static inline void set_bl_bit(void)
+{
+       unsigned long long __dummy0, __dummy1 = SR_BL_LL;
+
+       __asm__ __volatile__("getcon    " __SR ", %0\n\t"
+                            "or        %0, %1, %0\n\t"
+                            "putcon    %0, " __SR "\n\t"
+                            : "=&r" (__dummy0)
+                            : "r" (__dummy1));
+
+}
+
+static inline void clear_bl_bit(void)
+{
+       unsigned long long __dummy0, __dummy1 = ~SR_BL_LL;
+
+       __asm__ __volatile__("getcon    " __SR ", %0\n\t"
+                            "and       %0, %1, %0\n\t"
+                            "putcon    %0, " __SR "\n\t"
+                            : "=&r" (__dummy0)
+                            : "r" (__dummy1));
+}
+
+#endif /* __ASM_SH_BL_BIT_64_H */
index 6323f86..2b87d86 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef __ASM_SH_BUG_H
 #define __ASM_SH_BUG_H
 
+#include <linux/linkage.h>
+
 #define TRAPA_BUG_OPCODE       0xc33e  /* trapa #0x3e */
 #define BUGFLAG_UNWINDER       (1 << 1)
 
@@ -107,4 +109,7 @@ do {                                                        \
 
 #include <asm-generic/bug.h>
 
+struct pt_regs;
+extern void die(const char *str, struct pt_regs *regs, long err) __attribute__ ((noreturn));
+
 #endif /* __ASM_SH_BUG_H */
diff --git a/arch/sh/include/asm/cache_insns.h b/arch/sh/include/asm/cache_insns.h
new file mode 100644 (file)
index 0000000..d25fbe5
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef __ASM_SH_CACHE_INSNS_H
+#define __ASM_SH_CACHE_INSNS_H
+
+
+#ifdef CONFIG_SUPERH32
+# include "cache_insns_32.h"
+#else
+# include "cache_insns_64.h"
+#endif
+
+#endif /* __ASM_SH_CACHE_INSNS_H */
diff --git a/arch/sh/include/asm/cache_insns_32.h b/arch/sh/include/asm/cache_insns_32.h
new file mode 100644 (file)
index 0000000..b92fe54
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef __ASM_SH_CACHE_INSNS_32_H
+#define __ASM_SH_CACHE_INSNS_32_H
+
+#include <linux/types.h>
+
+#if defined(CONFIG_CPU_SH4A)
+#define __icbi(addr)   __asm__ __volatile__ ( "icbi @%0\n\t" : : "r" (addr))
+#else
+#define __icbi(addr)   mb()
+#endif
+
+#define __ocbp(addr)   __asm__ __volatile__ ( "ocbp @%0\n\t" : : "r" (addr))
+#define __ocbi(addr)   __asm__ __volatile__ ( "ocbi @%0\n\t" : : "r" (addr))
+#define __ocbwb(addr)  __asm__ __volatile__ ( "ocbwb @%0\n\t" : : "r" (addr))
+
+static inline reg_size_t register_align(void *val)
+{
+       return (unsigned long)(signed long)val;
+}
+
+#endif /* __ASM_SH_CACHE_INSNS_32_H */
diff --git a/arch/sh/include/asm/cache_insns_64.h b/arch/sh/include/asm/cache_insns_64.h
new file mode 100644 (file)
index 0000000..70b6357
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2000, 2001  Paolo Alberelli
+ * Copyright (C) 2003  Paul Mundt
+ * Copyright (C) 2004  Richard Curnow
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#ifndef __ASM_SH_CACHE_INSNS_64_H
+#define __ASM_SH_CACHE_INSNS_64_H
+
+#define __icbi(addr)   __asm__ __volatile__ ( "icbi %0, 0\n\t" : : "r" (addr))
+#define __ocbp(addr)   __asm__ __volatile__ ( "ocbp %0, 0\n\t" : : "r" (addr))
+#define __ocbi(addr)   __asm__ __volatile__ ( "ocbi %0, 0\n\t" : : "r" (addr))
+#define __ocbwb(addr)  __asm__ __volatile__ ( "ocbwb %0, 0\n\t" : : "r" (addr))
+
+static inline reg_size_t register_align(void *val)
+{
+       return (unsigned long long)(signed long long)(signed long)val;
+}
+
+#endif /* __ASM_SH_CACHE_INSNS_64_H */
index 43049ec..bd11f63 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef __ASM_SH_CMPXCHG_IRQ_H
 #define __ASM_SH_CMPXCHG_IRQ_H
 
+#include <linux/irqflags.h>
+
 static inline unsigned long xchg_u32(volatile u32 *m, unsigned long val)
 {
        unsigned long flags, retval;
diff --git a/arch/sh/include/asm/cmpxchg.h b/arch/sh/include/asm/cmpxchg.h
new file mode 100644 (file)
index 0000000..f6bd140
--- /dev/null
@@ -0,0 +1,70 @@
+#ifndef __ASM_SH_CMPXCHG_H
+#define __ASM_SH_CMPXCHG_H
+
+/*
+ * Atomic operations that C can't guarantee us.  Useful for
+ * resource counting etc..
+ */
+
+#include <linux/compiler.h>
+#include <linux/types.h>
+
+#if defined(CONFIG_GUSA_RB)
+#include <asm/cmpxchg-grb.h>
+#elif defined(CONFIG_CPU_SH4A)
+#include <asm/cmpxchg-llsc.h>
+#else
+#include <asm/cmpxchg-irq.h>
+#endif
+
+extern void __xchg_called_with_bad_pointer(void);
+
+#define __xchg(ptr, x, size)                           \
+({                                                     \
+       unsigned long __xchg__res;                      \
+       volatile void *__xchg_ptr = (ptr);              \
+       switch (size) {                                 \
+       case 4:                                         \
+               __xchg__res = xchg_u32(__xchg_ptr, x);  \
+               break;                                  \
+       case 1:                                         \
+               __xchg__res = xchg_u8(__xchg_ptr, x);   \
+               break;                                  \
+       default:                                        \
+               __xchg_called_with_bad_pointer();       \
+               __xchg__res = x;                        \
+               break;                                  \
+       }                                               \
+                                                       \
+       __xchg__res;                                    \
+})
+
+#define xchg(ptr,x)    \
+       ((__typeof__(*(ptr)))__xchg((ptr),(unsigned long)(x), sizeof(*(ptr))))
+
+/* This function doesn't exist, so you'll get a linker error
+ * if something tries to do an invalid cmpxchg(). */
+extern void __cmpxchg_called_with_bad_pointer(void);
+
+#define __HAVE_ARCH_CMPXCHG 1
+
+static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old,
+               unsigned long new, int size)
+{
+       switch (size) {
+       case 4:
+               return __cmpxchg_u32(ptr, old, new);
+       }
+       __cmpxchg_called_with_bad_pointer();
+       return old;
+}
+
+#define cmpxchg(ptr,o,n)                                                \
+  ({                                                                    \
+     __typeof__(*(ptr)) _o_ = (o);                                      \
+     __typeof__(*(ptr)) _n_ = (n);                                      \
+     (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,          \
+                                   (unsigned long)_n_, sizeof(*(ptr))); \
+  })
+
+#endif /* __ASM_SH_CMPXCHG_H */
diff --git a/arch/sh/include/asm/exec.h b/arch/sh/include/asm/exec.h
new file mode 100644 (file)
index 0000000..69486a9
--- /dev/null
@@ -0,0 +1,10 @@
+/*
+ * Copyright (C) 1999, 2000  Niibe Yutaka  &  Kaz Kojima
+ * Copyright (C) 2002 Paul Mundt
+ */
+#ifndef __ASM_SH_EXEC_H
+#define __ASM_SH_EXEC_H
+
+#define arch_align_stack(x) (x)
+
+#endif /* __ASM_SH_EXEC_H */
index 6cb9f19..63d3312 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __ASM_SH_FUTEX_IRQ_H
 #define __ASM_SH_FUTEX_IRQ_H
 
-#include <asm/system.h>
 
 static inline int atomic_futex_op_xchg_set(int oparg, u32 __user *uaddr,
                                           int *oldval)
index 28c5aa5..35fc8b0 100644 (file)
@@ -14,7 +14,6 @@
  */
 #include <linux/errno.h>
 #include <asm/cache.h>
-#include <asm/system.h>
 #include <asm/addrspace.h>
 #include <asm/machvec.h>
 #include <asm/pgtable.h>
index 9c7bdfc..a229c39 100644 (file)
@@ -101,6 +101,10 @@ extern struct sh_cpuinfo cpu_data[];
 #define cpu_sleep()    __asm__ __volatile__ ("sleep" : : : "memory")
 #define cpu_relax()    barrier()
 
+void default_idle(void);
+void cpu_idle_wait(void);
+void stop_this_cpu(void *);
+
 /* Forward decl */
 struct seq_operations;
 struct task_struct;
@@ -161,6 +165,17 @@ int vsyscall_init(void);
 #define vsyscall_init() do { } while (0)
 #endif
 
+/*
+ * SH-2A has both 16 and 32-bit opcodes, do lame encoding checks.
+ */
+#ifdef CONFIG_CPU_SH2A
+extern unsigned int instruction_size(unsigned int insn);
+#elif defined(CONFIG_SUPERH32)
+#define instruction_size(insn) (2)
+#else
+#define instruction_size(insn) (4)
+#endif
+
 #endif /* __ASSEMBLY__ */
 
 #ifdef CONFIG_SUPERH32
index 2d3679b..c7b7e1e 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/thread_info.h>
 #include <asm/addrspace.h>
 #include <asm/page.h>
-#include <asm/system.h>
 
 #define user_mode(regs)                        (((regs)->sr & 0x40000000)==0)
 #define kernel_stack_pointer(_regs)    ((unsigned long)(_regs)->regs[15])
index 01fa17a..465a22d 100644 (file)
@@ -20,6 +20,7 @@
 
 void sh_mv_setup(void);
 void check_for_initrd(void);
+void per_cpu_trap_init(void);
 
 #endif /* __KERNEL__ */
 
diff --git a/arch/sh/include/asm/switch_to.h b/arch/sh/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..62b1941
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2000, 2001  Paolo Alberelli
+ * Copyright (C) 2003  Paul Mundt
+ * Copyright (C) 2004  Richard Curnow
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#ifndef __ASM_SH_SWITCH_TO_H
+#define __ASM_SH_SWITCH_TO_H
+
+#ifdef CONFIG_SUPERH32
+# include "switch_to_32.h"
+#else
+# include "switch_to_64.h"
+#endif
+
+#endif /* __ASM_SH_SWITCH_TO_H */
diff --git a/arch/sh/include/asm/switch_to_32.h b/arch/sh/include/asm/switch_to_32.h
new file mode 100644 (file)
index 0000000..0c06551
--- /dev/null
@@ -0,0 +1,134 @@
+#ifndef __ASM_SH_SWITCH_TO_32_H
+#define __ASM_SH_SWITCH_TO_32_H
+
+#ifdef CONFIG_SH_DSP
+
+#define is_dsp_enabled(tsk)                                            \
+       (!!(tsk->thread.dsp_status.status & SR_DSP))
+
+#define __restore_dsp(tsk)                                             \
+do {                                                                   \
+       register u32 *__ts2 __asm__ ("r2") =                            \
+                       (u32 *)&tsk->thread.dsp_status;                 \
+       __asm__ __volatile__ (                                          \
+               ".balign 4\n\t"                                         \
+               "movs.l @r2+, a0\n\t"                                   \
+               "movs.l @r2+, a1\n\t"                                   \
+               "movs.l @r2+, a0g\n\t"                                  \
+               "movs.l @r2+, a1g\n\t"                                  \
+               "movs.l @r2+, m0\n\t"                                   \
+               "movs.l @r2+, m1\n\t"                                   \
+               "movs.l @r2+, x0\n\t"                                   \
+               "movs.l @r2+, x1\n\t"                                   \
+               "movs.l @r2+, y0\n\t"                                   \
+               "movs.l @r2+, y1\n\t"                                   \
+               "lds.l  @r2+, dsr\n\t"                                  \
+               "ldc.l  @r2+, rs\n\t"                                   \
+               "ldc.l  @r2+, re\n\t"                                   \
+               "ldc.l  @r2+, mod\n\t"                                  \
+               : : "r" (__ts2));                                       \
+} while (0)
+
+#define __save_dsp(tsk)                                                        \
+do {                                                                   \
+       register u32 *__ts2 __asm__ ("r2") =                            \
+                       (u32 *)&tsk->thread.dsp_status + 14;            \
+                                                                       \
+       __asm__ __volatile__ (                                          \
+               ".balign 4\n\t"                                         \
+               "stc.l  mod, @-r2\n\t"                                  \
+               "stc.l  re, @-r2\n\t"                                   \
+               "stc.l  rs, @-r2\n\t"                                   \
+               "sts.l  dsr, @-r2\n\t"                                  \
+               "movs.l y1, @-r2\n\t"                                   \
+               "movs.l y0, @-r2\n\t"                                   \
+               "movs.l x1, @-r2\n\t"                                   \
+               "movs.l x0, @-r2\n\t"                                   \
+               "movs.l m1, @-r2\n\t"                                   \
+               "movs.l m0, @-r2\n\t"                                   \
+               "movs.l a1g, @-r2\n\t"                                  \
+               "movs.l a0g, @-r2\n\t"                                  \
+               "movs.l a1, @-r2\n\t"                                   \
+               "movs.l a0, @-r2\n\t"                                   \
+               : : "r" (__ts2));                                       \
+} while (0)
+
+#else
+
+#define is_dsp_enabled(tsk)    (0)
+#define __save_dsp(tsk)                do { } while (0)
+#define __restore_dsp(tsk)     do { } while (0)
+#endif
+
+struct task_struct *__switch_to(struct task_struct *prev,
+                               struct task_struct *next);
+
+/*
+ *     switch_to() should switch tasks to task nr n, first
+ */
+#define switch_to(prev, next, last)                            \
+do {                                                           \
+       register u32 *__ts1 __asm__ ("r1");                     \
+       register u32 *__ts2 __asm__ ("r2");                     \
+       register u32 *__ts4 __asm__ ("r4");                     \
+       register u32 *__ts5 __asm__ ("r5");                     \
+       register u32 *__ts6 __asm__ ("r6");                     \
+       register u32 __ts7 __asm__ ("r7");                      \
+       struct task_struct *__last;                             \
+                                                               \
+       if (is_dsp_enabled(prev))                               \
+               __save_dsp(prev);                               \
+                                                               \
+       __ts1 = (u32 *)&prev->thread.sp;                        \
+       __ts2 = (u32 *)&prev->thread.pc;                        \
+       __ts4 = (u32 *)prev;                                    \
+       __ts5 = (u32 *)next;                                    \
+       __ts6 = (u32 *)&next->thread.sp;                        \
+       __ts7 = next->thread.pc;                                \
+                                                               \
+       __asm__ __volatile__ (                                  \
+               ".balign 4\n\t"                                 \
+               "stc.l  gbr, @-r15\n\t"                         \
+               "sts.l  pr, @-r15\n\t"                          \
+               "mov.l  r8, @-r15\n\t"                          \
+               "mov.l  r9, @-r15\n\t"                          \
+               "mov.l  r10, @-r15\n\t"                         \
+               "mov.l  r11, @-r15\n\t"                         \
+               "mov.l  r12, @-r15\n\t"                         \
+               "mov.l  r13, @-r15\n\t"                         \
+               "mov.l  r14, @-r15\n\t"                         \
+               "mov.l  r15, @r1\t! save SP\n\t"                \
+               "mov.l  @r6, r15\t! change to new stack\n\t"    \
+               "mova   1f, %0\n\t"                             \
+               "mov.l  %0, @r2\t! save PC\n\t"                 \
+               "mov.l  2f, %0\n\t"                             \
+               "jmp    @%0\t! call __switch_to\n\t"            \
+               " lds   r7, pr\t!  with return to new PC\n\t"   \
+               ".balign        4\n"                            \
+               "2:\n\t"                                        \
+               ".long  __switch_to\n"                          \
+               "1:\n\t"                                        \
+               "mov.l  @r15+, r14\n\t"                         \
+               "mov.l  @r15+, r13\n\t"                         \
+               "mov.l  @r15+, r12\n\t"                         \
+               "mov.l  @r15+, r11\n\t"                         \
+               "mov.l  @r15+, r10\n\t"                         \
+               "mov.l  @r15+, r9\n\t"                          \
+               "mov.l  @r15+, r8\n\t"                          \
+               "lds.l  @r15+, pr\n\t"                          \
+               "ldc.l  @r15+, gbr\n\t"                         \
+               : "=z" (__last)                                 \
+               : "r" (__ts1), "r" (__ts2), "r" (__ts4),        \
+                 "r" (__ts5), "r" (__ts6), "r" (__ts7)         \
+               : "r3", "t");                                   \
+                                                               \
+       last = __last;                                          \
+} while (0)
+
+#define finish_arch_switch(prev)                               \
+do {                                                           \
+       if (is_dsp_enabled(prev))                               \
+               __restore_dsp(prev);                            \
+} while (0)
+
+#endif /* __ASM_SH_SWITCH_TO_32_H */
diff --git a/arch/sh/include/asm/switch_to_64.h b/arch/sh/include/asm/switch_to_64.h
new file mode 100644 (file)
index 0000000..ba3129d
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2000, 2001  Paolo Alberelli
+ * Copyright (C) 2003  Paul Mundt
+ * Copyright (C) 2004  Richard Curnow
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#ifndef __ASM_SH_SWITCH_TO_64_H
+#define __ASM_SH_SWITCH_TO_64_H
+
+struct thread_struct;
+struct task_struct;
+
+/*
+ *     switch_to() should switch tasks to task nr n, first
+ */
+struct task_struct *sh64_switch_to(struct task_struct *prev,
+                                  struct thread_struct *prev_thread,
+                                  struct task_struct *next,
+                                  struct thread_struct *next_thread);
+
+#define switch_to(prev,next,last)                              \
+do {                                                           \
+       if (last_task_used_math != next) {                      \
+               struct pt_regs *regs = next->thread.uregs;      \
+               if (regs) regs->sr |= SR_FD;                    \
+       }                                                       \
+       last = sh64_switch_to(prev, &prev->thread, next,        \
+                             &next->thread);                   \
+} while (0)
+
+
+#endif /* __ASM_SH_SWITCH_TO_64_H */
diff --git a/arch/sh/include/asm/system.h b/arch/sh/include/asm/system.h
deleted file mode 100644 (file)
index 10c8b18..0000000
+++ /dev/null
@@ -1,184 +0,0 @@
-#ifndef __ASM_SH_SYSTEM_H
-#define __ASM_SH_SYSTEM_H
-
-/*
- * Copyright (C) 1999, 2000  Niibe Yutaka  &  Kaz Kojima
- * Copyright (C) 2002 Paul Mundt
- */
-
-#include <linux/irqflags.h>
-#include <linux/compiler.h>
-#include <linux/linkage.h>
-#include <asm/types.h>
-#include <asm/uncached.h>
-
-#define AT_VECTOR_SIZE_ARCH 5 /* entries in ARCH_DLINFO */
-
-/*
- * A brief note on ctrl_barrier(), the control register write barrier.
- *
- * Legacy SH cores typically require a sequence of 8 nops after
- * modification of a control register in order for the changes to take
- * effect. On newer cores (like the sh4a and sh5) this is accomplished
- * with icbi.
- *
- * Also note that on sh4a in the icbi case we can forego a synco for the
- * write barrier, as it's not necessary for control registers.
- *
- * Historically we have only done this type of barrier for the MMUCR, but
- * it's also necessary for the CCR, so we make it generic here instead.
- */
-#if defined(CONFIG_CPU_SH4A) || defined(CONFIG_CPU_SH5)
-#define mb()           __asm__ __volatile__ ("synco": : :"memory")
-#define rmb()          mb()
-#define wmb()          __asm__ __volatile__ ("synco": : :"memory")
-#define ctrl_barrier() __icbi(PAGE_OFFSET)
-#define read_barrier_depends() do { } while(0)
-#else
-#define mb()           __asm__ __volatile__ ("": : :"memory")
-#define rmb()          mb()
-#define wmb()          __asm__ __volatile__ ("": : :"memory")
-#define ctrl_barrier() __asm__ __volatile__ ("nop;nop;nop;nop;nop;nop;nop;nop")
-#define read_barrier_depends() do { } while(0)
-#endif
-
-#ifdef CONFIG_SMP
-#define smp_mb()       mb()
-#define smp_rmb()      rmb()
-#define smp_wmb()      wmb()
-#define smp_read_barrier_depends()     read_barrier_depends()
-#else
-#define smp_mb()       barrier()
-#define smp_rmb()      barrier()
-#define smp_wmb()      barrier()
-#define smp_read_barrier_depends()     do { } while(0)
-#endif
-
-#define set_mb(var, value) do { (void)xchg(&var, value); } while (0)
-
-#ifdef CONFIG_GUSA_RB
-#include <asm/cmpxchg-grb.h>
-#elif defined(CONFIG_CPU_SH4A)
-#include <asm/cmpxchg-llsc.h>
-#else
-#include <asm/cmpxchg-irq.h>
-#endif
-
-extern void __xchg_called_with_bad_pointer(void);
-
-#define __xchg(ptr, x, size)                           \
-({                                                     \
-       unsigned long __xchg__res;                      \
-       volatile void *__xchg_ptr = (ptr);              \
-       switch (size) {                                 \
-       case 4:                                         \
-               __xchg__res = xchg_u32(__xchg_ptr, x);  \
-               break;                                  \
-       case 1:                                         \
-               __xchg__res = xchg_u8(__xchg_ptr, x);   \
-               break;                                  \
-       default:                                        \
-               __xchg_called_with_bad_pointer();       \
-               __xchg__res = x;                        \
-               break;                                  \
-       }                                               \
-                                                       \
-       __xchg__res;                                    \
-})
-
-#define xchg(ptr,x)    \
-       ((__typeof__(*(ptr)))__xchg((ptr),(unsigned long)(x), sizeof(*(ptr))))
-
-/* This function doesn't exist, so you'll get a linker error
- * if something tries to do an invalid cmpxchg(). */
-extern void __cmpxchg_called_with_bad_pointer(void);
-
-#define __HAVE_ARCH_CMPXCHG 1
-
-static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old,
-               unsigned long new, int size)
-{
-       switch (size) {
-       case 4:
-               return __cmpxchg_u32(ptr, old, new);
-       }
-       __cmpxchg_called_with_bad_pointer();
-       return old;
-}
-
-#define cmpxchg(ptr,o,n)                                                \
-  ({                                                                    \
-     __typeof__(*(ptr)) _o_ = (o);                                      \
-     __typeof__(*(ptr)) _n_ = (n);                                      \
-     (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,          \
-                                   (unsigned long)_n_, sizeof(*(ptr))); \
-  })
-
-struct pt_regs;
-
-extern void die(const char *str, struct pt_regs *regs, long err) __attribute__ ((noreturn));
-void free_initmem(void);
-void free_initrd_mem(unsigned long start, unsigned long end);
-
-extern void *set_exception_table_vec(unsigned int vec, void *handler);
-
-static inline void *set_exception_table_evt(unsigned int evt, void *handler)
-{
-       return set_exception_table_vec(evt >> 5, handler);
-}
-
-/*
- * SH-2A has both 16 and 32-bit opcodes, do lame encoding checks.
- */
-#ifdef CONFIG_CPU_SH2A
-extern unsigned int instruction_size(unsigned int insn);
-#elif defined(CONFIG_SUPERH32)
-#define instruction_size(insn) (2)
-#else
-#define instruction_size(insn) (4)
-#endif
-
-void per_cpu_trap_init(void);
-void default_idle(void);
-void cpu_idle_wait(void);
-void stop_this_cpu(void *);
-
-#ifdef CONFIG_SUPERH32
-#define BUILD_TRAP_HANDLER(name)                                       \
-asmlinkage void name##_trap_handler(unsigned long r4, unsigned long r5,        \
-                                   unsigned long r6, unsigned long r7, \
-                                   struct pt_regs __regs)
-
-#define TRAP_HANDLER_DECL                              \
-       struct pt_regs *regs = RELOC_HIDE(&__regs, 0);  \
-       unsigned int vec = regs->tra;                   \
-       (void)vec;
-#else
-#define BUILD_TRAP_HANDLER(name)       \
-asmlinkage void name##_trap_handler(unsigned int vec, struct pt_regs *regs)
-#define TRAP_HANDLER_DECL
-#endif
-
-BUILD_TRAP_HANDLER(address_error);
-BUILD_TRAP_HANDLER(debug);
-BUILD_TRAP_HANDLER(bug);
-BUILD_TRAP_HANDLER(breakpoint);
-BUILD_TRAP_HANDLER(singlestep);
-BUILD_TRAP_HANDLER(fpu_error);
-BUILD_TRAP_HANDLER(fpu_state_restore);
-BUILD_TRAP_HANDLER(nmi);
-
-#define arch_align_stack(x) (x)
-
-struct mem_access {
-       unsigned long (*from)(void *dst, const void __user *src, unsigned long cnt);
-       unsigned long (*to)(void __user *dst, const void *src, unsigned long cnt);
-};
-
-#ifdef CONFIG_SUPERH32
-# include "system_32.h"
-#else
-# include "system_64.h"
-#endif
-
-#endif
diff --git a/arch/sh/include/asm/system_32.h b/arch/sh/include/asm/system_32.h
deleted file mode 100644 (file)
index a4ad1cd..0000000
+++ /dev/null
@@ -1,236 +0,0 @@
-#ifndef __ASM_SH_SYSTEM_32_H
-#define __ASM_SH_SYSTEM_32_H
-
-#include <linux/types.h>
-#include <asm/mmu.h>
-
-#ifdef CONFIG_SH_DSP
-
-#define is_dsp_enabled(tsk)                                            \
-       (!!(tsk->thread.dsp_status.status & SR_DSP))
-
-#define __restore_dsp(tsk)                                             \
-do {                                                                   \
-       register u32 *__ts2 __asm__ ("r2") =                            \
-                       (u32 *)&tsk->thread.dsp_status;                 \
-       __asm__ __volatile__ (                                          \
-               ".balign 4\n\t"                                         \
-               "movs.l @r2+, a0\n\t"                                   \
-               "movs.l @r2+, a1\n\t"                                   \
-               "movs.l @r2+, a0g\n\t"                                  \
-               "movs.l @r2+, a1g\n\t"                                  \
-               "movs.l @r2+, m0\n\t"                                   \
-               "movs.l @r2+, m1\n\t"                                   \
-               "movs.l @r2+, x0\n\t"                                   \
-               "movs.l @r2+, x1\n\t"                                   \
-               "movs.l @r2+, y0\n\t"                                   \
-               "movs.l @r2+, y1\n\t"                                   \
-               "lds.l  @r2+, dsr\n\t"                                  \
-               "ldc.l  @r2+, rs\n\t"                                   \
-               "ldc.l  @r2+, re\n\t"                                   \
-               "ldc.l  @r2+, mod\n\t"                                  \
-               : : "r" (__ts2));                                       \
-} while (0)
-
-
-#define __save_dsp(tsk)                                                        \
-do {                                                                   \
-       register u32 *__ts2 __asm__ ("r2") =                            \
-                       (u32 *)&tsk->thread.dsp_status + 14;            \
-                                                                       \
-       __asm__ __volatile__ (                                          \
-               ".balign 4\n\t"                                         \
-               "stc.l  mod, @-r2\n\t"                                  \
-               "stc.l  re, @-r2\n\t"                                   \
-               "stc.l  rs, @-r2\n\t"                                   \
-               "sts.l  dsr, @-r2\n\t"                                  \
-               "movs.l y1, @-r2\n\t"                                   \
-               "movs.l y0, @-r2\n\t"                                   \
-               "movs.l x1, @-r2\n\t"                                   \
-               "movs.l x0, @-r2\n\t"                                   \
-               "movs.l m1, @-r2\n\t"                                   \
-               "movs.l m0, @-r2\n\t"                                   \
-               "movs.l a1g, @-r2\n\t"                                  \
-               "movs.l a0g, @-r2\n\t"                                  \
-               "movs.l a1, @-r2\n\t"                                   \
-               "movs.l a0, @-r2\n\t"                                   \
-               : : "r" (__ts2));                                       \
-} while (0)
-
-#else
-
-#define is_dsp_enabled(tsk)    (0)
-#define __save_dsp(tsk)                do { } while (0)
-#define __restore_dsp(tsk)     do { } while (0)
-#endif
-
-#if defined(CONFIG_CPU_SH4A)
-#define __icbi(addr)   __asm__ __volatile__ ( "icbi @%0\n\t" : : "r" (addr))
-#else
-#define __icbi(addr)   mb()
-#endif
-
-#define __ocbp(addr)   __asm__ __volatile__ ( "ocbp @%0\n\t" : : "r" (addr))
-#define __ocbi(addr)   __asm__ __volatile__ ( "ocbi @%0\n\t" : : "r" (addr))
-#define __ocbwb(addr)  __asm__ __volatile__ ( "ocbwb @%0\n\t" : : "r" (addr))
-
-struct task_struct *__switch_to(struct task_struct *prev,
-                               struct task_struct *next);
-
-/*
- *     switch_to() should switch tasks to task nr n, first
- */
-#define switch_to(prev, next, last)                            \
-do {                                                           \
-       register u32 *__ts1 __asm__ ("r1");                     \
-       register u32 *__ts2 __asm__ ("r2");                     \
-       register u32 *__ts4 __asm__ ("r4");                     \
-       register u32 *__ts5 __asm__ ("r5");                     \
-       register u32 *__ts6 __asm__ ("r6");                     \
-       register u32 __ts7 __asm__ ("r7");                      \
-       struct task_struct *__last;                             \
-                                                               \
-       if (is_dsp_enabled(prev))                               \
-               __save_dsp(prev);                               \
-                                                               \
-       __ts1 = (u32 *)&prev->thread.sp;                        \
-       __ts2 = (u32 *)&prev->thread.pc;                        \
-       __ts4 = (u32 *)prev;                                    \
-       __ts5 = (u32 *)next;                                    \
-       __ts6 = (u32 *)&next->thread.sp;                        \
-       __ts7 = next->thread.pc;                                \
-                                                               \
-       __asm__ __volatile__ (                                  \
-               ".balign 4\n\t"                                 \
-               "stc.l  gbr, @-r15\n\t"                         \
-               "sts.l  pr, @-r15\n\t"                          \
-               "mov.l  r8, @-r15\n\t"                          \
-               "mov.l  r9, @-r15\n\t"                          \
-               "mov.l  r10, @-r15\n\t"                         \
-               "mov.l  r11, @-r15\n\t"                         \
-               "mov.l  r12, @-r15\n\t"                         \
-               "mov.l  r13, @-r15\n\t"                         \
-               "mov.l  r14, @-r15\n\t"                         \
-               "mov.l  r15, @r1\t! save SP\n\t"                \
-               "mov.l  @r6, r15\t! change to new stack\n\t"    \
-               "mova   1f, %0\n\t"                             \
-               "mov.l  %0, @r2\t! save PC\n\t"                 \
-               "mov.l  2f, %0\n\t"                             \
-               "jmp    @%0\t! call __switch_to\n\t"            \
-               " lds   r7, pr\t!  with return to new PC\n\t"   \
-               ".balign        4\n"                            \
-               "2:\n\t"                                        \
-               ".long  __switch_to\n"                          \
-               "1:\n\t"                                        \
-               "mov.l  @r15+, r14\n\t"                         \
-               "mov.l  @r15+, r13\n\t"                         \
-               "mov.l  @r15+, r12\n\t"                         \
-               "mov.l  @r15+, r11\n\t"                         \
-               "mov.l  @r15+, r10\n\t"                         \
-               "mov.l  @r15+, r9\n\t"                          \
-               "mov.l  @r15+, r8\n\t"                          \
-               "lds.l  @r15+, pr\n\t"                          \
-               "ldc.l  @r15+, gbr\n\t"                         \
-               : "=z" (__last)                                 \
-               : "r" (__ts1), "r" (__ts2), "r" (__ts4),        \
-                 "r" (__ts5), "r" (__ts6), "r" (__ts7)         \
-               : "r3", "t");                                   \
-                                                               \
-       last = __last;                                          \
-} while (0)
-
-#define finish_arch_switch(prev)                               \
-do {                                                           \
-       if (is_dsp_enabled(prev))                               \
-               __restore_dsp(prev);                            \
-} while (0)
-
-#ifdef CONFIG_CPU_HAS_SR_RB
-#define lookup_exception_vector()      \
-({                                     \
-       unsigned long _vec;             \
-                                       \
-       __asm__ __volatile__ (          \
-               "stc r2_bank, %0\n\t"   \
-               : "=r" (_vec)           \
-       );                              \
-                                       \
-       _vec;                           \
-})
-#else
-#define lookup_exception_vector()      \
-({                                     \
-       unsigned long _vec;             \
-       __asm__ __volatile__ (          \
-               "mov r4, %0\n\t"        \
-               : "=r" (_vec)           \
-       );                              \
-                                       \
-       _vec;                           \
-})
-#endif
-
-static inline reg_size_t register_align(void *val)
-{
-       return (unsigned long)(signed long)val;
-}
-
-int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs,
-                           struct mem_access *ma, int, unsigned long address);
-
-static inline void trigger_address_error(void)
-{
-       __asm__ __volatile__ (
-               "ldc %0, sr\n\t"
-               "mov.l @%1, %0"
-               :
-               : "r" (0x10000000), "r" (0x80000001)
-       );
-}
-
-asmlinkage void do_address_error(struct pt_regs *regs,
-                                unsigned long writeaccess,
-                                unsigned long address);
-asmlinkage void do_divide_error(unsigned long r4, unsigned long r5,
-                               unsigned long r6, unsigned long r7,
-                               struct pt_regs __regs);
-asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5,
-                               unsigned long r6, unsigned long r7,
-                               struct pt_regs __regs);
-asmlinkage void do_illegal_slot_inst(unsigned long r4, unsigned long r5,
-                               unsigned long r6, unsigned long r7,
-                               struct pt_regs __regs);
-asmlinkage void do_exception_error(unsigned long r4, unsigned long r5,
-                                  unsigned long r6, unsigned long r7,
-                                  struct pt_regs __regs);
-
-static inline void set_bl_bit(void)
-{
-       unsigned long __dummy0, __dummy1;
-
-       __asm__ __volatile__ (
-               "stc    sr, %0\n\t"
-               "or     %2, %0\n\t"
-               "and    %3, %0\n\t"
-               "ldc    %0, sr\n\t"
-               : "=&r" (__dummy0), "=r" (__dummy1)
-               : "r" (0x10000000), "r" (0xffffff0f)
-               : "memory"
-       );
-}
-
-static inline void clear_bl_bit(void)
-{
-       unsigned long __dummy0, __dummy1;
-
-       __asm__ __volatile__ (
-               "stc    sr, %0\n\t"
-               "and    %2, %0\n\t"
-               "ldc    %0, sr\n\t"
-               : "=&r" (__dummy0), "=r" (__dummy1)
-               : "1" (~0x10000000)
-               : "memory"
-       );
-}
-
-#endif /* __ASM_SH_SYSTEM_32_H */
diff --git a/arch/sh/include/asm/system_64.h b/arch/sh/include/asm/system_64.h
deleted file mode 100644 (file)
index 8593bc8..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-#ifndef __ASM_SH_SYSTEM_64_H
-#define __ASM_SH_SYSTEM_64_H
-
-/*
- * include/asm-sh/system_64.h
- *
- * Copyright (C) 2000, 2001  Paolo Alberelli
- * Copyright (C) 2003  Paul Mundt
- * Copyright (C) 2004  Richard Curnow
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-#include <cpu/registers.h>
-#include <asm/processor.h>
-
-/*
- *     switch_to() should switch tasks to task nr n, first
- */
-struct thread_struct;
-struct task_struct *sh64_switch_to(struct task_struct *prev,
-                                  struct thread_struct *prev_thread,
-                                  struct task_struct *next,
-                                  struct thread_struct *next_thread);
-
-#define switch_to(prev,next,last)                              \
-do {                                                           \
-       if (last_task_used_math != next) {                      \
-               struct pt_regs *regs = next->thread.uregs;      \
-               if (regs) regs->sr |= SR_FD;                    \
-       }                                                       \
-       last = sh64_switch_to(prev, &prev->thread, next,        \
-                             &next->thread);                   \
-} while (0)
-
-#define __icbi(addr)   __asm__ __volatile__ ( "icbi %0, 0\n\t" : : "r" (addr))
-#define __ocbp(addr)   __asm__ __volatile__ ( "ocbp %0, 0\n\t" : : "r" (addr))
-#define __ocbi(addr)   __asm__ __volatile__ ( "ocbi %0, 0\n\t" : : "r" (addr))
-#define __ocbwb(addr)  __asm__ __volatile__ ( "ocbwb %0, 0\n\t" : : "r" (addr))
-
-static inline reg_size_t register_align(void *val)
-{
-       return (unsigned long long)(signed long long)(signed long)val;
-}
-
-extern void phys_stext(void);
-
-static inline void trigger_address_error(void)
-{
-       phys_stext();
-}
-
-#define SR_BL_LL       0x0000000010000000LL
-
-static inline void set_bl_bit(void)
-{
-       unsigned long long __dummy0, __dummy1 = SR_BL_LL;
-
-       __asm__ __volatile__("getcon    " __SR ", %0\n\t"
-                            "or        %0, %1, %0\n\t"
-                            "putcon    %0, " __SR "\n\t"
-                            : "=&r" (__dummy0)
-                            : "r" (__dummy1));
-
-}
-
-static inline void clear_bl_bit(void)
-{
-       unsigned long long __dummy0, __dummy1 = ~SR_BL_LL;
-
-       __asm__ __volatile__("getcon    " __SR ", %0\n\t"
-                            "and       %0, %1, %0\n\t"
-                            "putcon    %0, " __SR "\n\t"
-                            : "=&r" (__dummy0)
-                            : "r" (__dummy1));
-}
-
-#endif /* __ASM_SH_SYSTEM_64_H */
diff --git a/arch/sh/include/asm/traps.h b/arch/sh/include/asm/traps.h
new file mode 100644 (file)
index 0000000..afd9df8
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef __ASM_SH_TRAPS_H
+#define __ASM_SH_TRAPS_H
+
+#include <linux/compiler.h>
+
+#ifdef CONFIG_SUPERH32
+# include "traps_32.h"
+#else
+# include "traps_64.h"
+#endif
+
+BUILD_TRAP_HANDLER(address_error);
+BUILD_TRAP_HANDLER(debug);
+BUILD_TRAP_HANDLER(bug);
+BUILD_TRAP_HANDLER(breakpoint);
+BUILD_TRAP_HANDLER(singlestep);
+BUILD_TRAP_HANDLER(fpu_error);
+BUILD_TRAP_HANDLER(fpu_state_restore);
+BUILD_TRAP_HANDLER(nmi);
+
+#endif /* __ASM_SH_TRAPS_H */
diff --git a/arch/sh/include/asm/traps_32.h b/arch/sh/include/asm/traps_32.h
new file mode 100644 (file)
index 0000000..cfd55ff
--- /dev/null
@@ -0,0 +1,68 @@
+#ifndef __ASM_SH_TRAPS_32_H
+#define __ASM_SH_TRAPS_32_H
+
+#include <linux/types.h>
+#include <asm/mmu.h>
+
+#ifdef CONFIG_CPU_HAS_SR_RB
+#define lookup_exception_vector()      \
+({                                     \
+       unsigned long _vec;             \
+                                       \
+       __asm__ __volatile__ (          \
+               "stc r2_bank, %0\n\t"   \
+               : "=r" (_vec)           \
+       );                              \
+                                       \
+       _vec;                           \
+})
+#else
+#define lookup_exception_vector()      \
+({                                     \
+       unsigned long _vec;             \
+       __asm__ __volatile__ (          \
+               "mov r4, %0\n\t"        \
+               : "=r" (_vec)           \
+       );                              \
+                                       \
+       _vec;                           \
+})
+#endif
+
+static inline void trigger_address_error(void)
+{
+       __asm__ __volatile__ (
+               "ldc %0, sr\n\t"
+               "mov.l @%1, %0"
+               :
+               : "r" (0x10000000), "r" (0x80000001)
+       );
+}
+
+asmlinkage void do_address_error(struct pt_regs *regs,
+                                unsigned long writeaccess,
+                                unsigned long address);
+asmlinkage void do_divide_error(unsigned long r4, unsigned long r5,
+                               unsigned long r6, unsigned long r7,
+                               struct pt_regs __regs);
+asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5,
+                               unsigned long r6, unsigned long r7,
+                               struct pt_regs __regs);
+asmlinkage void do_illegal_slot_inst(unsigned long r4, unsigned long r5,
+                               unsigned long r6, unsigned long r7,
+                               struct pt_regs __regs);
+asmlinkage void do_exception_error(unsigned long r4, unsigned long r5,
+                                  unsigned long r6, unsigned long r7,
+                                  struct pt_regs __regs);
+
+#define BUILD_TRAP_HANDLER(name)                                       \
+asmlinkage void name##_trap_handler(unsigned long r4, unsigned long r5,        \
+                                   unsigned long r6, unsigned long r7, \
+                                   struct pt_regs __regs)
+
+#define TRAP_HANDLER_DECL                              \
+       struct pt_regs *regs = RELOC_HIDE(&__regs, 0);  \
+       unsigned int vec = regs->tra;                   \
+       (void)vec;
+
+#endif /* __ASM_SH_TRAPS_32_H */
diff --git a/arch/sh/include/asm/traps_64.h b/arch/sh/include/asm/traps_64.h
new file mode 100644 (file)
index 0000000..c52d7f9
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2000, 2001  Paolo Alberelli
+ * Copyright (C) 2003  Paul Mundt
+ * Copyright (C) 2004  Richard Curnow
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#ifndef __ASM_SH_TRAPS_64_H
+#define __ASM_SH_TRAPS_64_H
+
+extern void phys_stext(void);
+
+static inline void trigger_address_error(void)
+{
+       phys_stext();
+}
+
+#define BUILD_TRAP_HANDLER(name)       \
+asmlinkage void name##_trap_handler(unsigned int vec, struct pt_regs *regs)
+#define TRAP_HANDLER_DECL
+
+#endif /* __ASM_SH_TRAPS_64_H */
index 075848f..050f221 100644 (file)
@@ -254,5 +254,19 @@ int fixup_exception(struct pt_regs *regs);
 unsigned long search_exception_table(unsigned long addr);
 const struct exception_table_entry *search_exception_tables(unsigned long addr);
 
+extern void *set_exception_table_vec(unsigned int vec, void *handler);
+
+static inline void *set_exception_table_evt(unsigned int evt, void *handler)
+{
+       return set_exception_table_vec(evt >> 5, handler);
+}
+
+struct mem_access {
+       unsigned long (*from)(void *dst, const void __user *src, unsigned long cnt);
+       unsigned long (*to)(void __user *dst, const void *src, unsigned long cnt);
+};
+
+int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs,
+                           struct mem_access *ma, int, unsigned long address);
 
 #endif /* __ASM_SH_UACCESS_H */
index fac742e..61a07da 100644 (file)
 #include <asm/processor.h>
 #include <asm/uaccess.h>
 #include <asm/page.h>
-#include <asm/system.h>
 #include <asm/cacheflush.h>
 #include <asm/cache.h>
 #include <asm/elf.h>
 #include <asm/io.h>
 #include <asm/smp.h>
 #include <asm/sh_bios.h>
+#include <asm/setup.h>
 
 #ifdef CONFIG_SH_FPU
 #define cpu_has_fpu    1
index 39b6a24..e7f1745 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/cache.h>
 #include <linux/irq.h>
 #include <linux/bitmap.h>
-#include <asm/system.h>
 #include <asm/irq.h>
 
 /* Bitmap of IRQ masked */
index 9704b79..72aa61c 100644 (file)
@@ -10,7 +10,6 @@
  * for more details.
  */
 #include <linux/kernel.h>
-#include <asm/system.h>
 
 /*
  * Instructions on SH are generally fixed at 16-bits, however, SH-2A
index 447482d..e74cd6c 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/io.h>
 #include <cpu/fpu.h>
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/fpu.h>
 
 /* The PR (precision) bit in the FP Status Register must be clear when
index efae6ab..f917376 100644 (file)
@@ -22,6 +22,7 @@
 #include <asm/hw_breakpoint.h>
 #include <asm/mmu_context.h>
 #include <asm/ptrace.h>
+#include <asm/traps.h>
 
 /*
  * Stores the breakpoints currently in use on each breakpoint address
index 7e48928..64852ec 100644 (file)
@@ -18,9 +18,9 @@
 #include <linux/smp.h>
 #include <linux/cpuidle.h>
 #include <asm/pgalloc.h>
-#include <asm/system.h>
 #include <linux/atomic.h>
 #include <asm/smp.h>
+#include <asm/bl_bit.h>
 
 void (*pm_idle)(void);
 
index 0f62f46..c0a9761 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/vmalloc.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <asm/system.h>
 #include <asm/mmu_context.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
index 7ec6651..f72e3a9 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/prefetch.h>
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
-#include <asm/system.h>
 #include <asm/fpu.h>
 #include <asm/syscalls.h>
 
index cbd4e4b..4264583 100644 (file)
@@ -30,6 +30,7 @@
 #include <asm/pgtable.h>
 #include <asm/mmu_context.h>
 #include <asm/fpu.h>
+#include <asm/switch_to.h>
 
 struct task_struct *last_task_used_math = NULL;
 
index a3e6515..9698671 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/hw_breakpoint.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/processor.h>
 #include <asm/mmu_context.h>
 #include <asm/syscalls.h>
index 3d0080b..bc81e07 100644 (file)
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/processor.h>
 #include <asm/mmu_context.h>
 #include <asm/syscalls.h>
 #include <asm/fpu.h>
+#include <asm/traps.h>
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/syscalls.h>
index ca6a5ca..04afe5b 100644 (file)
@@ -8,8 +8,8 @@
 #endif
 #include <asm/addrspace.h>
 #include <asm/reboot.h>
-#include <asm/system.h>
 #include <asm/tlbflush.h>
+#include <asm/traps.h>
 
 void (*pm_power_off)(void);
 EXPORT_SYMBOL(pm_power_off);
index a7a55ed..0bc5886 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/freezer.h>
 #include <linux/io.h>
 #include <linux/tracehook.h>
-#include <asm/system.h>
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
index f624174..a17a14d 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/sched.h>
 #include <linux/atomic.h>
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/mmu_context.h>
 #include <asm/smp.h>
 #include <asm/cacheflush.h>
index 0830c2a..a87e58a 100644 (file)
@@ -7,7 +7,7 @@
 #include <linux/uaccess.h>
 #include <linux/hardirq.h>
 #include <asm/unwinder.h>
-#include <asm/system.h>
+#include <asm/traps.h>
 
 #ifdef CONFIG_GENERIC_BUG
 static void handle_BUG(struct pt_regs *regs)
index 7bbef95..a37175d 100644 (file)
 #include <linux/sysfs.h>
 #include <linux/uaccess.h>
 #include <linux/perf_event.h>
-#include <asm/system.h>
 #include <asm/alignment.h>
 #include <asm/fpu.h>
 #include <asm/kprobes.h>
+#include <asm/traps.h>
+#include <asm/bl_bit.h>
 
 #ifdef CONFIG_CPU_SH2
 # define TRAP_RESERVED_INST    4
index cd3a404..6c04860 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/sysctl.h>
 #include <linux/module.h>
 #include <linux/perf_event.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <linux/atomic.h>
index 9771952..b876780 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/signal.h>
 #include <linux/perf_event.h>
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/processor.h>
 #include <asm/io.h>
index 7bebd04..324eef9 100644 (file)
@@ -17,9 +17,9 @@
 #include <linux/kprobes.h>
 #include <linux/perf_event.h>
 #include <asm/io_trapped.h>
-#include <asm/system.h>
 #include <asm/mmu_context.h>
 #include <asm/tlbflush.h>
+#include <asm/traps.h>
 
 static inline int notify_page_fault(struct pt_regs *regs, int trap)
 {
index 2b356ce..44a3410 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/mm.h>
 #include <linux/smp.h>
 #include <linux/interrupt.h>
-#include <asm/system.h>
 #include <asm/tlb.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
index cef4026..75a17f5 100644 (file)
@@ -1,6 +1,7 @@
 #include <linux/mm.h>
 #include <asm/mmu_context.h>
 #include <asm/cacheflush.h>
+#include <asm/traps.h>
 
 /*
  * Write back the dirty D-caches, but not invalidate them.
index fad52f1..7160c9f 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/vmalloc.h>
 #include <asm/cacheflush.h>
 #include <asm/sizes.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
index b71db6a..4db21ad 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/io.h>
-#include <asm/system.h>
 #include <asm/mmu_context.h>
 #include <asm/cacheflush.h>
 
index 7a940db..6554fb4 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/smp.h>
 #include <linux/interrupt.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
index cfdf793..d42dd7e 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/io.h>
-#include <asm/system.h>
 #include <asm/mmu_context.h>
 #include <asm/cacheflush.h>
 
index e3430e0..11c5a18 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/smp.h>
 #include <linux/perf_event.h>
 #include <linux/interrupt.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/tlb.h>
 #include <asm/uaccess.h>
index 9dd0a76..905832a 100644 (file)
@@ -13,9 +13,9 @@
 
 #include <linux/types.h>
 
+#include <asm/cmpxchg.h>
 #include <asm-generic/atomic64.h>
 
-#include <asm/system.h>
 
 #define ATOMIC_INIT(i)  { (i) }
 
index 9f421df..ce35a1c 100644 (file)
@@ -8,7 +8,7 @@
 #define __ARCH_SPARC64_ATOMIC__
 
 #include <linux/types.h>
-#include <asm/system.h>
+#include <asm/cmpxchg.h>
 
 #define ATOMIC_INIT(i)         { (i) }
 #define ATOMIC64_INIT(i)       { (i) }
@@ -85,7 +85,6 @@ static inline int __atomic_add_unless(atomic_t *v, int a, int u)
        return c;
 }
 
-
 #define atomic64_cmpxchg(v, o, n) \
        ((__typeof__((v)->counter))cmpxchg(&((v)->counter), (o), (n)))
 #define atomic64_xchg(v, new) (xchg(&((v)->counter), new))
index e03e088..3a31977 100644 (file)
@@ -6,7 +6,6 @@
 #ifndef _SPARC_AUXIO_H
 #define _SPARC_AUXIO_H
 
-#include <asm/system.h>
 #include <asm/vaddrs.h>
 
 /* This register is an unsigned char in IO space.  It does two things.
diff --git a/arch/sparc/include/asm/barrier.h b/arch/sparc/include/asm/barrier.h
new file mode 100644 (file)
index 0000000..b25f02a
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef ___ASM_SPARC_BARRIER_H
+#define ___ASM_SPARC_BARRIER_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/barrier_64.h>
+#else
+#include <asm/barrier_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/barrier_32.h b/arch/sparc/include/asm/barrier_32.h
new file mode 100644 (file)
index 0000000..c1b7665
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef __SPARC_BARRIER_H
+#define __SPARC_BARRIER_H
+
+/* XXX Change this if we ever use a PSO mode kernel. */
+#define mb()   __asm__ __volatile__ ("" : : : "memory")
+#define rmb()  mb()
+#define wmb()  mb()
+#define read_barrier_depends() do { } while(0)
+#define set_mb(__var, __value)  do { __var = __value; mb(); } while(0)
+#define smp_mb()       __asm__ __volatile__("":::"memory")
+#define smp_rmb()      __asm__ __volatile__("":::"memory")
+#define smp_wmb()      __asm__ __volatile__("":::"memory")
+#define smp_read_barrier_depends()     do { } while(0)
+
+#endif /* !(__SPARC_BARRIER_H) */
diff --git a/arch/sparc/include/asm/barrier_64.h b/arch/sparc/include/asm/barrier_64.h
new file mode 100644 (file)
index 0000000..95d4598
--- /dev/null
@@ -0,0 +1,56 @@
+#ifndef __SPARC64_BARRIER_H
+#define __SPARC64_BARRIER_H
+
+/* These are here in an effort to more fully work around Spitfire Errata
+ * #51.  Essentially, if a memory barrier occurs soon after a mispredicted
+ * branch, the chip can stop executing instructions until a trap occurs.
+ * Therefore, if interrupts are disabled, the chip can hang forever.
+ *
+ * It used to be believed that the memory barrier had to be right in the
+ * delay slot, but a case has been traced recently wherein the memory barrier
+ * was one instruction after the branch delay slot and the chip still hung.
+ * The offending sequence was the following in sym_wakeup_done() of the
+ * sym53c8xx_2 driver:
+ *
+ *     call    sym_ccb_from_dsa, 0
+ *      movge  %icc, 0, %l0
+ *     brz,pn  %o0, .LL1303
+ *      mov    %o0, %l2
+ *     membar  #LoadLoad
+ *
+ * The branch has to be mispredicted for the bug to occur.  Therefore, we put
+ * the memory barrier explicitly into a "branch always, predicted taken"
+ * delay slot to avoid the problem case.
+ */
+#define membar_safe(type) \
+do {   __asm__ __volatile__("ba,pt     %%xcc, 1f\n\t" \
+                            " membar   " type "\n" \
+                            "1:\n" \
+                            : : : "memory"); \
+} while (0)
+
+/* The kernel always executes in TSO memory model these days,
+ * and furthermore most sparc64 chips implement more stringent
+ * memory ordering than required by the specifications.
+ */
+#define mb()   membar_safe("#StoreLoad")
+#define rmb()  __asm__ __volatile__("":::"memory")
+#define wmb()  __asm__ __volatile__("":::"memory")
+
+#define read_barrier_depends()         do { } while(0)
+#define set_mb(__var, __value) \
+       do { __var = __value; membar_safe("#StoreLoad"); } while(0)
+
+#ifdef CONFIG_SMP
+#define smp_mb()       mb()
+#define smp_rmb()      rmb()
+#define smp_wmb()      wmb()
+#else
+#define smp_mb()       __asm__ __volatile__("":::"memory")
+#define smp_rmb()      __asm__ __volatile__("":::"memory")
+#define smp_wmb()      __asm__ __volatile__("":::"memory")
+#endif
+
+#define smp_read_barrier_depends()     do { } while(0)
+
+#endif /* !(__SPARC64_BARRIER_H) */
index 8a59e5a..6bd9f43 100644 (file)
@@ -19,4 +19,7 @@ extern void do_BUG(const char *file, int line);
 
 #include <asm-generic/bug.h>
 
+struct pt_regs;
+extern void die_if_kernel(char *str, struct pt_regs *regs) __attribute__ ((noreturn));
+
 #endif
index 2e46877..68431b4 100644 (file)
@@ -83,4 +83,13 @@ extern void sparc_flush_page_to_ram(struct page *page);
 #define flush_cache_vmap(start, end)           flush_cache_all()
 #define flush_cache_vunmap(start, end)         flush_cache_all()
 
+/* When a context switch happens we must flush all user windows so that
+ * the windows of the current process are flushed onto its stack. This
+ * way the windows are all clean for the next process and the stack
+ * frames are up to date.
+ */
+extern void flush_user_windows(void);
+extern void kill_user_windows(void);
+extern void flushw_all(void);
+
 #endif /* _SPARC_CACHEFLUSH_H */
index b953840..2efea2f 100644 (file)
@@ -9,6 +9,16 @@
 
 /* Cache flush operations. */
 
+
+#define flushi(addr)   __asm__ __volatile__ ("flush %0" : : "r" (addr) : "memory")
+#define flushw_all()   __asm__ __volatile__("flushw")
+
+extern void __flushw_user(void);
+#define flushw_user() __flushw_user()
+
+#define flush_user_windows flushw_user
+#define flush_register_windows flushw_all
+
 /* These are the same regardless of whether this is an SMP kernel or not. */
 #define flush_cache_mm(__mm) \
        do { if ((__mm) == current->mm) flushw_user(); } while(0)
diff --git a/arch/sparc/include/asm/cmpxchg.h b/arch/sparc/include/asm/cmpxchg.h
new file mode 100644 (file)
index 0000000..9355893
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef ___ASM_SPARC_CMPXCHG_H
+#define ___ASM_SPARC_CMPXCHG_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/cmpxchg_64.h>
+#else
+#include <asm/cmpxchg_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/cmpxchg_32.h b/arch/sparc/include/asm/cmpxchg_32.h
new file mode 100644 (file)
index 0000000..c786b0a
--- /dev/null
@@ -0,0 +1,112 @@
+/* 32-bit atomic xchg() and cmpxchg() definitions.
+ *
+ * Copyright (C) 1996 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 2000 Anton Blanchard (anton@linuxcare.com.au)
+ * Copyright (C) 2007 Kyle McMartin (kyle@parisc-linux.org)
+ *
+ * Additions by Keith M Wesolowski (wesolows@foobazco.org) based
+ * on asm-parisc/atomic.h Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>.
+ */
+
+#ifndef __ARCH_SPARC_CMPXCHG__
+#define __ARCH_SPARC_CMPXCHG__
+
+#include <asm/btfixup.h>
+
+/* This has special calling conventions */
+#ifndef CONFIG_SMP
+BTFIXUPDEF_CALL(void, ___xchg32, void)
+#endif
+
+static inline unsigned long xchg_u32(__volatile__ unsigned long *m, unsigned long val)
+{
+#ifdef CONFIG_SMP
+       __asm__ __volatile__("swap [%2], %0"
+                            : "=&r" (val)
+                            : "0" (val), "r" (m)
+                            : "memory");
+       return val;
+#else
+       register unsigned long *ptr asm("g1");
+       register unsigned long ret asm("g2");
+
+       ptr = (unsigned long *) m;
+       ret = val;
+
+       /* Note: this is magic and the nop there is
+          really needed. */
+       __asm__ __volatile__(
+       "mov    %%o7, %%g4\n\t"
+       "call   ___f____xchg32\n\t"
+       " nop\n\t"
+       : "=&r" (ret)
+       : "0" (ret), "r" (ptr)
+       : "g3", "g4", "g7", "memory", "cc");
+
+       return ret;
+#endif
+}
+
+extern void __xchg_called_with_bad_pointer(void);
+
+static inline unsigned long __xchg(unsigned long x, __volatile__ void * ptr, int size)
+{
+       switch (size) {
+       case 4:
+               return xchg_u32(ptr, x);
+       }
+       __xchg_called_with_bad_pointer();
+       return x;
+}
+
+#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
+
+/* Emulate cmpxchg() the same way we emulate atomics,
+ * by hashing the object address and indexing into an array
+ * of spinlocks to get a bit of performance...
+ *
+ * See arch/sparc/lib/atomic32.c for implementation.
+ *
+ * Cribbed from <asm-parisc/atomic.h>
+ */
+#define __HAVE_ARCH_CMPXCHG    1
+
+/* bug catcher for when unsupported size is used - won't link */
+extern void __cmpxchg_called_with_bad_pointer(void);
+/* we only need to support cmpxchg of a u32 on sparc */
+extern unsigned long __cmpxchg_u32(volatile u32 *m, u32 old, u32 new_);
+
+/* don't worry...optimizer will get rid of most of this */
+static inline unsigned long
+__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new_, int size)
+{
+       switch (size) {
+       case 4:
+               return __cmpxchg_u32((u32 *)ptr, (u32)old, (u32)new_);
+       default:
+               __cmpxchg_called_with_bad_pointer();
+               break;
+       }
+       return old;
+}
+
+#define cmpxchg(ptr, o, n)                                             \
+({                                                                     \
+       __typeof__(*(ptr)) _o_ = (o);                                   \
+       __typeof__(*(ptr)) _n_ = (n);                                   \
+       (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,       \
+                       (unsigned long)_n_, sizeof(*(ptr)));            \
+})
+
+#include <asm-generic/cmpxchg-local.h>
+
+/*
+ * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
+ * them available.
+ */
+#define cmpxchg_local(ptr, o, n)                                              \
+       ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
+                       (unsigned long)(n), sizeof(*(ptr))))
+#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
+
+#endif /* __ARCH_SPARC_CMPXCHG__ */
diff --git a/arch/sparc/include/asm/cmpxchg_64.h b/arch/sparc/include/asm/cmpxchg_64.h
new file mode 100644 (file)
index 0000000..b30eb37
--- /dev/null
@@ -0,0 +1,145 @@
+/* 64-bit atomic xchg() and cmpxchg() definitions.
+ *
+ * Copyright (C) 1996, 1997, 2000 David S. Miller (davem@redhat.com)
+ */
+
+#ifndef __ARCH_SPARC64_CMPXCHG__
+#define __ARCH_SPARC64_CMPXCHG__
+
+static inline unsigned long xchg32(__volatile__ unsigned int *m, unsigned int val)
+{
+       unsigned long tmp1, tmp2;
+
+       __asm__ __volatile__(
+"      mov             %0, %1\n"
+"1:    lduw            [%4], %2\n"
+"      cas             [%4], %2, %0\n"
+"      cmp             %2, %0\n"
+"      bne,a,pn        %%icc, 1b\n"
+"       mov            %1, %0\n"
+       : "=&r" (val), "=&r" (tmp1), "=&r" (tmp2)
+       : "0" (val), "r" (m)
+       : "cc", "memory");
+       return val;
+}
+
+static inline unsigned long xchg64(__volatile__ unsigned long *m, unsigned long val)
+{
+       unsigned long tmp1, tmp2;
+
+       __asm__ __volatile__(
+"      mov             %0, %1\n"
+"1:    ldx             [%4], %2\n"
+"      casx            [%4], %2, %0\n"
+"      cmp             %2, %0\n"
+"      bne,a,pn        %%xcc, 1b\n"
+"       mov            %1, %0\n"
+       : "=&r" (val), "=&r" (tmp1), "=&r" (tmp2)
+       : "0" (val), "r" (m)
+       : "cc", "memory");
+       return val;
+}
+
+#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
+
+extern void __xchg_called_with_bad_pointer(void);
+
+static inline unsigned long __xchg(unsigned long x, __volatile__ void * ptr,
+                                      int size)
+{
+       switch (size) {
+       case 4:
+               return xchg32(ptr, x);
+       case 8:
+               return xchg64(ptr, x);
+       }
+       __xchg_called_with_bad_pointer();
+       return x;
+}
+
+/*
+ * Atomic compare and exchange.  Compare OLD with MEM, if identical,
+ * store NEW in MEM.  Return the initial value in MEM.  Success is
+ * indicated by comparing RETURN with OLD.
+ */
+
+#include <asm-generic/cmpxchg-local.h>
+
+#define __HAVE_ARCH_CMPXCHG 1
+
+static inline unsigned long
+__cmpxchg_u32(volatile int *m, int old, int new)
+{
+       __asm__ __volatile__("cas [%2], %3, %0"
+                            : "=&r" (new)
+                            : "0" (new), "r" (m), "r" (old)
+                            : "memory");
+
+       return new;
+}
+
+static inline unsigned long
+__cmpxchg_u64(volatile long *m, unsigned long old, unsigned long new)
+{
+       __asm__ __volatile__("casx [%2], %3, %0"
+                            : "=&r" (new)
+                            : "0" (new), "r" (m), "r" (old)
+                            : "memory");
+
+       return new;
+}
+
+/* This function doesn't exist, so you'll get a linker error
+   if something tries to do an invalid cmpxchg().  */
+extern void __cmpxchg_called_with_bad_pointer(void);
+
+static inline unsigned long
+__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
+{
+       switch (size) {
+               case 4:
+                       return __cmpxchg_u32(ptr, old, new);
+               case 8:
+                       return __cmpxchg_u64(ptr, old, new);
+       }
+       __cmpxchg_called_with_bad_pointer();
+       return old;
+}
+
+#define cmpxchg(ptr,o,n)                                                \
+  ({                                                                    \
+     __typeof__(*(ptr)) _o_ = (o);                                      \
+     __typeof__(*(ptr)) _n_ = (n);                                      \
+     (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,          \
+                                   (unsigned long)_n_, sizeof(*(ptr))); \
+  })
+
+/*
+ * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
+ * them available.
+ */
+
+static inline unsigned long __cmpxchg_local(volatile void *ptr,
+                                     unsigned long old,
+                                     unsigned long new, int size)
+{
+       switch (size) {
+       case 4:
+       case 8: return __cmpxchg(ptr, old, new, size);
+       default:
+               return __cmpxchg_local_generic(ptr, old, new, size);
+       }
+
+       return old;
+}
+
+#define cmpxchg_local(ptr, o, n)                                       \
+       ((__typeof__(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(o), \
+                       (unsigned long)(n), sizeof(*(ptr))))
+#define cmpxchg64_local(ptr, o, n)                                     \
+  ({                                                                   \
+       BUILD_BUG_ON(sizeof(*(ptr)) != 8);                              \
+       cmpxchg_local((ptr), (o), (n));                                 \
+  })
+
+#endif /* __ARCH_SPARC64_CMPXCHG__ */
diff --git a/arch/sparc/include/asm/cpu_type.h b/arch/sparc/include/asm/cpu_type.h
new file mode 100644 (file)
index 0000000..4ca184d
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef __ASM_CPU_TYPE_H
+#define __ASM_CPU_TYPE_H
+
+/*
+ * Sparc (general) CPU types
+ */
+enum sparc_cpu {
+  sun4        = 0x00,
+  sun4c       = 0x01,
+  sun4m       = 0x02,
+  sun4d       = 0x03,
+  sun4e       = 0x04,
+  sun4u       = 0x05, /* V8 ploos ploos */
+  sun_unknown = 0x06,
+  ap1000      = 0x07, /* almost a sun4m */
+  sparc_leon  = 0x08, /* Leon SoC */
+};
+
+#ifdef CONFIG_SPARC32
+extern enum sparc_cpu sparc_cpu_model;
+
+#define ARCH_SUN4C (sparc_cpu_model==sun4c)
+
+#define SUN4M_NCPUS            4              /* Architectural limit of sun4m. */
+
+#else
+
+#define sparc_cpu_model sun4u
+
+/* This cannot ever be a sun4c :) That's just history. */
+#define ARCH_SUN4C 0
+#endif
+
+#endif /* __ASM_CPU_TYPE_H */
diff --git a/arch/sparc/include/asm/exec.h b/arch/sparc/include/asm/exec.h
new file mode 100644 (file)
index 0000000..2e08588
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __SPARC_EXEC_H
+#define __SPARC_EXEC_H
+
+#define arch_align_stack(x) (x)
+
+#endif /* __SPARC_EXEC_H */
index 7440915..698d955 100644 (file)
@@ -11,7 +11,6 @@
 
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/idprom.h>
 #include <asm/machines.h>
 #include <asm/oplib.h>
index 444e7be..4e899b0 100644 (file)
@@ -4,7 +4,6 @@
 #include <linux/futex.h>
 #include <linux/uaccess.h>
 #include <asm/errno.h>
-#include <asm/system.h>
 
 #define __futex_cas_op(insn, ret, oldval, uaddr, oparg)        \
        __asm__ __volatile__(                           \
index 2006e5d..c1acbd8 100644 (file)
@@ -6,7 +6,6 @@
 #include <linux/ioport.h>  /* struct resource */
 
 #include <asm/page.h>      /* IO address mapping routines need this */
-#include <asm/system.h>
 #include <asm-generic/pci_iomap.h>
 
 #define page_to_phys(page)     (page_to_pfn(page) << PAGE_SHIFT)
index 9481e5a..09b0b88 100644 (file)
@@ -6,7 +6,6 @@
 #include <linux/types.h>
 
 #include <asm/page.h>      /* IO address mapping routines need this */
-#include <asm/system.h>
 #include <asm/asi.h>
 #include <asm-generic/pci_iomap.h>
 
index 1484890..e414c06 100644 (file)
@@ -13,6 +13,7 @@
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
+#include <asm/psr.h>
 
 extern void arch_local_irq_restore(unsigned long);
 extern unsigned long arch_local_irq_save(void);
index 666a73f..a97fd08 100644 (file)
@@ -6,7 +6,6 @@
 #ifndef __ASSEMBLY__
 
 #include <linux/spinlock.h>
-#include <asm/system.h>
 #include <asm/spitfire.h>
 #include <asm-generic/mm_hooks.h>
 
index af75548..6b947ee 100644 (file)
@@ -79,7 +79,6 @@
 
 #include <linux/spinlock.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 
 extern spinlock_t ns87303_lock;
index 8d8720a..3332d2c 100644 (file)
@@ -168,6 +168,29 @@ struct vcounter_struct {
   unsigned long long vcnt1;
 };
 
+#else /* !(__KERNEL__) */
+
+#ifndef CONFIG_SPARC32
+
+/* Performance counter register access. */
+#define read_pcr(__p)  __asm__ __volatile__("rd        %%pcr, %0" : "=r" (__p))
+#define write_pcr(__p) __asm__ __volatile__("wr        %0, 0x0, %%pcr" : : "r" (__p))
+#define read_pic(__p)  __asm__ __volatile__("rd %%pic, %0" : "=r" (__p))
+
+/* Blackbird errata workaround.  See commentary in
+ * arch/sparc64/kernel/smp.c:smp_percpu_timer_interrupt()
+ * for more information.
+ */
+#define write_pic(__p)                                         \
+       __asm__ __volatile__("ba,pt     %%xcc, 99f\n\t"         \
+                            " nop\n\t"                         \
+                            ".align    64\n"                   \
+                         "99:wr        %0, 0x0, %%pic\n\t"     \
+                            "rd        %%pic, %%g0" : : "r" (__p))
+#define reset_pic()    write_pic(0)
+
+#endif /* !CONFIG_SPARC32 */
+
 #endif /* !(__KERNEL__) */
 
 #endif /* !(PERF_COUNTER_API) */
index a790cc6..3d71018 100644 (file)
@@ -21,7 +21,7 @@
 #include <asm/vac-ops.h>
 #include <asm/oplib.h>
 #include <asm/btfixup.h>
-#include <asm/system.h>
+#include <asm/cpu_type.h>
 
 
 struct vm_area_struct;
index 38ebb2c..6fa2f79 100644 (file)
@@ -19,7 +19,6 @@
 #include <asm/types.h>
 #include <asm/spitfire.h>
 #include <asm/asi.h>
-#include <asm/system.h>
 #include <asm/page.h>
 #include <asm/processor.h>
 
index 9da9646..2fe99e6 100644 (file)
@@ -5,4 +5,7 @@
 #else
 #include <asm/processor_32.h>
 #endif
+
+#define nop()          __asm__ __volatile__ ("nop")
+
 #endif
index 59fcebb..e713db2 100644 (file)
@@ -18,6 +18,9 @@
 #include <asm/ptrace.h>
 #include <asm/page.h>
 
+/* Don't hold the runqueue lock over context switch */
+#define __ARCH_WANT_UNLOCKED_CTXSW
+
 /* The sparc has no problems with write protection */
 #define wp_works_ok 1
 #define wp_works_ok__is_a_macro /* for versions in ksyms.c */
index c00c3b5..ef8c7c0 100644 (file)
@@ -98,6 +98,8 @@ struct sparc_trapf {
  */
 #ifndef __ASSEMBLY__
 
+#include <linux/types.h>
+
 struct pt_regs {
        unsigned long psr;
        unsigned long pc;
@@ -163,7 +165,6 @@ struct sparc_stackf {
 #ifdef __KERNEL__
 
 #include <linux/threads.h>
-#include <asm/system.h>
 
 static inline int pt_regs_trap_type(struct pt_regs *regs)
 {
@@ -240,8 +241,6 @@ extern unsigned long profile_pc(struct pt_regs *);
 
 #ifdef __KERNEL__
 
-#include <asm/system.h>
-
 static inline bool pt_regs_is_syscall(struct pt_regs *regs)
 {
        return (regs->psr & PSR_SYSCALL);
index 64718ba..00497ab 100644 (file)
 
 #ifdef __KERNEL__
 
+extern char reboot_command[];
+
 #ifdef CONFIG_SPARC32
 /* The CPU that was used for booting
  * Only sun4d + leon may have boot_cpu_id != 0
  */
 extern unsigned char boot_cpu_id;
 extern unsigned char boot_cpu_id4;
+
+extern unsigned long empty_bad_page;
+extern unsigned long empty_bad_page_table;
+extern unsigned long empty_zero_page;
+
+extern int serial_console;
+static inline int con_is_present(void)
+{
+       return serial_console ? 0 : 1;
+}
 #endif
 
+extern void sun_do_break(void);
+extern int stop_a_enabled;
+extern int scons_pwroff;
+
 #endif /* __KERNEL__ */
 
 #endif /* _SPARC_SETUP_H */
diff --git a/arch/sparc/include/asm/switch_to.h b/arch/sparc/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..2dc4fa5
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef ___ASM_SPARC_SWITCH_TO_H
+#define ___ASM_SPARC_SWITCH_TO_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/switch_to_64.h>
+#else
+#include <asm/switch_to_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/switch_to_32.h b/arch/sparc/include/asm/switch_to_32.h
new file mode 100644 (file)
index 0000000..e32e82b
--- /dev/null
@@ -0,0 +1,106 @@
+#ifndef __SPARC_SWITCH_TO_H
+#define __SPARC_SWITCH_TO_H
+
+#include <asm/smp.h>
+
+extern struct thread_info *current_set[NR_CPUS];
+
+/*
+ * Flush windows so that the VM switch which follows
+ * would not pull the stack from under us.
+ *
+ * SWITCH_ENTER and SWITH_DO_LAZY_FPU do not work yet (e.g. SMP does not work)
+ * XXX WTF is the above comment? Found in late teen 2.4.x.
+ */
+#ifdef CONFIG_SMP
+#define SWITCH_ENTER(prv) \
+       do {                    \
+       if (test_tsk_thread_flag(prv, TIF_USEDFPU)) { \
+               put_psr(get_psr() | PSR_EF); \
+               fpsave(&(prv)->thread.float_regs[0], &(prv)->thread.fsr, \
+                      &(prv)->thread.fpqueue[0], &(prv)->thread.fpqdepth); \
+               clear_tsk_thread_flag(prv, TIF_USEDFPU); \
+               (prv)->thread.kregs->psr &= ~PSR_EF; \
+       } \
+       } while(0)
+
+#define SWITCH_DO_LAZY_FPU(next)       /* */
+#else
+#define SWITCH_ENTER(prv)              /* */
+#define SWITCH_DO_LAZY_FPU(nxt)        \
+       do {                    \
+       if (last_task_used_math != (nxt))               \
+               (nxt)->thread.kregs->psr&=~PSR_EF;      \
+       } while(0)
+#endif
+
+#define prepare_arch_switch(next) do { \
+       __asm__ __volatile__( \
+       ".globl\tflush_patch_switch\nflush_patch_switch:\n\t" \
+       "save %sp, -0x40, %sp; save %sp, -0x40, %sp; save %sp, -0x40, %sp\n\t" \
+       "save %sp, -0x40, %sp; save %sp, -0x40, %sp; save %sp, -0x40, %sp\n\t" \
+       "save %sp, -0x40, %sp\n\t" \
+       "restore; restore; restore; restore; restore; restore; restore"); \
+} while(0)
+
+       /* Much care has gone into this code, do not touch it.
+        *
+        * We need to loadup regs l0/l1 for the newly forked child
+        * case because the trap return path relies on those registers
+        * holding certain values, gcc is told that they are clobbered.
+        * Gcc needs registers for 3 values in and 1 value out, so we
+        * clobber every non-fixed-usage register besides l2/l3/o4/o5.  -DaveM
+        *
+        * Hey Dave, that do not touch sign is too much of an incentive
+        * - Anton & Pete
+        */
+#define switch_to(prev, next, last) do {                                               \
+       SWITCH_ENTER(prev);                                                             \
+       SWITCH_DO_LAZY_FPU(next);                                                       \
+       cpumask_set_cpu(smp_processor_id(), mm_cpumask(next->active_mm));               \
+       __asm__ __volatile__(                                                           \
+       "sethi  %%hi(here - 0x8), %%o7\n\t"                                             \
+       "mov    %%g6, %%g3\n\t"                                                         \
+       "or     %%o7, %%lo(here - 0x8), %%o7\n\t"                                       \
+       "rd     %%psr, %%g4\n\t"                                                        \
+       "std    %%sp, [%%g6 + %4]\n\t"                                                  \
+       "rd     %%wim, %%g5\n\t"                                                        \
+       "wr     %%g4, 0x20, %%psr\n\t"                                                  \
+       "nop\n\t"                                                                       \
+       "std    %%g4, [%%g6 + %3]\n\t"                                                  \
+       "ldd    [%2 + %3], %%g4\n\t"                                                    \
+       "mov    %2, %%g6\n\t"                                                           \
+       ".globl patchme_store_new_current\n"                                            \
+"patchme_store_new_current:\n\t"                                                       \
+       "st     %2, [%1]\n\t"                                                           \
+       "wr     %%g4, 0x20, %%psr\n\t"                                                  \
+       "nop\n\t"                                                                       \
+       "nop\n\t"                                                                       \
+       "nop\n\t"       /* LEON needs all 3 nops: load to %sp depends on CWP. */                \
+       "ldd    [%%g6 + %4], %%sp\n\t"                                                  \
+       "wr     %%g5, 0x0, %%wim\n\t"                                                   \
+       "ldd    [%%sp + 0x00], %%l0\n\t"                                                \
+       "ldd    [%%sp + 0x38], %%i6\n\t"                                                \
+       "wr     %%g4, 0x0, %%psr\n\t"                                                   \
+       "nop\n\t"                                                                       \
+       "nop\n\t"                                                                       \
+       "jmpl   %%o7 + 0x8, %%g0\n\t"                                                   \
+       " ld    [%%g3 + %5], %0\n\t"                                                    \
+       "here:\n"                                                                       \
+        : "=&r" (last)                                                                 \
+        : "r" (&(current_set[hard_smp_processor_id()])),       \
+         "r" (task_thread_info(next)),                         \
+         "i" (TI_KPSR),                                        \
+         "i" (TI_KSP),                                         \
+         "i" (TI_TASK)                                         \
+       :       "g1", "g2", "g3", "g4", "g5",       "g7",       \
+         "l0", "l1",       "l3", "l4", "l5", "l6", "l7",       \
+         "i0", "i1", "i2", "i3", "i4", "i5",                   \
+         "o0", "o1", "o2", "o3",                   "o7");      \
+       } while(0)
+
+extern void fpsave(unsigned long *fpregs, unsigned long *fsr,
+                  void *fpqueue, unsigned long *fpqdepth);
+extern void synchronize_user_stack(void);
+
+#endif /* __SPARC_SWITCH_TO_H */
diff --git a/arch/sparc/include/asm/switch_to_64.h b/arch/sparc/include/asm/switch_to_64.h
new file mode 100644 (file)
index 0000000..7923c4a
--- /dev/null
@@ -0,0 +1,72 @@
+#ifndef __SPARC64_SWITCH_TO_64_H
+#define __SPARC64_SWITCH_TO_64_H
+
+#include <asm/visasm.h>
+
+#define prepare_arch_switch(next)              \
+do {                                           \
+       flushw_all();                           \
+} while (0)
+
+       /* See what happens when you design the chip correctly?
+        *
+        * We tell gcc we clobber all non-fixed-usage registers except
+        * for l0/l1.  It will use one for 'next' and the other to hold
+        * the output value of 'last'.  'next' is not referenced again
+        * past the invocation of switch_to in the scheduler, so we need
+        * not preserve it's value.  Hairy, but it lets us remove 2 loads
+        * and 2 stores in this critical code path.  -DaveM
+        */
+#define switch_to(prev, next, last)                                    \
+do {   flush_tlb_pending();                                            \
+       save_and_clear_fpu();                                           \
+       /* If you are tempted to conditionalize the following */        \
+       /* so that ASI is only written if it changes, think again. */   \
+       __asm__ __volatile__("wr %%g0, %0, %%asi"                       \
+       : : "r" (__thread_flag_byte_ptr(task_thread_info(next))[TI_FLAG_BYTE_CURRENT_DS]));\
+       trap_block[current_thread_info()->cpu].thread =                 \
+               task_thread_info(next);                                 \
+       __asm__ __volatile__(                                           \
+       "mov    %%g4, %%g7\n\t"                                         \
+       "stx    %%i6, [%%sp + 2047 + 0x70]\n\t"                         \
+       "stx    %%i7, [%%sp + 2047 + 0x78]\n\t"                         \
+       "rdpr   %%wstate, %%o5\n\t"                                     \
+       "stx    %%o6, [%%g6 + %6]\n\t"                                  \
+       "stb    %%o5, [%%g6 + %5]\n\t"                                  \
+       "rdpr   %%cwp, %%o5\n\t"                                        \
+       "stb    %%o5, [%%g6 + %8]\n\t"                                  \
+       "wrpr   %%g0, 15, %%pil\n\t"                                    \
+       "mov    %4, %%g6\n\t"                                           \
+       "ldub   [%4 + %8], %%g1\n\t"                                    \
+       "wrpr   %%g1, %%cwp\n\t"                                        \
+       "ldx    [%%g6 + %6], %%o6\n\t"                                  \
+       "ldub   [%%g6 + %5], %%o5\n\t"                                  \
+       "ldub   [%%g6 + %7], %%o7\n\t"                                  \
+       "wrpr   %%o5, 0x0, %%wstate\n\t"                                \
+       "ldx    [%%sp + 2047 + 0x70], %%i6\n\t"                         \
+       "ldx    [%%sp + 2047 + 0x78], %%i7\n\t"                         \
+       "ldx    [%%g6 + %9], %%g4\n\t"                                  \
+       "wrpr   %%g0, 14, %%pil\n\t"                                    \
+       "brz,pt %%o7, switch_to_pc\n\t"                                 \
+       " mov   %%g7, %0\n\t"                                           \
+       "sethi  %%hi(ret_from_syscall), %%g1\n\t"                       \
+       "jmpl   %%g1 + %%lo(ret_from_syscall), %%g0\n\t"                \
+       " nop\n\t"                                                      \
+       ".globl switch_to_pc\n\t"                                       \
+       "switch_to_pc:\n\t"                                             \
+       : "=&r" (last), "=r" (current), "=r" (current_thread_info_reg), \
+         "=r" (__local_per_cpu_offset)                                 \
+       : "0" (task_thread_info(next)),                                 \
+         "i" (TI_WSTATE), "i" (TI_KSP), "i" (TI_NEW_CHILD),            \
+         "i" (TI_CWP), "i" (TI_TASK)                                   \
+       : "cc",                                                         \
+               "g1", "g2", "g3",                   "g7",               \
+               "l1", "l2", "l3", "l4", "l5", "l6", "l7",               \
+         "i0", "i1", "i2", "i3", "i4", "i5",                           \
+         "o0", "o1", "o2", "o3", "o4", "o5",       "o7");              \
+} while(0)
+
+extern void synchronize_user_stack(void);
+extern void fault_in_user_windows(void);
+
+#endif /* __SPARC64_SWITCH_TO_64_H */
diff --git a/arch/sparc/include/asm/system.h b/arch/sparc/include/asm/system.h
deleted file mode 100644 (file)
index 7944a7c..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef ___ASM_SPARC_SYSTEM_H
-#define ___ASM_SPARC_SYSTEM_H
-#if defined(__sparc__) && defined(__arch64__)
-#include <asm/system_64.h>
-#else
-#include <asm/system_32.h>
-#endif
-#endif
diff --git a/arch/sparc/include/asm/system_32.h b/arch/sparc/include/asm/system_32.h
deleted file mode 100644 (file)
index aba1609..0000000
+++ /dev/null
@@ -1,284 +0,0 @@
-#ifndef __SPARC_SYSTEM_H
-#define __SPARC_SYSTEM_H
-
-#include <linux/kernel.h>
-#include <linux/threads.h>     /* NR_CPUS */
-#include <linux/thread_info.h>
-
-#include <asm/page.h>
-#include <asm/psr.h>
-#include <asm/ptrace.h>
-#include <asm/btfixup.h>
-#include <asm/smp.h>
-
-#ifndef __ASSEMBLY__
-
-#include <linux/irqflags.h>
-
-/*
- * Sparc (general) CPU types
- */
-enum sparc_cpu {
-  sun4        = 0x00,
-  sun4c       = 0x01,
-  sun4m       = 0x02,
-  sun4d       = 0x03,
-  sun4e       = 0x04,
-  sun4u       = 0x05, /* V8 ploos ploos */
-  sun_unknown = 0x06,
-  ap1000      = 0x07, /* almost a sun4m */
-  sparc_leon  = 0x08, /* Leon SoC */
-};
-
-/* Really, userland should not be looking at any of this... */
-#ifdef __KERNEL__
-
-extern enum sparc_cpu sparc_cpu_model;
-
-#define ARCH_SUN4C (sparc_cpu_model==sun4c)
-
-#define SUN4M_NCPUS            4              /* Architectural limit of sun4m. */
-
-extern char reboot_command[];
-
-extern struct thread_info *current_set[NR_CPUS];
-
-extern unsigned long empty_bad_page;
-extern unsigned long empty_bad_page_table;
-extern unsigned long empty_zero_page;
-
-extern void sun_do_break(void);
-extern int serial_console;
-extern int stop_a_enabled;
-extern int scons_pwroff;
-
-static inline int con_is_present(void)
-{
-       return serial_console ? 0 : 1;
-}
-
-/* When a context switch happens we must flush all user windows so that
- * the windows of the current process are flushed onto its stack. This
- * way the windows are all clean for the next process and the stack
- * frames are up to date.
- */
-extern void flush_user_windows(void);
-extern void kill_user_windows(void);
-extern void synchronize_user_stack(void);
-extern void fpsave(unsigned long *fpregs, unsigned long *fsr,
-                  void *fpqueue, unsigned long *fpqdepth);
-
-#ifdef CONFIG_SMP
-#define SWITCH_ENTER(prv) \
-       do {                    \
-       if (test_tsk_thread_flag(prv, TIF_USEDFPU)) { \
-               put_psr(get_psr() | PSR_EF); \
-               fpsave(&(prv)->thread.float_regs[0], &(prv)->thread.fsr, \
-                      &(prv)->thread.fpqueue[0], &(prv)->thread.fpqdepth); \
-               clear_tsk_thread_flag(prv, TIF_USEDFPU); \
-               (prv)->thread.kregs->psr &= ~PSR_EF; \
-       } \
-       } while(0)
-
-#define SWITCH_DO_LAZY_FPU(next)       /* */
-#else
-#define SWITCH_ENTER(prv)              /* */
-#define SWITCH_DO_LAZY_FPU(nxt)        \
-       do {                    \
-       if (last_task_used_math != (nxt))               \
-               (nxt)->thread.kregs->psr&=~PSR_EF;      \
-       } while(0)
-#endif
-
-extern void flushw_all(void);
-
-/*
- * Flush windows so that the VM switch which follows
- * would not pull the stack from under us.
- *
- * SWITCH_ENTER and SWITH_DO_LAZY_FPU do not work yet (e.g. SMP does not work)
- * XXX WTF is the above comment? Found in late teen 2.4.x.
- */
-#define prepare_arch_switch(next) do { \
-       __asm__ __volatile__( \
-       ".globl\tflush_patch_switch\nflush_patch_switch:\n\t" \
-       "save %sp, -0x40, %sp; save %sp, -0x40, %sp; save %sp, -0x40, %sp\n\t" \
-       "save %sp, -0x40, %sp; save %sp, -0x40, %sp; save %sp, -0x40, %sp\n\t" \
-       "save %sp, -0x40, %sp\n\t" \
-       "restore; restore; restore; restore; restore; restore; restore"); \
-} while(0)
-
-       /* Much care has gone into this code, do not touch it.
-        *
-        * We need to loadup regs l0/l1 for the newly forked child
-        * case because the trap return path relies on those registers
-        * holding certain values, gcc is told that they are clobbered.
-        * Gcc needs registers for 3 values in and 1 value out, so we
-        * clobber every non-fixed-usage register besides l2/l3/o4/o5.  -DaveM
-        *
-        * Hey Dave, that do not touch sign is too much of an incentive
-        * - Anton & Pete
-        */
-#define switch_to(prev, next, last) do {                                               \
-       SWITCH_ENTER(prev);                                                             \
-       SWITCH_DO_LAZY_FPU(next);                                                       \
-       cpumask_set_cpu(smp_processor_id(), mm_cpumask(next->active_mm));               \
-       __asm__ __volatile__(                                                           \
-       "sethi  %%hi(here - 0x8), %%o7\n\t"                                             \
-       "mov    %%g6, %%g3\n\t"                                                         \
-       "or     %%o7, %%lo(here - 0x8), %%o7\n\t"                                       \
-       "rd     %%psr, %%g4\n\t"                                                        \
-       "std    %%sp, [%%g6 + %4]\n\t"                                                  \
-       "rd     %%wim, %%g5\n\t"                                                        \
-       "wr     %%g4, 0x20, %%psr\n\t"                                                  \
-       "nop\n\t"                                                                       \
-       "std    %%g4, [%%g6 + %3]\n\t"                                                  \
-       "ldd    [%2 + %3], %%g4\n\t"                                                    \
-       "mov    %2, %%g6\n\t"                                                           \
-       ".globl patchme_store_new_current\n"                                            \
-"patchme_store_new_current:\n\t"                                                       \
-       "st     %2, [%1]\n\t"                                                           \
-       "wr     %%g4, 0x20, %%psr\n\t"                                                  \
-       "nop\n\t"                                                                       \
-       "nop\n\t"                                                                       \
-       "nop\n\t"       /* LEON needs all 3 nops: load to %sp depends on CWP. */                \
-       "ldd    [%%g6 + %4], %%sp\n\t"                                                  \
-       "wr     %%g5, 0x0, %%wim\n\t"                                                   \
-       "ldd    [%%sp + 0x00], %%l0\n\t"                                                \
-       "ldd    [%%sp + 0x38], %%i6\n\t"                                                \
-       "wr     %%g4, 0x0, %%psr\n\t"                                                   \
-       "nop\n\t"                                                                       \
-       "nop\n\t"                                                                       \
-       "jmpl   %%o7 + 0x8, %%g0\n\t"                                                   \
-       " ld    [%%g3 + %5], %0\n\t"                                                    \
-       "here:\n"                                                                       \
-        : "=&r" (last)                                                                 \
-        : "r" (&(current_set[hard_smp_processor_id()])),       \
-         "r" (task_thread_info(next)),                         \
-         "i" (TI_KPSR),                                        \
-         "i" (TI_KSP),                                         \
-         "i" (TI_TASK)                                         \
-       :       "g1", "g2", "g3", "g4", "g5",       "g7",       \
-         "l0", "l1",       "l3", "l4", "l5", "l6", "l7",       \
-         "i0", "i1", "i2", "i3", "i4", "i5",                   \
-         "o0", "o1", "o2", "o3",                   "o7");      \
-       } while(0)
-
-/* XXX Change this if we ever use a PSO mode kernel. */
-#define mb()   __asm__ __volatile__ ("" : : : "memory")
-#define rmb()  mb()
-#define wmb()  mb()
-#define read_barrier_depends() do { } while(0)
-#define set_mb(__var, __value)  do { __var = __value; mb(); } while(0)
-#define smp_mb()       __asm__ __volatile__("":::"memory")
-#define smp_rmb()      __asm__ __volatile__("":::"memory")
-#define smp_wmb()      __asm__ __volatile__("":::"memory")
-#define smp_read_barrier_depends()     do { } while(0)
-
-#define nop() __asm__ __volatile__ ("nop")
-
-/* This has special calling conventions */
-#ifndef CONFIG_SMP
-BTFIXUPDEF_CALL(void, ___xchg32, void)
-#endif
-
-static inline unsigned long xchg_u32(__volatile__ unsigned long *m, unsigned long val)
-{
-#ifdef CONFIG_SMP
-       __asm__ __volatile__("swap [%2], %0"
-                            : "=&r" (val)
-                            : "0" (val), "r" (m)
-                            : "memory");
-       return val;
-#else
-       register unsigned long *ptr asm("g1");
-       register unsigned long ret asm("g2");
-
-       ptr = (unsigned long *) m;
-       ret = val;
-
-       /* Note: this is magic and the nop there is
-          really needed. */
-       __asm__ __volatile__(
-       "mov    %%o7, %%g4\n\t"
-       "call   ___f____xchg32\n\t"
-       " nop\n\t"
-       : "=&r" (ret)
-       : "0" (ret), "r" (ptr)
-       : "g3", "g4", "g7", "memory", "cc");
-
-       return ret;
-#endif
-}
-
-#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
-
-extern void __xchg_called_with_bad_pointer(void);
-
-static inline unsigned long __xchg(unsigned long x, __volatile__ void * ptr, int size)
-{
-       switch (size) {
-       case 4:
-               return xchg_u32(ptr, x);
-       }
-       __xchg_called_with_bad_pointer();
-       return x;
-}
-
-/* Emulate cmpxchg() the same way we emulate atomics,
- * by hashing the object address and indexing into an array
- * of spinlocks to get a bit of performance...
- *
- * See arch/sparc/lib/atomic32.c for implementation.
- *
- * Cribbed from <asm-parisc/atomic.h>
- */
-#define __HAVE_ARCH_CMPXCHG    1
-
-/* bug catcher for when unsupported size is used - won't link */
-extern void __cmpxchg_called_with_bad_pointer(void);
-/* we only need to support cmpxchg of a u32 on sparc */
-extern unsigned long __cmpxchg_u32(volatile u32 *m, u32 old, u32 new_);
-
-/* don't worry...optimizer will get rid of most of this */
-static inline unsigned long
-__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new_, int size)
-{
-       switch (size) {
-       case 4:
-               return __cmpxchg_u32((u32 *)ptr, (u32)old, (u32)new_);
-       default:
-               __cmpxchg_called_with_bad_pointer();
-               break;
-       }
-       return old;
-}
-
-#define cmpxchg(ptr, o, n)                                             \
-({                                                                     \
-       __typeof__(*(ptr)) _o_ = (o);                                   \
-       __typeof__(*(ptr)) _n_ = (n);                                   \
-       (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,       \
-                       (unsigned long)_n_, sizeof(*(ptr)));            \
-})
-
-#include <asm-generic/cmpxchg-local.h>
-
-/*
- * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
- * them available.
- */
-#define cmpxchg_local(ptr, o, n)                                              \
-       ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
-                       (unsigned long)(n), sizeof(*(ptr))))
-#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
-
-extern void die_if_kernel(char *str, struct pt_regs *regs) __attribute__ ((noreturn));
-
-#endif /* __KERNEL__ */
-
-#endif /* __ASSEMBLY__ */
-
-#define arch_align_stack(x) (x)
-
-#endif /* !(__SPARC_SYSTEM_H) */
diff --git a/arch/sparc/include/asm/system_64.h b/arch/sparc/include/asm/system_64.h
deleted file mode 100644 (file)
index 10bcabc..0000000
+++ /dev/null
@@ -1,331 +0,0 @@
-#ifndef __SPARC64_SYSTEM_H
-#define __SPARC64_SYSTEM_H
-
-#include <asm/ptrace.h>
-#include <asm/processor.h>
-#include <asm/visasm.h>
-
-#ifndef __ASSEMBLY__
-
-#include <linux/irqflags.h>
-#include <asm-generic/cmpxchg-local.h>
-
-/*
- * Sparc (general) CPU types
- */
-enum sparc_cpu {
-  sun4        = 0x00,
-  sun4c       = 0x01,
-  sun4m       = 0x02,
-  sun4d       = 0x03,
-  sun4e       = 0x04,
-  sun4u       = 0x05, /* V8 ploos ploos */
-  sun_unknown = 0x06,
-  ap1000      = 0x07, /* almost a sun4m */
-};
-
-#define sparc_cpu_model sun4u
-
-/* This cannot ever be a sun4c :) That's just history. */
-#define ARCH_SUN4C 0
-
-extern char reboot_command[];
-
-/* These are here in an effort to more fully work around Spitfire Errata
- * #51.  Essentially, if a memory barrier occurs soon after a mispredicted
- * branch, the chip can stop executing instructions until a trap occurs.
- * Therefore, if interrupts are disabled, the chip can hang forever.
- *
- * It used to be believed that the memory barrier had to be right in the
- * delay slot, but a case has been traced recently wherein the memory barrier
- * was one instruction after the branch delay slot and the chip still hung.
- * The offending sequence was the following in sym_wakeup_done() of the
- * sym53c8xx_2 driver:
- *
- *     call    sym_ccb_from_dsa, 0
- *      movge  %icc, 0, %l0
- *     brz,pn  %o0, .LL1303
- *      mov    %o0, %l2
- *     membar  #LoadLoad
- *
- * The branch has to be mispredicted for the bug to occur.  Therefore, we put
- * the memory barrier explicitly into a "branch always, predicted taken"
- * delay slot to avoid the problem case.
- */
-#define membar_safe(type) \
-do {   __asm__ __volatile__("ba,pt     %%xcc, 1f\n\t" \
-                            " membar   " type "\n" \
-                            "1:\n" \
-                            : : : "memory"); \
-} while (0)
-
-/* The kernel always executes in TSO memory model these days,
- * and furthermore most sparc64 chips implement more stringent
- * memory ordering than required by the specifications.
- */
-#define mb()   membar_safe("#StoreLoad")
-#define rmb()  __asm__ __volatile__("":::"memory")
-#define wmb()  __asm__ __volatile__("":::"memory")
-
-#endif
-
-#define nop()          __asm__ __volatile__ ("nop")
-
-#define read_barrier_depends()         do { } while(0)
-#define set_mb(__var, __value) \
-       do { __var = __value; membar_safe("#StoreLoad"); } while(0)
-
-#ifdef CONFIG_SMP
-#define smp_mb()       mb()
-#define smp_rmb()      rmb()
-#define smp_wmb()      wmb()
-#else
-#define smp_mb()       __asm__ __volatile__("":::"memory")
-#define smp_rmb()      __asm__ __volatile__("":::"memory")
-#define smp_wmb()      __asm__ __volatile__("":::"memory")
-#endif
-
-#define smp_read_barrier_depends()     do { } while(0)
-
-#define flushi(addr)   __asm__ __volatile__ ("flush %0" : : "r" (addr) : "memory")
-
-#define flushw_all()   __asm__ __volatile__("flushw")
-
-/* Performance counter register access. */
-#define read_pcr(__p)  __asm__ __volatile__("rd        %%pcr, %0" : "=r" (__p))
-#define write_pcr(__p) __asm__ __volatile__("wr        %0, 0x0, %%pcr" : : "r" (__p))
-#define read_pic(__p)  __asm__ __volatile__("rd %%pic, %0" : "=r" (__p))
-
-/* Blackbird errata workaround.  See commentary in
- * arch/sparc64/kernel/smp.c:smp_percpu_timer_interrupt()
- * for more information.
- */
-#define write_pic(__p)                                         \
-       __asm__ __volatile__("ba,pt     %%xcc, 99f\n\t"         \
-                            " nop\n\t"                         \
-                            ".align    64\n"                   \
-                         "99:wr        %0, 0x0, %%pic\n\t"     \
-                            "rd        %%pic, %%g0" : : "r" (__p))
-#define reset_pic()    write_pic(0)
-
-#ifndef __ASSEMBLY__
-
-extern void sun_do_break(void);
-extern int stop_a_enabled;
-extern int scons_pwroff;
-
-extern void fault_in_user_windows(void);
-extern void synchronize_user_stack(void);
-
-extern void __flushw_user(void);
-#define flushw_user() __flushw_user()
-
-#define flush_user_windows flushw_user
-#define flush_register_windows flushw_all
-
-/* Don't hold the runqueue lock over context switch */
-#define __ARCH_WANT_UNLOCKED_CTXSW
-#define prepare_arch_switch(next)              \
-do {                                           \
-       flushw_all();                           \
-} while (0)
-
-       /* See what happens when you design the chip correctly?
-        *
-        * We tell gcc we clobber all non-fixed-usage registers except
-        * for l0/l1.  It will use one for 'next' and the other to hold
-        * the output value of 'last'.  'next' is not referenced again
-        * past the invocation of switch_to in the scheduler, so we need
-        * not preserve it's value.  Hairy, but it lets us remove 2 loads
-        * and 2 stores in this critical code path.  -DaveM
-        */
-#define switch_to(prev, next, last)                                    \
-do {   flush_tlb_pending();                                            \
-       save_and_clear_fpu();                                           \
-       /* If you are tempted to conditionalize the following */        \
-       /* so that ASI is only written if it changes, think again. */   \
-       __asm__ __volatile__("wr %%g0, %0, %%asi"                       \
-       : : "r" (__thread_flag_byte_ptr(task_thread_info(next))[TI_FLAG_BYTE_CURRENT_DS]));\
-       trap_block[current_thread_info()->cpu].thread =                 \
-               task_thread_info(next);                                 \
-       __asm__ __volatile__(                                           \
-       "mov    %%g4, %%g7\n\t"                                         \
-       "stx    %%i6, [%%sp + 2047 + 0x70]\n\t"                         \
-       "stx    %%i7, [%%sp + 2047 + 0x78]\n\t"                         \
-       "rdpr   %%wstate, %%o5\n\t"                                     \
-       "stx    %%o6, [%%g6 + %6]\n\t"                                  \
-       "stb    %%o5, [%%g6 + %5]\n\t"                                  \
-       "rdpr   %%cwp, %%o5\n\t"                                        \
-       "stb    %%o5, [%%g6 + %8]\n\t"                                  \
-       "wrpr   %%g0, 15, %%pil\n\t"                                    \
-       "mov    %4, %%g6\n\t"                                           \
-       "ldub   [%4 + %8], %%g1\n\t"                                    \
-       "wrpr   %%g1, %%cwp\n\t"                                        \
-       "ldx    [%%g6 + %6], %%o6\n\t"                                  \
-       "ldub   [%%g6 + %5], %%o5\n\t"                                  \
-       "ldub   [%%g6 + %7], %%o7\n\t"                                  \
-       "wrpr   %%o5, 0x0, %%wstate\n\t"                                \
-       "ldx    [%%sp + 2047 + 0x70], %%i6\n\t"                         \
-       "ldx    [%%sp + 2047 + 0x78], %%i7\n\t"                         \
-       "ldx    [%%g6 + %9], %%g4\n\t"                                  \
-       "wrpr   %%g0, 14, %%pil\n\t"                                    \
-       "brz,pt %%o7, switch_to_pc\n\t"                                 \
-       " mov   %%g7, %0\n\t"                                           \
-       "sethi  %%hi(ret_from_syscall), %%g1\n\t"                       \
-       "jmpl   %%g1 + %%lo(ret_from_syscall), %%g0\n\t"                \
-       " nop\n\t"                                                      \
-       ".globl switch_to_pc\n\t"                                       \
-       "switch_to_pc:\n\t"                                             \
-       : "=&r" (last), "=r" (current), "=r" (current_thread_info_reg), \
-         "=r" (__local_per_cpu_offset)                                 \
-       : "0" (task_thread_info(next)),                                 \
-         "i" (TI_WSTATE), "i" (TI_KSP), "i" (TI_NEW_CHILD),            \
-         "i" (TI_CWP), "i" (TI_TASK)                                   \
-       : "cc",                                                         \
-               "g1", "g2", "g3",                   "g7",               \
-               "l1", "l2", "l3", "l4", "l5", "l6", "l7",               \
-         "i0", "i1", "i2", "i3", "i4", "i5",                           \
-         "o0", "o1", "o2", "o3", "o4", "o5",       "o7");              \
-} while(0)
-
-static inline unsigned long xchg32(__volatile__ unsigned int *m, unsigned int val)
-{
-       unsigned long tmp1, tmp2;
-
-       __asm__ __volatile__(
-"      mov             %0, %1\n"
-"1:    lduw            [%4], %2\n"
-"      cas             [%4], %2, %0\n"
-"      cmp             %2, %0\n"
-"      bne,a,pn        %%icc, 1b\n"
-"       mov            %1, %0\n"
-       : "=&r" (val), "=&r" (tmp1), "=&r" (tmp2)
-       : "0" (val), "r" (m)
-       : "cc", "memory");
-       return val;
-}
-
-static inline unsigned long xchg64(__volatile__ unsigned long *m, unsigned long val)
-{
-       unsigned long tmp1, tmp2;
-
-       __asm__ __volatile__(
-"      mov             %0, %1\n"
-"1:    ldx             [%4], %2\n"
-"      casx            [%4], %2, %0\n"
-"      cmp             %2, %0\n"
-"      bne,a,pn        %%xcc, 1b\n"
-"       mov            %1, %0\n"
-       : "=&r" (val), "=&r" (tmp1), "=&r" (tmp2)
-       : "0" (val), "r" (m)
-       : "cc", "memory");
-       return val;
-}
-
-#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
-
-extern void __xchg_called_with_bad_pointer(void);
-
-static inline unsigned long __xchg(unsigned long x, __volatile__ void * ptr,
-                                      int size)
-{
-       switch (size) {
-       case 4:
-               return xchg32(ptr, x);
-       case 8:
-               return xchg64(ptr, x);
-       }
-       __xchg_called_with_bad_pointer();
-       return x;
-}
-
-extern void die_if_kernel(char *str, struct pt_regs *regs) __attribute__ ((noreturn));
-
-/*
- * Atomic compare and exchange.  Compare OLD with MEM, if identical,
- * store NEW in MEM.  Return the initial value in MEM.  Success is
- * indicated by comparing RETURN with OLD.
- */
-
-#define __HAVE_ARCH_CMPXCHG 1
-
-static inline unsigned long
-__cmpxchg_u32(volatile int *m, int old, int new)
-{
-       __asm__ __volatile__("cas [%2], %3, %0"
-                            : "=&r" (new)
-                            : "0" (new), "r" (m), "r" (old)
-                            : "memory");
-
-       return new;
-}
-
-static inline unsigned long
-__cmpxchg_u64(volatile long *m, unsigned long old, unsigned long new)
-{
-       __asm__ __volatile__("casx [%2], %3, %0"
-                            : "=&r" (new)
-                            : "0" (new), "r" (m), "r" (old)
-                            : "memory");
-
-       return new;
-}
-
-/* This function doesn't exist, so you'll get a linker error
-   if something tries to do an invalid cmpxchg().  */
-extern void __cmpxchg_called_with_bad_pointer(void);
-
-static inline unsigned long
-__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
-{
-       switch (size) {
-               case 4:
-                       return __cmpxchg_u32(ptr, old, new);
-               case 8:
-                       return __cmpxchg_u64(ptr, old, new);
-       }
-       __cmpxchg_called_with_bad_pointer();
-       return old;
-}
-
-#define cmpxchg(ptr,o,n)                                                \
-  ({                                                                    \
-     __typeof__(*(ptr)) _o_ = (o);                                      \
-     __typeof__(*(ptr)) _n_ = (n);                                      \
-     (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,          \
-                                   (unsigned long)_n_, sizeof(*(ptr))); \
-  })
-
-/*
- * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
- * them available.
- */
-
-static inline unsigned long __cmpxchg_local(volatile void *ptr,
-                                     unsigned long old,
-                                     unsigned long new, int size)
-{
-       switch (size) {
-       case 4:
-       case 8: return __cmpxchg(ptr, old, new, size);
-       default:
-               return __cmpxchg_local_generic(ptr, old, new, size);
-       }
-
-       return old;
-}
-
-#define cmpxchg_local(ptr, o, n)                                       \
-       ((__typeof__(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(o), \
-                       (unsigned long)(n), sizeof(*(ptr))))
-#define cmpxchg64_local(ptr, o, n)                                     \
-  ({                                                                   \
-       BUILD_BUG_ON(sizeof(*(ptr)) != 8);                              \
-       cmpxchg_local((ptr), (o), (n));                                 \
-  })
-
-#endif /* !(__ASSEMBLY__) */
-
-#define arch_align_stack(x) (x)
-
-#endif /* !(__SPARC64_SYSTEM_H) */
index 2ec030e..1a91e11 100644 (file)
@@ -8,12 +8,13 @@
 #ifndef _SPARC_TIMER_H
 #define _SPARC_TIMER_H
 
-#include <asm/system.h>  /* For SUN4M_NCPUS */
+#include <asm/cpu_type.h>  /* For SUN4M_NCPUS */
 #include <asm/btfixup.h>
 
 extern __volatile__ unsigned int *master_l10_counter;
 
 /* FIXME: Make do_[gs]ettimeofday btfixup calls */
+struct timespec;
 BTFIXUPDEF_CALL(int, bus_do_settimeofday, struct timespec *tv)
 #define bus_do_settimeofday(tv) BTFIXUP_CALL(bus_do_settimeofday)(tv)
 
index 3e1449f..a1091af 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/string.h>
 #include <linux/thread_info.h>
 #include <asm/asi.h>
-#include <asm/system.h>
 #include <asm/spitfire.h>
 #include <asm-generic/uaccess-unaligned.h>
 #endif
index 9d83d3b..432afa8 100644 (file)
@@ -284,6 +284,7 @@ struct vio_dev {
 };
 
 struct vio_driver {
+       const char                      *name;
        struct list_head                node;
        const struct vio_device_id      *id_table;
        int (*probe)(struct vio_dev *dev, const struct vio_device_id *id);
@@ -371,7 +372,13 @@ do {       if (vio->debug & VIO_DEBUG_##TYPE) \
                       vio->vdev->channel_id, ## a); \
 } while (0)
 
-extern int vio_register_driver(struct vio_driver *drv);
+extern int __vio_register_driver(struct vio_driver *drv, struct module *owner,
+                                const char *mod_name);
+/*
+ * vio_register_driver must be a macro so that KBUILD_MODNAME can be expanded
+ */
+#define vio_register_driver(driver)            \
+       __vio_register_driver(driver, THIS_MODULE, KBUILD_MODNAME)
 extern void vio_unregister_driver(struct vio_driver *drv);
 
 static inline struct vio_driver *to_vio_driver(struct device_driver *drv)
index f7ea8f0..56d0f52 100644 (file)
@@ -13,6 +13,7 @@
 #include <asm/io.h>
 #include <asm/auxio.h>
 #include <asm/string.h>                /* memset(), Linux has no bzero() */
+#include <asm/cpu_type.h>
 
 /* Probe and map in the Auxiliary I/O register */
 
index 113c052..6b2f56a 100644 (file)
@@ -17,8 +17,8 @@
 #include <asm/oplib.h>
 #include <asm/prom.h>
 #include <asm/smp.h>
-#include <asm/system.h>
 #include <asm/cpudata.h>
+#include <asm/cpu_type.h>
 
 extern void clock_stop_probe(void); /* tadpole.c */
 extern void sun4c_probe_memerr_reg(void);
index 381edcd..fea13c7 100644 (file)
@@ -1244,10 +1244,7 @@ static struct vio_driver ds_driver = {
        .id_table       = ds_match,
        .probe          = ds_probe,
        .remove         = ds_remove,
-       .driver         = {
-               .name   = "ds",
-               .owner  = THIS_MODULE,
-       }
+       .name           = "ds",
 };
 
 static int __init ds_init(void)
index 4285112..5a021dd 100644 (file)
@@ -1,6 +1,7 @@
 #include <linux/platform_device.h>
 
 #include <asm/btfixup.h>
+#include <asm/cpu_type.h>
 
 struct irq_bucket {
         struct irq_bucket *next;
index d45b710..dff2c3d 100644 (file)
@@ -26,7 +26,6 @@
 #include <asm/ptrace.h>
 #include <asm/processor.h>
 #include <linux/atomic.h>
-#include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/io.h>
 #include <asm/iommu.h>
index 539243b..2e424a5 100644 (file)
@@ -9,6 +9,7 @@
 #include <asm/kdebug.h>
 #include <asm/ptrace.h>
 #include <asm/irq.h>
+#include <asm/cacheflush.h>
 
 extern unsigned long trapbase;
 
index e551987..276359e 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <asm/processor.h>
 #include <asm/spitfire.h>
+#include <asm/cacheflush.h>
 
 #include "entry.h"
 
index 6ce1021..f7db516 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/mm.h>
 #include <asm/ptrace.h>
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 
 #include "kernel.h"
index c76fe0b..eb1c1f0 100644 (file)
@@ -22,6 +22,7 @@
 #include <asm/perf_event.h>
 #include <asm/ptrace.h>
 #include <asm/pcr.h>
+#include <asm/perfctr.h>
 
 #include "kstack.h"
 
index a24072a..0ce0dd2 100644 (file)
@@ -14,6 +14,7 @@
 #include <asm/pcr.h>
 #include <asm/nmi.h>
 #include <asm/spitfire.h>
+#include <asm/perfctr.h>
 
 /* This code is shared between various users of the performance
  * counters.  Users will be oprofile, pseudo-NMI watchdog, and the
index 8e16a4a..28559ce 100644 (file)
@@ -25,6 +25,8 @@
 #include <linux/atomic.h>
 #include <asm/nmi.h>
 #include <asm/pcr.h>
+#include <asm/perfctr.h>
+#include <asm/cacheflush.h>
 
 #include "kernel.h"
 #include "kstack.h"
index 935fdbc..efa0754 100644 (file)
@@ -28,7 +28,6 @@
 #include <asm/auxio.h>
 #include <asm/oplib.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/page.h>
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
@@ -38,6 +37,7 @@
 #include <asm/elf.h>
 #include <asm/prom.h>
 #include <asm/unistd.h>
+#include <asm/setup.h>
 
 /* 
  * Power management idle function 
index 06b5b5f..aff0c72 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/nmi.h>
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/page.h>
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
index 27b9e93..896ba7c 100644 (file)
@@ -23,8 +23,8 @@
 #include <linux/tracehook.h>
 
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
+#include <asm/cacheflush.h>
 
 /* #define ALLOW_INIT_TRACING */
 
index 9388844..6f97c07 100644 (file)
@@ -29,7 +29,6 @@
 
 #include <asm/asi.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/psrcompat.h>
 #include <asm/visasm.h>
index 006a42d..eba7d91 100644 (file)
@@ -7,9 +7,9 @@
 #include <linux/export.h>
 #include <linux/pm.h>
 
-#include <asm/system.h>
 #include <asm/oplib.h>
 #include <asm/prom.h>
+#include <asm/setup.h>
 
 /* sysctl - toggle power-off restriction for serial console
  * systems in machine_power_off()
index ffb883d..d444468 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/kdebug.h>
 #include <linux/export.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/processor.h>
 #include <asm/oplib.h>
@@ -46,6 +45,7 @@
 #include <asm/machines.h>
 #include <asm/cpudata.h>
 #include <asm/setup.h>
+#include <asm/cacheflush.h>
 
 #include "kernel.h"
 
index a854a1c..1414d16 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/initrd.h>
 #include <linux/module.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/processor.h>
 #include <asm/oplib.h>
@@ -49,6 +48,7 @@
 #include <asm/btext.h>
 #include <asm/elf.h>
 #include <asm/mdesc.h>
+#include <asm/cacheflush.h>
 
 #ifdef CONFIG_IP_PNP
 #include <net/ipconfig.h>
index c8f5b50..948700f 100644 (file)
@@ -28,6 +28,7 @@
 #include <asm/fpumacro.h>
 #include <asm/visasm.h>
 #include <asm/compat_signal.h>
+#include <asm/switch_to.h>
 
 #include "sigutil.h"
 
index 7bb71b6..1e750e4 100644 (file)
@@ -25,6 +25,7 @@
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
 #include <asm/cacheflush.h>    /* flush_sig_insns */
+#include <asm/switch_to.h>
 
 #include "sigutil.h"
 
index d8a67e6..48b0f57 100644 (file)
@@ -31,6 +31,8 @@
 #include <asm/uctx.h>
 #include <asm/siginfo.h>
 #include <asm/visasm.h>
+#include <asm/switch_to.h>
+#include <asm/cacheflush.h>
 
 #include "entry.h"
 #include "systbls.h"
index 35c7897..0f6eebe 100644 (file)
@@ -7,6 +7,7 @@
 #include <asm/sigcontext.h>
 #include <asm/fpumacro.h>
 #include <asm/ptrace.h>
+#include <asm/switch_to.h>
 
 #include "sigutil.h"
 
index b19570d..387834a 100644 (file)
@@ -7,6 +7,7 @@
 #include <asm/sigcontext.h>
 #include <asm/fpumacro.h>
 #include <asm/ptrace.h>
+#include <asm/switch_to.h>
 
 #include "sigutil.h"
 
index 12ff098..9f5e24d 100644 (file)
 #include <linux/init.h>
 #include <linux/bitops.h>
 
-#include <asm/system.h>
 #include <asm/cpudata.h>
 #include <asm/uaccess.h>
 #include <asm/spitfire.h>
 #include <asm/oplib.h>
 #include <asm/hypervisor.h>
+#include <asm/cacheflush.h>
 
 struct poll {
        int fd;
index 1060e06..7d0c088 100644 (file)
@@ -37,7 +37,6 @@
 #include <asm/oplib.h>
 #include <asm/timex.h>
 #include <asm/timer.h>
-#include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/io.h>
 #include <asm/idprom.h>
index 591f20c..d2de213 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/export.h>
 
 #include <asm/delay.h>
-#include <asm/system.h>
 #include <asm/ptrace.h>
 #include <asm/oplib.h>
 #include <asm/page.h>
index 0cbdaa4..c72fdf5 100644 (file)
@@ -22,7 +22,6 @@
 
 #include <asm/smp.h>
 #include <asm/delay.h>
-#include <asm/system.h>
 #include <asm/ptrace.h>
 #include <asm/oplib.h>
 #include <asm/page.h>
@@ -41,6 +40,7 @@
 #include <asm/head.h>
 #include <asm/prom.h>
 #include <asm/memctrl.h>
+#include <asm/cacheflush.h>
 
 #include "entry.h"
 #include "kstack.h"
index 4d043a1..c0ec897 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/mm.h>
 #include <asm/ptrace.h>
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <linux/smp.h>
 #include <linux/perf_event.h>
index 76e4ac1..dae85bc 100644 (file)
@@ -16,7 +16,6 @@
 #include <asm/ptrace.h>
 #include <asm/pstate.h>
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <linux/smp.h>
 #include <linux/bitops.h>
@@ -24,6 +23,7 @@
 #include <linux/ratelimit.h>
 #include <linux/bitops.h>
 #include <asm/fpumacro.h>
+#include <asm/cacheflush.h>
 
 enum direction {
        load,    /* ld, ldd, ldh, ldsh */
index f67e28e..5cffdc5 100644 (file)
@@ -119,13 +119,17 @@ static struct bus_type vio_bus_type = {
        .remove         = vio_device_remove,
 };
 
-int vio_register_driver(struct vio_driver *viodrv)
+int __vio_register_driver(struct vio_driver *viodrv, struct module *owner,
+                       const char *mod_name)
 {
        viodrv->driver.bus = &vio_bus_type;
+       viodrv->driver.name = viodrv->name;
+       viodrv->driver.owner = owner;
+       viodrv->driver.mod_name = mod_name;
 
        return driver_register(&viodrv->driver);
 }
-EXPORT_SYMBOL(vio_register_driver);
+EXPORT_SYMBOL(__vio_register_driver);
 
 void vio_unregister_driver(struct vio_driver *viodrv)
 {
index 7337067..08e074b 100644 (file)
@@ -9,9 +9,9 @@
 
 #include <asm/ptrace.h>
 #include <asm/pstate.h>
-#include <asm/system.h>
 #include <asm/fpumacro.h>
 #include <asm/uaccess.h>
+#include <asm/cacheflush.h>
 
 /* OPF field of various VIS instructions.  */
 
index e575bd2..2bbe2f2 100644 (file)
@@ -16,6 +16,7 @@
 #include <asm/fpumacro.h>
 #include <asm/ptrace.h>
 #include <asm/uaccess.h>
+#include <asm/cacheflush.h>
 
 #include "sfp-util_64.h"
 #include <math-emu/soft-fp.h>
index 8a7f817..09d6af2 100644 (file)
@@ -12,7 +12,6 @@
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
 #include <asm/oplib.h>
-#include <asm/system.h>
 #include <asm/cacheflush.h>
 
 #define BTFIXUP_OPTIMIZE_NOP
index 8023fd7..7705c67 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/interrupt.h>
 #include <linux/kdebug.h>
 
-#include <asm/system.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/memreg.h>
index 7b00de6..c5f9021 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/gfp.h>
 
 #include <asm/sections.h>
-#include <asm/system.h>
 #include <asm/vac-ops.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
index b3f5e7d..21faaee 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/gfp.h>
 
 #include <asm/head.h>
-#include <asm/system.h>
 #include <asm/page.h>
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
index 77d1b31..3e1ac8b 100644 (file)
@@ -36,8 +36,6 @@ extern unsigned long kern_locked_tte_data;
 
 extern void prom_world(int enter);
 
-extern void free_initmem(void);
-
 #ifdef CONFIG_SPARSEMEM_VMEMMAP
 #define VMEMMAP_CHUNK_SHIFT    22
 #define VMEMMAP_CHUNK          (1UL << VMEMMAP_CHUNK_SHIFT)
index 82ec8f6..c5bf2a6 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/mm.h>
 #include <linux/init.h>
 
-#include <asm/system.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/mmu_context.h>
index 536412d..c52add7 100644 (file)
@@ -6,7 +6,6 @@
 #include <linux/kernel.h>
 #include <linux/preempt.h>
 #include <linux/slab.h>
-#include <asm/system.h>
 #include <asm/page.h>
 #include <asm/tlbflush.h>
 #include <asm/tlb.h>
index a00f47b..1cfb50f 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/sched.h>
 #include <asm/openprom.h>
 #include <asm/oplib.h>
-#include <asm/system.h>
 #include <linux/string.h>
 
 extern void restore_current(void);
index 9de6c8c..f95edcc 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/sched.h>
 #include <asm/openprom.h>
 #include <asm/oplib.h>
-#include <asm/system.h>
 #include <linux/string.h>
 
 static int __prom_console_write_buf(const char *buf, int len)
index 677b6a1..8dc0b6b 100644 (file)
@@ -13,7 +13,6 @@
 #include <asm/openprom.h>
 #include <asm/oplib.h>
 #include <asm/auxio.h>
-#include <asm/system.h>
 
 extern void restore_current(void);
 
index e4f31d4..f178b9d 100644 (file)
@@ -15,7 +15,6 @@
 
 #include <asm/openprom.h>
 #include <asm/oplib.h>
-#include <asm/system.h>
 #include <asm/ldc.h>
 
 static int prom_service_exists(const char *service_name)
index d9850c2..04a4540 100644 (file)
@@ -13,7 +13,6 @@
 
 #include <asm/openprom.h>
 #include <asm/oplib.h>
-#include <asm/system.h>
 #include <asm/spitfire.h>
 #include <asm/pstate.h>
 #include <asm/ldc.h>
index 0857aa9..ad143c1 100644 (file)
@@ -11,7 +11,6 @@
 #include <asm/openprom.h>
 #include <asm/oplib.h>
 #include <asm/types.h>
-#include <asm/system.h>
 
 static struct linux_prom_ranges promlib_obio_ranges[PROMREG_MAX];
 static int num_obio_ranges;
index 921dbeb..bb696da 100644 (file)
@@ -20,7 +20,7 @@
 #ifndef __ASSEMBLY__
 
 #include <linux/compiler.h>
-#include <asm/system.h>
+#include <linux/types.h>
 
 #define ATOMIC_INIT(i) { (i) }
 
index c03349e..466dc4a 100644 (file)
@@ -17,6 +17,7 @@
 #ifndef _ASM_TILE_ATOMIC_32_H
 #define _ASM_TILE_ATOMIC_32_H
 
+#include <asm/barrier.h>
 #include <arch/chip.h>
 
 #ifndef __ASSEMBLY__
index 27fe667..f4500c6 100644 (file)
@@ -19,6 +19,7 @@
 
 #ifndef __ASSEMBLY__
 
+#include <asm/barrier.h>
 #include <arch/spr_def.h>
 
 /* First, the 32-bit atomic ops that are "real" on our 64-bit platform. */
diff --git a/arch/tile/include/asm/barrier.h b/arch/tile/include/asm/barrier.h
new file mode 100644 (file)
index 0000000..990a217
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * 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.
+ */
+
+#ifndef _ASM_TILE_BARRIER_H
+#define _ASM_TILE_BARRIER_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+#include <arch/chip.h>
+#include <arch/spr_def.h>
+#include <asm/timex.h>
+
+/*
+ * read_barrier_depends - Flush all pending reads that subsequents reads
+ * depend on.
+ *
+ * No data-dependent reads from memory-like regions are ever reordered
+ * over this barrier.  All reads preceding this primitive are guaranteed
+ * to access memory (but not necessarily other CPUs' caches) before any
+ * reads following this primitive that depend on the data return by
+ * any of the preceding reads.  This primitive is much lighter weight than
+ * rmb() on most CPUs, and is never heavier weight than is
+ * rmb().
+ *
+ * These ordering constraints are respected by both the local CPU
+ * and the compiler.
+ *
+ * Ordering is not guaranteed by anything other than these primitives,
+ * not even by data dependencies.  See the documentation for
+ * memory_barrier() for examples and URLs to more information.
+ *
+ * For example, the following code would force ordering (the initial
+ * value of "a" is zero, "b" is one, and "p" is "&a"):
+ *
+ * <programlisting>
+ *     CPU 0                           CPU 1
+ *
+ *     b = 2;
+ *     memory_barrier();
+ *     p = &b;                         q = p;
+ *                                     read_barrier_depends();
+ *                                     d = *q;
+ * </programlisting>
+ *
+ * because the read of "*q" depends on the read of "p" and these
+ * two reads are separated by a read_barrier_depends().  However,
+ * the following code, with the same initial values for "a" and "b":
+ *
+ * <programlisting>
+ *     CPU 0                           CPU 1
+ *
+ *     a = 2;
+ *     memory_barrier();
+ *     b = 3;                          y = b;
+ *                                     read_barrier_depends();
+ *                                     x = a;
+ * </programlisting>
+ *
+ * does not enforce ordering, since there is no data dependency between
+ * the read of "a" and the read of "b".  Therefore, on some CPUs, such
+ * as Alpha, "y" could be set to 3 and "x" to 0.  Use rmb()
+ * in cases like this where there are no data dependencies.
+ */
+#define read_barrier_depends() do { } while (0)
+
+#define __sync()       __insn_mf()
+
+#if !CHIP_HAS_MF_WAITS_FOR_VICTIMS()
+#include <hv/syscall_public.h>
+/*
+ * Issue an uncacheable load to each memory controller, then
+ * wait until those loads have completed.
+ */
+static inline void __mb_incoherent(void)
+{
+       long clobber_r10;
+       asm volatile("swint2"
+                    : "=R10" (clobber_r10)
+                    : "R10" (HV_SYS_fence_incoherent)
+                    : "r0", "r1", "r2", "r3", "r4",
+                      "r5", "r6", "r7", "r8", "r9",
+                      "r11", "r12", "r13", "r14",
+                      "r15", "r16", "r17", "r18", "r19",
+                      "r20", "r21", "r22", "r23", "r24",
+                      "r25", "r26", "r27", "r28", "r29");
+}
+#endif
+
+/* Fence to guarantee visibility of stores to incoherent memory. */
+static inline void
+mb_incoherent(void)
+{
+       __insn_mf();
+
+#if !CHIP_HAS_MF_WAITS_FOR_VICTIMS()
+       {
+#if CHIP_HAS_TILE_WRITE_PENDING()
+               const unsigned long WRITE_TIMEOUT_CYCLES = 400;
+               unsigned long start = get_cycles_low();
+               do {
+                       if (__insn_mfspr(SPR_TILE_WRITE_PENDING) == 0)
+                               return;
+               } while ((get_cycles_low() - start) < WRITE_TIMEOUT_CYCLES);
+#endif /* CHIP_HAS_TILE_WRITE_PENDING() */
+               (void) __mb_incoherent();
+       }
+#endif /* CHIP_HAS_MF_WAITS_FOR_VICTIMS() */
+}
+
+#define fast_wmb()     __sync()
+#define fast_rmb()     __sync()
+#define fast_mb()      __sync()
+#define fast_iob()     mb_incoherent()
+
+#define wmb()          fast_wmb()
+#define rmb()          fast_rmb()
+#define mb()           fast_mb()
+#define iob()          fast_iob()
+
+#ifdef CONFIG_SMP
+#define smp_mb()       mb()
+#define smp_rmb()      rmb()
+#define smp_wmb()      wmb()
+#define smp_read_barrier_depends()     read_barrier_depends()
+#else
+#define smp_mb()       barrier()
+#define smp_rmb()      barrier()
+#define smp_wmb()      barrier()
+#define smp_read_barrier_depends()     do { } while (0)
+#endif
+
+#define set_mb(var, value) \
+       do { var = value; mb(); } while (0)
+
+#endif /* !__ASSEMBLY__ */
+#endif /* _ASM_TILE_BARRIER_H */
index 571b118..ddc4c1e 100644 (file)
@@ -17,7 +17,6 @@
 
 #include <linux/compiler.h>
 #include <linux/atomic.h>
-#include <asm/system.h>
 
 /* Tile-specific routines to support <asm/bitops.h>. */
 unsigned long _atomic_or(volatile unsigned long *p, unsigned long mask);
index e9c8e38..58d021a 100644 (file)
@@ -17,7 +17,6 @@
 
 #include <linux/compiler.h>
 #include <linux/atomic.h>
-#include <asm/system.h>
 
 /* See <asm/bitops.h> for API comments. */
 
index e925f4b..0fc63c4 100644 (file)
@@ -20,7 +20,6 @@
 /* Keep includes the same across arches.  */
 #include <linux/mm.h>
 #include <linux/cache.h>
-#include <asm/system.h>
 #include <arch/icache.h>
 
 /* Caches are physically-indexed and so don't need special treatment */
@@ -152,4 +151,14 @@ static inline void finv_buffer_local(void *buffer, size_t size)
  */
 void finv_buffer_remote(void *buffer, size_t size, int hfh);
 
+/*
+ * On SMP systems, when the scheduler does migration-cost autodetection,
+ * it needs a way to flush as much of the CPU's caches as possible:
+ *
+ * TODO: fill this in!
+ */
+static inline void sched_cacheflush(void)
+{
+}
+
 #endif /* _ASM_TILE_CACHEFLUSH_H */
diff --git a/arch/tile/include/asm/exec.h b/arch/tile/include/asm/exec.h
new file mode 100644 (file)
index 0000000..a714e19
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+#ifndef _ASM_TILE_EXEC_H
+#define _ASM_TILE_EXEC_H
+
+#define arch_align_stack(x) (x)
+
+#endif /* _ASM_TILE_EXEC_H */
index 1a20b7e..6749091 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/spinlock.h>
 #include <asm/processor.h>
 #include <asm/fixmap.h>
-#include <asm/system.h>
 
 struct mm_struct;
 struct vm_area_struct;
index 7caf0f3..e58613e 100644 (file)
@@ -31,6 +31,28 @@ void early_panic(const char *fmt, ...);
 void warn_early_printk(void);
 void __init disable_early_printk(void);
 
+/* Init-time routine to do tile-specific per-cpu setup. */
+void setup_cpu(int boot);
+
+/* User-level DMA management functions */
+void grant_dma_mpls(void);
+void restrict_dma_mpls(void);
+
+#ifdef CONFIG_HARDWALL
+/* User-level network management functions */
+void reset_network_state(void);
+void grant_network_mpls(void);
+void restrict_network_mpls(void);
+struct task_struct;
+int hardwall_deactivate(struct task_struct *task);
+
+/* Hook hardwall code into changes in affinity. */
+#define arch_set_cpus_allowed(p, new_mask) do { \
+       if (p->thread.hardwall && !cpumask_equal(&p->cpus_allowed, new_mask)) \
+               hardwall_deactivate(p); \
+} while (0)
+#endif
+
 #endif /* __KERNEL__ */
 
 #endif /* _ASM_TILE_SETUP_H */
index a5e4208..c0a77b3 100644 (file)
@@ -19,7 +19,6 @@
 
 #include <linux/atomic.h>
 #include <asm/page.h>
-#include <asm/system.h>
 #include <linux/compiler.h>
 
 /*
diff --git a/arch/tile/include/asm/switch_to.h b/arch/tile/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..1d48c5f
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+
+#ifndef _ASM_TILE_SWITCH_TO_H
+#define _ASM_TILE_SWITCH_TO_H
+
+#include <arch/sim_def.h>
+
+/*
+ * switch_to(n) should switch tasks to task nr n, first
+ * checking that n isn't the current task, in which case it does nothing.
+ * The number of callee-saved registers saved on the kernel stack
+ * is defined here for use in copy_thread() and must agree with __switch_to().
+ */
+#define CALLEE_SAVED_FIRST_REG 30
+#define CALLEE_SAVED_REGS_COUNT 24   /* r30 to r52, plus an empty to align */
+
+#ifndef __ASSEMBLY__
+
+struct task_struct;
+
+/*
+ * Pause the DMA engine and static network before task switching.
+ */
+#define prepare_arch_switch(next) _prepare_arch_switch(next)
+void _prepare_arch_switch(struct task_struct *next);
+
+struct task_struct;
+#define switch_to(prev, next, last) ((last) = _switch_to((prev), (next)))
+extern struct task_struct *_switch_to(struct task_struct *prev,
+                                     struct task_struct *next);
+
+/* Helper function for _switch_to(). */
+extern struct task_struct *__switch_to(struct task_struct *prev,
+                                      struct task_struct *next,
+                                      unsigned long new_system_save_k_0);
+
+/* Address that switched-away from tasks are at. */
+extern unsigned long get_switch_to_pc(void);
+
+/*
+ * Kernel threads can check to see if they need to migrate their
+ * stack whenever they return from a context switch; for user
+ * threads, we defer until they are returning to user-space.
+ */
+#define finish_arch_switch(prev) do {                                     \
+       if (unlikely((prev)->state == TASK_DEAD))                         \
+               __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_OS_EXIT |       \
+                       ((prev)->pid << _SIM_CONTROL_OPERATOR_BITS));     \
+       __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_OS_SWITCH |             \
+               (current->pid << _SIM_CONTROL_OPERATOR_BITS));            \
+       if (current->mm == NULL && !kstack_hash &&                        \
+           current_thread_info()->homecache_cpu != smp_processor_id())   \
+               homecache_migrate_kthread();                              \
+} while (0)
+
+/* Support function for forking a new task. */
+void ret_from_fork(void);
+
+/* Called from ret_from_fork() when a new process starts up. */
+struct task_struct *sim_notify_fork(struct task_struct *prev);
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* _ASM_TILE_SWITCH_TO_H */
diff --git a/arch/tile/include/asm/system.h b/arch/tile/include/asm/system.h
deleted file mode 100644 (file)
index 23d1842..0000000
+++ /dev/null
@@ -1,261 +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.
- */
-
-#ifndef _ASM_TILE_SYSTEM_H
-#define _ASM_TILE_SYSTEM_H
-
-#ifndef __ASSEMBLY__
-
-#include <linux/types.h>
-#include <linux/irqflags.h>
-
-/* NOTE: we can't include <linux/ptrace.h> due to #include dependencies. */
-#include <asm/ptrace.h>
-
-#include <arch/chip.h>
-#include <arch/sim_def.h>
-#include <arch/spr_def.h>
-
-/*
- * read_barrier_depends - Flush all pending reads that subsequents reads
- * depend on.
- *
- * No data-dependent reads from memory-like regions are ever reordered
- * over this barrier.  All reads preceding this primitive are guaranteed
- * to access memory (but not necessarily other CPUs' caches) before any
- * reads following this primitive that depend on the data return by
- * any of the preceding reads.  This primitive is much lighter weight than
- * rmb() on most CPUs, and is never heavier weight than is
- * rmb().
- *
- * These ordering constraints are respected by both the local CPU
- * and the compiler.
- *
- * Ordering is not guaranteed by anything other than these primitives,
- * not even by data dependencies.  See the documentation for
- * memory_barrier() for examples and URLs to more information.
- *
- * For example, the following code would force ordering (the initial
- * value of "a" is zero, "b" is one, and "p" is "&a"):
- *
- * <programlisting>
- *     CPU 0                           CPU 1
- *
- *     b = 2;
- *     memory_barrier();
- *     p = &b;                         q = p;
- *                                     read_barrier_depends();
- *                                     d = *q;
- * </programlisting>
- *
- * because the read of "*q" depends on the read of "p" and these
- * two reads are separated by a read_barrier_depends().  However,
- * the following code, with the same initial values for "a" and "b":
- *
- * <programlisting>
- *     CPU 0                           CPU 1
- *
- *     a = 2;
- *     memory_barrier();
- *     b = 3;                          y = b;
- *                                     read_barrier_depends();
- *                                     x = a;
- * </programlisting>
- *
- * does not enforce ordering, since there is no data dependency between
- * the read of "a" and the read of "b".  Therefore, on some CPUs, such
- * as Alpha, "y" could be set to 3 and "x" to 0.  Use rmb()
- * in cases like this where there are no data dependencies.
- */
-
-#define read_barrier_depends() do { } while (0)
-
-#define __sync()       __insn_mf()
-
-#if CHIP_HAS_SPLIT_CYCLE()
-#define get_cycles_low() __insn_mfspr(SPR_CYCLE_LOW)
-#else
-#define get_cycles_low() __insn_mfspr(SPR_CYCLE)   /* just get all 64 bits */
-#endif
-
-#if !CHIP_HAS_MF_WAITS_FOR_VICTIMS()
-#include <hv/syscall_public.h>
-/*
- * Issue an uncacheable load to each memory controller, then
- * wait until those loads have completed.
- */
-static inline void __mb_incoherent(void)
-{
-       long clobber_r10;
-       asm volatile("swint2"
-                    : "=R10" (clobber_r10)
-                    : "R10" (HV_SYS_fence_incoherent)
-                    : "r0", "r1", "r2", "r3", "r4",
-                      "r5", "r6", "r7", "r8", "r9",
-                      "r11", "r12", "r13", "r14",
-                      "r15", "r16", "r17", "r18", "r19",
-                      "r20", "r21", "r22", "r23", "r24",
-                      "r25", "r26", "r27", "r28", "r29");
-}
-#endif
-
-/* Fence to guarantee visibility of stores to incoherent memory. */
-static inline void
-mb_incoherent(void)
-{
-       __insn_mf();
-
-#if !CHIP_HAS_MF_WAITS_FOR_VICTIMS()
-       {
-#if CHIP_HAS_TILE_WRITE_PENDING()
-               const unsigned long WRITE_TIMEOUT_CYCLES = 400;
-               unsigned long start = get_cycles_low();
-               do {
-                       if (__insn_mfspr(SPR_TILE_WRITE_PENDING) == 0)
-                               return;
-               } while ((get_cycles_low() - start) < WRITE_TIMEOUT_CYCLES);
-#endif /* CHIP_HAS_TILE_WRITE_PENDING() */
-               (void) __mb_incoherent();
-       }
-#endif /* CHIP_HAS_MF_WAITS_FOR_VICTIMS() */
-}
-
-#define fast_wmb()     __sync()
-#define fast_rmb()     __sync()
-#define fast_mb()      __sync()
-#define fast_iob()     mb_incoherent()
-
-#define wmb()          fast_wmb()
-#define rmb()          fast_rmb()
-#define mb()           fast_mb()
-#define iob()          fast_iob()
-
-#ifdef CONFIG_SMP
-#define smp_mb()       mb()
-#define smp_rmb()      rmb()
-#define smp_wmb()      wmb()
-#define smp_read_barrier_depends()     read_barrier_depends()
-#else
-#define smp_mb()       barrier()
-#define smp_rmb()      barrier()
-#define smp_wmb()      barrier()
-#define smp_read_barrier_depends()     do { } while (0)
-#endif
-
-#define set_mb(var, value) \
-       do { var = value; mb(); } while (0)
-
-/*
- * Pause the DMA engine and static network before task switching.
- */
-#define prepare_arch_switch(next) _prepare_arch_switch(next)
-void _prepare_arch_switch(struct task_struct *next);
-
-
-/*
- * switch_to(n) should switch tasks to task nr n, first
- * checking that n isn't the current task, in which case it does nothing.
- * The number of callee-saved registers saved on the kernel stack
- * is defined here for use in copy_thread() and must agree with __switch_to().
- */
-#endif /* !__ASSEMBLY__ */
-#define CALLEE_SAVED_FIRST_REG 30
-#define CALLEE_SAVED_REGS_COUNT 24   /* r30 to r52, plus an empty to align */
-#ifndef __ASSEMBLY__
-struct task_struct;
-#define switch_to(prev, next, last) ((last) = _switch_to((prev), (next)))
-extern struct task_struct *_switch_to(struct task_struct *prev,
-                                     struct task_struct *next);
-
-/* Helper function for _switch_to(). */
-extern struct task_struct *__switch_to(struct task_struct *prev,
-                                      struct task_struct *next,
-                                      unsigned long new_system_save_k_0);
-
-/* Address that switched-away from tasks are at. */
-extern unsigned long get_switch_to_pc(void);
-
-/*
- * On SMP systems, when the scheduler does migration-cost autodetection,
- * it needs a way to flush as much of the CPU's caches as possible:
- *
- * TODO: fill this in!
- */
-static inline void sched_cacheflush(void)
-{
-}
-
-#define arch_align_stack(x) (x)
-
-/*
- * Is the kernel doing fixups of unaligned accesses?  If <0, no kernel
- * intervention occurs and SIGBUS is delivered with no data address
- * info.  If 0, the kernel single-steps the instruction to discover
- * the data address to provide with the SIGBUS.  If 1, the kernel does
- * a fixup.
- */
-extern int unaligned_fixup;
-
-/* Is the kernel printing on each unaligned fixup? */
-extern int unaligned_printk;
-
-/* Number of unaligned fixups performed */
-extern unsigned int unaligned_fixup_count;
-
-/* Init-time routine to do tile-specific per-cpu setup. */
-void setup_cpu(int boot);
-
-/* User-level DMA management functions */
-void grant_dma_mpls(void);
-void restrict_dma_mpls(void);
-
-#ifdef CONFIG_HARDWALL
-/* User-level network management functions */
-void reset_network_state(void);
-void grant_network_mpls(void);
-void restrict_network_mpls(void);
-int hardwall_deactivate(struct task_struct *task);
-
-/* Hook hardwall code into changes in affinity. */
-#define arch_set_cpus_allowed(p, new_mask) do { \
-       if (p->thread.hardwall && !cpumask_equal(&p->cpus_allowed, new_mask)) \
-               hardwall_deactivate(p); \
-} while (0)
-#endif
-
-/*
- * Kernel threads can check to see if they need to migrate their
- * stack whenever they return from a context switch; for user
- * threads, we defer until they are returning to user-space.
- */
-#define finish_arch_switch(prev) do {                                     \
-       if (unlikely((prev)->state == TASK_DEAD))                         \
-               __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_OS_EXIT |       \
-                       ((prev)->pid << _SIM_CONTROL_OPERATOR_BITS));     \
-       __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_OS_SWITCH |             \
-               (current->pid << _SIM_CONTROL_OPERATOR_BITS));            \
-       if (current->mm == NULL && !kstack_hash &&                        \
-           current_thread_info()->homecache_cpu != smp_processor_id())   \
-               homecache_migrate_kthread();                              \
-} while (0)
-
-/* Support function for forking a new task. */
-void ret_from_fork(void);
-
-/* Called from ret_from_fork() when a new process starts up. */
-struct task_struct *sim_notify_fork(struct task_struct *prev);
-
-#endif /* !__ASSEMBLY__ */
-
-#endif /* _ASM_TILE_SYSTEM_H */
index 29921f0..dc987d5 100644 (file)
@@ -29,11 +29,13 @@ typedef unsigned long long cycles_t;
 
 #if CHIP_HAS_SPLIT_CYCLE()
 cycles_t get_cycles(void);
+#define get_cycles_low() __insn_mfspr(SPR_CYCLE_LOW)
 #else
 static inline cycles_t get_cycles(void)
 {
        return __insn_mfspr(SPR_CYCLE);
 }
+#define get_cycles_low() __insn_mfspr(SPR_CYCLE)   /* just get all 64 bits */
 #endif
 
 cycles_t get_clock_rate(void);
index 137e2de..37dfbe5 100644 (file)
 #define get_unaligned  __get_unaligned_le
 #define put_unaligned  __put_unaligned_le
 
+/*
+ * Is the kernel doing fixups of unaligned accesses?  If <0, no kernel
+ * intervention occurs and SIGBUS is delivered with no data address
+ * info.  If 0, the kernel single-steps the instruction to discover
+ * the data address to provide with the SIGBUS.  If 1, the kernel does
+ * a fixup.
+ */
+extern int unaligned_fixup;
+
+/* Is the kernel printing on each unaligned fixup? */
+extern int unaligned_printk;
+
+/* Number of unaligned fixups performed */
+extern unsigned int unaligned_fixup_count;
+
 #endif /* _ASM_TILE_UNALIGNED_H */
index 493a0e6..afb9c9a 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/string.h>
+#include <linux/irqflags.h>
 #include <asm/setup.h>
 #include <hv/hypervisor.h>
 
index 62d8208..7a93270 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/sysctl.h>
 #include <linux/hardirq.h>
 #include <linux/mman.h>
+#include <asm/unaligned.h>
 #include <asm/pgtable.h>
 #include <asm/processor.h>
 #include <asm/sections.h>
index 6ae495e..30caeca 100644 (file)
 #include <linux/kernel.h>
 #include <linux/tracehook.h>
 #include <linux/signal.h>
-#include <asm/system.h>
 #include <asm/stack.h>
 #include <asm/homecache.h>
 #include <asm/syscalls.h>
 #include <asm/traps.h>
+#include <asm/setup.h>
 #ifdef CONFIG_HARDWALL
 #include <asm/hardwall.h>
 #endif
 #include <arch/chip.h>
 #include <arch/abi.h>
+#include <arch/sim_def.h>
 
 
 /*
index caa1310..c12280c 100644 (file)
  */
 
 #include <linux/linkage.h>
-#include <asm/system.h>
 #include <asm/ptrace.h>
 #include <asm/asm-offsets.h>
 #include <arch/spr_def.h>
 #include <asm/processor.h>
+#include <asm/switch_to.h>
 
 /*
  * See <asm/system.h>; called with prev and next task_struct pointers.
index f748c1e..0829fd0 100644 (file)
  */
 
 #include <linux/linkage.h>
-#include <asm/system.h>
 #include <asm/ptrace.h>
 #include <asm/asm-offsets.h>
 #include <arch/spr_def.h>
 #include <asm/processor.h>
+#include <asm/switch_to.h>
 
 /*
  * See <asm/system.h>; called with prev and next task_struct pointers.
index b7a8795..bc1eb58 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/types.h>
 #include <linux/err.h>
 #include <asm/cacheflush.h>
+#include <asm/unaligned.h>
 #include <arch/abi.h>
 #include <arch/opcode.h>
 
index 4f47b8a..2bb6602 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/ptrace.h>
 #include <asm/stack.h>
 #include <asm/traps.h>
+#include <asm/setup.h>
 
 #include <arch/interrupts.h>
 #include <arch/spr_def.h>
index 1a00fb6..758b603 100644 (file)
@@ -21,6 +21,7 @@
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
 #include <asm/sections.h>
+#include <arch/sim_def.h>
 
 /* Notify a running simulator, if any, that an exec just occurred. */
 static void sim_notify_exec(const char *binary_name)
index c1eaaa1..cba30e9 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/syscalls.h>
 #include <linux/uaccess.h>
 
-#include <asm/system.h>
 #include <asm/pgalloc.h>
 #include <asm/sections.h>
 #include <asm/traps.h>
index 7309988..830c490 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/uaccess.h>
 #include <asm/mmu_context.h>
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
 #include <asm/dma.h>
index de7d8e2..8730369 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/vmalloc.h>
 #include <linux/smp.h>
 
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
 #include <asm/fixmap.h>
index 69c0252..21a423b 100644 (file)
@@ -2,7 +2,6 @@
 #define __UM_FIXMAP_H
 
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/kmap_types.h>
 #include <asm/archparam.h>
 #include <asm/page.h>
index ca113d6..34b789b 100644 (file)
@@ -3,7 +3,6 @@ include include/asm-generic/Kbuild.asm
 generic-y += atomic.h
 generic-y += auxvec.h
 generic-y += bitsperlong.h
-generic-y += bug.h
 generic-y += bugs.h
 generic-y += cputime.h
 generic-y += current.h
diff --git a/arch/unicore32/include/asm/barrier.h b/arch/unicore32/include/asm/barrier.h
new file mode 100644 (file)
index 0000000..a6620e5
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Memory barrier implementations for PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2012 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 __UNICORE_BARRIER_H__
+#define __UNICORE_BARRIER_H__
+
+#define isb() __asm__ __volatile__ ("" : : : "memory")
+#define dsb() __asm__ __volatile__ ("" : : : "memory")
+#define dmb() __asm__ __volatile__ ("" : : : "memory")
+
+#define mb()                           barrier()
+#define rmb()                          barrier()
+#define wmb()                          barrier()
+#define smp_mb()                       barrier()
+#define smp_rmb()                      barrier()
+#define smp_wmb()                      barrier()
+#define read_barrier_depends()         do { } while (0)
+#define smp_read_barrier_depends()     do { } while (0)
+
+#define set_mb(var, value)             do { var = value; smp_mb(); } while (0)
+
+#endif /* __UNICORE_BARRIER_H__ */
diff --git a/arch/unicore32/include/asm/bug.h b/arch/unicore32/include/asm/bug.h
new file mode 100644 (file)
index 0000000..b1ff8ca
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Bug handling for PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2012 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 __UNICORE_BUG_H__
+#define __UNICORE_BUG_H__
+
+#include <asm-generic/bug.h>
+
+struct pt_regs;
+struct siginfo;
+
+extern void die(const char *msg, struct pt_regs *regs, int err);
+extern void uc32_notify_die(const char *str, struct pt_regs *regs,
+               struct siginfo *info, unsigned long err, unsigned long trap);
+
+extern asmlinkage void __backtrace(void);
+extern asmlinkage void c_backtrace(unsigned long fp, int pmode);
+
+extern void __show_regs(struct pt_regs *);
+
+#endif /* __UNICORE_BUG_H__ */
diff --git a/arch/unicore32/include/asm/cmpxchg.h b/arch/unicore32/include/asm/cmpxchg.h
new file mode 100644 (file)
index 0000000..df4d5ac
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Atomics xchg/cmpxchg for PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2012 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 __UNICORE_CMPXCHG_H__
+#define __UNICORE_CMPXCHG_H__
+
+/*
+ * Generate a link failure on undefined symbol if the pointer points to a value
+ * of unsupported size.
+ */
+extern void __xchg_bad_pointer(void);
+
+static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
+               int size)
+{
+       unsigned long ret;
+
+       switch (size) {
+       case 1:
+               asm volatile("swapb     %0, %1, [%2]"
+                       : "=&r" (ret)
+                       : "r" (x), "r" (ptr)
+                       : "memory", "cc");
+               break;
+       case 4:
+               asm volatile("swapw     %0, %1, [%2]"
+                       : "=&r" (ret)
+                       : "r" (x), "r" (ptr)
+                       : "memory", "cc");
+               break;
+       default:
+               ret = __xchg_bad_pointer();
+       }
+
+       return ret;
+}
+
+#define xchg(ptr, x) \
+       ((__typeof__(*(ptr)))__xchg((unsigned long)(x), (ptr), sizeof(*(ptr))))
+
+#include <asm-generic/cmpxchg-local.h>
+
+/*
+ * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
+ * them available.
+ */
+#define cmpxchg_local(ptr, o, n)                                       \
+               ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr),     \
+               (unsigned long)(o), (unsigned long)(n), sizeof(*(ptr))))
+#define cmpxchg64_local(ptr, o, n)                                     \
+               __cmpxchg64_local_generic((ptr), (o), (n))
+
+#include <asm-generic/cmpxchg.h>
+
+#endif /* __UNICORE_CMPXCHG_H__ */
diff --git a/arch/unicore32/include/asm/exec.h b/arch/unicore32/include/asm/exec.h
new file mode 100644 (file)
index 0000000..06d1f0f
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * Process execution bits for PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2012 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 __UNICORE_EXEC_H__
+#define __UNICORE_EXEC_H__
+
+#define arch_align_stack(x)            (x)
+
+#endif /* __UNICORE_EXEC_H__ */
diff --git a/arch/unicore32/include/asm/hwdef-copro.h b/arch/unicore32/include/asm/hwdef-copro.h
new file mode 100644 (file)
index 0000000..a3292f0
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Co-processor register definitions for PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2012 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 __UNICORE_HWDEF_COPRO_H__
+#define __UNICORE_HWDEF_COPRO_H__
+
+/*
+ * Control Register bits (CP#0 CR1)
+ */
+#define CR_M   (1 << 0)        /* MMU enable                           */
+#define CR_A   (1 << 1)        /* Alignment abort enable               */
+#define CR_D   (1 << 2)        /* Dcache enable                        */
+#define CR_I   (1 << 3)        /* Icache enable                        */
+#define CR_B   (1 << 4)        /* Dcache write mechanism: write back   */
+#define CR_T   (1 << 5)        /* Burst enable                         */
+#define CR_V   (1 << 13)       /* Vectors relocated to 0xffff0000      */
+
+#ifndef __ASSEMBLY__
+
+#define vectors_high()         (cr_alignment & CR_V)
+
+extern unsigned long cr_no_alignment;  /* defined in entry.S */
+extern unsigned long cr_alignment;     /* defined in entry.S */
+
+static inline unsigned int get_cr(void)
+{
+       unsigned int val;
+       asm("movc %0, p0.c1, #0" : "=r" (val) : : "cc");
+       return val;
+}
+
+static inline void set_cr(unsigned int val)
+{
+       asm volatile("movc p0.c1, %0, #0" : : "r" (val) : "cc");
+       isb();
+}
+
+extern void adjust_cr(unsigned long mask, unsigned long set);
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __UNICORE_HWDEF_COPRO_H__ */
index adddf6d..39decb6 100644 (file)
@@ -16,7 +16,6 @@
 
 #include <asm/byteorder.h>
 #include <asm/memory.h>
-#include <asm/system.h>
 
 #define PCI_IOBASE     PKUNITY_PCILIO_BASE
 #include <asm-generic/io.h>
diff --git a/arch/unicore32/include/asm/switch_to.h b/arch/unicore32/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..39572d2
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Task switching for PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2012 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 __UNICORE_SWITCH_TO_H__
+#define __UNICORE_SWITCH_TO_H__
+
+struct task_struct;
+struct thread_info;
+
+/*
+ * switch_to(prev, next) should switch from task `prev' to `next'
+ * `prev' will never be the same as `next'.  schedule() itself
+ * contains the memory barrier to tell GCC not to cache `current'.
+ */
+extern struct task_struct *__switch_to(struct task_struct *,
+               struct thread_info *, struct thread_info *);
+
+#define switch_to(prev, next, last)                                    \
+       do {                                                            \
+               last = __switch_to(prev, task_thread_info(prev),        \
+                                       task_thread_info(next));        \
+       } while (0)
+
+#endif /* __UNICORE_SWITCH_TO_H__ */
diff --git a/arch/unicore32/include/asm/system.h b/arch/unicore32/include/asm/system.h
deleted file mode 100644 (file)
index 246b71c..0000000
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * linux/arch/unicore32/include/asm/system.h
- *
- * Code specific to PKUnity SoC and UniCore ISA
- *
- * Copyright (C) 2001-2010 GUAN Xue-tao
- *
- * This program is free software; you can 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 __UNICORE_SYSTEM_H__
-#define __UNICORE_SYSTEM_H__
-
-#ifdef __KERNEL__
-
-/*
- * CR1 bits (CP#0 CR1)
- */
-#define CR_M   (1 << 0)        /* MMU enable                           */
-#define CR_A   (1 << 1)        /* Alignment abort enable               */
-#define CR_D   (1 << 2)        /* Dcache enable                        */
-#define CR_I   (1 << 3)        /* Icache enable                        */
-#define CR_B   (1 << 4)        /* Dcache write mechanism: write back   */
-#define CR_T   (1 << 5)        /* Burst enable                         */
-#define CR_V   (1 << 13)       /* Vectors relocated to 0xffff0000      */
-
-#ifndef __ASSEMBLY__
-
-#include <linux/linkage.h>
-#include <linux/irqflags.h>
-
-struct thread_info;
-struct task_struct;
-
-struct pt_regs;
-
-void die(const char *msg, struct pt_regs *regs, int err);
-
-struct siginfo;
-void uc32_notify_die(const char *str, struct pt_regs *regs,
-               struct siginfo *info, unsigned long err, unsigned long trap);
-
-void hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int,
-                                      struct pt_regs *),
-                    int sig, int code, const char *name);
-
-#define xchg(ptr, x) \
-       ((__typeof__(*(ptr)))__xchg((unsigned long)(x), (ptr), sizeof(*(ptr))))
-
-extern asmlinkage void __backtrace(void);
-extern asmlinkage void c_backtrace(unsigned long fp, int pmode);
-
-struct mm_struct;
-extern void show_pte(struct mm_struct *mm, unsigned long addr);
-extern void __show_regs(struct pt_regs *);
-
-extern int cpu_architecture(void);
-extern void cpu_init(void);
-
-#define vectors_high() (cr_alignment & CR_V)
-
-#define isb() __asm__ __volatile__ ("" : : : "memory")
-#define dsb() __asm__ __volatile__ ("" : : : "memory")
-#define dmb() __asm__ __volatile__ ("" : : : "memory")
-
-#define mb()           barrier()
-#define rmb()          barrier()
-#define wmb()          barrier()
-#define smp_mb()       barrier()
-#define smp_rmb()      barrier()
-#define smp_wmb()      barrier()
-#define read_barrier_depends()         do { } while (0)
-#define smp_read_barrier_depends()     do { } while (0)
-
-#define set_mb(var, value)     do { var = value; smp_mb(); } while (0)
-#define nop() __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t");
-
-extern unsigned long cr_no_alignment;  /* defined in entry-unicore.S */
-extern unsigned long cr_alignment;     /* defined in entry-unicore.S */
-
-static inline unsigned int get_cr(void)
-{
-       unsigned int val;
-       asm("movc %0, p0.c1, #0" : "=r" (val) : : "cc");
-       return val;
-}
-
-static inline void set_cr(unsigned int val)
-{
-       asm volatile("movc p0.c1, %0, #0        @set CR"
-         : : "r" (val) : "cc");
-       isb();
-}
-
-extern void adjust_cr(unsigned long mask, unsigned long set);
-
-/*
- * switch_to(prev, next) should switch from task `prev' to `next'
- * `prev' will never be the same as `next'.  schedule() itself
- * contains the memory barrier to tell GCC not to cache `current'.
- */
-extern struct task_struct *__switch_to(struct task_struct *,
-               struct thread_info *, struct thread_info *);
-extern void panic(const char *fmt, ...);
-
-#define switch_to(prev, next, last)                                    \
-do {                                                                   \
-       last = __switch_to(prev,                                        \
-               task_thread_info(prev), task_thread_info(next));        \
-} while (0)
-
-static inline unsigned long
-__xchg(unsigned long x, volatile void *ptr, int size)
-{
-       unsigned long ret;
-
-       switch (size) {
-       case 1:
-               asm volatile("@ __xchg1\n"
-               "       swapb   %0, %1, [%2]"
-                       : "=&r" (ret)
-                       : "r" (x), "r" (ptr)
-                       : "memory", "cc");
-               break;
-       case 4:
-               asm volatile("@ __xchg4\n"
-               "       swapw   %0, %1, [%2]"
-                       : "=&r" (ret)
-                       : "r" (x), "r" (ptr)
-                       : "memory", "cc");
-               break;
-       default:
-               panic("xchg: bad data size: ptr 0x%p, size %d\n",
-                       ptr, size);
-       }
-
-       return ret;
-}
-
-#include <asm-generic/cmpxchg-local.h>
-
-/*
- * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
- * them available.
- */
-#define cmpxchg_local(ptr, o, n)                                       \
-               ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr),     \
-               (unsigned long)(o), (unsigned long)(n), sizeof(*(ptr))))
-#define cmpxchg64_local(ptr, o, n)                                     \
-               __cmpxchg64_local_generic((ptr), (o), (n))
-
-#include <asm-generic/cmpxchg.h>
-
-#endif /* __ASSEMBLY__ */
-
-#define arch_align_stack(x) (x)
-
-#endif /* __KERNEL__ */
-
-#endif
index 2acda50..897e11a 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/errno.h>
 
 #include <asm/memory.h>
-#include <asm/system.h>
 
 #define __copy_from_user       __copy_from_user
 #define __copy_to_user         __copy_to_user
index ae441bc..ed2d4d7 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/errno.h>
 #include <linux/io.h>
 
-#include <asm/system.h>
 #include <asm/irq.h>
 #include <mach/hardware.h>
 #include <mach/dma.h>
index 8caf322..e8f0b98 100644 (file)
@@ -17,7 +17,7 @@
 #include <generated/asm-offsets.h>
 #include <asm/memory.h>
 #include <asm/thread_info.h>
-#include <asm/system.h>
+#include <asm/hwdef-copro.h>
 #include <asm/pgtable-hwdef.h>
 
 #if (PHYS_OFFSET & 0x003fffff)
index 7d0f0b7..d75ef8b 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/suspend.h>
 #include <linux/bootmem.h>
 
-#include <asm/system.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
index d4efa7d..0be5ccd 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/syscore_ops.h>
 #include <linux/gpio.h>
 
-#include <asm/system.h>
 #include <mach/hardware.h>
 
 #include "setup.h"
index d98bd81..d285d71 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/io.h>
 
 #include <asm/checksum.h>
-#include <asm/system.h>
 
 #include "ksyms.h"
 
index 432b429..b6f0458 100644 (file)
@@ -34,7 +34,6 @@
 
 #include <asm/cacheflush.h>
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/stacktrace.h>
 
 #include "setup.h"
index dcd1306..f239550 100644 (file)
 #ifndef __UNICORE_KERNEL_SETUP_H__
 #define __UNICORE_KERNEL_SETUP_H__
 
+#include <asm/hwdef-copro.h>
+
 extern void paging_init(void);
 extern void puv3_core_init(void);
+extern void cpu_init(void);
 
 extern void puv3_ps2_init(void);
 extern void pci_puv3_preinit(void);
index b9a2646..2054f0d 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/unistd.h>
 
 #include <asm/cacheflush.h>
-#include <asm/system.h>
 #include <asm/traps.h>
 
 #include "setup.h"
index 28f576d..de7dc5f 100644 (file)
@@ -24,6 +24,8 @@
 #include <asm/tlbflush.h>
 #include <asm/unaligned.h>
 
+#include "mm.h"
+
 #define CODING_BITS(i) (i & 0xe0000120)
 
 #define LDST_P_BIT(i)  (i & (1 << 28)) /* Preindex             */
index 283aa4b..2eeb9c0 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/sched.h>
 #include <linux/io.h>
 
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
 
index 93478cc..6d4c096 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/pagemap.h>
 
 #include <asm/cacheflush.h>
-#include <asm/system.h>
 #include <asm/tlbflush.h>
 
 void flush_cache_mm(struct mm_struct *mm)
index 3296bca..05c7f53 100644 (file)
@@ -9,6 +9,8 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <asm/hwdef-copro.h>
+
 /* the upper-most page table pointer */
 extern pmd_t *top_pmd;
 extern int sysctl_overcommit_memory;
@@ -34,6 +36,9 @@ struct mem_type {
 const struct mem_type *get_mem_type(unsigned int type);
 
 extern void __flush_dcache_page(struct address_space *, struct page *);
+extern void hook_fault_code(int nr, int (*fn)
+               (unsigned long, unsigned int, struct pt_regs *),
+               int sig, int code, const char *name);
 
 void __init bootmem_init(void);
 void uc32_mm_memblock_reserve(void);
index 9019523..3ad653d 100644 (file)
@@ -2125,6 +2125,13 @@ config NET5501
        ---help---
          This option enables system support for the Soekris Engineering net5501.
 
+config GEOS
+       bool "Traverse Technologies GEOS System Support (LEDS, GPIO, etc)"
+       select GPIOLIB
+       depends on DMI
+       ---help---
+         This option enables system support for the Traverse Technologies GEOS.
+
 endif # X86_32
 
 config AMD_NB
index 4c2e59a..d511d95 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/init.h>
 #include <linux/jiffies.h>
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
 #include <asm/cacheflush.h>
index a9371c9..4b2caee 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/atomic.h>
 #include <asm/fixmap.h>
 #include <asm/mpspec.h>
-#include <asm/system.h>
 #include <asm/msr.h>
 
 #define ARCH_APICTIMER_STOPS_ON_C3     1
index 1316b4c..77203ac 100644 (file)
@@ -9,4 +9,11 @@
 #endif
 #define AT_SYSINFO_EHDR                33
 
+/* entries in ARCH_DLINFO: */
+#if defined(CONFIG_IA32_EMULATION) || !defined(CONFIG_X86_64)
+# define AT_VECTOR_SIZE_ARCH 2
+#else /* else it's non-compat x86-64 */
+# define AT_VECTOR_SIZE_ARCH 1
+#endif
+
 #endif /* _ASM_X86_AUXVEC_H */
diff --git a/arch/x86/include/asm/barrier.h b/arch/x86/include/asm/barrier.h
new file mode 100644 (file)
index 0000000..c6cd358
--- /dev/null
@@ -0,0 +1,116 @@
+#ifndef _ASM_X86_BARRIER_H
+#define _ASM_X86_BARRIER_H
+
+#include <asm/alternative.h>
+#include <asm/nops.h>
+
+/*
+ * Force strict CPU ordering.
+ * And yes, this is required on UP too when we're talking
+ * to devices.
+ */
+
+#ifdef CONFIG_X86_32
+/*
+ * Some non-Intel clones support out of order store. wmb() ceases to be a
+ * nop for these.
+ */
+#define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2)
+#define rmb() alternative("lock; addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2)
+#define wmb() alternative("lock; addl $0,0(%%esp)", "sfence", X86_FEATURE_XMM)
+#else
+#define mb()   asm volatile("mfence":::"memory")
+#define rmb()  asm volatile("lfence":::"memory")
+#define wmb()  asm volatile("sfence" ::: "memory")
+#endif
+
+/**
+ * read_barrier_depends - Flush all pending reads that subsequents reads
+ * depend on.
+ *
+ * No data-dependent reads from memory-like regions are ever reordered
+ * over this barrier.  All reads preceding this primitive are guaranteed
+ * to access memory (but not necessarily other CPUs' caches) before any
+ * reads following this primitive that depend on the data return by
+ * any of the preceding reads.  This primitive is much lighter weight than
+ * rmb() on most CPUs, and is never heavier weight than is
+ * rmb().
+ *
+ * These ordering constraints are respected by both the local CPU
+ * and the compiler.
+ *
+ * Ordering is not guaranteed by anything other than these primitives,
+ * not even by data dependencies.  See the documentation for
+ * memory_barrier() for examples and URLs to more information.
+ *
+ * For example, the following code would force ordering (the initial
+ * value of "a" is zero, "b" is one, and "p" is "&a"):
+ *
+ * <programlisting>
+ *     CPU 0                           CPU 1
+ *
+ *     b = 2;
+ *     memory_barrier();
+ *     p = &b;                         q = p;
+ *                                     read_barrier_depends();
+ *                                     d = *q;
+ * </programlisting>
+ *
+ * because the read of "*q" depends on the read of "p" and these
+ * two reads are separated by a read_barrier_depends().  However,
+ * the following code, with the same initial values for "a" and "b":
+ *
+ * <programlisting>
+ *     CPU 0                           CPU 1
+ *
+ *     a = 2;
+ *     memory_barrier();
+ *     b = 3;                          y = b;
+ *                                     read_barrier_depends();
+ *                                     x = a;
+ * </programlisting>
+ *
+ * does not enforce ordering, since there is no data dependency between
+ * the read of "a" and the read of "b".  Therefore, on some CPUs, such
+ * as Alpha, "y" could be set to 3 and "x" to 0.  Use rmb()
+ * in cases like this where there are no data dependencies.
+ **/
+
+#define read_barrier_depends() do { } while (0)
+
+#ifdef CONFIG_SMP
+#define smp_mb()       mb()
+#ifdef CONFIG_X86_PPRO_FENCE
+# define smp_rmb()     rmb()
+#else
+# define smp_rmb()     barrier()
+#endif
+#ifdef CONFIG_X86_OOSTORE
+# define smp_wmb()     wmb()
+#else
+# define smp_wmb()     barrier()
+#endif
+#define smp_read_barrier_depends()     read_barrier_depends()
+#define set_mb(var, value) do { (void)xchg(&var, value); } while (0)
+#else
+#define smp_mb()       barrier()
+#define smp_rmb()      barrier()
+#define smp_wmb()      barrier()
+#define smp_read_barrier_depends()     do { } while (0)
+#define set_mb(var, value) do { var = value; barrier(); } while (0)
+#endif
+
+/*
+ * Stop RDTSC speculation. This is needed when you need to use RDTSC
+ * (or get_cycles or vread that possibly accesses the TSC) in a defined
+ * code region.
+ *
+ * (Could use an alternative three way for this if there was one.)
+ */
+static __always_inline void rdtsc_barrier(void)
+{
+       alternative(ASM_NOP3, "mfence", X86_FEATURE_MFENCE_RDTSC);
+       alternative(ASM_NOP3, "lfence", X86_FEATURE_LFENCE_RDTSC);
+}
+
+#endif /* _ASM_X86_BARRIER_H */
index f654d1b..11e1152 100644 (file)
@@ -36,4 +36,8 @@ do {                                                          \
 #endif /* !CONFIG_BUG */
 
 #include <asm-generic/bug.h>
+
+
+extern void show_regs_common(void);
+
 #endif /* _ASM_X86_BUG_H */
index 4e12668..9863ee3 100644 (file)
@@ -3,6 +3,7 @@
 
 /* Caches aren't brain-dead on the intel. */
 #include <asm-generic/cacheflush.h>
+#include <asm/special_insns.h>
 
 #ifdef CONFIG_X86_PAT
 /*
index 5f962df..f27f79a 100644 (file)
@@ -84,7 +84,6 @@ extern unsigned int vdso_enabled;
        (((x)->e_machine == EM_386) || ((x)->e_machine == EM_486))
 
 #include <asm/processor.h>
-#include <asm/system.h>
 
 #ifdef CONFIG_X86_32
 #include <asm/desc.h>
diff --git a/arch/x86/include/asm/exec.h b/arch/x86/include/asm/exec.h
new file mode 100644 (file)
index 0000000..54c2e1d
--- /dev/null
@@ -0,0 +1 @@
+/* define arch_align_stack() here */
index d09bb03..71ecbcb 100644 (file)
@@ -9,7 +9,6 @@
 #include <asm/asm.h>
 #include <asm/errno.h>
 #include <asm/processor.h>
-#include <asm/system.h>
 
 #define __futex_atomic_op1(insn, ret, oldval, uaddr, oparg)    \
        asm volatile("1:\t" insn "\n"                           \
index 7ce0798..257d9cc 100644 (file)
@@ -14,7 +14,6 @@
 
 #include <linux/sched.h>
 #include <linux/hardirq.h>
-#include <asm/system.h>
 
 struct pt_regs;
 struct user_i387_struct;
index 4d8dcbd..e7d1c19 100644 (file)
@@ -321,4 +321,8 @@ struct kvm_xcrs {
        __u64 padding[16];
 };
 
+/* definition of registers in kvm_run */
+struct kvm_sync_regs {
+};
+
 #endif /* _ASM_X86_KVM_H */
index 7b9cfc4..c222e1a 100644 (file)
@@ -176,6 +176,7 @@ struct x86_emulate_ops {
        void (*set_idt)(struct x86_emulate_ctxt *ctxt, struct desc_ptr *dt);
        ulong (*get_cr)(struct x86_emulate_ctxt *ctxt, int cr);
        int (*set_cr)(struct x86_emulate_ctxt *ctxt, int cr, ulong val);
+       void (*set_rflags)(struct x86_emulate_ctxt *ctxt, ulong val);
        int (*cpl)(struct x86_emulate_ctxt *ctxt);
        int (*get_dr)(struct x86_emulate_ctxt *ctxt, int dr, ulong *dest);
        int (*set_dr)(struct x86_emulate_ctxt *ctxt, int dr, ulong value);
@@ -388,7 +389,7 @@ bool x86_page_table_writing_insn(struct x86_emulate_ctxt *ctxt);
 #define EMULATION_INTERCEPTED 2
 int x86_emulate_insn(struct x86_emulate_ctxt *ctxt);
 int emulator_task_switch(struct x86_emulate_ctxt *ctxt,
-                        u16 tss_selector, int reason,
+                        u16 tss_selector, int idt_index, int reason,
                         bool has_error_code, u32 error_code);
 int emulate_int_real(struct x86_emulate_ctxt *ctxt, int irq);
 #endif /* _ASM_X86_KVM_X86_EMULATE_H */
index 52d6640..e216ba0 100644 (file)
@@ -29,7 +29,7 @@
 #include <asm/msr-index.h>
 
 #define KVM_MAX_VCPUS 254
-#define KVM_SOFT_MAX_VCPUS 64
+#define KVM_SOFT_MAX_VCPUS 160
 #define KVM_MEMORY_SLOTS 32
 /* memory slots that does not exposed to userspace */
 #define KVM_PRIVATE_MEM_SLOTS 4
@@ -181,13 +181,6 @@ struct kvm_mmu_memory_cache {
        void *objects[KVM_NR_MEM_OBJS];
 };
 
-#define NR_PTE_CHAIN_ENTRIES 5
-
-struct kvm_pte_chain {
-       u64 *parent_ptes[NR_PTE_CHAIN_ENTRIES];
-       struct hlist_node link;
-};
-
 /*
  * kvm_mmu_page_role, below, is defined as:
  *
@@ -427,12 +420,16 @@ struct kvm_vcpu_arch {
 
        u64 last_guest_tsc;
        u64 last_kernel_ns;
-       u64 last_tsc_nsec;
-       u64 last_tsc_write;
-       u32 virtual_tsc_khz;
+       u64 last_host_tsc;
+       u64 tsc_offset_adjustment;
+       u64 this_tsc_nsec;
+       u64 this_tsc_write;
+       u8  this_tsc_generation;
        bool tsc_catchup;
-       u32  tsc_catchup_mult;
-       s8   tsc_catchup_shift;
+       bool tsc_always_catchup;
+       s8 virtual_tsc_shift;
+       u32 virtual_tsc_mult;
+       u32 virtual_tsc_khz;
 
        atomic_t nmi_queued;  /* unprocessed asynchronous NMIs */
        unsigned nmi_pending; /* NMI queued after currently running handler */
@@ -478,6 +475,21 @@ struct kvm_vcpu_arch {
                u32 id;
                bool send_user_only;
        } apf;
+
+       /* OSVW MSRs (AMD only) */
+       struct {
+               u64 length;
+               u64 status;
+       } osvw;
+};
+
+struct kvm_lpage_info {
+       unsigned long rmap_pde;
+       int write_count;
+};
+
+struct kvm_arch_memory_slot {
+       struct kvm_lpage_info *lpage_info[KVM_NR_PAGE_SIZES - 1];
 };
 
 struct kvm_arch {
@@ -511,8 +523,12 @@ struct kvm_arch {
        s64 kvmclock_offset;
        raw_spinlock_t tsc_write_lock;
        u64 last_tsc_nsec;
-       u64 last_tsc_offset;
        u64 last_tsc_write;
+       u32 last_tsc_khz;
+       u64 cur_tsc_nsec;
+       u64 cur_tsc_write;
+       u64 cur_tsc_offset;
+       u8  cur_tsc_generation;
 
        struct kvm_xen_hvm_config xen_hvm_config;
 
@@ -644,7 +660,7 @@ struct kvm_x86_ops {
        u64 (*get_mt_mask)(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio);
        int (*get_lpage_level)(void);
        bool (*rdtscp_supported)(void);
-       void (*adjust_tsc_offset)(struct kvm_vcpu *vcpu, s64 adjustment);
+       void (*adjust_tsc_offset)(struct kvm_vcpu *vcpu, s64 adjustment, bool host);
 
        void (*set_tdp_cr3)(struct kvm_vcpu *vcpu, unsigned long cr3);
 
@@ -652,7 +668,7 @@ struct kvm_x86_ops {
 
        bool (*has_wbinvd_exit)(void);
 
-       void (*set_tsc_khz)(struct kvm_vcpu *vcpu, u32 user_tsc_khz);
+       void (*set_tsc_khz)(struct kvm_vcpu *vcpu, u32 user_tsc_khz, bool scale);
        void (*write_tsc_offset)(struct kvm_vcpu *vcpu, u64 offset);
 
        u64 (*compute_tsc_offset)(struct kvm_vcpu *vcpu, u64 target_tsc);
@@ -674,6 +690,17 @@ struct kvm_arch_async_pf {
 
 extern struct kvm_x86_ops *kvm_x86_ops;
 
+static inline void adjust_tsc_offset_guest(struct kvm_vcpu *vcpu,
+                                          s64 adjustment)
+{
+       kvm_x86_ops->adjust_tsc_offset(vcpu, adjustment, false);
+}
+
+static inline void adjust_tsc_offset_host(struct kvm_vcpu *vcpu, s64 adjustment)
+{
+       kvm_x86_ops->adjust_tsc_offset(vcpu, adjustment, true);
+}
+
 int kvm_mmu_module_init(void);
 void kvm_mmu_module_exit(void);
 
@@ -741,8 +768,8 @@ int kvm_emulate_wbinvd(struct kvm_vcpu *vcpu);
 void kvm_get_segment(struct kvm_vcpu *vcpu, struct kvm_segment *var, int seg);
 int kvm_load_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector, int seg);
 
-int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason,
-                   bool has_error_code, u32 error_code);
+int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int idt_index,
+                   int reason, bool has_error_code, u32 error_code);
 
 int kvm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0);
 int kvm_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3);
index 9cdae5d..c8bed0d 100644 (file)
@@ -3,7 +3,6 @@
 
 #include <linux/percpu.h>
 
-#include <asm/system.h>
 #include <linux/atomic.h>
 #include <asm/asm.h>
 
index 0e8e85b..d354fb7 100644 (file)
@@ -5,7 +5,6 @@
 #define _ASM_X86_MC146818RTC_H
 
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/processor.h>
 #include <linux/mc146818rtc.h>
 
index bce688d..e21fdd1 100644 (file)
@@ -55,7 +55,6 @@ extern unsigned long init_memory_mapping(unsigned long start,
                                         unsigned long end);
 
 extern void initmem_init(void);
-extern void free_initmem(void);
 
 #endif /* !__ASSEMBLY__ */
 
index e8fb2c7..2291895 100644 (file)
@@ -23,6 +23,7 @@
 #define ARCH_PERFMON_EVENTSEL_USR                      (1ULL << 16)
 #define ARCH_PERFMON_EVENTSEL_OS                       (1ULL << 17)
 #define ARCH_PERFMON_EVENTSEL_EDGE                     (1ULL << 18)
+#define ARCH_PERFMON_EVENTSEL_PIN_CONTROL              (1ULL << 19)
 #define ARCH_PERFMON_EVENTSEL_INT                      (1ULL << 20)
 #define ARCH_PERFMON_EVENTSEL_ANY                      (1ULL << 21)
 #define ARCH_PERFMON_EVENTSEL_ENABLE                   (1ULL << 22)
index 5533b30..a19542c 100644 (file)
@@ -14,13 +14,13 @@ struct mm_struct;
 #include <asm/sigcontext.h>
 #include <asm/current.h>
 #include <asm/cpufeature.h>
-#include <asm/system.h>
 #include <asm/page.h>
 #include <asm/pgtable_types.h>
 #include <asm/percpu.h>
 #include <asm/msr.h>
 #include <asm/desc_defs.h>
 #include <asm/nops.h>
+#include <asm/special_insns.h>
 
 #include <linux/personality.h>
 #include <linux/cpumask.h>
@@ -29,6 +29,15 @@ struct mm_struct;
 #include <linux/math64.h>
 #include <linux/init.h>
 #include <linux/err.h>
+#include <linux/irqflags.h>
+
+/*
+ * We handle most unaligned accesses in hardware.  On the other hand
+ * unaligned DMA can be quite expensive on some Nehalem processors.
+ *
+ * Based on this we disable the IP header alignment in network drivers.
+ */
+#define NET_IP_ALIGN   0
 
 #define HBP_NUM 4
 /*
@@ -959,4 +968,24 @@ extern bool cpu_has_amd_erratum(const int *);
 #define cpu_has_amd_erratum(x) (false)
 #endif /* CONFIG_CPU_SUP_AMD */
 
+#ifdef CONFIG_X86_32
+/*
+ * disable hlt during certain critical i/o operations
+ */
+#define HAVE_DISABLE_HLT
+#endif
+
+void disable_hlt(void);
+void enable_hlt(void);
+
+void cpu_idle_wait(void);
+
+extern unsigned long arch_align_stack(unsigned long sp);
+extern void free_init_pages(char *what, unsigned long begin, unsigned long end);
+
+void default_idle(void);
+bool set_pm_idle_to_default(void);
+
+void stop_this_cpu(void *dummy);
+
 #endif /* _ASM_X86_PROCESSOR_H */
index 5e64171..1654662 100644 (file)
 #ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 extern const char early_idt_handlers[NUM_EXCEPTION_VECTORS][10];
-#endif
-#endif
+
+/*
+ * Load a segment. Fall back on loading the zero
+ * segment if something goes wrong..
+ */
+#define loadsegment(seg, value)                                                \
+do {                                                                   \
+       unsigned short __val = (value);                                 \
+                                                                       \
+       asm volatile("                                          \n"     \
+                    "1:        movl %k0,%%" #seg "             \n"     \
+                                                                       \
+                    ".section .fixup,\"ax\"                    \n"     \
+                    "2:        xorl %k0,%k0                    \n"     \
+                    "          jmp 1b                          \n"     \
+                    ".previous                                 \n"     \
+                                                                       \
+                    _ASM_EXTABLE(1b, 2b)                               \
+                                                                       \
+                    : "+r" (__val) : : "memory");                      \
+} while (0)
+
+/*
+ * Save a segment register away
+ */
+#define savesegment(seg, value)                                \
+       asm("mov %%" #seg ",%0":"=r" (value) : : "memory")
+
+/*
+ * x86_32 user gs accessors.
+ */
+#ifdef CONFIG_X86_32
+#ifdef CONFIG_X86_32_LAZY_GS
+#define get_user_gs(regs)      (u16)({unsigned long v; savesegment(gs, v); v;})
+#define set_user_gs(regs, v)   loadsegment(gs, (unsigned long)(v))
+#define task_user_gs(tsk)      ((tsk)->thread.gs)
+#define lazy_save_gs(v)                savesegment(gs, (v))
+#define lazy_load_gs(v)                loadsegment(gs, (v))
+#else  /* X86_32_LAZY_GS */
+#define get_user_gs(regs)      (u16)((regs)->gs)
+#define set_user_gs(regs, v)   do { (regs)->gs = (v); } while (0)
+#define task_user_gs(tsk)      (task_pt_regs(tsk)->gs)
+#define lazy_save_gs(v)                do { } while (0)
+#define lazy_load_gs(v)                do { } while (0)
+#endif /* X86_32_LAZY_GS */
+#endif /* X86_32 */
+
+static inline unsigned long get_limit(unsigned long segment)
+{
+       unsigned long __limit;
+       asm("lsll %1,%0" : "=r" (__limit) : "r" (segment));
+       return __limit + 1;
+}
+
+#endif /* !__ASSEMBLY__ */
+#endif /* __KERNEL__ */
 
 #endif /* _ASM_X86_SEGMENT_H */
diff --git a/arch/x86/include/asm/special_insns.h b/arch/x86/include/asm/special_insns.h
new file mode 100644 (file)
index 0000000..41fc93a
--- /dev/null
@@ -0,0 +1,199 @@
+#ifndef _ASM_X86_SPECIAL_INSNS_H
+#define _ASM_X86_SPECIAL_INSNS_H
+
+
+#ifdef __KERNEL__
+
+static inline void native_clts(void)
+{
+       asm volatile("clts");
+}
+
+/*
+ * Volatile isn't enough to prevent the compiler from reordering the
+ * read/write functions for the control registers and messing everything up.
+ * A memory clobber would solve the problem, but would prevent reordering of
+ * all loads stores around it, which can hurt performance. Solution is to
+ * use a variable and mimic reads and writes to it to enforce serialization
+ */
+static unsigned long __force_order;
+
+static inline unsigned long native_read_cr0(void)
+{
+       unsigned long val;
+       asm volatile("mov %%cr0,%0\n\t" : "=r" (val), "=m" (__force_order));
+       return val;
+}
+
+static inline void native_write_cr0(unsigned long val)
+{
+       asm volatile("mov %0,%%cr0": : "r" (val), "m" (__force_order));
+}
+
+static inline unsigned long native_read_cr2(void)
+{
+       unsigned long val;
+       asm volatile("mov %%cr2,%0\n\t" : "=r" (val), "=m" (__force_order));
+       return val;
+}
+
+static inline void native_write_cr2(unsigned long val)
+{
+       asm volatile("mov %0,%%cr2": : "r" (val), "m" (__force_order));
+}
+
+static inline unsigned long native_read_cr3(void)
+{
+       unsigned long val;
+       asm volatile("mov %%cr3,%0\n\t" : "=r" (val), "=m" (__force_order));
+       return val;
+}
+
+static inline void native_write_cr3(unsigned long val)
+{
+       asm volatile("mov %0,%%cr3": : "r" (val), "m" (__force_order));
+}
+
+static inline unsigned long native_read_cr4(void)
+{
+       unsigned long val;
+       asm volatile("mov %%cr4,%0\n\t" : "=r" (val), "=m" (__force_order));
+       return val;
+}
+
+static inline unsigned long native_read_cr4_safe(void)
+{
+       unsigned long val;
+       /* This could fault if %cr4 does not exist. In x86_64, a cr4 always
+        * exists, so it will never fail. */
+#ifdef CONFIG_X86_32
+       asm volatile("1: mov %%cr4, %0\n"
+                    "2:\n"
+                    _ASM_EXTABLE(1b, 2b)
+                    : "=r" (val), "=m" (__force_order) : "0" (0));
+#else
+       val = native_read_cr4();
+#endif
+       return val;
+}
+
+static inline void native_write_cr4(unsigned long val)
+{
+       asm volatile("mov %0,%%cr4": : "r" (val), "m" (__force_order));
+}
+
+#ifdef CONFIG_X86_64
+static inline unsigned long native_read_cr8(void)
+{
+       unsigned long cr8;
+       asm volatile("movq %%cr8,%0" : "=r" (cr8));
+       return cr8;
+}
+
+static inline void native_write_cr8(unsigned long val)
+{
+       asm volatile("movq %0,%%cr8" :: "r" (val) : "memory");
+}
+#endif
+
+static inline void native_wbinvd(void)
+{
+       asm volatile("wbinvd": : :"memory");
+}
+
+extern void native_load_gs_index(unsigned);
+
+#ifdef CONFIG_PARAVIRT
+#include <asm/paravirt.h>
+#else
+
+static inline unsigned long read_cr0(void)
+{
+       return native_read_cr0();
+}
+
+static inline void write_cr0(unsigned long x)
+{
+       native_write_cr0(x);
+}
+
+static inline unsigned long read_cr2(void)
+{
+       return native_read_cr2();
+}
+
+static inline void write_cr2(unsigned long x)
+{
+       native_write_cr2(x);
+}
+
+static inline unsigned long read_cr3(void)
+{
+       return native_read_cr3();
+}
+
+static inline void write_cr3(unsigned long x)
+{
+       native_write_cr3(x);
+}
+
+static inline unsigned long read_cr4(void)
+{
+       return native_read_cr4();
+}
+
+static inline unsigned long read_cr4_safe(void)
+{
+       return native_read_cr4_safe();
+}
+
+static inline void write_cr4(unsigned long x)
+{
+       native_write_cr4(x);
+}
+
+static inline void wbinvd(void)
+{
+       native_wbinvd();
+}
+
+#ifdef CONFIG_X86_64
+
+static inline unsigned long read_cr8(void)
+{
+       return native_read_cr8();
+}
+
+static inline void write_cr8(unsigned long x)
+{
+       native_write_cr8(x);
+}
+
+static inline void load_gs_index(unsigned selector)
+{
+       native_load_gs_index(selector);
+}
+
+#endif
+
+/* Clear the 'TS' bit */
+static inline void clts(void)
+{
+       native_clts();
+}
+
+#endif/* CONFIG_PARAVIRT */
+
+#define stts() write_cr0(read_cr0() | X86_CR0_TS)
+
+static inline void clflush(volatile void *__p)
+{
+       asm volatile("clflush %0" : "+m" (*(volatile char __force *)__p));
+}
+
+#define nop() asm volatile ("nop")
+
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_X86_SPECIAL_INSNS_H */
index 1575177..b5d9533 100644 (file)
@@ -38,7 +38,6 @@
 #include <asm/tsc.h>
 #include <asm/processor.h>
 #include <asm/percpu.h>
-#include <asm/system.h>
 #include <asm/desc.h>
 #include <linux/random.h>
 
diff --git a/arch/x86/include/asm/switch_to.h b/arch/x86/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..4ec45b3
--- /dev/null
@@ -0,0 +1,129 @@
+#ifndef _ASM_X86_SWITCH_TO_H
+#define _ASM_X86_SWITCH_TO_H
+
+struct task_struct; /* one of the stranger aspects of C forward declarations */
+struct task_struct *__switch_to(struct task_struct *prev,
+                               struct task_struct *next);
+struct tss_struct;
+void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
+                     struct tss_struct *tss);
+
+#ifdef CONFIG_X86_32
+
+#ifdef CONFIG_CC_STACKPROTECTOR
+#define __switch_canary                                                        \
+       "movl %P[task_canary](%[next]), %%ebx\n\t"                      \
+       "movl %%ebx, "__percpu_arg([stack_canary])"\n\t"
+#define __switch_canary_oparam                                         \
+       , [stack_canary] "=m" (stack_canary.canary)
+#define __switch_canary_iparam                                         \
+       , [task_canary] "i" (offsetof(struct task_struct, stack_canary))
+#else  /* CC_STACKPROTECTOR */
+#define __switch_canary
+#define __switch_canary_oparam
+#define __switch_canary_iparam
+#endif /* CC_STACKPROTECTOR */
+
+/*
+ * Saving eflags is important. It switches not only IOPL between tasks,
+ * it also protects other tasks from NT leaking through sysenter etc.
+ */
+#define switch_to(prev, next, last)                                    \
+do {                                                                   \
+       /*                                                              \
+        * Context-switching clobbers all registers, so we clobber      \
+        * them explicitly, via unused output variables.                \
+        * (EAX and EBP is not listed because EBP is saved/restored     \
+        * explicitly for wchan access and EAX is the return value of   \
+        * __switch_to())                                               \
+        */                                                             \
+       unsigned long ebx, ecx, edx, esi, edi;                          \
+                                                                       \
+       asm volatile("pushfl\n\t"               /* save    flags */     \
+                    "pushl %%ebp\n\t"          /* save    EBP   */     \
+                    "movl %%esp,%[prev_sp]\n\t"        /* save    ESP   */ \
+                    "movl %[next_sp],%%esp\n\t"        /* restore ESP   */ \
+                    "movl $1f,%[prev_ip]\n\t"  /* save    EIP   */     \
+                    "pushl %[next_ip]\n\t"     /* restore EIP   */     \
+                    __switch_canary                                    \
+                    "jmp __switch_to\n"        /* regparm call  */     \
+                    "1:\t"                                             \
+                    "popl %%ebp\n\t"           /* restore EBP   */     \
+                    "popfl\n"                  /* restore flags */     \
+                                                                       \
+                    /* output parameters */                            \
+                    : [prev_sp] "=m" (prev->thread.sp),                \
+                      [prev_ip] "=m" (prev->thread.ip),                \
+                      "=a" (last),                                     \
+                                                                       \
+                      /* clobbered output registers: */                \
+                      "=b" (ebx), "=c" (ecx), "=d" (edx),              \
+                      "=S" (esi), "=D" (edi)                           \
+                                                                       \
+                      __switch_canary_oparam                           \
+                                                                       \
+                      /* input parameters: */                          \
+                    : [next_sp]  "m" (next->thread.sp),                \
+                      [next_ip]  "m" (next->thread.ip),                \
+                                                                       \
+                      /* regparm parameters for __switch_to(): */      \
+                      [prev]     "a" (prev),                           \
+                      [next]     "d" (next)                            \
+                                                                       \
+                      __switch_canary_iparam                           \
+                                                                       \
+                    : /* reloaded segment registers */                 \
+                       "memory");                                      \
+} while (0)
+
+#else /* CONFIG_X86_32 */
+
+/* frame pointer must be last for get_wchan */
+#define SAVE_CONTEXT    "pushf ; pushq %%rbp ; movq %%rsi,%%rbp\n\t"
+#define RESTORE_CONTEXT "movq %%rbp,%%rsi ; popq %%rbp ; popf\t"
+
+#define __EXTRA_CLOBBER  \
+       , "rcx", "rbx", "rdx", "r8", "r9", "r10", "r11", \
+         "r12", "r13", "r14", "r15"
+
+#ifdef CONFIG_CC_STACKPROTECTOR
+#define __switch_canary                                                          \
+       "movq %P[task_canary](%%rsi),%%r8\n\t"                            \
+       "movq %%r8,"__percpu_arg([gs_canary])"\n\t"
+#define __switch_canary_oparam                                           \
+       , [gs_canary] "=m" (irq_stack_union.stack_canary)
+#define __switch_canary_iparam                                           \
+       , [task_canary] "i" (offsetof(struct task_struct, stack_canary))
+#else  /* CC_STACKPROTECTOR */
+#define __switch_canary
+#define __switch_canary_oparam
+#define __switch_canary_iparam
+#endif /* CC_STACKPROTECTOR */
+
+/* Save restore flags to clear handle leaking NT */
+#define switch_to(prev, next, last) \
+       asm volatile(SAVE_CONTEXT                                         \
+            "movq %%rsp,%P[threadrsp](%[prev])\n\t" /* save RSP */       \
+            "movq %P[threadrsp](%[next]),%%rsp\n\t" /* restore RSP */    \
+            "call __switch_to\n\t"                                       \
+            "movq "__percpu_arg([current_task])",%%rsi\n\t"              \
+            __switch_canary                                              \
+            "movq %P[thread_info](%%rsi),%%r8\n\t"                       \
+            "movq %%rax,%%rdi\n\t"                                       \
+            "testl  %[_tif_fork],%P[ti_flags](%%r8)\n\t"                 \
+            "jnz   ret_from_fork\n\t"                                    \
+            RESTORE_CONTEXT                                              \
+            : "=a" (last)                                                \
+              __switch_canary_oparam                                     \
+            : [next] "S" (next), [prev] "D" (prev),                      \
+              [threadrsp] "i" (offsetof(struct task_struct, thread.sp)), \
+              [ti_flags] "i" (offsetof(struct thread_info, flags)),      \
+              [_tif_fork] "i" (_TIF_FORK),                               \
+              [thread_info] "i" (offsetof(struct task_struct, stack)),   \
+              [current_task] "m" (current_task)                          \
+              __switch_canary_iparam                                     \
+            : "memory", "cc" __EXTRA_CLOBBER)
+
+#endif /* CONFIG_X86_32 */
+
+#endif /* _ASM_X86_SWITCH_TO_H */
diff --git a/arch/x86/include/asm/system.h b/arch/x86/include/asm/system.h
deleted file mode 100644 (file)
index 2d2f01c..0000000
+++ /dev/null
@@ -1,523 +0,0 @@
-#ifndef _ASM_X86_SYSTEM_H
-#define _ASM_X86_SYSTEM_H
-
-#include <asm/asm.h>
-#include <asm/segment.h>
-#include <asm/cpufeature.h>
-#include <asm/cmpxchg.h>
-#include <asm/nops.h>
-
-#include <linux/kernel.h>
-#include <linux/irqflags.h>
-
-/* entries in ARCH_DLINFO: */
-#if defined(CONFIG_IA32_EMULATION) || !defined(CONFIG_X86_64)
-# define AT_VECTOR_SIZE_ARCH 2
-#else /* else it's non-compat x86-64 */
-# define AT_VECTOR_SIZE_ARCH 1
-#endif
-
-struct task_struct; /* one of the stranger aspects of C forward declarations */
-struct task_struct *__switch_to(struct task_struct *prev,
-                               struct task_struct *next);
-struct tss_struct;
-void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
-                     struct tss_struct *tss);
-extern void show_regs_common(void);
-
-#ifdef CONFIG_X86_32
-
-#ifdef CONFIG_CC_STACKPROTECTOR
-#define __switch_canary                                                        \
-       "movl %P[task_canary](%[next]), %%ebx\n\t"                      \
-       "movl %%ebx, "__percpu_arg([stack_canary])"\n\t"
-#define __switch_canary_oparam                                         \
-       , [stack_canary] "=m" (stack_canary.canary)
-#define __switch_canary_iparam                                         \
-       , [task_canary] "i" (offsetof(struct task_struct, stack_canary))
-#else  /* CC_STACKPROTECTOR */
-#define __switch_canary
-#define __switch_canary_oparam
-#define __switch_canary_iparam
-#endif /* CC_STACKPROTECTOR */
-
-/*
- * Saving eflags is important. It switches not only IOPL between tasks,
- * it also protects other tasks from NT leaking through sysenter etc.
- */
-#define switch_to(prev, next, last)                                    \
-do {                                                                   \
-       /*                                                              \
-        * Context-switching clobbers all registers, so we clobber      \
-        * them explicitly, via unused output variables.                \
-        * (EAX and EBP is not listed because EBP is saved/restored     \
-        * explicitly for wchan access and EAX is the return value of   \
-        * __switch_to())                                               \
-        */                                                             \
-       unsigned long ebx, ecx, edx, esi, edi;                          \
-                                                                       \
-       asm volatile("pushfl\n\t"               /* save    flags */     \
-                    "pushl %%ebp\n\t"          /* save    EBP   */     \
-                    "movl %%esp,%[prev_sp]\n\t"        /* save    ESP   */ \
-                    "movl %[next_sp],%%esp\n\t"        /* restore ESP   */ \
-                    "movl $1f,%[prev_ip]\n\t"  /* save    EIP   */     \
-                    "pushl %[next_ip]\n\t"     /* restore EIP   */     \
-                    __switch_canary                                    \
-                    "jmp __switch_to\n"        /* regparm call  */     \
-                    "1:\t"                                             \
-                    "popl %%ebp\n\t"           /* restore EBP   */     \
-                    "popfl\n"                  /* restore flags */     \
-                                                                       \
-                    /* output parameters */                            \
-                    : [prev_sp] "=m" (prev->thread.sp),                \
-                      [prev_ip] "=m" (prev->thread.ip),                \
-                      "=a" (last),                                     \
-                                                                       \
-                      /* clobbered output registers: */                \
-                      "=b" (ebx), "=c" (ecx), "=d" (edx),              \
-                      "=S" (esi), "=D" (edi)                           \
-                                                                       \
-                      __switch_canary_oparam                           \
-                                                                       \
-                      /* input parameters: */                          \
-                    : [next_sp]  "m" (next->thread.sp),                \
-                      [next_ip]  "m" (next->thread.ip),                \
-                                                                       \
-                      /* regparm parameters for __switch_to(): */      \
-                      [prev]     "a" (prev),                           \
-                      [next]     "d" (next)                            \
-                                                                       \
-                      __switch_canary_iparam                           \
-                                                                       \
-                    : /* reloaded segment registers */                 \
-                       "memory");                                      \
-} while (0)
-
-/*
- * disable hlt during certain critical i/o operations
- */
-#define HAVE_DISABLE_HLT
-#else
-
-/* frame pointer must be last for get_wchan */
-#define SAVE_CONTEXT    "pushf ; pushq %%rbp ; movq %%rsi,%%rbp\n\t"
-#define RESTORE_CONTEXT "movq %%rbp,%%rsi ; popq %%rbp ; popf\t"
-
-#define __EXTRA_CLOBBER  \
-       , "rcx", "rbx", "rdx", "r8", "r9", "r10", "r11", \
-         "r12", "r13", "r14", "r15"
-
-#ifdef CONFIG_CC_STACKPROTECTOR
-#define __switch_canary                                                          \
-       "movq %P[task_canary](%%rsi),%%r8\n\t"                            \
-       "movq %%r8,"__percpu_arg([gs_canary])"\n\t"
-#define __switch_canary_oparam                                           \
-       , [gs_canary] "=m" (irq_stack_union.stack_canary)
-#define __switch_canary_iparam                                           \
-       , [task_canary] "i" (offsetof(struct task_struct, stack_canary))
-#else  /* CC_STACKPROTECTOR */
-#define __switch_canary
-#define __switch_canary_oparam
-#define __switch_canary_iparam
-#endif /* CC_STACKPROTECTOR */
-
-/* Save restore flags to clear handle leaking NT */
-#define switch_to(prev, next, last) \
-       asm volatile(SAVE_CONTEXT                                         \
-            "movq %%rsp,%P[threadrsp](%[prev])\n\t" /* save RSP */       \
-            "movq %P[threadrsp](%[next]),%%rsp\n\t" /* restore RSP */    \
-            "call __switch_to\n\t"                                       \
-            "movq "__percpu_arg([current_task])",%%rsi\n\t"              \
-            __switch_canary                                              \
-            "movq %P[thread_info](%%rsi),%%r8\n\t"                       \
-            "movq %%rax,%%rdi\n\t"                                       \
-            "testl  %[_tif_fork],%P[ti_flags](%%r8)\n\t"                 \
-            "jnz   ret_from_fork\n\t"                                    \
-            RESTORE_CONTEXT                                              \
-            : "=a" (last)                                                \
-              __switch_canary_oparam                                     \
-            : [next] "S" (next), [prev] "D" (prev),                      \
-              [threadrsp] "i" (offsetof(struct task_struct, thread.sp)), \
-              [ti_flags] "i" (offsetof(struct thread_info, flags)),      \
-              [_tif_fork] "i" (_TIF_FORK),                               \
-              [thread_info] "i" (offsetof(struct task_struct, stack)),   \
-              [current_task] "m" (current_task)                          \
-              __switch_canary_iparam                                     \
-            : "memory", "cc" __EXTRA_CLOBBER)
-#endif
-
-#ifdef __KERNEL__
-
-extern void native_load_gs_index(unsigned);
-
-/*
- * Load a segment. Fall back on loading the zero
- * segment if something goes wrong..
- */
-#define loadsegment(seg, value)                                                \
-do {                                                                   \
-       unsigned short __val = (value);                                 \
-                                                                       \
-       asm volatile("                                          \n"     \
-                    "1:        movl %k0,%%" #seg "             \n"     \
-                                                                       \
-                    ".section .fixup,\"ax\"                    \n"     \
-                    "2:        xorl %k0,%k0                    \n"     \
-                    "          jmp 1b                          \n"     \
-                    ".previous                                 \n"     \
-                                                                       \
-                    _ASM_EXTABLE(1b, 2b)                               \
-                                                                       \
-                    : "+r" (__val) : : "memory");                      \
-} while (0)
-
-/*
- * Save a segment register away
- */
-#define savesegment(seg, value)                                \
-       asm("mov %%" #seg ",%0":"=r" (value) : : "memory")
-
-/*
- * x86_32 user gs accessors.
- */
-#ifdef CONFIG_X86_32
-#ifdef CONFIG_X86_32_LAZY_GS
-#define get_user_gs(regs)      (u16)({unsigned long v; savesegment(gs, v); v;})
-#define set_user_gs(regs, v)   loadsegment(gs, (unsigned long)(v))
-#define task_user_gs(tsk)      ((tsk)->thread.gs)
-#define lazy_save_gs(v)                savesegment(gs, (v))
-#define lazy_load_gs(v)                loadsegment(gs, (v))
-#else  /* X86_32_LAZY_GS */
-#define get_user_gs(regs)      (u16)((regs)->gs)
-#define set_user_gs(regs, v)   do { (regs)->gs = (v); } while (0)
-#define task_user_gs(tsk)      (task_pt_regs(tsk)->gs)
-#define lazy_save_gs(v)                do { } while (0)
-#define lazy_load_gs(v)                do { } while (0)
-#endif /* X86_32_LAZY_GS */
-#endif /* X86_32 */
-
-static inline unsigned long get_limit(unsigned long segment)
-{
-       unsigned long __limit;
-       asm("lsll %1,%0" : "=r" (__limit) : "r" (segment));
-       return __limit + 1;
-}
-
-static inline void native_clts(void)
-{
-       asm volatile("clts");
-}
-
-/*
- * Volatile isn't enough to prevent the compiler from reordering the
- * read/write functions for the control registers and messing everything up.
- * A memory clobber would solve the problem, but would prevent reordering of
- * all loads stores around it, which can hurt performance. Solution is to
- * use a variable and mimic reads and writes to it to enforce serialization
- */
-static unsigned long __force_order;
-
-static inline unsigned long native_read_cr0(void)
-{
-       unsigned long val;
-       asm volatile("mov %%cr0,%0\n\t" : "=r" (val), "=m" (__force_order));
-       return val;
-}
-
-static inline void native_write_cr0(unsigned long val)
-{
-       asm volatile("mov %0,%%cr0": : "r" (val), "m" (__force_order));
-}
-
-static inline unsigned long native_read_cr2(void)
-{
-       unsigned long val;
-       asm volatile("mov %%cr2,%0\n\t" : "=r" (val), "=m" (__force_order));
-       return val;
-}
-
-static inline void native_write_cr2(unsigned long val)
-{
-       asm volatile("mov %0,%%cr2": : "r" (val), "m" (__force_order));
-}
-
-static inline unsigned long native_read_cr3(void)
-{
-       unsigned long val;
-       asm volatile("mov %%cr3,%0\n\t" : "=r" (val), "=m" (__force_order));
-       return val;
-}
-
-static inline void native_write_cr3(unsigned long val)
-{
-       asm volatile("mov %0,%%cr3": : "r" (val), "m" (__force_order));
-}
-
-static inline unsigned long native_read_cr4(void)
-{
-       unsigned long val;
-       asm volatile("mov %%cr4,%0\n\t" : "=r" (val), "=m" (__force_order));
-       return val;
-}
-
-static inline unsigned long native_read_cr4_safe(void)
-{
-       unsigned long val;
-       /* This could fault if %cr4 does not exist. In x86_64, a cr4 always
-        * exists, so it will never fail. */
-#ifdef CONFIG_X86_32
-       asm volatile("1: mov %%cr4, %0\n"
-                    "2:\n"
-                    _ASM_EXTABLE(1b, 2b)
-                    : "=r" (val), "=m" (__force_order) : "0" (0));
-#else
-       val = native_read_cr4();
-#endif
-       return val;
-}
-
-static inline void native_write_cr4(unsigned long val)
-{
-       asm volatile("mov %0,%%cr4": : "r" (val), "m" (__force_order));
-}
-
-#ifdef CONFIG_X86_64
-static inline unsigned long native_read_cr8(void)
-{
-       unsigned long cr8;
-       asm volatile("movq %%cr8,%0" : "=r" (cr8));
-       return cr8;
-}
-
-static inline void native_write_cr8(unsigned long val)
-{
-       asm volatile("movq %0,%%cr8" :: "r" (val) : "memory");
-}
-#endif
-
-static inline void native_wbinvd(void)
-{
-       asm volatile("wbinvd": : :"memory");
-}
-
-#ifdef CONFIG_PARAVIRT
-#include <asm/paravirt.h>
-#else
-
-static inline unsigned long read_cr0(void)
-{
-       return native_read_cr0();
-}
-
-static inline void write_cr0(unsigned long x)
-{
-       native_write_cr0(x);
-}
-
-static inline unsigned long read_cr2(void)
-{
-       return native_read_cr2();
-}
-
-static inline void write_cr2(unsigned long x)
-{
-       native_write_cr2(x);
-}
-
-static inline unsigned long read_cr3(void)
-{
-       return native_read_cr3();
-}
-
-static inline void write_cr3(unsigned long x)
-{
-       native_write_cr3(x);
-}
-
-static inline unsigned long read_cr4(void)
-{
-       return native_read_cr4();
-}
-
-static inline unsigned long read_cr4_safe(void)
-{
-       return native_read_cr4_safe();
-}
-
-static inline void write_cr4(unsigned long x)
-{
-       native_write_cr4(x);
-}
-
-static inline void wbinvd(void)
-{
-       native_wbinvd();
-}
-
-#ifdef CONFIG_X86_64
-
-static inline unsigned long read_cr8(void)
-{
-       return native_read_cr8();
-}
-
-static inline void write_cr8(unsigned long x)
-{
-       native_write_cr8(x);
-}
-
-static inline void load_gs_index(unsigned selector)
-{
-       native_load_gs_index(selector);
-}
-
-#endif
-
-/* Clear the 'TS' bit */
-static inline void clts(void)
-{
-       native_clts();
-}
-
-#endif/* CONFIG_PARAVIRT */
-
-#define stts() write_cr0(read_cr0() | X86_CR0_TS)
-
-#endif /* __KERNEL__ */
-
-static inline void clflush(volatile void *__p)
-{
-       asm volatile("clflush %0" : "+m" (*(volatile char __force *)__p));
-}
-
-#define nop() asm volatile ("nop")
-
-void disable_hlt(void);
-void enable_hlt(void);
-
-void cpu_idle_wait(void);
-
-extern unsigned long arch_align_stack(unsigned long sp);
-extern void free_init_pages(char *what, unsigned long begin, unsigned long end);
-
-void default_idle(void);
-bool set_pm_idle_to_default(void);
-
-void stop_this_cpu(void *dummy);
-
-/*
- * Force strict CPU ordering.
- * And yes, this is required on UP too when we're talking
- * to devices.
- */
-#ifdef CONFIG_X86_32
-/*
- * Some non-Intel clones support out of order store. wmb() ceases to be a
- * nop for these.
- */
-#define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2)
-#define rmb() alternative("lock; addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2)
-#define wmb() alternative("lock; addl $0,0(%%esp)", "sfence", X86_FEATURE_XMM)
-#else
-#define mb()   asm volatile("mfence":::"memory")
-#define rmb()  asm volatile("lfence":::"memory")
-#define wmb()  asm volatile("sfence" ::: "memory")
-#endif
-
-/**
- * read_barrier_depends - Flush all pending reads that subsequents reads
- * depend on.
- *
- * No data-dependent reads from memory-like regions are ever reordered
- * over this barrier.  All reads preceding this primitive are guaranteed
- * to access memory (but not necessarily other CPUs' caches) before any
- * reads following this primitive that depend on the data return by
- * any of the preceding reads.  This primitive is much lighter weight than
- * rmb() on most CPUs, and is never heavier weight than is
- * rmb().
- *
- * These ordering constraints are respected by both the local CPU
- * and the compiler.
- *
- * Ordering is not guaranteed by anything other than these primitives,
- * not even by data dependencies.  See the documentation for
- * memory_barrier() for examples and URLs to more information.
- *
- * For example, the following code would force ordering (the initial
- * value of "a" is zero, "b" is one, and "p" is "&a"):
- *
- * <programlisting>
- *     CPU 0                           CPU 1
- *
- *     b = 2;
- *     memory_barrier();
- *     p = &b;                         q = p;
- *                                     read_barrier_depends();
- *                                     d = *q;
- * </programlisting>
- *
- * because the read of "*q" depends on the read of "p" and these
- * two reads are separated by a read_barrier_depends().  However,
- * the following code, with the same initial values for "a" and "b":
- *
- * <programlisting>
- *     CPU 0                           CPU 1
- *
- *     a = 2;
- *     memory_barrier();
- *     b = 3;                          y = b;
- *                                     read_barrier_depends();
- *                                     x = a;
- * </programlisting>
- *
- * does not enforce ordering, since there is no data dependency between
- * the read of "a" and the read of "b".  Therefore, on some CPUs, such
- * as Alpha, "y" could be set to 3 and "x" to 0.  Use rmb()
- * in cases like this where there are no data dependencies.
- **/
-
-#define read_barrier_depends() do { } while (0)
-
-#ifdef CONFIG_SMP
-#define smp_mb()       mb()
-#ifdef CONFIG_X86_PPRO_FENCE
-# define smp_rmb()     rmb()
-#else
-# define smp_rmb()     barrier()
-#endif
-#ifdef CONFIG_X86_OOSTORE
-# define smp_wmb()     wmb()
-#else
-# define smp_wmb()     barrier()
-#endif
-#define smp_read_barrier_depends()     read_barrier_depends()
-#define set_mb(var, value) do { (void)xchg(&var, value); } while (0)
-#else
-#define smp_mb()       barrier()
-#define smp_rmb()      barrier()
-#define smp_wmb()      barrier()
-#define smp_read_barrier_depends()     do { } while (0)
-#define set_mb(var, value) do { var = value; barrier(); } while (0)
-#endif
-
-/*
- * Stop RDTSC speculation. This is needed when you need to use RDTSC
- * (or get_cycles or vread that possibly accesses the TSC) in a defined
- * code region.
- *
- * (Could use an alternative three way for this if there was one.)
- */
-static __always_inline void rdtsc_barrier(void)
-{
-       alternative(ASM_NOP3, "mfence", X86_FEATURE_MFENCE_RDTSC);
-       alternative(ASM_NOP3, "lfence", X86_FEATURE_LFENCE_RDTSC);
-}
-
-/*
- * We handle most unaligned accesses in hardware.  On the other hand
- * unaligned DMA can be quite expensive on some Nehalem processors.
- *
- * Based on this we disable the IP header alignment in network drivers.
- */
-#define NET_IP_ALIGN   0
-#endif /* _ASM_X86_SYSTEM_H */
index 169be89..c0e108e 100644 (file)
@@ -5,7 +5,7 @@
 #include <linux/sched.h>
 
 #include <asm/processor.h>
-#include <asm/system.h>
+#include <asm/special_insns.h>
 
 #ifdef CONFIG_PARAVIRT
 #include <asm/paravirt.h>
index 15d9915..c91e8b9 100644 (file)
@@ -61,7 +61,7 @@ extern void check_tsc_sync_source(int cpu);
 extern void check_tsc_sync_target(void);
 
 extern int notsc_setup(char *);
-extern void save_sched_clock_state(void);
-extern void restore_sched_clock_state(void);
+extern void tsc_save_sched_clock_state(void);
+extern void tsc_restore_sched_clock_state(void);
 
 #endif /* _ASM_X86_TSC_H */
index e0f9aa1..5da71c2 100644 (file)
@@ -16,7 +16,6 @@
 #define _ASM_X86_VIRTEX_H
 
 #include <asm/processor.h>
-#include <asm/system.h>
 
 #include <asm/vmx.h>
 #include <asm/svm.h>
index 517d476..baaca8d 100644 (file)
@@ -145,9 +145,11 @@ struct x86_init_ops {
 /**
  * struct x86_cpuinit_ops - platform specific cpu hotplug setups
  * @setup_percpu_clockev:      set up the per cpu clock event device
+ * @early_percpu_clock_init:   early init of the per cpu clock event device
  */
 struct x86_cpuinit_ops {
        void (*setup_percpu_clockev)(void);
+       void (*early_percpu_clock_init)(void);
        void (*fixup_cpu_id)(struct cpuinfo_x86 *c, int node);
 };
 
@@ -160,6 +162,8 @@ struct x86_cpuinit_ops {
  * @is_untracked_pat_range     exclude from PAT logic
  * @nmi_init                   enable NMI on cpus
  * @i8042_detect               pre-detect if i8042 controller exists
+ * @save_sched_clock_state:    save state for sched_clock() on suspend
+ * @restore_sched_clock_state: restore state for sched_clock() on resume
  */
 struct x86_platform_ops {
        unsigned long (*calibrate_tsc)(void);
@@ -171,6 +175,8 @@ struct x86_platform_ops {
        void (*nmi_init)(void);
        unsigned char (*get_nmi_reason)(void);
        int (*i8042_detect)(void);
+       void (*save_sched_clock_state)(void);
+       void (*restore_sched_clock_state)(void);
 };
 
 struct pci_dev;
index f50e7fb..d2b7f27 100644 (file)
@@ -14,6 +14,7 @@
 #include <acpi/processor.h>
 #include <asm/acpi.h>
 #include <asm/mwait.h>
+#include <asm/special_insns.h>
 
 /*
  * Initialize bm_flags based on the CPU cache properties
index 5d56931..459e78c 100644 (file)
 #include <linux/syscore_ops.h>
 #include <linux/i8253.h>
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/desc.h>
 #include <asm/olpc.h>
index 5c0e653..2d5454c 100644 (file)
@@ -9,7 +9,6 @@
 #include <linux/smp.h>
 
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/mce.h>
 #include <asm/msr.h>
 
index 67bb17a..47a1870 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/cpu.h>
 
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/apic.h>
 #include <asm/idle.h>
 #include <asm/mce.h>
index 54060f5..2d7998f 100644 (file)
@@ -8,7 +8,6 @@
 #include <linux/init.h>
 
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/mce.h>
 #include <asm/msr.h>
 
index 97b2635..75772ae 100644 (file)
@@ -12,7 +12,6 @@
 #include <asm/processor-flags.h>
 #include <asm/cpufeature.h>
 #include <asm/tlbflush.h>
-#include <asm/system.h>
 #include <asm/mtrr.h>
 #include <asm/msr.h>
 #include <asm/pat.h>
index a524353..39472dd 100644 (file)
@@ -43,7 +43,6 @@
 
 #include <asm/processor.h>
 #include <asm/msr.h>
-#include <asm/system.h>
 
 static struct class *cpuid_class;
 
index 6104852..36d1853 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/delay.h>
 
 #include <linux/atomic.h>
-#include <asm/system.h>
 #include <asm/timer.h>
 #include <asm/hw_irq.h>
 #include <asm/pgtable.h>
index 43e2b1c..6d5fc8c 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/delay.h>
 
 #include <linux/atomic.h>
-#include <asm/system.h>
 #include <asm/timer.h>
 #include <asm/hw_irq.h>
 #include <asm/pgtable.h>
index fdc37b3..db6720e 100644 (file)
@@ -46,7 +46,6 @@
 
 #include <asm/debugreg.h>
 #include <asm/apicdef.h>
-#include <asm/system.h>
 #include <asm/apic.h>
 #include <asm/nmi.h>
 
index 44842d7..f8492da 100644 (file)
@@ -136,6 +136,15 @@ int kvm_register_clock(char *txt)
        return ret;
 }
 
+static void kvm_save_sched_clock_state(void)
+{
+}
+
+static void kvm_restore_sched_clock_state(void)
+{
+       kvm_register_clock("primary cpu clock, resume");
+}
+
 #ifdef CONFIG_X86_LOCAL_APIC
 static void __cpuinit kvm_setup_secondary_clock(void)
 {
@@ -144,8 +153,6 @@ static void __cpuinit kvm_setup_secondary_clock(void)
         * we shouldn't fail.
         */
        WARN_ON(kvm_register_clock("secondary cpu clock"));
-       /* ok, done with our trickery, call native */
-       setup_secondary_APIC_clock();
 }
 #endif
 
@@ -194,9 +201,11 @@ void __init kvmclock_init(void)
        x86_platform.get_wallclock = kvm_get_wallclock;
        x86_platform.set_wallclock = kvm_set_wallclock;
 #ifdef CONFIG_X86_LOCAL_APIC
-       x86_cpuinit.setup_percpu_clockev =
+       x86_cpuinit.early_percpu_clock_init =
                kvm_setup_secondary_clock;
 #endif
+       x86_platform.save_sched_clock_state = kvm_save_sched_clock_state;
+       x86_platform.restore_sched_clock_state = kvm_restore_sched_clock_state;
        machine_ops.shutdown  = kvm_shutdown;
 #ifdef CONFIG_KEXEC
        machine_ops.crash_shutdown  = kvm_crash_shutdown;
index ea69726..ebc9873 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/vmalloc.h>
 #include <linux/uaccess.h>
 
-#include <asm/system.h>
 #include <asm/ldt.h>
 #include <asm/desc.h>
 #include <asm/mmu_context.h>
index a3fa43b..5b19e4d 100644 (file)
@@ -23,7 +23,6 @@
 #include <asm/apic.h>
 #include <asm/cpufeature.h>
 #include <asm/desc.h>
-#include <asm/system.h>
 #include <asm/cacheflush.h>
 #include <asm/debugreg.h>
 
index 177183c..7eb1e2b 100644 (file)
@@ -43,7 +43,6 @@
 #include <linux/mca.h>
 #include <linux/kprobes.h>
 #include <linux/slab.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <linux/proc_fs.h>
 #include <linux/mman.h>
index 925179f..f21fd94 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/gfp.h>
 #include <linux/jump_label.h>
 
-#include <asm/system.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 
index 9635676..eb11369 100644 (file)
@@ -40,7 +40,6 @@
 
 #include <asm/processor.h>
 #include <asm/msr.h>
-#include <asm/system.h>
 
 static struct class *msr_class;
 
index 9c57c02..ab13760 100644 (file)
@@ -38,6 +38,7 @@
 #include <asm/apic.h>
 #include <asm/tlbflush.h>
 #include <asm/timer.h>
+#include <asm/special_insns.h>
 
 /* nop stub */
 void _paravirt_nop(void)
index 726494b..6ac5782 100644 (file)
@@ -42,7 +42,6 @@
 #include <asm/calgary.h>
 #include <asm/tce.h>
 #include <asm/pci-direct.h>
-#include <asm/system.h>
 #include <asm/dma.h>
 #include <asm/rio.h>
 #include <asm/bios_ebda.h>
index 14baf78..9b24f36 100644 (file)
@@ -15,7 +15,6 @@
 #include <trace/events/power.h>
 #include <linux/hw_breakpoint.h>
 #include <asm/cpu.h>
-#include <asm/system.h>
 #include <asm/apic.h>
 #include <asm/syscalls.h>
 #include <asm/idle.h>
index 9d7d484..aae4f4b 100644 (file)
@@ -41,7 +41,6 @@
 #include <linux/cpuidle.h>
 
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/ldt.h>
 #include <asm/processor.h>
 #include <asm/i387.h>
@@ -59,6 +58,7 @@
 #include <asm/syscalls.h>
 #include <asm/debugreg.h>
 #include <asm/nmi.h>
+#include <asm/switch_to.h>
 
 asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
 
index 292da13..61270e8 100644 (file)
@@ -40,7 +40,6 @@
 #include <linux/cpuidle.h>
 
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/processor.h>
 #include <asm/i387.h>
 #include <asm/fpu-internal.h>
@@ -53,6 +52,7 @@
 #include <asm/syscalls.h>
 #include <asm/debugreg.h>
 #include <asm/nmi.h>
+#include <asm/switch_to.h>
 
 asmlinkage extern void ret_from_fork(void);
 
index 78f05e4..8a634c8 100644 (file)
@@ -24,7 +24,6 @@
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/processor.h>
 #include <asm/i387.h>
 #include <asm/fpu-internal.h>
index ab77aae..1a29015 100644 (file)
@@ -90,7 +90,6 @@
 #include <asm/processor.h>
 #include <asm/bugs.h>
 
-#include <asm/system.h>
 #include <asm/vsyscall.h>
 #include <asm/cpu.h>
 #include <asm/desc.h>
index e578a79..5104a2b 100644 (file)
@@ -255,6 +255,7 @@ notrace static void __cpuinit start_secondary(void *unused)
         * most necessary things.
         */
        cpu_init();
+       x86_cpuinit.early_percpu_clock_init();
        preempt_disable();
        smp_callin();
 
index 9e540fe..ab40954 100644 (file)
@@ -34,6 +34,7 @@
 #include <asm/tce.h>
 #include <asm/calgary.h>
 #include <asm/proto.h>
+#include <asm/cacheflush.h>
 
 /* flush a tce at 'tceaddr' to main memory */
 static inline void flush_tce(void* tceaddr)
index 6bb7b85..73920e4 100644 (file)
@@ -6,7 +6,6 @@
 
 #include <asm/uaccess.h>
 #include <asm/desc.h>
-#include <asm/system.h>
 #include <asm/ldt.h>
 #include <asm/processor.h>
 #include <asm/proto.h>
index ec61d4c..860f126 100644 (file)
@@ -50,7 +50,6 @@
 #include <asm/processor.h>
 #include <asm/debugreg.h>
 #include <linux/atomic.h>
-#include <asm/system.h>
 #include <asm/traps.h>
 #include <asm/desc.h>
 #include <asm/i387.h>
index 183c592..899a03f 100644 (file)
@@ -630,7 +630,7 @@ static void set_cyc2ns_scale(unsigned long cpu_khz, int cpu)
 
 static unsigned long long cyc2ns_suspend;
 
-void save_sched_clock_state(void)
+void tsc_save_sched_clock_state(void)
 {
        if (!sched_clock_stable)
                return;
@@ -646,7 +646,7 @@ void save_sched_clock_state(void)
  * that sched_clock() continues from the point where it was left off during
  * suspend.
  */
-void restore_sched_clock_state(void)
+void tsc_restore_sched_clock_state(void)
 {
        unsigned long long offset;
        unsigned long flags;
index 947a06c..e9f265f 100644 (file)
@@ -91,6 +91,7 @@ struct x86_init_ops x86_init __initdata = {
 };
 
 struct x86_cpuinit_ops x86_cpuinit __cpuinitdata = {
+       .early_percpu_clock_init        = x86_init_noop,
        .setup_percpu_clockev           = setup_secondary_APIC_clock,
        .fixup_cpu_id                   = x86_default_fixup_cpu_id,
 };
@@ -107,7 +108,9 @@ struct x86_platform_ops x86_platform = {
        .is_untracked_pat_range         = is_ISA_range,
        .nmi_init                       = default_nmi_init,
        .get_nmi_reason                 = default_get_nmi_reason,
-       .i8042_detect                   = default_i8042_detect
+       .i8042_detect                   = default_i8042_detect,
+       .save_sched_clock_state         = tsc_save_sched_clock_state,
+       .restore_sched_clock_state      = tsc_restore_sched_clock_state,
 };
 
 EXPORT_SYMBOL_GPL(x86_platform);
index 89b02bf..9fed5be 100644 (file)
@@ -236,7 +236,7 @@ static int do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
        const u32 kvm_supported_word6_x86_features =
                F(LAHF_LM) | F(CMP_LEGACY) | 0 /*SVM*/ | 0 /* ExtApicSpace */ |
                F(CR8_LEGACY) | F(ABM) | F(SSE4A) | F(MISALIGNSSE) |
-               F(3DNOWPREFETCH) | 0 /* OSVW */ | 0 /* IBS */ | F(XOP) |
+               F(3DNOWPREFETCH) | F(OSVW) | 0 /* IBS */ | F(XOP) |
                0 /* SKINIT, WDT, LWP */ | F(FMA4) | F(TBM);
 
        /* cpuid 0xC0000001.edx */
index 5b97e17..26d1fb4 100644 (file)
@@ -43,4 +43,12 @@ static inline bool guest_cpuid_has_fsgsbase(struct kvm_vcpu *vcpu)
        return best && (best->ebx & bit(X86_FEATURE_FSGSBASE));
 }
 
+static inline bool guest_cpuid_has_osvw(struct kvm_vcpu *vcpu)
+{
+       struct kvm_cpuid_entry2 *best;
+
+       best = kvm_find_cpuid_entry(vcpu, 0x80000001, 0);
+       return best && (best->ecx & bit(X86_FEATURE_OSVW));
+}
+
 #endif
index 0982507..8375622 100644 (file)
@@ -57,6 +57,7 @@
 #define OpDS              23ull  /* DS */
 #define OpFS              24ull  /* FS */
 #define OpGS              25ull  /* GS */
+#define OpMem8            26ull  /* 8-bit zero extended memory operand */
 
 #define OpBits             5  /* Width of operand field */
 #define OpMask             ((1ull << OpBits) - 1)
 #define SrcAcc      (OpAcc << SrcShift)
 #define SrcImmU16   (OpImmU16 << SrcShift)
 #define SrcDX       (OpDX << SrcShift)
+#define SrcMem8     (OpMem8 << SrcShift)
 #define SrcMask     (OpMask << SrcShift)
 #define BitOp       (1<<11)
 #define MemAbs      (1<<12)      /* Memory operand is absolute displacement */
@@ -858,8 +860,7 @@ static void write_sse_reg(struct x86_emulate_ctxt *ctxt, sse128_t *data,
 }
 
 static void decode_register_operand(struct x86_emulate_ctxt *ctxt,
-                                   struct operand *op,
-                                   int inhibit_bytereg)
+                                   struct operand *op)
 {
        unsigned reg = ctxt->modrm_reg;
        int highbyte_regs = ctxt->rex_prefix == 0;
@@ -876,7 +877,7 @@ static void decode_register_operand(struct x86_emulate_ctxt *ctxt,
        }
 
        op->type = OP_REG;
-       if ((ctxt->d & ByteOp) && !inhibit_bytereg) {
+       if (ctxt->d & ByteOp) {
                op->addr.reg = decode_register(reg, ctxt->regs, highbyte_regs);
                op->bytes = 1;
        } else {
@@ -1151,6 +1152,22 @@ static int pio_in_emulated(struct x86_emulate_ctxt *ctxt,
        return 1;
 }
 
+static int read_interrupt_descriptor(struct x86_emulate_ctxt *ctxt,
+                                    u16 index, struct desc_struct *desc)
+{
+       struct desc_ptr dt;
+       ulong addr;
+
+       ctxt->ops->get_idt(ctxt, &dt);
+
+       if (dt.size < index * 8 + 7)
+               return emulate_gp(ctxt, index << 3 | 0x2);
+
+       addr = dt.address + index * 8;
+       return ctxt->ops->read_std(ctxt, addr, desc, sizeof *desc,
+                                  &ctxt->exception);
+}
+
 static void get_descriptor_table_ptr(struct x86_emulate_ctxt *ctxt,
                                     u16 selector, struct desc_ptr *dt)
 {
@@ -1227,6 +1244,8 @@ static int load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
                seg_desc.type = 3;
                seg_desc.p = 1;
                seg_desc.s = 1;
+               if (ctxt->mode == X86EMUL_MODE_VM86)
+                       seg_desc.dpl = 3;
                goto load;
        }
 
@@ -1891,6 +1910,17 @@ setup_syscalls_segments(struct x86_emulate_ctxt *ctxt,
        ss->p = 1;
 }
 
+static bool vendor_intel(struct x86_emulate_ctxt *ctxt)
+{
+       u32 eax, ebx, ecx, edx;
+
+       eax = ecx = 0;
+       return ctxt->ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx)
+               && ebx == X86EMUL_CPUID_VENDOR_GenuineIntel_ebx
+               && ecx == X86EMUL_CPUID_VENDOR_GenuineIntel_ecx
+               && edx == X86EMUL_CPUID_VENDOR_GenuineIntel_edx;
+}
+
 static bool em_syscall_is_enabled(struct x86_emulate_ctxt *ctxt)
 {
        struct x86_emulate_ops *ops = ctxt->ops;
@@ -2007,6 +2037,14 @@ static int em_sysenter(struct x86_emulate_ctxt *ctxt)
        if (ctxt->mode == X86EMUL_MODE_REAL)
                return emulate_gp(ctxt, 0);
 
+       /*
+        * Not recognized on AMD in compat mode (but is recognized in legacy
+        * mode).
+        */
+       if ((ctxt->mode == X86EMUL_MODE_PROT32) && (efer & EFER_LMA)
+           && !vendor_intel(ctxt))
+               return emulate_ud(ctxt);
+
        /* XXX sysenter/sysexit have not been tested in 64bit mode.
        * Therefore, we inject an #UD.
        */
@@ -2306,6 +2344,8 @@ static int load_state_from_tss32(struct x86_emulate_ctxt *ctxt,
                return emulate_gp(ctxt, 0);
        ctxt->_eip = tss->eip;
        ctxt->eflags = tss->eflags | 2;
+
+       /* General purpose registers */
        ctxt->regs[VCPU_REGS_RAX] = tss->eax;
        ctxt->regs[VCPU_REGS_RCX] = tss->ecx;
        ctxt->regs[VCPU_REGS_RDX] = tss->edx;
@@ -2328,6 +2368,24 @@ static int load_state_from_tss32(struct x86_emulate_ctxt *ctxt,
        set_segment_selector(ctxt, tss->gs, VCPU_SREG_GS);
 
        /*
+        * If we're switching between Protected Mode and VM86, we need to make
+        * sure to update the mode before loading the segment descriptors so
+        * that the selectors are interpreted correctly.
+        *
+        * Need to get rflags to the vcpu struct immediately because it
+        * influences the CPL which is checked at least when loading the segment
+        * descriptors and when pushing an error code to the new kernel stack.
+        *
+        * TODO Introduce a separate ctxt->ops->set_cpl callback
+        */
+       if (ctxt->eflags & X86_EFLAGS_VM)
+               ctxt->mode = X86EMUL_MODE_VM86;
+       else
+               ctxt->mode = X86EMUL_MODE_PROT32;
+
+       ctxt->ops->set_rflags(ctxt, ctxt->eflags);
+
+       /*
         * Now load segment descriptors. If fault happenes at this stage
         * it is handled in a context of new task
         */
@@ -2401,7 +2459,7 @@ static int task_switch_32(struct x86_emulate_ctxt *ctxt,
 }
 
 static int emulator_do_task_switch(struct x86_emulate_ctxt *ctxt,
-                                  u16 tss_selector, int reason,
+                                  u16 tss_selector, int idt_index, int reason,
                                   bool has_error_code, u32 error_code)
 {
        struct x86_emulate_ops *ops = ctxt->ops;
@@ -2423,12 +2481,35 @@ static int emulator_do_task_switch(struct x86_emulate_ctxt *ctxt,
 
        /* FIXME: check that next_tss_desc is tss */
 
-       if (reason != TASK_SWITCH_IRET) {
-               if ((tss_selector & 3) > next_tss_desc.dpl ||
-                   ops->cpl(ctxt) > next_tss_desc.dpl)
-                       return emulate_gp(ctxt, 0);
+       /*
+        * Check privileges. The three cases are task switch caused by...
+        *
+        * 1. jmp/call/int to task gate: Check against DPL of the task gate
+        * 2. Exception/IRQ/iret: No check is performed
+        * 3. jmp/call to TSS: Check agains DPL of the TSS
+        */
+       if (reason == TASK_SWITCH_GATE) {
+               if (idt_index != -1) {
+                       /* Software interrupts */
+                       struct desc_struct task_gate_desc;
+                       int dpl;
+
+                       ret = read_interrupt_descriptor(ctxt, idt_index,
+                                                       &task_gate_desc);
+                       if (ret != X86EMUL_CONTINUE)
+                               return ret;
+
+                       dpl = task_gate_desc.dpl;
+                       if ((tss_selector & 3) > dpl || ops->cpl(ctxt) > dpl)
+                               return emulate_gp(ctxt, (idt_index << 3) | 0x2);
+               }
+       } else if (reason != TASK_SWITCH_IRET) {
+               int dpl = next_tss_desc.dpl;
+               if ((tss_selector & 3) > dpl || ops->cpl(ctxt) > dpl)
+                       return emulate_gp(ctxt, tss_selector);
        }
 
+
        desc_limit = desc_limit_scaled(&next_tss_desc);
        if (!next_tss_desc.p ||
            ((desc_limit < 0x67 && (next_tss_desc.type & 8)) ||
@@ -2481,7 +2562,7 @@ static int emulator_do_task_switch(struct x86_emulate_ctxt *ctxt,
 }
 
 int emulator_task_switch(struct x86_emulate_ctxt *ctxt,
-                        u16 tss_selector, int reason,
+                        u16 tss_selector, int idt_index, int reason,
                         bool has_error_code, u32 error_code)
 {
        int rc;
@@ -2489,7 +2570,7 @@ int emulator_task_switch(struct x86_emulate_ctxt *ctxt,
        ctxt->_eip = ctxt->eip;
        ctxt->dst.type = OP_NONE;
 
-       rc = emulator_do_task_switch(ctxt, tss_selector, reason,
+       rc = emulator_do_task_switch(ctxt, tss_selector, idt_index, reason,
                                     has_error_code, error_code);
 
        if (rc == X86EMUL_CONTINUE)
@@ -3514,13 +3595,13 @@ static struct opcode twobyte_table[256] = {
        I(DstMem | SrcReg | ModRM | BitOp | Lock, em_btr),
        I(DstReg | SrcMemFAddr | ModRM | Src2FS, em_lseg),
        I(DstReg | SrcMemFAddr | ModRM | Src2GS, em_lseg),
-       D(ByteOp | DstReg | SrcMem | ModRM | Mov), D(DstReg | SrcMem16 | ModRM | Mov),
+       D(DstReg | SrcMem8 | ModRM | Mov), D(DstReg | SrcMem16 | ModRM | Mov),
        /* 0xB8 - 0xBF */
        N, N,
        G(BitOp, group8),
        I(DstMem | SrcReg | ModRM | BitOp | Lock | PageTable, em_btc),
        I(DstReg | SrcMem | ModRM, em_bsf), I(DstReg | SrcMem | ModRM, em_bsr),
-       D(ByteOp | DstReg | SrcMem | ModRM | Mov), D(DstReg | SrcMem16 | ModRM | Mov),
+       D(DstReg | SrcMem8 | ModRM | Mov), D(DstReg | SrcMem16 | ModRM | Mov),
        /* 0xC0 - 0xCF */
        D2bv(DstMem | SrcReg | ModRM | Lock),
        N, D(DstMem | SrcReg | ModRM | Mov),
@@ -3602,9 +3683,7 @@ static int decode_operand(struct x86_emulate_ctxt *ctxt, struct operand *op,
 
        switch (d) {
        case OpReg:
-               decode_register_operand(ctxt, op,
-                        op == &ctxt->dst &&
-                        ctxt->twobyte && (ctxt->b == 0xb6 || ctxt->b == 0xb7));
+               decode_register_operand(ctxt, op);
                break;
        case OpImmUByte:
                rc = decode_imm(ctxt, op, 1, false);
@@ -3656,6 +3735,9 @@ static int decode_operand(struct x86_emulate_ctxt *ctxt, struct operand *op,
        case OpImm:
                rc = decode_imm(ctxt, op, imm_size(ctxt), true);
                break;
+       case OpMem8:
+               ctxt->memop.bytes = 1;
+               goto mem_common;
        case OpMem16:
                ctxt->memop.bytes = 2;
                goto mem_common;
index b6a7353..81cf4fa 100644 (file)
@@ -307,6 +307,7 @@ static void pic_ioport_write(void *opaque, u32 addr, u32 val)
                if (val & 0x10) {
                        s->init4 = val & 1;
                        s->last_irr = 0;
+                       s->irr &= s->elcr;
                        s->imr = 0;
                        s->priority_add = 0;
                        s->special_mask = 0;
index 31bfc69..8584322 100644 (file)
@@ -433,7 +433,7 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
                break;
 
        case APIC_DM_INIT:
-               if (level) {
+               if (!trig_mode || level) {
                        result = 1;
                        vcpu->arch.mp_state = KVM_MP_STATE_INIT_RECEIVED;
                        kvm_make_request(KVM_REQ_EVENT, vcpu);
@@ -731,7 +731,7 @@ static void start_apic_timer(struct kvm_lapic *apic)
                u64 guest_tsc, tscdeadline = apic->lapic_timer.tscdeadline;
                u64 ns = 0;
                struct kvm_vcpu *vcpu = apic->vcpu;
-               unsigned long this_tsc_khz = vcpu_tsc_khz(vcpu);
+               unsigned long this_tsc_khz = vcpu->arch.virtual_tsc_khz;
                unsigned long flags;
 
                if (unlikely(!tscdeadline || !this_tsc_khz))
index 224b02c..4cb1642 100644 (file)
@@ -688,9 +688,8 @@ static struct kvm_lpage_info *lpage_info_slot(gfn_t gfn,
 {
        unsigned long idx;
 
-       idx = (gfn >> KVM_HPAGE_GFN_SHIFT(level)) -
-             (slot->base_gfn >> KVM_HPAGE_GFN_SHIFT(level));
-       return &slot->lpage_info[level - 2][idx];
+       idx = gfn_to_index(gfn, slot->base_gfn, level);
+       return &slot->arch.lpage_info[level - 2][idx];
 }
 
 static void account_shadowed(struct kvm *kvm, gfn_t gfn)
@@ -946,7 +945,7 @@ static void pte_list_walk(unsigned long *pte_list, pte_list_walk_fn fn)
        }
 }
 
-static unsigned long *__gfn_to_rmap(struct kvm *kvm, gfn_t gfn, int level,
+static unsigned long *__gfn_to_rmap(gfn_t gfn, int level,
                                    struct kvm_memory_slot *slot)
 {
        struct kvm_lpage_info *linfo;
@@ -966,7 +965,7 @@ static unsigned long *gfn_to_rmap(struct kvm *kvm, gfn_t gfn, int level)
        struct kvm_memory_slot *slot;
 
        slot = gfn_to_memslot(kvm, gfn);
-       return __gfn_to_rmap(kvm, gfn, level, slot);
+       return __gfn_to_rmap(gfn, level, slot);
 }
 
 static bool rmap_can_add(struct kvm_vcpu *vcpu)
@@ -988,7 +987,7 @@ static int rmap_add(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn)
        return pte_list_add(vcpu, spte, rmapp);
 }
 
-static u64 *rmap_next(struct kvm *kvm, unsigned long *rmapp, u64 *spte)
+static u64 *rmap_next(unsigned long *rmapp, u64 *spte)
 {
        return pte_list_next(rmapp, spte);
 }
@@ -1018,8 +1017,8 @@ int kvm_mmu_rmap_write_protect(struct kvm *kvm, u64 gfn,
        u64 *spte;
        int i, write_protected = 0;
 
-       rmapp = __gfn_to_rmap(kvm, gfn, PT_PAGE_TABLE_LEVEL, slot);
-       spte = rmap_next(kvm, rmapp, NULL);
+       rmapp = __gfn_to_rmap(gfn, PT_PAGE_TABLE_LEVEL, slot);
+       spte = rmap_next(rmapp, NULL);
        while (spte) {
                BUG_ON(!(*spte & PT_PRESENT_MASK));
                rmap_printk("rmap_write_protect: spte %p %llx\n", spte, *spte);
@@ -1027,14 +1026,14 @@ int kvm_mmu_rmap_write_protect(struct kvm *kvm, u64 gfn,
                        mmu_spte_update(spte, *spte & ~PT_WRITABLE_MASK);
                        write_protected = 1;
                }
-               spte = rmap_next(kvm, rmapp, spte);
+               spte = rmap_next(rmapp, spte);
        }
 
        /* check for huge page mappings */
        for (i = PT_DIRECTORY_LEVEL;
             i < PT_PAGE_TABLE_LEVEL + KVM_NR_PAGE_SIZES; ++i) {
-               rmapp = __gfn_to_rmap(kvm, gfn, i, slot);
-               spte = rmap_next(kvm, rmapp, NULL);
+               rmapp = __gfn_to_rmap(gfn, i, slot);
+               spte = rmap_next(rmapp, NULL);
                while (spte) {
                        BUG_ON(!(*spte & PT_PRESENT_MASK));
                        BUG_ON(!is_large_pte(*spte));
@@ -1045,7 +1044,7 @@ int kvm_mmu_rmap_write_protect(struct kvm *kvm, u64 gfn,
                                spte = NULL;
                                write_protected = 1;
                        }
-                       spte = rmap_next(kvm, rmapp, spte);
+                       spte = rmap_next(rmapp, spte);
                }
        }
 
@@ -1066,7 +1065,7 @@ static int kvm_unmap_rmapp(struct kvm *kvm, unsigned long *rmapp,
        u64 *spte;
        int need_tlb_flush = 0;
 
-       while ((spte = rmap_next(kvm, rmapp, NULL))) {
+       while ((spte = rmap_next(rmapp, NULL))) {
                BUG_ON(!(*spte & PT_PRESENT_MASK));
                rmap_printk("kvm_rmap_unmap_hva: spte %p %llx\n", spte, *spte);
                drop_spte(kvm, spte);
@@ -1085,14 +1084,14 @@ static int kvm_set_pte_rmapp(struct kvm *kvm, unsigned long *rmapp,
 
        WARN_ON(pte_huge(*ptep));
        new_pfn = pte_pfn(*ptep);
-       spte = rmap_next(kvm, rmapp, NULL);
+       spte = rmap_next(rmapp, NULL);
        while (spte) {
                BUG_ON(!is_shadow_present_pte(*spte));
                rmap_printk("kvm_set_pte_rmapp: spte %p %llx\n", spte, *spte);
                need_flush = 1;
                if (pte_write(*ptep)) {
                        drop_spte(kvm, spte);
-                       spte = rmap_next(kvm, rmapp, NULL);
+                       spte = rmap_next(rmapp, NULL);
                } else {
                        new_spte = *spte &~ (PT64_BASE_ADDR_MASK);
                        new_spte |= (u64)new_pfn << PAGE_SHIFT;
@@ -1102,7 +1101,7 @@ static int kvm_set_pte_rmapp(struct kvm *kvm, unsigned long *rmapp,
                        new_spte &= ~shadow_accessed_mask;
                        mmu_spte_clear_track_bits(spte);
                        mmu_spte_set(spte, new_spte);
-                       spte = rmap_next(kvm, rmapp, spte);
+                       spte = rmap_next(rmapp, spte);
                }
        }
        if (need_flush)
@@ -1176,7 +1175,7 @@ static int kvm_age_rmapp(struct kvm *kvm, unsigned long *rmapp,
        if (!shadow_accessed_mask)
                return kvm_unmap_rmapp(kvm, rmapp, data);
 
-       spte = rmap_next(kvm, rmapp, NULL);
+       spte = rmap_next(rmapp, NULL);
        while (spte) {
                int _young;
                u64 _spte = *spte;
@@ -1186,7 +1185,7 @@ static int kvm_age_rmapp(struct kvm *kvm, unsigned long *rmapp,
                        young = 1;
                        clear_bit(PT_ACCESSED_SHIFT, (unsigned long *)spte);
                }
-               spte = rmap_next(kvm, rmapp, spte);
+               spte = rmap_next(rmapp, spte);
        }
        return young;
 }
@@ -1205,7 +1204,7 @@ static int kvm_test_age_rmapp(struct kvm *kvm, unsigned long *rmapp,
        if (!shadow_accessed_mask)
                goto out;
 
-       spte = rmap_next(kvm, rmapp, NULL);
+       spte = rmap_next(rmapp, NULL);
        while (spte) {
                u64 _spte = *spte;
                BUG_ON(!(_spte & PT_PRESENT_MASK));
@@ -1214,7 +1213,7 @@ static int kvm_test_age_rmapp(struct kvm *kvm, unsigned long *rmapp,
                        young = 1;
                        break;
                }
-               spte = rmap_next(kvm, rmapp, spte);
+               spte = rmap_next(rmapp, spte);
        }
 out:
        return young;
@@ -1391,11 +1390,6 @@ struct kvm_mmu_pages {
        unsigned int nr;
 };
 
-#define for_each_unsync_children(bitmap, idx)          \
-       for (idx = find_first_bit(bitmap, 512);         \
-            idx < 512;                                 \
-            idx = find_next_bit(bitmap, 512, idx+1))
-
 static int mmu_pages_add(struct kvm_mmu_pages *pvec, struct kvm_mmu_page *sp,
                         int idx)
 {
@@ -1417,7 +1411,7 @@ static int __mmu_unsync_walk(struct kvm_mmu_page *sp,
 {
        int i, ret, nr_unsync_leaf = 0;
 
-       for_each_unsync_children(sp->unsync_child_bitmap, i) {
+       for_each_set_bit(i, sp->unsync_child_bitmap, 512) {
                struct kvm_mmu_page *child;
                u64 ent = sp->spt[i];
 
@@ -1803,6 +1797,7 @@ static void drop_large_spte(struct kvm_vcpu *vcpu, u64 *sptep)
 {
        if (is_large_pte(*sptep)) {
                drop_spte(vcpu->kvm, sptep);
+               --vcpu->kvm->stat.lpages;
                kvm_flush_remote_tlbs(vcpu->kvm);
        }
 }
@@ -3190,15 +3185,14 @@ static bool sync_mmio_spte(u64 *sptep, gfn_t gfn, unsigned access,
 #undef PTTYPE
 
 static void reset_rsvds_bits_mask(struct kvm_vcpu *vcpu,
-                                 struct kvm_mmu *context,
-                                 int level)
+                                 struct kvm_mmu *context)
 {
        int maxphyaddr = cpuid_maxphyaddr(vcpu);
        u64 exb_bit_rsvd = 0;
 
        if (!context->nx)
                exb_bit_rsvd = rsvd_bits(63, 63);
-       switch (level) {
+       switch (context->root_level) {
        case PT32_ROOT_LEVEL:
                /* no rsvd bits for 2 level 4K page table entries */
                context->rsvd_bits_mask[0][1] = 0;
@@ -3256,8 +3250,9 @@ static int paging64_init_context_common(struct kvm_vcpu *vcpu,
                                        int level)
 {
        context->nx = is_nx(vcpu);
+       context->root_level = level;
 
-       reset_rsvds_bits_mask(vcpu, context, level);
+       reset_rsvds_bits_mask(vcpu, context);
 
        ASSERT(is_pae(vcpu));
        context->new_cr3 = paging_new_cr3;
@@ -3267,7 +3262,6 @@ static int paging64_init_context_common(struct kvm_vcpu *vcpu,
        context->invlpg = paging64_invlpg;
        context->update_pte = paging64_update_pte;
        context->free = paging_free;
-       context->root_level = level;
        context->shadow_root_level = level;
        context->root_hpa = INVALID_PAGE;
        context->direct_map = false;
@@ -3284,8 +3278,9 @@ static int paging32_init_context(struct kvm_vcpu *vcpu,
                                 struct kvm_mmu *context)
 {
        context->nx = false;
+       context->root_level = PT32_ROOT_LEVEL;
 
-       reset_rsvds_bits_mask(vcpu, context, PT32_ROOT_LEVEL);
+       reset_rsvds_bits_mask(vcpu, context);
 
        context->new_cr3 = paging_new_cr3;
        context->page_fault = paging32_page_fault;
@@ -3294,7 +3289,6 @@ static int paging32_init_context(struct kvm_vcpu *vcpu,
        context->sync_page = paging32_sync_page;
        context->invlpg = paging32_invlpg;
        context->update_pte = paging32_update_pte;
-       context->root_level = PT32_ROOT_LEVEL;
        context->shadow_root_level = PT32E_ROOT_LEVEL;
        context->root_hpa = INVALID_PAGE;
        context->direct_map = false;
@@ -3325,7 +3319,6 @@ static int init_kvm_tdp_mmu(struct kvm_vcpu *vcpu)
        context->get_cr3 = get_cr3;
        context->get_pdptr = kvm_pdptr_read;
        context->inject_page_fault = kvm_inject_page_fault;
-       context->nx = is_nx(vcpu);
 
        if (!is_paging(vcpu)) {
                context->nx = false;
@@ -3333,19 +3326,19 @@ static int init_kvm_tdp_mmu(struct kvm_vcpu *vcpu)
                context->root_level = 0;
        } else if (is_long_mode(vcpu)) {
                context->nx = is_nx(vcpu);
-               reset_rsvds_bits_mask(vcpu, context, PT64_ROOT_LEVEL);
-               context->gva_to_gpa = paging64_gva_to_gpa;
                context->root_level = PT64_ROOT_LEVEL;
+               reset_rsvds_bits_mask(vcpu, context);
+               context->gva_to_gpa = paging64_gva_to_gpa;
        } else if (is_pae(vcpu)) {
                context->nx = is_nx(vcpu);
-               reset_rsvds_bits_mask(vcpu, context, PT32E_ROOT_LEVEL);
-               context->gva_to_gpa = paging64_gva_to_gpa;
                context->root_level = PT32E_ROOT_LEVEL;
+               reset_rsvds_bits_mask(vcpu, context);
+               context->gva_to_gpa = paging64_gva_to_gpa;
        } else {
                context->nx = false;
-               reset_rsvds_bits_mask(vcpu, context, PT32_ROOT_LEVEL);
-               context->gva_to_gpa = paging32_gva_to_gpa;
                context->root_level = PT32_ROOT_LEVEL;
+               reset_rsvds_bits_mask(vcpu, context);
+               context->gva_to_gpa = paging32_gva_to_gpa;
        }
 
        return 0;
@@ -3408,18 +3401,18 @@ static int init_kvm_nested_mmu(struct kvm_vcpu *vcpu)
                g_context->gva_to_gpa = nonpaging_gva_to_gpa_nested;
        } else if (is_long_mode(vcpu)) {
                g_context->nx = is_nx(vcpu);
-               reset_rsvds_bits_mask(vcpu, g_context, PT64_ROOT_LEVEL);
                g_context->root_level = PT64_ROOT_LEVEL;
+               reset_rsvds_bits_mask(vcpu, g_context);
                g_context->gva_to_gpa = paging64_gva_to_gpa_nested;
        } else if (is_pae(vcpu)) {
                g_context->nx = is_nx(vcpu);
-               reset_rsvds_bits_mask(vcpu, g_context, PT32E_ROOT_LEVEL);
                g_context->root_level = PT32E_ROOT_LEVEL;
+               reset_rsvds_bits_mask(vcpu, g_context);
                g_context->gva_to_gpa = paging64_gva_to_gpa_nested;
        } else {
                g_context->nx = false;
-               reset_rsvds_bits_mask(vcpu, g_context, PT32_ROOT_LEVEL);
                g_context->root_level = PT32_ROOT_LEVEL;
+               reset_rsvds_bits_mask(vcpu, g_context);
                g_context->gva_to_gpa = paging32_gva_to_gpa_nested;
        }
 
@@ -3555,7 +3548,7 @@ static u64 mmu_pte_write_fetch_gpte(struct kvm_vcpu *vcpu, gpa_t *gpa,
  * If we're seeing too many writes to a page, it may no longer be a page table,
  * or we may be forking, in which case it is better to unmap the page.
  */
-static bool detect_write_flooding(struct kvm_mmu_page *sp, u64 *spte)
+static bool detect_write_flooding(struct kvm_mmu_page *sp)
 {
        /*
         * Skip write-flooding detected for the sp whose level is 1, because
@@ -3664,10 +3657,8 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
 
        mask.cr0_wp = mask.cr4_pae = mask.nxe = 1;
        for_each_gfn_indirect_valid_sp(vcpu->kvm, sp, gfn, node) {
-               spte = get_written_sptes(sp, gpa, &npte);
-
                if (detect_write_misaligned(sp, gpa, bytes) ||
-                     detect_write_flooding(sp, spte)) {
+                     detect_write_flooding(sp)) {
                        zap_page |= !!kvm_mmu_prepare_zap_page(vcpu->kvm, sp,
                                                     &invalid_list);
                        ++vcpu->kvm->stat.mmu_flooded;
index ea7b4fd..715da5a 100644 (file)
@@ -200,13 +200,13 @@ static void audit_write_protection(struct kvm *kvm, struct kvm_mmu_page *sp)
        slot = gfn_to_memslot(kvm, sp->gfn);
        rmapp = &slot->rmap[sp->gfn - slot->base_gfn];
 
-       spte = rmap_next(kvm, rmapp, NULL);
+       spte = rmap_next(rmapp, NULL);
        while (spte) {
                if (is_writable_pte(*spte))
                        audit_printk(kvm, "shadow page has writable "
                                     "mappings: gfn %llx role %x\n",
                                     sp->gfn, sp->role.word);
-               spte = rmap_next(kvm, rmapp, spte);
+               spte = rmap_next(rmapp, spte);
        }
 }
 
index 7aad544..a73f0c1 100644 (file)
@@ -33,10 +33,11 @@ static struct kvm_arch_event_perf_mapping {
        [4] = { 0x2e, 0x41, PERF_COUNT_HW_CACHE_MISSES },
        [5] = { 0xc4, 0x00, PERF_COUNT_HW_BRANCH_INSTRUCTIONS },
        [6] = { 0xc5, 0x00, PERF_COUNT_HW_BRANCH_MISSES },
+       [7] = { 0x00, 0x30, PERF_COUNT_HW_REF_CPU_CYCLES },
 };
 
 /* mapping between fixed pmc index and arch_events array */
-int fixed_pmc_events[] = {1, 0, 2};
+int fixed_pmc_events[] = {1, 0, 7};
 
 static bool pmc_is_gp(struct kvm_pmc *pmc)
 {
@@ -210,6 +211,9 @@ static void reprogram_gp_counter(struct kvm_pmc *pmc, u64 eventsel)
        unsigned config, type = PERF_TYPE_RAW;
        u8 event_select, unit_mask;
 
+       if (eventsel & ARCH_PERFMON_EVENTSEL_PIN_CONTROL)
+               printk_once("kvm pmu: pin control bit is ignored\n");
+
        pmc->eventsel = eventsel;
 
        stop_counter(pmc);
@@ -220,7 +224,7 @@ static void reprogram_gp_counter(struct kvm_pmc *pmc, u64 eventsel)
        event_select = eventsel & ARCH_PERFMON_EVENTSEL_EVENT;
        unit_mask = (eventsel & ARCH_PERFMON_EVENTSEL_UMASK) >> 8;
 
-       if (!(event_select & (ARCH_PERFMON_EVENTSEL_EDGE |
+       if (!(eventsel & (ARCH_PERFMON_EVENTSEL_EDGE |
                                ARCH_PERFMON_EVENTSEL_INV |
                                ARCH_PERFMON_EVENTSEL_CMASK))) {
                config = find_arch_event(&pmc->vcpu->arch.pmu, event_select,
@@ -413,7 +417,7 @@ int kvm_pmu_read_pmc(struct kvm_vcpu *vcpu, unsigned pmc, u64 *data)
        struct kvm_pmc *counters;
        u64 ctr;
 
-       pmc &= (3u << 30) - 1;
+       pmc &= ~(3u << 30);
        if (!fixed && pmc >= pmu->nr_arch_gp_counters)
                return 1;
        if (fixed && pmc >= pmu->nr_arch_fixed_counters)
index e385214..e334389 100644 (file)
@@ -111,6 +111,12 @@ struct nested_state {
 #define MSRPM_OFFSETS  16
 static u32 msrpm_offsets[MSRPM_OFFSETS] __read_mostly;
 
+/*
+ * Set osvw_len to higher value when updated Revision Guides
+ * are published and we know what the new status bits are
+ */
+static uint64_t osvw_len = 4, osvw_status;
+
 struct vcpu_svm {
        struct kvm_vcpu vcpu;
        struct vmcb *vmcb;
@@ -177,11 +183,13 @@ static bool npt_enabled = true;
 #else
 static bool npt_enabled;
 #endif
-static int npt = 1;
 
+/* allow nested paging (virtualized MMU) for all guests */
+static int npt = true;
 module_param(npt, int, S_IRUGO);
 
-static int nested = 1;
+/* allow nested virtualization in KVM/SVM */
+static int nested = true;
 module_param(nested, int, S_IRUGO);
 
 static void svm_flush_tlb(struct kvm_vcpu *vcpu);
@@ -557,6 +565,27 @@ static void svm_init_erratum_383(void)
        erratum_383_found = true;
 }
 
+static void svm_init_osvw(struct kvm_vcpu *vcpu)
+{
+       /*
+        * Guests should see errata 400 and 415 as fixed (assuming that
+        * HLT and IO instructions are intercepted).
+        */
+       vcpu->arch.osvw.length = (osvw_len >= 3) ? (osvw_len) : 3;
+       vcpu->arch.osvw.status = osvw_status & ~(6ULL);
+
+       /*
+        * By increasing VCPU's osvw.length to 3 we are telling the guest that
+        * all osvw.status bits inside that length, including bit 0 (which is
+        * reserved for erratum 298), are valid. However, if host processor's
+        * osvw_len is 0 then osvw_status[0] carries no information. We need to
+        * be conservative here and therefore we tell the guest that erratum 298
+        * is present (because we really don't know).
+        */
+       if (osvw_len == 0 && boot_cpu_data.x86 == 0x10)
+               vcpu->arch.osvw.status |= 1;
+}
+
 static int has_svm(void)
 {
        const char *msg;
@@ -623,6 +652,36 @@ static int svm_hardware_enable(void *garbage)
                __get_cpu_var(current_tsc_ratio) = TSC_RATIO_DEFAULT;
        }
 
+
+       /*
+        * Get OSVW bits.
+        *
+        * Note that it is possible to have a system with mixed processor
+        * revisions and therefore different OSVW bits. If bits are not the same
+        * on different processors then choose the worst case (i.e. if erratum
+        * is present on one processor and not on another then assume that the
+        * erratum is present everywhere).
+        */
+       if (cpu_has(&boot_cpu_data, X86_FEATURE_OSVW)) {
+               uint64_t len, status = 0;
+               int err;
+
+               len = native_read_msr_safe(MSR_AMD64_OSVW_ID_LENGTH, &err);
+               if (!err)
+                       status = native_read_msr_safe(MSR_AMD64_OSVW_STATUS,
+                                                     &err);
+
+               if (err)
+                       osvw_status = osvw_len = 0;
+               else {
+                       if (len < osvw_len)
+                               osvw_len = len;
+                       osvw_status |= status;
+                       osvw_status &= (1ULL << osvw_len) - 1;
+               }
+       } else
+               osvw_status = osvw_len = 0;
+
        svm_init_erratum_383();
 
        amd_pmu_enable_virt();
@@ -910,20 +969,25 @@ static u64 svm_scale_tsc(struct kvm_vcpu *vcpu, u64 tsc)
        return _tsc;
 }
 
-static void svm_set_tsc_khz(struct kvm_vcpu *vcpu, u32 user_tsc_khz)
+static void svm_set_tsc_khz(struct kvm_vcpu *vcpu, u32 user_tsc_khz, bool scale)
 {
        struct vcpu_svm *svm = to_svm(vcpu);
        u64 ratio;
        u64 khz;
 
-       /* TSC scaling supported? */
-       if (!boot_cpu_has(X86_FEATURE_TSCRATEMSR))
+       /* Guest TSC same frequency as host TSC? */
+       if (!scale) {
+               svm->tsc_ratio = TSC_RATIO_DEFAULT;
                return;
+       }
 
-       /* TSC-Scaling disabled or guest TSC same frequency as host TSC? */
-       if (user_tsc_khz == 0) {
-               vcpu->arch.virtual_tsc_khz = 0;
-               svm->tsc_ratio = TSC_RATIO_DEFAULT;
+       /* TSC scaling supported? */
+       if (!boot_cpu_has(X86_FEATURE_TSCRATEMSR)) {
+               if (user_tsc_khz > tsc_khz) {
+                       vcpu->arch.tsc_catchup = 1;
+                       vcpu->arch.tsc_always_catchup = 1;
+               } else
+                       WARN(1, "user requested TSC rate below hardware speed\n");
                return;
        }
 
@@ -938,7 +1002,6 @@ static void svm_set_tsc_khz(struct kvm_vcpu *vcpu, u32 user_tsc_khz)
                                user_tsc_khz);
                return;
        }
-       vcpu->arch.virtual_tsc_khz = user_tsc_khz;
        svm->tsc_ratio             = ratio;
 }
 
@@ -958,10 +1021,14 @@ static void svm_write_tsc_offset(struct kvm_vcpu *vcpu, u64 offset)
        mark_dirty(svm->vmcb, VMCB_INTERCEPTS);
 }
 
-static void svm_adjust_tsc_offset(struct kvm_vcpu *vcpu, s64 adjustment)
+static void svm_adjust_tsc_offset(struct kvm_vcpu *vcpu, s64 adjustment, bool host)
 {
        struct vcpu_svm *svm = to_svm(vcpu);
 
+       WARN_ON(adjustment < 0);
+       if (host)
+               adjustment = svm_scale_tsc(vcpu, adjustment);
+
        svm->vmcb->control.tsc_offset += adjustment;
        if (is_guest_mode(vcpu))
                svm->nested.hsave->control.tsc_offset += adjustment;
@@ -1191,6 +1258,8 @@ static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id)
        if (kvm_vcpu_is_bsp(&svm->vcpu))
                svm->vcpu.arch.apic_base |= MSR_IA32_APICBASE_BSP;
 
+       svm_init_osvw(&svm->vcpu);
+
        return &svm->vcpu;
 
 free_page4:
@@ -1268,6 +1337,21 @@ static void svm_vcpu_put(struct kvm_vcpu *vcpu)
                wrmsrl(host_save_user_msrs[i], svm->host_user_msrs[i]);
 }
 
+static void svm_update_cpl(struct kvm_vcpu *vcpu)
+{
+       struct vcpu_svm *svm = to_svm(vcpu);
+       int cpl;
+
+       if (!is_protmode(vcpu))
+               cpl = 0;
+       else if (svm->vmcb->save.rflags & X86_EFLAGS_VM)
+               cpl = 3;
+       else
+               cpl = svm->vmcb->save.cs.selector & 0x3;
+
+       svm->vmcb->save.cpl = cpl;
+}
+
 static unsigned long svm_get_rflags(struct kvm_vcpu *vcpu)
 {
        return to_svm(vcpu)->vmcb->save.rflags;
@@ -1275,7 +1359,11 @@ static unsigned long svm_get_rflags(struct kvm_vcpu *vcpu)
 
 static void svm_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags)
 {
+       unsigned long old_rflags = to_svm(vcpu)->vmcb->save.rflags;
+
        to_svm(vcpu)->vmcb->save.rflags = rflags;
+       if ((old_rflags ^ rflags) & X86_EFLAGS_VM)
+               svm_update_cpl(vcpu);
 }
 
 static void svm_cache_reg(struct kvm_vcpu *vcpu, enum kvm_reg reg)
@@ -1543,9 +1631,7 @@ static void svm_set_segment(struct kvm_vcpu *vcpu,
                s->attrib |= (var->g & 1) << SVM_SELECTOR_G_SHIFT;
        }
        if (seg == VCPU_SREG_CS)
-               svm->vmcb->save.cpl
-                       = (svm->vmcb->save.cs.attrib
-                          >> SVM_SELECTOR_DPL_SHIFT) & 3;
+               svm_update_cpl(vcpu);
 
        mark_dirty(svm->vmcb, VMCB_SEG);
 }
@@ -2735,7 +2821,10 @@ static int task_switch_interception(struct vcpu_svm *svm)
             (int_vec == OF_VECTOR || int_vec == BP_VECTOR)))
                skip_emulated_instruction(&svm->vcpu);
 
-       if (kvm_task_switch(&svm->vcpu, tss_selector, reason,
+       if (int_type != SVM_EXITINTINFO_TYPE_SOFT)
+               int_vec = -1;
+
+       if (kvm_task_switch(&svm->vcpu, tss_selector, int_vec, reason,
                                has_error_code, error_code) == EMULATE_FAIL) {
                svm->vcpu.run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
                svm->vcpu.run->internal.suberror = KVM_INTERNAL_ERROR_EMULATION;
index 246490f..280751c 100644 (file)
@@ -70,9 +70,6 @@ module_param(emulate_invalid_guest_state, bool, S_IRUGO);
 static bool __read_mostly vmm_exclusive = 1;
 module_param(vmm_exclusive, bool, S_IRUGO);
 
-static bool __read_mostly yield_on_hlt = 1;
-module_param(yield_on_hlt, bool, S_IRUGO);
-
 static bool __read_mostly fasteoi = 1;
 module_param(fasteoi, bool, S_IRUGO);
 
@@ -1655,17 +1652,6 @@ static void skip_emulated_instruction(struct kvm_vcpu *vcpu)
        vmx_set_interrupt_shadow(vcpu, 0);
 }
 
-static void vmx_clear_hlt(struct kvm_vcpu *vcpu)
-{
-       /* Ensure that we clear the HLT state in the VMCS.  We don't need to
-        * explicitly skip the instruction because if the HLT state is set, then
-        * the instruction is already executing and RIP has already been
-        * advanced. */
-       if (!yield_on_hlt &&
-           vmcs_read32(GUEST_ACTIVITY_STATE) == GUEST_ACTIVITY_HLT)
-               vmcs_write32(GUEST_ACTIVITY_STATE, GUEST_ACTIVITY_ACTIVE);
-}
-
 /*
  * KVM wants to inject page-faults which it got to the guest. This function
  * checks whether in a nested guest, we need to inject them to L1 or L2.
@@ -1678,7 +1664,7 @@ static int nested_pf_handled(struct kvm_vcpu *vcpu)
        struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
 
        /* TODO: also check PFEC_MATCH/MASK, not just EB.PF. */
-       if (!(vmcs12->exception_bitmap & PF_VECTOR))
+       if (!(vmcs12->exception_bitmap & (1u << PF_VECTOR)))
                return 0;
 
        nested_vmx_vmexit(vcpu);
@@ -1718,7 +1704,6 @@ static void vmx_queue_exception(struct kvm_vcpu *vcpu, unsigned nr,
                intr_info |= INTR_TYPE_HARD_EXCEPTION;
 
        vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, intr_info);
-       vmx_clear_hlt(vcpu);
 }
 
 static bool vmx_rdtscp_supported(void)
@@ -1817,13 +1802,19 @@ u64 vmx_read_l1_tsc(struct kvm_vcpu *vcpu)
 }
 
 /*
- * Empty call-back. Needs to be implemented when VMX enables the SET_TSC_KHZ
- * ioctl. In this case the call-back should update internal vmx state to make
- * the changes effective.
+ * Engage any workarounds for mis-matched TSC rates.  Currently limited to
+ * software catchup for faster rates on slower CPUs.
  */
-static void vmx_set_tsc_khz(struct kvm_vcpu *vcpu, u32 user_tsc_khz)
+static void vmx_set_tsc_khz(struct kvm_vcpu *vcpu, u32 user_tsc_khz, bool scale)
 {
-       /* Nothing to do here */
+       if (!scale)
+               return;
+
+       if (user_tsc_khz > tsc_khz) {
+               vcpu->arch.tsc_catchup = 1;
+               vcpu->arch.tsc_always_catchup = 1;
+       } else
+               WARN(1, "user requested TSC rate below hardware speed\n");
 }
 
 /*
@@ -1850,7 +1841,7 @@ static void vmx_write_tsc_offset(struct kvm_vcpu *vcpu, u64 offset)
        }
 }
 
-static void vmx_adjust_tsc_offset(struct kvm_vcpu *vcpu, s64 adjustment)
+static void vmx_adjust_tsc_offset(struct kvm_vcpu *vcpu, s64 adjustment, bool host)
 {
        u64 offset = vmcs_read64(TSC_OFFSET);
        vmcs_write64(TSC_OFFSET, offset + adjustment);
@@ -2219,6 +2210,9 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data)
                msr = find_msr_entry(vmx, msr_index);
                if (msr) {
                        msr->data = data;
+                       if (msr - vmx->guest_msrs < vmx->save_nmsrs)
+                               kvm_set_shared_msr(msr->index, msr->data,
+                                                  msr->mask);
                        break;
                }
                ret = kvm_set_msr_common(vcpu, msr_index, data);
@@ -2399,7 +2393,7 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf)
                                &_pin_based_exec_control) < 0)
                return -EIO;
 
-       min =
+       min = CPU_BASED_HLT_EXITING |
 #ifdef CONFIG_X86_64
              CPU_BASED_CR8_LOAD_EXITING |
              CPU_BASED_CR8_STORE_EXITING |
@@ -2414,9 +2408,6 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf)
              CPU_BASED_INVLPG_EXITING |
              CPU_BASED_RDPMC_EXITING;
 
-       if (yield_on_hlt)
-               min |= CPU_BASED_HLT_EXITING;
-
        opt = CPU_BASED_TPR_SHADOW |
              CPU_BASED_USE_MSR_BITMAPS |
              CPU_BASED_ACTIVATE_SECONDARY_CONTROLS;
@@ -4003,7 +3994,6 @@ static void vmx_inject_irq(struct kvm_vcpu *vcpu)
        } else
                intr |= INTR_TYPE_EXT_INTR;
        vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, intr);
-       vmx_clear_hlt(vcpu);
 }
 
 static void vmx_inject_nmi(struct kvm_vcpu *vcpu)
@@ -4035,7 +4025,6 @@ static void vmx_inject_nmi(struct kvm_vcpu *vcpu)
        }
        vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
                        INTR_TYPE_NMI_INTR | INTR_INFO_VALID_MASK | NMI_VECTOR);
-       vmx_clear_hlt(vcpu);
 }
 
 static int vmx_nmi_allowed(struct kvm_vcpu *vcpu)
@@ -4672,9 +4661,10 @@ static int handle_task_switch(struct kvm_vcpu *vcpu)
        bool has_error_code = false;
        u32 error_code = 0;
        u16 tss_selector;
-       int reason, type, idt_v;
+       int reason, type, idt_v, idt_index;
 
        idt_v = (vmx->idt_vectoring_info & VECTORING_INFO_VALID_MASK);
+       idt_index = (vmx->idt_vectoring_info & VECTORING_INFO_VECTOR_MASK);
        type = (vmx->idt_vectoring_info & VECTORING_INFO_TYPE_MASK);
 
        exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
@@ -4712,8 +4702,9 @@ static int handle_task_switch(struct kvm_vcpu *vcpu)
                       type != INTR_TYPE_NMI_INTR))
                skip_emulated_instruction(vcpu);
 
-       if (kvm_task_switch(vcpu, tss_selector, reason,
-                               has_error_code, error_code) == EMULATE_FAIL) {
+       if (kvm_task_switch(vcpu, tss_selector,
+                           type == INTR_TYPE_SOFT_INTR ? idt_index : -1, reason,
+                           has_error_code, error_code) == EMULATE_FAIL) {
                vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
                vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_EMULATION;
                vcpu->run->internal.ndata = 0;
index 54696b5..4044ce0 100644 (file)
@@ -97,6 +97,10 @@ EXPORT_SYMBOL_GPL(kvm_has_tsc_control);
 u32  kvm_max_guest_tsc_khz;
 EXPORT_SYMBOL_GPL(kvm_max_guest_tsc_khz);
 
+/* tsc tolerance in parts per million - default to 1/2 of the NTP threshold */
+static u32 tsc_tolerance_ppm = 250;
+module_param(tsc_tolerance_ppm, uint, S_IRUGO | S_IWUSR);
+
 #define KVM_NR_SHARED_MSRS 16
 
 struct kvm_shared_msrs_global {
@@ -969,50 +973,51 @@ static inline u64 get_kernel_ns(void)
 static DEFINE_PER_CPU(unsigned long, cpu_tsc_khz);
 unsigned long max_tsc_khz;
 
-static inline int kvm_tsc_changes_freq(void)
+static inline u64 nsec_to_cycles(struct kvm_vcpu *vcpu, u64 nsec)
 {
-       int cpu = get_cpu();
-       int ret = !boot_cpu_has(X86_FEATURE_CONSTANT_TSC) &&
-                 cpufreq_quick_get(cpu) != 0;
-       put_cpu();
-       return ret;
+       return pvclock_scale_delta(nsec, vcpu->arch.virtual_tsc_mult,
+                                  vcpu->arch.virtual_tsc_shift);
 }
 
-u64 vcpu_tsc_khz(struct kvm_vcpu *vcpu)
+static u32 adjust_tsc_khz(u32 khz, s32 ppm)
 {
-       if (vcpu->arch.virtual_tsc_khz)
-               return vcpu->arch.virtual_tsc_khz;
-       else
-               return __this_cpu_read(cpu_tsc_khz);
+       u64 v = (u64)khz * (1000000 + ppm);
+       do_div(v, 1000000);
+       return v;
 }
 
-static inline u64 nsec_to_cycles(struct kvm_vcpu *vcpu, u64 nsec)
+static void kvm_set_tsc_khz(struct kvm_vcpu *vcpu, u32 this_tsc_khz)
 {
-       u64 ret;
-
-       WARN_ON(preemptible());
-       if (kvm_tsc_changes_freq())
-               printk_once(KERN_WARNING
-                "kvm: unreliable cycle conversion on adjustable rate TSC\n");
-       ret = nsec * vcpu_tsc_khz(vcpu);
-       do_div(ret, USEC_PER_SEC);
-       return ret;
-}
+       u32 thresh_lo, thresh_hi;
+       int use_scaling = 0;
 
-static void kvm_init_tsc_catchup(struct kvm_vcpu *vcpu, u32 this_tsc_khz)
-{
        /* Compute a scale to convert nanoseconds in TSC cycles */
        kvm_get_time_scale(this_tsc_khz, NSEC_PER_SEC / 1000,
-                          &vcpu->arch.tsc_catchup_shift,
-                          &vcpu->arch.tsc_catchup_mult);
+                          &vcpu->arch.virtual_tsc_shift,
+                          &vcpu->arch.virtual_tsc_mult);
+       vcpu->arch.virtual_tsc_khz = this_tsc_khz;
+
+       /*
+        * Compute the variation in TSC rate which is acceptable
+        * within the range of tolerance and decide if the
+        * rate being applied is within that bounds of the hardware
+        * rate.  If so, no scaling or compensation need be done.
+        */
+       thresh_lo = adjust_tsc_khz(tsc_khz, -tsc_tolerance_ppm);
+       thresh_hi = adjust_tsc_khz(tsc_khz, tsc_tolerance_ppm);
+       if (this_tsc_khz < thresh_lo || this_tsc_khz > thresh_hi) {
+               pr_debug("kvm: requested TSC rate %u falls outside tolerance [%u,%u]\n", this_tsc_khz, thresh_lo, thresh_hi);
+               use_scaling = 1;
+       }
+       kvm_x86_ops->set_tsc_khz(vcpu, this_tsc_khz, use_scaling);
 }
 
 static u64 compute_guest_tsc(struct kvm_vcpu *vcpu, s64 kernel_ns)
 {
-       u64 tsc = pvclock_scale_delta(kernel_ns-vcpu->arch.last_tsc_nsec,
-                                     vcpu->arch.tsc_catchup_mult,
-                                     vcpu->arch.tsc_catchup_shift);
-       tsc += vcpu->arch.last_tsc_write;
+       u64 tsc = pvclock_scale_delta(kernel_ns-vcpu->arch.this_tsc_nsec,
+                                     vcpu->arch.virtual_tsc_mult,
+                                     vcpu->arch.virtual_tsc_shift);
+       tsc += vcpu->arch.this_tsc_write;
        return tsc;
 }
 
@@ -1021,48 +1026,88 @@ void kvm_write_tsc(struct kvm_vcpu *vcpu, u64 data)
        struct kvm *kvm = vcpu->kvm;
        u64 offset, ns, elapsed;
        unsigned long flags;
-       s64 sdiff;
+       s64 usdiff;
 
        raw_spin_lock_irqsave(&kvm->arch.tsc_write_lock, flags);
        offset = kvm_x86_ops->compute_tsc_offset(vcpu, data);
        ns = get_kernel_ns();
        elapsed = ns - kvm->arch.last_tsc_nsec;
-       sdiff = data - kvm->arch.last_tsc_write;
-       if (sdiff < 0)
-               sdiff = -sdiff;
+
+       /* n.b - signed multiplication and division required */
+       usdiff = data - kvm->arch.last_tsc_write;
+#ifdef CONFIG_X86_64
+       usdiff = (usdiff * 1000) / vcpu->arch.virtual_tsc_khz;
+#else
+       /* do_div() only does unsigned */
+       asm("idivl %2; xor %%edx, %%edx"
+           : "=A"(usdiff)
+           : "A"(usdiff * 1000), "rm"(vcpu->arch.virtual_tsc_khz));
+#endif
+       do_div(elapsed, 1000);
+       usdiff -= elapsed;
+       if (usdiff < 0)
+               usdiff = -usdiff;
 
        /*
-        * Special case: close write to TSC within 5 seconds of
-        * another CPU is interpreted as an attempt to synchronize
-        * The 5 seconds is to accommodate host load / swapping as
-        * well as any reset of TSC during the boot process.
-        *
-        * In that case, for a reliable TSC, we can match TSC offsets,
-        * or make a best guest using elapsed value.
-        */
-       if (sdiff < nsec_to_cycles(vcpu, 5ULL * NSEC_PER_SEC) &&
-           elapsed < 5ULL * NSEC_PER_SEC) {
+        * Special case: TSC write with a small delta (1 second) of virtual
+        * cycle time against real time is interpreted as an attempt to
+        * synchronize the CPU.
+         *
+        * For a reliable TSC, we can match TSC offsets, and for an unstable
+        * TSC, we add elapsed time in this computation.  We could let the
+        * compensation code attempt to catch up if we fall behind, but
+        * it's better to try to match offsets from the beginning.
+         */
+       if (usdiff < USEC_PER_SEC &&
+           vcpu->arch.virtual_tsc_khz == kvm->arch.last_tsc_khz) {
                if (!check_tsc_unstable()) {
-                       offset = kvm->arch.last_tsc_offset;
+                       offset = kvm->arch.cur_tsc_offset;
                        pr_debug("kvm: matched tsc offset for %llu\n", data);
                } else {
                        u64 delta = nsec_to_cycles(vcpu, elapsed);
-                       offset += delta;
+                       data += delta;
+                       offset = kvm_x86_ops->compute_tsc_offset(vcpu, data);
                        pr_debug("kvm: adjusted tsc offset by %llu\n", delta);
                }
-               ns = kvm->arch.last_tsc_nsec;
+       } else {
+               /*
+                * We split periods of matched TSC writes into generations.
+                * For each generation, we track the original measured
+                * nanosecond time, offset, and write, so if TSCs are in
+                * sync, we can match exact offset, and if not, we can match
+                * exact software computaion in compute_guest_tsc()
+                *
+                * These values are tracked in kvm->arch.cur_xxx variables.
+                */
+               kvm->arch.cur_tsc_generation++;
+               kvm->arch.cur_tsc_nsec = ns;
+               kvm->arch.cur_tsc_write = data;
+               kvm->arch.cur_tsc_offset = offset;
+               pr_debug("kvm: new tsc generation %u, clock %llu\n",
+                        kvm->arch.cur_tsc_generation, data);
        }
+
+       /*
+        * We also track th most recent recorded KHZ, write and time to
+        * allow the matching interval to be extended at each write.
+        */
        kvm->arch.last_tsc_nsec = ns;
        kvm->arch.last_tsc_write = data;
-       kvm->arch.last_tsc_offset = offset;
-       kvm_x86_ops->write_tsc_offset(vcpu, offset);
-       raw_spin_unlock_irqrestore(&kvm->arch.tsc_write_lock, flags);
+       kvm->arch.last_tsc_khz = vcpu->arch.virtual_tsc_khz;
 
        /* Reset of TSC must disable overshoot protection below */
        vcpu->arch.hv_clock.tsc_timestamp = 0;
-       vcpu->arch.last_tsc_write = data;
-       vcpu->arch.last_tsc_nsec = ns;
+       vcpu->arch.last_guest_tsc = data;
+
+       /* Keep track of which generation this VCPU has synchronized to */
+       vcpu->arch.this_tsc_generation = kvm->arch.cur_tsc_generation;
+       vcpu->arch.this_tsc_nsec = kvm->arch.cur_tsc_nsec;
+       vcpu->arch.this_tsc_write = kvm->arch.cur_tsc_write;
+
+       kvm_x86_ops->write_tsc_offset(vcpu, offset);
+       raw_spin_unlock_irqrestore(&kvm->arch.tsc_write_lock, flags);
 }
+
 EXPORT_SYMBOL_GPL(kvm_write_tsc);
 
 static int kvm_guest_time_update(struct kvm_vcpu *v)
@@ -1078,7 +1123,7 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
        local_irq_save(flags);
        tsc_timestamp = kvm_x86_ops->read_l1_tsc(v);
        kernel_ns = get_kernel_ns();
-       this_tsc_khz = vcpu_tsc_khz(v);
+       this_tsc_khz = __get_cpu_var(cpu_tsc_khz);
        if (unlikely(this_tsc_khz == 0)) {
                local_irq_restore(flags);
                kvm_make_request(KVM_REQ_CLOCK_UPDATE, v);
@@ -1098,7 +1143,7 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
        if (vcpu->tsc_catchup) {
                u64 tsc = compute_guest_tsc(v, kernel_ns);
                if (tsc > tsc_timestamp) {
-                       kvm_x86_ops->adjust_tsc_offset(v, tsc - tsc_timestamp);
+                       adjust_tsc_offset_guest(v, tsc - tsc_timestamp);
                        tsc_timestamp = tsc;
                }
        }
@@ -1130,7 +1175,7 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
         * observed by the guest and ensure the new system time is greater.
         */
        max_kernel_ns = 0;
-       if (vcpu->hv_clock.tsc_timestamp && vcpu->last_guest_tsc) {
+       if (vcpu->hv_clock.tsc_timestamp) {
                max_kernel_ns = vcpu->last_guest_tsc -
                                vcpu->hv_clock.tsc_timestamp;
                max_kernel_ns = pvclock_scale_delta(max_kernel_ns,
@@ -1504,6 +1549,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)
        case MSR_K7_HWCR:
                data &= ~(u64)0x40;     /* ignore flush filter disable */
                data &= ~(u64)0x100;    /* ignore ignne emulation enable */
+               data &= ~(u64)0x8;      /* ignore TLB cache disable */
                if (data != 0) {
                        pr_unimpl(vcpu, "unimplemented HWCR wrmsr: 0x%llx\n",
                                data);
@@ -1676,6 +1722,16 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)
                 */
                pr_unimpl(vcpu, "ignored wrmsr: 0x%x data %llx\n", msr, data);
                break;
+       case MSR_AMD64_OSVW_ID_LENGTH:
+               if (!guest_cpuid_has_osvw(vcpu))
+                       return 1;
+               vcpu->arch.osvw.length = data;
+               break;
+       case MSR_AMD64_OSVW_STATUS:
+               if (!guest_cpuid_has_osvw(vcpu))
+                       return 1;
+               vcpu->arch.osvw.status = data;
+               break;
        default:
                if (msr && (msr == vcpu->kvm->arch.xen_hvm_config.msr))
                        return xen_hvm_config(vcpu, data);
@@ -1960,6 +2016,16 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
                 */
                data = 0xbe702111;
                break;
+       case MSR_AMD64_OSVW_ID_LENGTH:
+               if (!guest_cpuid_has_osvw(vcpu))
+                       return 1;
+               data = vcpu->arch.osvw.length;
+               break;
+       case MSR_AMD64_OSVW_STATUS:
+               if (!guest_cpuid_has_osvw(vcpu))
+                       return 1;
+               data = vcpu->arch.osvw.status;
+               break;
        default:
                if (kvm_pmu_msr(vcpu, msr))
                        return kvm_pmu_get_msr(vcpu, msr, pdata);
@@ -2080,6 +2146,7 @@ int kvm_dev_ioctl_check_extension(long ext)
        case KVM_CAP_XSAVE:
        case KVM_CAP_ASYNC_PF:
        case KVM_CAP_GET_TSC_KHZ:
+       case KVM_CAP_PCI_2_3:
                r = 1;
                break;
        case KVM_CAP_COALESCED_MMIO:
@@ -2214,19 +2281,23 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
        }
 
        kvm_x86_ops->vcpu_load(vcpu, cpu);
-       if (unlikely(vcpu->cpu != cpu) || check_tsc_unstable()) {
-               /* Make sure TSC doesn't go backwards */
-               s64 tsc_delta;
-               u64 tsc;
 
-               tsc = kvm_x86_ops->read_l1_tsc(vcpu);
-               tsc_delta = !vcpu->arch.last_guest_tsc ? 0 :
-                            tsc - vcpu->arch.last_guest_tsc;
+       /* Apply any externally detected TSC adjustments (due to suspend) */
+       if (unlikely(vcpu->arch.tsc_offset_adjustment)) {
+               adjust_tsc_offset_host(vcpu, vcpu->arch.tsc_offset_adjustment);
+               vcpu->arch.tsc_offset_adjustment = 0;
+               set_bit(KVM_REQ_CLOCK_UPDATE, &vcpu->requests);
+       }
 
+       if (unlikely(vcpu->cpu != cpu) || check_tsc_unstable()) {
+               s64 tsc_delta = !vcpu->arch.last_host_tsc ? 0 :
+                               native_read_tsc() - vcpu->arch.last_host_tsc;
                if (tsc_delta < 0)
                        mark_tsc_unstable("KVM discovered backwards TSC");
                if (check_tsc_unstable()) {
-                       kvm_x86_ops->adjust_tsc_offset(vcpu, -tsc_delta);
+                       u64 offset = kvm_x86_ops->compute_tsc_offset(vcpu,
+                                               vcpu->arch.last_guest_tsc);
+                       kvm_x86_ops->write_tsc_offset(vcpu, offset);
                        vcpu->arch.tsc_catchup = 1;
                }
                kvm_make_request(KVM_REQ_CLOCK_UPDATE, vcpu);
@@ -2243,7 +2314,7 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
 {
        kvm_x86_ops->vcpu_put(vcpu);
        kvm_put_guest_fpu(vcpu);
-       vcpu->arch.last_guest_tsc = kvm_x86_ops->read_l1_tsc(vcpu);
+       vcpu->arch.last_host_tsc = native_read_tsc();
 }
 
 static int kvm_vcpu_ioctl_get_lapic(struct kvm_vcpu *vcpu,
@@ -2785,26 +2856,21 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
                u32 user_tsc_khz;
 
                r = -EINVAL;
-               if (!kvm_has_tsc_control)
-                       break;
-
                user_tsc_khz = (u32)arg;
 
                if (user_tsc_khz >= kvm_max_guest_tsc_khz)
                        goto out;
 
-               kvm_x86_ops->set_tsc_khz(vcpu, user_tsc_khz);
+               if (user_tsc_khz == 0)
+                       user_tsc_khz = tsc_khz;
+
+               kvm_set_tsc_khz(vcpu, user_tsc_khz);
 
                r = 0;
                goto out;
        }
        case KVM_GET_TSC_KHZ: {
-               r = -EIO;
-               if (check_tsc_unstable())
-                       goto out;
-
-               r = vcpu_tsc_khz(vcpu);
-
+               r = vcpu->arch.virtual_tsc_khz;
                goto out;
        }
        default:
@@ -2815,6 +2881,11 @@ out:
        return r;
 }
 
+int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf)
+{
+       return VM_FAULT_SIGBUS;
+}
+
 static int kvm_vm_ioctl_set_tss_addr(struct kvm *kvm, unsigned long addr)
 {
        int ret;
@@ -2998,6 +3069,8 @@ static void write_protect_slot(struct kvm *kvm,
                               unsigned long *dirty_bitmap,
                               unsigned long nr_dirty_pages)
 {
+       spin_lock(&kvm->mmu_lock);
+
        /* Not many dirty pages compared to # of shadow pages. */
        if (nr_dirty_pages < kvm->arch.n_used_mmu_pages) {
                unsigned long gfn_offset;
@@ -3005,16 +3078,13 @@ static void write_protect_slot(struct kvm *kvm,
                for_each_set_bit(gfn_offset, dirty_bitmap, memslot->npages) {
                        unsigned long gfn = memslot->base_gfn + gfn_offset;
 
-                       spin_lock(&kvm->mmu_lock);
                        kvm_mmu_rmap_write_protect(kvm, gfn, memslot);
-                       spin_unlock(&kvm->mmu_lock);
                }
                kvm_flush_remote_tlbs(kvm);
-       } else {
-               spin_lock(&kvm->mmu_lock);
+       } else
                kvm_mmu_slot_remove_write_access(kvm, memslot->id);
-               spin_unlock(&kvm->mmu_lock);
-       }
+
+       spin_unlock(&kvm->mmu_lock);
 }
 
 /*
@@ -3133,6 +3203,9 @@ long kvm_arch_vm_ioctl(struct file *filp,
                r = -EEXIST;
                if (kvm->arch.vpic)
                        goto create_irqchip_unlock;
+               r = -EINVAL;
+               if (atomic_read(&kvm->online_vcpus))
+                       goto create_irqchip_unlock;
                r = -ENOMEM;
                vpic = kvm_create_pic(kvm);
                if (vpic) {
@@ -4063,6 +4136,11 @@ static int emulator_set_cr(struct x86_emulate_ctxt *ctxt, int cr, ulong val)
        return res;
 }
 
+static void emulator_set_rflags(struct x86_emulate_ctxt *ctxt, ulong val)
+{
+       kvm_set_rflags(emul_to_vcpu(ctxt), val);
+}
+
 static int emulator_get_cpl(struct x86_emulate_ctxt *ctxt)
 {
        return kvm_x86_ops->get_cpl(emul_to_vcpu(ctxt));
@@ -4244,6 +4322,7 @@ static struct x86_emulate_ops emulate_ops = {
        .set_idt             = emulator_set_idt,
        .get_cr              = emulator_get_cr,
        .set_cr              = emulator_set_cr,
+       .set_rflags          = emulator_set_rflags,
        .cpl                 = emulator_get_cpl,
        .get_dr              = emulator_get_dr,
        .set_dr              = emulator_set_dr,
@@ -5288,6 +5367,8 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
                profile_hit(KVM_PROFILING, (void *)rip);
        }
 
+       if (unlikely(vcpu->arch.tsc_always_catchup))
+               kvm_make_request(KVM_REQ_CLOCK_UPDATE, vcpu);
 
        kvm_lapic_sync_from_vapic(vcpu);
 
@@ -5587,15 +5668,15 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
        return 0;
 }
 
-int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason,
-                   bool has_error_code, u32 error_code)
+int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int idt_index,
+                   int reason, bool has_error_code, u32 error_code)
 {
        struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt;
        int ret;
 
        init_emulate_ctxt(vcpu);
 
-       ret = emulator_task_switch(ctxt, tss_selector, reason,
+       ret = emulator_task_switch(ctxt, tss_selector, idt_index, reason,
                                   has_error_code, error_code);
 
        if (ret)
@@ -5928,13 +6009,88 @@ int kvm_arch_hardware_enable(void *garbage)
        struct kvm *kvm;
        struct kvm_vcpu *vcpu;
        int i;
+       int ret;
+       u64 local_tsc;
+       u64 max_tsc = 0;
+       bool stable, backwards_tsc = false;
 
        kvm_shared_msr_cpu_online();
-       list_for_each_entry(kvm, &vm_list, vm_list)
-               kvm_for_each_vcpu(i, vcpu, kvm)
-                       if (vcpu->cpu == smp_processor_id())
-                               kvm_make_request(KVM_REQ_CLOCK_UPDATE, vcpu);
-       return kvm_x86_ops->hardware_enable(garbage);
+       ret = kvm_x86_ops->hardware_enable(garbage);
+       if (ret != 0)
+               return ret;
+
+       local_tsc = native_read_tsc();
+       stable = !check_tsc_unstable();
+       list_for_each_entry(kvm, &vm_list, vm_list) {
+               kvm_for_each_vcpu(i, vcpu, kvm) {
+                       if (!stable && vcpu->cpu == smp_processor_id())
+                               set_bit(KVM_REQ_CLOCK_UPDATE, &vcpu->requests);
+                       if (stable && vcpu->arch.last_host_tsc > local_tsc) {
+                               backwards_tsc = true;
+                               if (vcpu->arch.last_host_tsc > max_tsc)
+                                       max_tsc = vcpu->arch.last_host_tsc;
+                       }
+               }
+       }
+
+       /*
+        * Sometimes, even reliable TSCs go backwards.  This happens on
+        * platforms that reset TSC during suspend or hibernate actions, but
+        * maintain synchronization.  We must compensate.  Fortunately, we can
+        * detect that condition here, which happens early in CPU bringup,
+        * before any KVM threads can be running.  Unfortunately, we can't
+        * bring the TSCs fully up to date with real time, as we aren't yet far
+        * enough into CPU bringup that we know how much real time has actually
+        * elapsed; our helper function, get_kernel_ns() will be using boot
+        * variables that haven't been updated yet.
+        *
+        * So we simply find the maximum observed TSC above, then record the
+        * adjustment to TSC in each VCPU.  When the VCPU later gets loaded,
+        * the adjustment will be applied.  Note that we accumulate
+        * adjustments, in case multiple suspend cycles happen before some VCPU
+        * gets a chance to run again.  In the event that no KVM threads get a
+        * chance to run, we will miss the entire elapsed period, as we'll have
+        * reset last_host_tsc, so VCPUs will not have the TSC adjusted and may
+        * loose cycle time.  This isn't too big a deal, since the loss will be
+        * uniform across all VCPUs (not to mention the scenario is extremely
+        * unlikely). It is possible that a second hibernate recovery happens
+        * much faster than a first, causing the observed TSC here to be
+        * smaller; this would require additional padding adjustment, which is
+        * why we set last_host_tsc to the local tsc observed here.
+        *
+        * N.B. - this code below runs only on platforms with reliable TSC,
+        * as that is the only way backwards_tsc is set above.  Also note
+        * that this runs for ALL vcpus, which is not a bug; all VCPUs should
+        * have the same delta_cyc adjustment applied if backwards_tsc
+        * is detected.  Note further, this adjustment is only done once,
+        * as we reset last_host_tsc on all VCPUs to stop this from being
+        * called multiple times (one for each physical CPU bringup).
+        *
+        * Platforms with unnreliable TSCs don't have to deal with this, they
+        * will be compensated by the logic in vcpu_load, which sets the TSC to
+        * catchup mode.  This will catchup all VCPUs to real time, but cannot
+        * guarantee that they stay in perfect synchronization.
+        */
+       if (backwards_tsc) {
+               u64 delta_cyc = max_tsc - local_tsc;
+               list_for_each_entry(kvm, &vm_list, vm_list) {
+                       kvm_for_each_vcpu(i, vcpu, kvm) {
+                               vcpu->arch.tsc_offset_adjustment += delta_cyc;
+                               vcpu->arch.last_host_tsc = local_tsc;
+                       }
+
+                       /*
+                        * We have to disable TSC offset matching.. if you were
+                        * booting a VM while issuing an S4 host suspend....
+                        * you may have some problem.  Solving this issue is
+                        * left as an exercise to the reader.
+                        */
+                       kvm->arch.last_tsc_nsec = 0;
+                       kvm->arch.last_tsc_write = 0;
+               }
+
+       }
+       return 0;
 }
 
 void kvm_arch_hardware_disable(void *garbage)
@@ -5958,6 +6114,11 @@ void kvm_arch_check_processor_compat(void *rtn)
        kvm_x86_ops->check_processor_compatibility(rtn);
 }
 
+bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu)
+{
+       return irqchip_in_kernel(vcpu->kvm) == (vcpu->arch.apic != NULL);
+}
+
 int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
 {
        struct page *page;
@@ -5980,7 +6141,7 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
        }
        vcpu->arch.pio_data = page_address(page);
 
-       kvm_init_tsc_catchup(vcpu, max_tsc_khz);
+       kvm_set_tsc_khz(vcpu, max_tsc_khz);
 
        r = kvm_mmu_create(vcpu);
        if (r < 0)
@@ -6032,8 +6193,11 @@ void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu)
        free_page((unsigned long)vcpu->arch.pio_data);
 }
 
-int kvm_arch_init_vm(struct kvm *kvm)
+int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
 {
+       if (type)
+               return -EINVAL;
+
        INIT_LIST_HEAD(&kvm->arch.active_mmu_pages);
        INIT_LIST_HEAD(&kvm->arch.assigned_dev_head);
 
@@ -6093,6 +6257,65 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
                put_page(kvm->arch.ept_identity_pagetable);
 }
 
+void kvm_arch_free_memslot(struct kvm_memory_slot *free,
+                          struct kvm_memory_slot *dont)
+{
+       int i;
+
+       for (i = 0; i < KVM_NR_PAGE_SIZES - 1; ++i) {
+               if (!dont || free->arch.lpage_info[i] != dont->arch.lpage_info[i]) {
+                       vfree(free->arch.lpage_info[i]);
+                       free->arch.lpage_info[i] = NULL;
+               }
+       }
+}
+
+int kvm_arch_create_memslot(struct kvm_memory_slot *slot, unsigned long npages)
+{
+       int i;
+
+       for (i = 0; i < KVM_NR_PAGE_SIZES - 1; ++i) {
+               unsigned long ugfn;
+               int lpages;
+               int level = i + 2;
+
+               lpages = gfn_to_index(slot->base_gfn + npages - 1,
+                                     slot->base_gfn, level) + 1;
+
+               slot->arch.lpage_info[i] =
+                       vzalloc(lpages * sizeof(*slot->arch.lpage_info[i]));
+               if (!slot->arch.lpage_info[i])
+                       goto out_free;
+
+               if (slot->base_gfn & (KVM_PAGES_PER_HPAGE(level) - 1))
+                       slot->arch.lpage_info[i][0].write_count = 1;
+               if ((slot->base_gfn + npages) & (KVM_PAGES_PER_HPAGE(level) - 1))
+                       slot->arch.lpage_info[i][lpages - 1].write_count = 1;
+               ugfn = slot->userspace_addr >> PAGE_SHIFT;
+               /*
+                * If the gfn and userspace address are not aligned wrt each
+                * other, or if explicitly asked to, disable large page
+                * support for this slot
+                */
+               if ((slot->base_gfn ^ ugfn) & (KVM_PAGES_PER_HPAGE(level) - 1) ||
+                   !kvm_largepages_enabled()) {
+                       unsigned long j;
+
+                       for (j = 0; j < lpages; ++j)
+                               slot->arch.lpage_info[i][j].write_count = 1;
+               }
+       }
+
+       return 0;
+
+out_free:
+       for (i = 0; i < KVM_NR_PAGE_SIZES - 1; ++i) {
+               vfree(slot->arch.lpage_info[i]);
+               slot->arch.lpage_info[i] = NULL;
+       }
+       return -ENOMEM;
+}
+
 int kvm_arch_prepare_memory_region(struct kvm *kvm,
                                struct kvm_memory_slot *memslot,
                                struct kvm_memory_slot old,
index 6cabf65..4f0cec7 100644 (file)
@@ -12,7 +12,6 @@
 #include <asm/page_types.h>
 #include <asm/sections.h>
 #include <asm/setup.h>
-#include <asm/system.h>
 #include <asm/tlbflush.h>
 #include <asm/tlb.h>
 #include <asm/proto.h>
index 8663f6c..575d86f 100644 (file)
@@ -35,7 +35,6 @@
 #include <asm/asm.h>
 #include <asm/bios_ebda.h>
 #include <asm/processor.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/dma.h>
index 436a030..fc18be0 100644 (file)
@@ -35,7 +35,6 @@
 
 #include <asm/processor.h>
 #include <asm/bios_ebda.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
index cac7184..a69bcb8 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/spinlock.h>
 #include <linux/module.h>
 
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
 #include <asm/fixmap.h>
index e70be38..ce874f8 100644 (file)
                                        interrupts = <14 1>;
                                };
 
-                               gpio@b,1 {
+                               pcigpio: gpio@b,1 {
+                                       #gpio-cells = <2>;
+                                       #interrupt-cells = <2>;
                                        compatible = "pci8086,2e67.2",
                                                   "pci8086,2e67",
                                                   "pciclassff0000",
                                                   "pciclassff00";
 
-                                       #gpio-cells = <2>;
                                        reg = <0x15900 0x0 0x0 0x0 0x0>;
                                        interrupts = <15 1>;
+                                       interrupt-controller;
                                        gpio-controller;
+                                       intel,muxctl = <0>;
                                };
 
                                i2c-controller@b,2 {
index 246b788..5b51194 100644 (file)
@@ -1,2 +1,3 @@
 obj-$(CONFIG_ALIX)             += alix.o
 obj-$(CONFIG_NET5501)          += net5501.o
+obj-$(CONFIG_GEOS)             += geos.o
diff --git a/arch/x86/platform/geode/geos.c b/arch/x86/platform/geode/geos.c
new file mode 100644 (file)
index 0000000..c2e6d53
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * System Specific setup for Traverse Technologies GEOS.
+ * At the moment this means setup of GPIO control of LEDs.
+ *
+ * Copyright (C) 2008 Constantin Baranov <const@mimas.ru>
+ * Copyright (C) 2011 Ed Wildgoose <kernel@wildgooses.com>
+ *                and Philip Prindeville <philipp@redfish-solutions.com>
+ *
+ * TODO: There are large similarities with leds-net5501.c
+ * by Alessandro Zummo <a.zummo@towertech.it>
+ * In the future leds-net5501.c should be migrated over to platform
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/string.h>
+#include <linux/module.h>
+#include <linux/leds.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
+#include <linux/dmi.h>
+
+#include <asm/geode.h>
+
+static struct gpio_keys_button geos_gpio_buttons[] = {
+       {
+               .code = KEY_RESTART,
+               .gpio = 3,
+               .active_low = 1,
+               .desc = "Reset button",
+               .type = EV_KEY,
+               .wakeup = 0,
+               .debounce_interval = 100,
+               .can_disable = 0,
+       }
+};
+static struct gpio_keys_platform_data geos_buttons_data = {
+       .buttons = geos_gpio_buttons,
+       .nbuttons = ARRAY_SIZE(geos_gpio_buttons),
+       .poll_interval = 20,
+};
+
+static struct platform_device geos_buttons_dev = {
+       .name = "gpio-keys-polled",
+       .id = 1,
+       .dev = {
+               .platform_data = &geos_buttons_data,
+       }
+};
+
+static struct gpio_led geos_leds[] = {
+       {
+               .name = "geos:1",
+               .gpio = 6,
+               .default_trigger = "default-on",
+               .active_low = 1,
+       },
+       {
+               .name = "geos:2",
+               .gpio = 25,
+               .default_trigger = "default-off",
+               .active_low = 1,
+       },
+       {
+               .name = "geos:3",
+               .gpio = 27,
+               .default_trigger = "default-off",
+               .active_low = 1,
+       },
+};
+
+static struct gpio_led_platform_data geos_leds_data = {
+       .num_leds = ARRAY_SIZE(geos_leds),
+       .leds = geos_leds,
+};
+
+static struct platform_device geos_leds_dev = {
+       .name = "leds-gpio",
+       .id = -1,
+       .dev.platform_data = &geos_leds_data,
+};
+
+static struct __initdata platform_device *geos_devs[] = {
+       &geos_buttons_dev,
+       &geos_leds_dev,
+};
+
+static void __init register_geos(void)
+{
+       /* Setup LED control through leds-gpio driver */
+       platform_add_devices(geos_devs, ARRAY_SIZE(geos_devs));
+}
+
+static int __init geos_init(void)
+{
+       const char *vendor, *product;
+
+       if (!is_geode())
+               return 0;
+
+       vendor = dmi_get_system_info(DMI_SYS_VENDOR);
+       if (!vendor || strcmp(vendor, "Traverse Technologies"))
+               return 0;
+
+       product = dmi_get_system_info(DMI_PRODUCT_NAME);
+       if (!product || strcmp(product, "Geos"))
+               return 0;
+
+       printk(KERN_INFO "%s: system is recognized as \"%s %s\"\n",
+              KBUILD_MODNAME, vendor, product);
+
+       register_geos();
+
+       return 0;
+}
+
+module_init(geos_init);
+
+MODULE_AUTHOR("Philip Prindeville <philipp@redfish-solutions.com>");
+MODULE_DESCRIPTION("Traverse Technologies Geos System Setup");
+MODULE_LICENSE("GPL");
index 4889655..4793683 100644 (file)
@@ -115,7 +115,7 @@ static void __save_processor_state(struct saved_context *ctxt)
 void save_processor_state(void)
 {
        __save_processor_state(&saved_context);
-       save_sched_clock_state();
+       x86_platform.save_sched_clock_state();
 }
 #ifdef CONFIG_X86_32
 EXPORT_SYMBOL(save_processor_state);
@@ -231,8 +231,8 @@ static void __restore_processor_state(struct saved_context *ctxt)
 /* Needed by apm.c */
 void restore_processor_state(void)
 {
+       x86_platform.restore_sched_clock_state();
        __restore_processor_state(&saved_context);
-       restore_sched_clock_state();
 }
 #ifdef CONFIG_X86_32
 EXPORT_SYMBOL(restore_processor_state);
index 3769079..74202c1 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/suspend.h>
 #include <linux/bootmem.h>
 
-#include <asm/system.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/mmzone.h>
index 23592ef..b409893 100644 (file)
@@ -18,7 +18,7 @@
 
 #ifdef __KERNEL__
 #include <asm/processor.h>
-#include <asm/system.h>
+#include <asm/cmpxchg.h>
 
 #define ATOMIC_INIT(i) { (i) }
 
diff --git a/arch/xtensa/include/asm/barrier.h b/arch/xtensa/include/asm/barrier.h
new file mode 100644 (file)
index 0000000..55707a8
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_SYSTEM_H
+#define _XTENSA_SYSTEM_H
+
+#define smp_read_barrier_depends() do { } while(0)
+#define read_barrier_depends() do { } while(0)
+
+#define mb()  barrier()
+#define rmb() mb()
+#define wmb() mb()
+
+#ifdef CONFIG_SMP
+#error smp_* not defined
+#else
+#define smp_mb()       barrier()
+#define smp_rmb()      barrier()
+#define smp_wmb()      barrier()
+#endif
+
+#define set_mb(var, value)     do { var = value; mb(); } while (0)
+
+#endif /* _XTENSA_SYSTEM_H */
index 40aa7fe..5270197 100644 (file)
@@ -21,7 +21,6 @@
 
 #include <asm/processor.h>
 #include <asm/byteorder.h>
-#include <asm/system.h>
 
 #ifdef CONFIG_SMP
 # error SMP not supported on this architecture
diff --git a/arch/xtensa/include/asm/cmpxchg.h b/arch/xtensa/include/asm/cmpxchg.h
new file mode 100644 (file)
index 0000000..e321490
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Atomic xchg and cmpxchg operations.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_CMPXCHG_H
+#define _XTENSA_CMPXCHG_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/stringify.h>
+
+/*
+ * cmpxchg
+ */
+
+static inline unsigned long
+__cmpxchg_u32(volatile int *p, int old, int new)
+{
+  __asm__ __volatile__("rsil    a15, "__stringify(LOCKLEVEL)"\n\t"
+                      "l32i    %0, %1, 0              \n\t"
+                      "bne     %0, %2, 1f             \n\t"
+                      "s32i    %3, %1, 0              \n\t"
+                      "1:                             \n\t"
+                      "wsr     a15, "__stringify(PS)" \n\t"
+                      "rsync                          \n\t"
+                      : "=&a" (old)
+                      : "a" (p), "a" (old), "r" (new)
+                      : "a15", "memory");
+  return old;
+}
+/* This function doesn't exist, so you'll get a linker error
+ * if something tries to do an invalid cmpxchg(). */
+
+extern void __cmpxchg_called_with_bad_pointer(void);
+
+static __inline__ unsigned long
+__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
+{
+       switch (size) {
+       case 4:  return __cmpxchg_u32(ptr, old, new);
+       default: __cmpxchg_called_with_bad_pointer();
+                return old;
+       }
+}
+
+#define cmpxchg(ptr,o,n)                                                     \
+       ({ __typeof__(*(ptr)) _o_ = (o);                                      \
+          __typeof__(*(ptr)) _n_ = (n);                                      \
+          (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,          \
+                                       (unsigned long)_n_, sizeof (*(ptr))); \
+       })
+
+#include <asm-generic/cmpxchg-local.h>
+
+static inline unsigned long __cmpxchg_local(volatile void *ptr,
+                                     unsigned long old,
+                                     unsigned long new, int size)
+{
+       switch (size) {
+       case 4:
+               return __cmpxchg_u32(ptr, old, new);
+       default:
+               return __cmpxchg_local_generic(ptr, old, new, size);
+       }
+
+       return old;
+}
+
+/*
+ * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
+ * them available.
+ */
+#define cmpxchg_local(ptr, o, n)                                              \
+       ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
+                       (unsigned long)(n), sizeof(*(ptr))))
+#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
+
+/*
+ * xchg_u32
+ *
+ * Note that a15 is used here because the register allocation
+ * done by the compiler is not guaranteed and a window overflow
+ * may not occur between the rsil and wsr instructions. By using
+ * a15 in the rsil, the machine is guaranteed to be in a state
+ * where no register reference will cause an overflow.
+ */
+
+static inline unsigned long xchg_u32(volatile int * m, unsigned long val)
+{
+  unsigned long tmp;
+  __asm__ __volatile__("rsil    a15, "__stringify(LOCKLEVEL)"\n\t"
+                      "l32i    %0, %1, 0              \n\t"
+                      "s32i    %2, %1, 0              \n\t"
+                      "wsr     a15, "__stringify(PS)" \n\t"
+                      "rsync                          \n\t"
+                      : "=&a" (tmp)
+                      : "a" (m), "a" (val)
+                      : "a15", "memory");
+  return tmp;
+}
+
+#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
+
+/*
+ * This only works if the compiler isn't horribly bad at optimizing.
+ * gcc-2.5.8 reportedly can't handle this, but I define that one to
+ * be dead anyway.
+ */
+
+extern void __xchg_called_with_bad_pointer(void);
+
+static __inline__ unsigned long
+__xchg(unsigned long x, volatile void * ptr, int size)
+{
+       switch (size) {
+               case 4:
+                       return xchg_u32(ptr, x);
+       }
+       __xchg_called_with_bad_pointer();
+       return x;
+}
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _XTENSA_CMPXCHG_H */
diff --git a/arch/xtensa/include/asm/exec.h b/arch/xtensa/include/asm/exec.h
new file mode 100644 (file)
index 0000000..af949e2
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_EXEC_H
+#define _XTENSA_EXEC_H
+
+#define arch_align_stack(x) (x)
+
+#endif /* _XTENSA_EXEC_H */
index e363652..9fa8ad9 100644 (file)
@@ -13,4 +13,6 @@
 
 #define COMMAND_LINE_SIZE      256
 
+extern void set_except_vector(int n, void *addr);
+
 #endif
diff --git a/arch/xtensa/include/asm/switch_to.h b/arch/xtensa/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..6b73bf0
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_SWITCH_TO_H
+#define _XTENSA_SWITCH_TO_H
+
+/* * switch_to(n) should switch tasks to task nr n, first
+ * checking that n isn't the current task, in which case it does nothing.
+ */
+extern void *_switch_to(void *last, void *next);
+
+#define switch_to(prev,next,last)              \
+do {                                           \
+       (last) = _switch_to(prev, next);        \
+} while(0)
+
+#endif /* _XTENSA_SWITCH_TO_H */
diff --git a/arch/xtensa/include/asm/system.h b/arch/xtensa/include/asm/system.h
deleted file mode 100644 (file)
index 1e7e09a..0000000
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * include/asm-xtensa/system.h
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2001 - 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_SYSTEM_H
-#define _XTENSA_SYSTEM_H
-
-#include <linux/stringify.h>
-#include <linux/irqflags.h>
-
-#include <asm/processor.h>
-
-#define smp_read_barrier_depends() do { } while(0)
-#define read_barrier_depends() do { } while(0)
-
-#define mb()  barrier()
-#define rmb() mb()
-#define wmb() mb()
-
-#ifdef CONFIG_SMP
-#error smp_* not defined
-#else
-#define smp_mb()       barrier()
-#define smp_rmb()      barrier()
-#define smp_wmb()      barrier()
-#endif
-
-#define set_mb(var, value)     do { var = value; mb(); } while (0)
-
-#if !defined (__ASSEMBLY__)
-
-/* * switch_to(n) should switch tasks to task nr n, first
- * checking that n isn't the current task, in which case it does nothing.
- */
-extern void *_switch_to(void *last, void *next);
-
-#endif /* __ASSEMBLY__ */
-
-#define switch_to(prev,next,last)              \
-do {                                           \
-       (last) = _switch_to(prev, next);        \
-} while(0)
-
-/*
- * cmpxchg
- */
-
-static inline unsigned long
-__cmpxchg_u32(volatile int *p, int old, int new)
-{
-  __asm__ __volatile__("rsil    a15, "__stringify(LOCKLEVEL)"\n\t"
-                      "l32i    %0, %1, 0              \n\t"
-                      "bne     %0, %2, 1f             \n\t"
-                      "s32i    %3, %1, 0              \n\t"
-                      "1:                             \n\t"
-                      "wsr     a15, "__stringify(PS)" \n\t"
-                      "rsync                          \n\t"
-                      : "=&a" (old)
-                      : "a" (p), "a" (old), "r" (new)
-                      : "a15", "memory");
-  return old;
-}
-/* This function doesn't exist, so you'll get a linker error
- * if something tries to do an invalid cmpxchg(). */
-
-extern void __cmpxchg_called_with_bad_pointer(void);
-
-static __inline__ unsigned long
-__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
-{
-       switch (size) {
-       case 4:  return __cmpxchg_u32(ptr, old, new);
-       default: __cmpxchg_called_with_bad_pointer();
-                return old;
-       }
-}
-
-#define cmpxchg(ptr,o,n)                                                     \
-       ({ __typeof__(*(ptr)) _o_ = (o);                                      \
-          __typeof__(*(ptr)) _n_ = (n);                                      \
-          (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,          \
-                                       (unsigned long)_n_, sizeof (*(ptr))); \
-       })
-
-#include <asm-generic/cmpxchg-local.h>
-
-static inline unsigned long __cmpxchg_local(volatile void *ptr,
-                                     unsigned long old,
-                                     unsigned long new, int size)
-{
-       switch (size) {
-       case 4:
-               return __cmpxchg_u32(ptr, old, new);
-       default:
-               return __cmpxchg_local_generic(ptr, old, new, size);
-       }
-
-       return old;
-}
-
-/*
- * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
- * them available.
- */
-#define cmpxchg_local(ptr, o, n)                                              \
-       ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
-                       (unsigned long)(n), sizeof(*(ptr))))
-#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
-
-/*
- * xchg_u32
- *
- * Note that a15 is used here because the register allocation
- * done by the compiler is not guaranteed and a window overflow
- * may not occur between the rsil and wsr instructions. By using
- * a15 in the rsil, the machine is guaranteed to be in a state
- * where no register reference will cause an overflow.
- */
-
-static inline unsigned long xchg_u32(volatile int * m, unsigned long val)
-{
-  unsigned long tmp;
-  __asm__ __volatile__("rsil    a15, "__stringify(LOCKLEVEL)"\n\t"
-                      "l32i    %0, %1, 0              \n\t"
-                      "s32i    %2, %1, 0              \n\t"
-                      "wsr     a15, "__stringify(PS)" \n\t"
-                      "rsync                          \n\t"
-                      : "=&a" (tmp)
-                      : "a" (m), "a" (val)
-                      : "a15", "memory");
-  return tmp;
-}
-
-#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
-
-/*
- * This only works if the compiler isn't horribly bad at optimizing.
- * gcc-2.5.8 reportedly can't handle this, but I define that one to
- * be dead anyway.
- */
-
-extern void __xchg_called_with_bad_pointer(void);
-
-static __inline__ unsigned long
-__xchg(unsigned long x, volatile void * ptr, int size)
-{
-       switch (size) {
-               case 4:
-                       return xchg_u32(ptr, x);
-       }
-       __xchg_called_with_bad_pointer();
-       return x;
-}
-
-extern void set_except_vector(int n, void *addr);
-
-static inline void spill_registers(void)
-{
-       unsigned int a0, ps;
-
-       __asm__ __volatile__ (
-               "movi   a14," __stringify (PS_EXCM_BIT) " | 1\n\t"
-               "mov    a12, a0\n\t"
-               "rsr    a13," __stringify(SAR) "\n\t"
-               "xsr    a14," __stringify(PS) "\n\t"
-               "movi   a0, _spill_registers\n\t"
-               "rsync\n\t"
-               "callx0 a0\n\t"
-               "mov    a0, a12\n\t"
-               "wsr    a13," __stringify(SAR) "\n\t"
-               "wsr    a14," __stringify(PS) "\n\t"
-               :: "a" (&a0), "a" (&ps)
-               : "a2", "a3", "a4", "a7", "a11", "a12", "a13", "a14", "a15", "memory");
-}
-
-#define arch_align_stack(x) (x)
-
-#endif /* _XTENSA_SYSTEM_H */
index 3fa526f..6e4bb3b 100644 (file)
@@ -17,7 +17,9 @@
 #define _XTENSA_UACCESS_H
 
 #include <linux/errno.h>
+#ifndef __ASSEMBLY__
 #include <linux/prefetch.h>
+#endif
 #include <asm/types.h>
 
 #define VERIFY_READ    0
index 2c90047..6a2d6ed 100644 (file)
@@ -34,7 +34,6 @@
 
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/processor.h>
 #include <asm/platform.h>
index 2dff698..33eea4c 100644 (file)
@@ -24,7 +24,6 @@
 
 #include <asm/pgtable.h>
 #include <asm/page.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/ptrace.h>
 #include <asm/elf.h>
index 1e5a034..17e746f 100644 (file)
@@ -34,7 +34,6 @@
 # include <linux/seq_file.h>
 #endif
 
-#include <asm/system.h>
 #include <asm/bootparam.h>
 #include <asm/pgtable.h>
 #include <asm/processor.h>
index e64efac..bc1e14c 100644 (file)
@@ -381,6 +381,25 @@ static __always_inline unsigned long *stack_pointer(struct task_struct *task)
        return sp;
 }
 
+static inline void spill_registers(void)
+{
+       unsigned int a0, ps;
+
+       __asm__ __volatile__ (
+               "movi   a14," __stringify (PS_EXCM_BIT) " | 1\n\t"
+               "mov    a12, a0\n\t"
+               "rsr    a13," __stringify(SAR) "\n\t"
+               "xsr    a14," __stringify(PS) "\n\t"
+               "movi   a0, _spill_registers\n\t"
+               "rsync\n\t"
+               "callx0 a0\n\t"
+               "mov    a0, a12\n\t"
+               "wsr    a13," __stringify(SAR) "\n\t"
+               "wsr    a14," __stringify(PS) "\n\t"
+               :: "a" (&a0), "a" (&ps)
+               : "a2", "a3", "a4", "a7", "a11", "a12", "a13", "a14", "a15", "memory");
+}
+
 void show_trace(struct task_struct *task, unsigned long *sp)
 {
        unsigned long a0, a1, pc;
index e367e30..b17885a 100644 (file)
@@ -19,7 +19,6 @@
 #include <asm/cacheflush.h>
 #include <asm/hardirq.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/pgalloc.h>
 
 unsigned long asid_cache = ASID_USER_FIRST;
index 239461d..e2700b2 100644 (file)
@@ -18,7 +18,6 @@
 #include <asm/processor.h>
 #include <asm/mmu_context.h>
 #include <asm/tlbflush.h>
-#include <asm/system.h>
 #include <asm/cacheflush.h>
 
 
index b19a18d..e37615f 100644 (file)
@@ -445,6 +445,16 @@ int ec_transaction(u8 command,
 
 EXPORT_SYMBOL(ec_transaction);
 
+/* Get the handle to the EC device */
+acpi_handle ec_get_handle(void)
+{
+       if (!first_ec)
+               return NULL;
+       return first_ec->handle;
+}
+
+EXPORT_SYMBOL(ec_get_handle);
+
 void acpi_ec_block_transactions(void)
 {
        struct acpi_ec *ec = first_ec;
index 2801b41..d4d9cb7 100644 (file)
@@ -46,7 +46,6 @@
 #include <linux/slab.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/cpu.h>
 #include <asm/delay.h>
 #include <asm/uaccess.h>
index f3f0fe7..45d8097 100644 (file)
@@ -23,7 +23,7 @@
  * Depending on whether ACPI graphics extensions (cmp. ACPI spec Appendix B)
  * are available, video.ko should be used to handle the device.
  *
- * Otherwise vendor specific drivers like thinkpad_acpi, asus_acpi,
+ * Otherwise vendor specific drivers like thinkpad_acpi, asus-laptop,
  * sony_acpi,... can take care about backlight brightness.
  *
  * If CONFIG_ACPI_VIDEO is neither set as "compiled in" (y) nor as a module (m)
index 6ff612d..2059ee4 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/atm_eni.h>
 #include <linux/bitops.h>
 #include <linux/slab.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <linux/atomic.h>
 #include <asm/uaccess.h>
index 5072f8a..86fed1b 100644 (file)
@@ -49,7 +49,6 @@
 #include <linux/bitops.h>
 #include <linux/slab.h>
 #include <asm/byteorder.h>
-#include <asm/system.h>
 #include <asm/string.h>
 #include <asm/io.h>
 #include <linux/atomic.h>
index b812103..75fd691 100644 (file)
@@ -43,7 +43,6 @@
 #include <linux/wait.h>
 #include <linux/slab.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <linux/atomic.h>
 #include <asm/uaccess.h>
index 487a547..45d5063 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/atm_idt77105.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
-#include <asm/system.h>
 #include <asm/param.h>
 #include <asm/uaccess.h>
 
index 9e373ba..d438601 100644 (file)
@@ -56,7 +56,6 @@
 #include <linux/interrupt.h>
 #include <linux/wait.h>
 #include <linux/slab.h>
-#include <asm/system.h>  
 #include <asm/io.h>  
 #include <linux/atomic.h>
 #include <asm/uaccess.h>  
index 90f1ccc..0215934 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/capability.h>
 #include <linux/atm_suni.h>
 #include <linux/slab.h>
-#include <asm/system.h>
 #include <asm/param.h>
 #include <asm/uaccess.h>
 #include <linux/atomic.h>
index d889f56..abe4e20 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/wait.h>
 #include <linux/slab.h>
 #include <asm/byteorder.h>
-#include <asm/system.h>
 #include <asm/string.h>
 #include <asm/io.h>
 #include <linux/atomic.h>
index e38ad24..07cbbc6 100644 (file)
@@ -71,7 +71,7 @@ static inline int is_dma_buf_file(struct file *file)
  * ops, or error in allocating struct dma_buf, will return negative error.
  *
  */
-struct dma_buf *dma_buf_export(void *priv, struct dma_buf_ops *ops,
+struct dma_buf *dma_buf_export(void *priv, const struct dma_buf_ops *ops,
                                size_t size, int flags)
 {
        struct dma_buf *dmabuf;
@@ -80,7 +80,9 @@ struct dma_buf *dma_buf_export(void *priv, struct dma_buf_ops *ops,
        if (WARN_ON(!priv || !ops
                          || !ops->map_dma_buf
                          || !ops->unmap_dma_buf
-                         || !ops->release)) {
+                         || !ops->release
+                         || !ops->kmap_atomic
+                         || !ops->kmap)) {
                return ERR_PTR(-EINVAL);
        }
 
@@ -107,17 +109,18 @@ EXPORT_SYMBOL_GPL(dma_buf_export);
 /**
  * dma_buf_fd - returns a file descriptor for the given dma_buf
  * @dmabuf:    [in]    pointer to dma_buf for which fd is required.
+ * @flags:      [in]    flags to give to fd
  *
  * On success, returns an associated 'fd'. Else, returns error.
  */
-int dma_buf_fd(struct dma_buf *dmabuf)
+int dma_buf_fd(struct dma_buf *dmabuf, int flags)
 {
        int error, fd;
 
        if (!dmabuf || !dmabuf->file)
                return -EINVAL;
 
-       error = get_unused_fd();
+       error = get_unused_fd_flags(flags);
        if (error < 0)
                return error;
        fd = error;
@@ -185,17 +188,18 @@ struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
        struct dma_buf_attachment *attach;
        int ret;
 
-       if (WARN_ON(!dmabuf || !dev || !dmabuf->ops))
+       if (WARN_ON(!dmabuf || !dev))
                return ERR_PTR(-EINVAL);
 
        attach = kzalloc(sizeof(struct dma_buf_attachment), GFP_KERNEL);
        if (attach == NULL)
-               goto err_alloc;
-
-       mutex_lock(&dmabuf->lock);
+               return ERR_PTR(-ENOMEM);
 
        attach->dev = dev;
        attach->dmabuf = dmabuf;
+
+       mutex_lock(&dmabuf->lock);
+
        if (dmabuf->ops->attach) {
                ret = dmabuf->ops->attach(dmabuf, dev, attach);
                if (ret)
@@ -206,8 +210,6 @@ struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
        mutex_unlock(&dmabuf->lock);
        return attach;
 
-err_alloc:
-       return ERR_PTR(-ENOMEM);
 err_attach:
        kfree(attach);
        mutex_unlock(&dmabuf->lock);
@@ -224,7 +226,7 @@ EXPORT_SYMBOL_GPL(dma_buf_attach);
  */
 void dma_buf_detach(struct dma_buf *dmabuf, struct dma_buf_attachment *attach)
 {
-       if (WARN_ON(!dmabuf || !attach || !dmabuf->ops))
+       if (WARN_ON(!dmabuf || !attach))
                return;
 
        mutex_lock(&dmabuf->lock);
@@ -255,13 +257,10 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
 
        might_sleep();
 
-       if (WARN_ON(!attach || !attach->dmabuf || !attach->dmabuf->ops))
+       if (WARN_ON(!attach || !attach->dmabuf))
                return ERR_PTR(-EINVAL);
 
-       mutex_lock(&attach->dmabuf->lock);
-       if (attach->dmabuf->ops->map_dma_buf)
-               sg_table = attach->dmabuf->ops->map_dma_buf(attach, direction);
-       mutex_unlock(&attach->dmabuf->lock);
+       sg_table = attach->dmabuf->ops->map_dma_buf(attach, direction);
 
        return sg_table;
 }
@@ -273,19 +272,137 @@ EXPORT_SYMBOL_GPL(dma_buf_map_attachment);
  * dma_buf_ops.
  * @attach:    [in]    attachment to unmap buffer from
  * @sg_table:  [in]    scatterlist info of the buffer to unmap
+ * @direction:  [in]    direction of DMA transfer
  *
  */
 void dma_buf_unmap_attachment(struct dma_buf_attachment *attach,
-                               struct sg_table *sg_table)
+                               struct sg_table *sg_table,
+                               enum dma_data_direction direction)
 {
-       if (WARN_ON(!attach || !attach->dmabuf || !sg_table
-                           || !attach->dmabuf->ops))
+       if (WARN_ON(!attach || !attach->dmabuf || !sg_table))
                return;
 
-       mutex_lock(&attach->dmabuf->lock);
-       if (attach->dmabuf->ops->unmap_dma_buf)
-               attach->dmabuf->ops->unmap_dma_buf(attach, sg_table);
-       mutex_unlock(&attach->dmabuf->lock);
-
+       attach->dmabuf->ops->unmap_dma_buf(attach, sg_table,
+                                               direction);
 }
 EXPORT_SYMBOL_GPL(dma_buf_unmap_attachment);
+
+
+/**
+ * dma_buf_begin_cpu_access - Must be called before accessing a dma_buf from the
+ * cpu in the kernel context. Calls begin_cpu_access to allow exporter-specific
+ * preparations. Coherency is only guaranteed in the specified range for the
+ * specified access direction.
+ * @dma_buf:   [in]    buffer to prepare cpu access for.
+ * @start:     [in]    start of range for cpu access.
+ * @len:       [in]    length of range for cpu access.
+ * @direction: [in]    length of range for cpu access.
+ *
+ * Can return negative error values, returns 0 on success.
+ */
+int dma_buf_begin_cpu_access(struct dma_buf *dmabuf, size_t start, size_t len,
+                            enum dma_data_direction direction)
+{
+       int ret = 0;
+
+       if (WARN_ON(!dmabuf))
+               return -EINVAL;
+
+       if (dmabuf->ops->begin_cpu_access)
+               ret = dmabuf->ops->begin_cpu_access(dmabuf, start, len, direction);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(dma_buf_begin_cpu_access);
+
+/**
+ * dma_buf_end_cpu_access - Must be called after accessing a dma_buf from the
+ * cpu in the kernel context. Calls end_cpu_access to allow exporter-specific
+ * actions. Coherency is only guaranteed in the specified range for the
+ * specified access direction.
+ * @dma_buf:   [in]    buffer to complete cpu access for.
+ * @start:     [in]    start of range for cpu access.
+ * @len:       [in]    length of range for cpu access.
+ * @direction: [in]    length of range for cpu access.
+ *
+ * This call must always succeed.
+ */
+void dma_buf_end_cpu_access(struct dma_buf *dmabuf, size_t start, size_t len,
+                           enum dma_data_direction direction)
+{
+       WARN_ON(!dmabuf);
+
+       if (dmabuf->ops->end_cpu_access)
+               dmabuf->ops->end_cpu_access(dmabuf, start, len, direction);
+}
+EXPORT_SYMBOL_GPL(dma_buf_end_cpu_access);
+
+/**
+ * dma_buf_kmap_atomic - Map a page of the buffer object into kernel address
+ * space. The same restrictions as for kmap_atomic and friends apply.
+ * @dma_buf:   [in]    buffer to map page from.
+ * @page_num:  [in]    page in PAGE_SIZE units to map.
+ *
+ * This call must always succeed, any necessary preparations that might fail
+ * need to be done in begin_cpu_access.
+ */
+void *dma_buf_kmap_atomic(struct dma_buf *dmabuf, unsigned long page_num)
+{
+       WARN_ON(!dmabuf);
+
+       return dmabuf->ops->kmap_atomic(dmabuf, page_num);
+}
+EXPORT_SYMBOL_GPL(dma_buf_kmap_atomic);
+
+/**
+ * dma_buf_kunmap_atomic - Unmap a page obtained by dma_buf_kmap_atomic.
+ * @dma_buf:   [in]    buffer to unmap page from.
+ * @page_num:  [in]    page in PAGE_SIZE units to unmap.
+ * @vaddr:     [in]    kernel space pointer obtained from dma_buf_kmap_atomic.
+ *
+ * This call must always succeed.
+ */
+void dma_buf_kunmap_atomic(struct dma_buf *dmabuf, unsigned long page_num,
+                          void *vaddr)
+{
+       WARN_ON(!dmabuf);
+
+       if (dmabuf->ops->kunmap_atomic)
+               dmabuf->ops->kunmap_atomic(dmabuf, page_num, vaddr);
+}
+EXPORT_SYMBOL_GPL(dma_buf_kunmap_atomic);
+
+/**
+ * dma_buf_kmap - Map a page of the buffer object into kernel address space. The
+ * same restrictions as for kmap and friends apply.
+ * @dma_buf:   [in]    buffer to map page from.
+ * @page_num:  [in]    page in PAGE_SIZE units to map.
+ *
+ * This call must always succeed, any necessary preparations that might fail
+ * need to be done in begin_cpu_access.
+ */
+void *dma_buf_kmap(struct dma_buf *dmabuf, unsigned long page_num)
+{
+       WARN_ON(!dmabuf);
+
+       return dmabuf->ops->kmap(dmabuf, page_num);
+}
+EXPORT_SYMBOL_GPL(dma_buf_kmap);
+
+/**
+ * dma_buf_kunmap - Unmap a page obtained by dma_buf_kmap.
+ * @dma_buf:   [in]    buffer to unmap page from.
+ * @page_num:  [in]    page in PAGE_SIZE units to unmap.
+ * @vaddr:     [in]    kernel space pointer obtained from dma_buf_kmap.
+ *
+ * This call must always succeed.
+ */
+void dma_buf_kunmap(struct dma_buf *dmabuf, unsigned long page_num,
+                   void *vaddr)
+{
+       WARN_ON(!dmabuf);
+
+       if (dmabuf->ops->kunmap)
+               dmabuf->ops->kunmap(dmabuf, page_num, vaddr);
+}
+EXPORT_SYMBOL_GPL(dma_buf_kunmap);
index 744f078..76a0823 100644 (file)
@@ -202,7 +202,6 @@ static int slow_floppy;
 
 #include <asm/dma.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 
 static int FLOPPY_IRQ = 6;
 static int FLOPPY_DMA = 2;
index b52c9ca..bf397bf 100644 (file)
@@ -44,7 +44,6 @@
 #define HD_IRQ 14
 
 #define REALLY_SLOW_IO
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
index 864db10..061427a 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/kthread.h>
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/types.h>
 
 #include <linux/nbd.h>
index 48e8fee..9dcf76a 100644 (file)
@@ -839,10 +839,7 @@ static struct vio_driver vdc_port_driver = {
        .id_table       = vdc_port_match,
        .probe          = vdc_port_probe,
        .remove         = vdc_port_remove,
-       .driver         = {
-               .name   = "vdc_port",
-               .owner  = THIS_MODULE,
-       }
+       .name           = "vdc_port",
 };
 
 static int __init vdc_init(void)
index 51a9727..ff54052 100644 (file)
@@ -52,7 +52,6 @@
 #include <linux/io.h>
 #include <linux/gfp.h>
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/dma.h>
 
index 9c09d6f..308c859 100644 (file)
@@ -39,7 +39,6 @@
 #include <linux/serial.h>
 #include <linux/serial_reg.h>
 #include <linux/bitops.h>
-#include <asm/system.h>
 #include <asm/io.h>
 
 #include <linux/device.h>
index 194224d..c4fc2f3 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/serial.h>
 #include <linux/serial_reg.h>
 #include <linux/bitops.h>
-#include <asm/system.h>
 #include <asm/io.h>
 
 #include <pcmcia/cistpl.h>
index 049c059..6e8d961 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/serial.h>
 #include <linux/serial_reg.h>
 #include <linux/bitops.h>
-#include <asm/system.h>
 #include <asm/io.h>
 
 #include <pcmcia/cistpl.h>
index f4837a8..57501ca 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/kthread.h>
 #include <linux/delay.h>
 
-#include <asm/system.h>
 
 /*
  * The apm_bios device is one of the misc char devices.
index ed8303f..7d34b20 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/uaccess.h>
 #include <linux/io.h>
 
-#include <asm/system.h>
 #include <asm/rtc.h>
 #if defined(CONFIG_M32R)
 #include <asm/m32r.h>
index 53c524e..a082d00 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/efi.h>
 #include <linux/uaccess.h>
 
-#include <asm/system.h>
 
 #define EFI_RTC_VERSION                "0.4"
 
index f773a9d..21cb980 100644 (file)
@@ -56,7 +56,6 @@
 #include <linux/workqueue.h>
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/rtc.h>
 
 /*
index 0833896..3845ab4 100644 (file)
@@ -36,7 +36,6 @@
 #include <linux/io.h>
 
 #include <asm/current.h>
-#include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/div64.h>
 
index 2aa3977..9eb360f 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/errno.h>
-#include <asm/system.h>
 #include <linux/poll.h>
 #include <linux/sched.h>
 #include <linux/spinlock.h>
index 5c1820c..2c29942 100644 (file)
@@ -33,7 +33,6 @@
 
 #include <linux/module.h>
 #include <linux/errno.h>
-#include <asm/system.h>
 #include <linux/poll.h>
 #include <linux/sched.h>
 #include <linux/seq_file.h>
index 3c7e693..1e638ff 100644 (file)
@@ -41,7 +41,6 @@
 
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <asm/system.h>
 #include <linux/sched.h>
 #include <linux/seq_file.h>
 #include <linux/timer.h>
index 99dc1da..7ed356e 100644 (file)
 #endif
 
 static DEFINE_MUTEX(ipmi_watchdog_mutex);
-static int nowayout = WATCHDOG_NOWAYOUT;
+static bool nowayout = WATCHDOG_NOWAYOUT;
 
 static ipmi_user_t watchdog_user;
 static int watchdog_ifnum;
@@ -320,7 +320,7 @@ module_param(start_now, int, 0444);
 MODULE_PARM_DESC(start_now, "Set to 1 to start the watchdog as"
                 "soon as the driver is loaded.");
 
-module_param(nowayout, int, 0644);
+module_param(nowayout, bool, 0644);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
                 "(default=CONFIG_WATCHDOG_NOWAYOUT)");
 
index f434856..0fbf1a7 100644 (file)
 
 #include <asm/irq.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 
 /* if you have more than 8 printers, remember to increase LP_NO */
 #define LP_NO 8
index 1aeaaba..47ff7e4 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/slab.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/sn/addrs.h>
 #include <asm/sn/intr.h>
index 5c0d96a..8b78750 100644 (file)
@@ -44,7 +44,6 @@
 #include <linux/slab.h>
 #include <linux/numa.h>
 #include <asm/page.h>
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <linux/atomic.h>
 #include <asm/tlbflush.h>
index 492dbfb..881c9e5 100644 (file)
@@ -56,7 +56,6 @@
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/irq.h>
 #include "smapi.h"
 #include "mwavedd.h"
index eaade8a..9df78e2 100644 (file)
 #include <linux/uaccess.h>
 #include <linux/mutex.h>
 
-#include <asm/system.h>
 
 static DEFINE_MUTEX(nvram_mutex);
 static DEFINE_SPINLOCK(nvram_state_lock);
index bf586ae..d45c334 100644 (file)
@@ -32,7 +32,6 @@
 #include <asm/io.h>
 #include <asm/leds.h>
 #include <asm/mach-types.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 
 /*****************************************************************************/
index f6453df..0a484b4 100644 (file)
@@ -60,7 +60,6 @@
 #include <linux/ioctl.h>
 #include <linux/synclink.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/dma.h>
index 872e09a..af94374 100644 (file)
@@ -83,7 +83,6 @@
 #include <linux/ratelimit.h>
 
 #include <asm/current.h>
-#include <asm/system.h>
 
 #ifdef CONFIG_X86
 #include <asm/hpet.h>
index 1ee8ce7..45713f0 100644 (file)
@@ -54,7 +54,6 @@
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include <linux/sonypi.h>
 
index e90e1c7..31ba11c 100644 (file)
@@ -89,7 +89,6 @@
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 
 #ifdef CONFIG_OF
 /* For open firmware. */
index 9b3cd08..165e1fe 100644 (file)
@@ -8,3 +8,40 @@ config HAVE_CLK_PREPARE
 
 config HAVE_MACH_CLKDEV
        bool
+
+config COMMON_CLK
+       bool
+       select HAVE_CLK_PREPARE
+       ---help---
+         The common clock framework is a single definition of struct
+         clk, useful across many platforms, as well as an
+         implementation of the clock API in include/linux/clk.h.
+         Architectures utilizing the common struct clk should select
+         this option.
+
+menu "Common Clock Framework"
+       depends on COMMON_CLK
+
+config COMMON_CLK_DISABLE_UNUSED
+       bool "Disabled unused clocks at boot"
+       depends on COMMON_CLK
+       ---help---
+         Traverses the entire clock tree and disables any clocks that are
+         enabled in hardware but have not been enabled by any device drivers.
+         This saves power and keeps the software model of the clock in line
+         with reality.
+
+         If in doubt, say "N".
+
+config COMMON_CLK_DEBUG
+       bool "DebugFS representation of clock tree"
+       depends on COMMON_CLK
+       select DEBUG_FS
+       ---help---
+         Creates a directory hierchy in debugfs for visualizing the clk
+         tree structure.  Each directory contains read-only members
+         that export information specific to that clk node: clk_rate,
+         clk_flags, clk_prepare_count, clk_enable_count &
+         clk_notifier_count.
+
+endmenu
index 07613fa..1f736bc 100644 (file)
@@ -1,2 +1,4 @@
 
 obj-$(CONFIG_CLKDEV_LOOKUP)    += clkdev.o
+obj-$(CONFIG_COMMON_CLK)       += clk.o clk-fixed-rate.o clk-gate.o \
+                                  clk-mux.o clk-divider.o
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
new file mode 100644 (file)
index 0000000..d5ac6a7
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2011 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
+ * Copyright (C) 2011 Richard Zhao, Linaro <richard.zhao@linaro.org>
+ * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd <mturquette@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Adjustable divider clock implementation
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/string.h>
+
+/*
+ * DOC: basic adjustable divider clock that cannot gate
+ *
+ * Traits of this clock:
+ * prepare - clk_prepare only ensures that parents are prepared
+ * enable - clk_enable only ensures that parents are enabled
+ * rate - rate is adjustable.  clk->rate = parent->rate / divisor
+ * parent - fixed parent.  No clk_set_parent support
+ */
+
+#define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw)
+
+#define div_mask(d)    ((1 << (d->width)) - 1)
+
+static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
+               unsigned long parent_rate)
+{
+       struct clk_divider *divider = to_clk_divider(hw);
+       unsigned int div;
+
+       div = readl(divider->reg) >> divider->shift;
+       div &= div_mask(divider);
+
+       if (!(divider->flags & CLK_DIVIDER_ONE_BASED))
+               div++;
+
+       return parent_rate / div;
+}
+EXPORT_SYMBOL_GPL(clk_divider_recalc_rate);
+
+/*
+ * The reverse of DIV_ROUND_UP: The maximum number which
+ * divided by m is r
+ */
+#define MULT_ROUND_UP(r, m) ((r) * (m) + (m) - 1)
+
+static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
+               unsigned long *best_parent_rate)
+{
+       struct clk_divider *divider = to_clk_divider(hw);
+       int i, bestdiv = 0;
+       unsigned long parent_rate, best = 0, now, maxdiv;
+
+       if (!rate)
+               rate = 1;
+
+       maxdiv = (1 << divider->width);
+
+       if (divider->flags & CLK_DIVIDER_ONE_BASED)
+               maxdiv--;
+
+       if (!best_parent_rate) {
+               parent_rate = __clk_get_rate(__clk_get_parent(hw->clk));
+               bestdiv = DIV_ROUND_UP(parent_rate, rate);
+               bestdiv = bestdiv == 0 ? 1 : bestdiv;
+               bestdiv = bestdiv > maxdiv ? maxdiv : bestdiv;
+               return bestdiv;
+       }
+
+       /*
+        * The maximum divider we can use without overflowing
+        * unsigned long in rate * i below
+        */
+       maxdiv = min(ULONG_MAX / rate, maxdiv);
+
+       for (i = 1; i <= maxdiv; i++) {
+               parent_rate = __clk_round_rate(__clk_get_parent(hw->clk),
+                               MULT_ROUND_UP(rate, i));
+               now = parent_rate / i;
+               if (now <= rate && now > best) {
+                       bestdiv = i;
+                       best = now;
+                       *best_parent_rate = parent_rate;
+               }
+       }
+
+       if (!bestdiv) {
+               bestdiv = (1 << divider->width);
+               if (divider->flags & CLK_DIVIDER_ONE_BASED)
+                       bestdiv--;
+               *best_parent_rate = __clk_round_rate(__clk_get_parent(hw->clk), 1);
+       }
+
+       return bestdiv;
+}
+
+static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
+                               unsigned long *prate)
+{
+       int div;
+       div = clk_divider_bestdiv(hw, rate, prate);
+
+       if (prate)
+               return *prate / div;
+       else {
+               unsigned long r;
+               r = __clk_get_rate(__clk_get_parent(hw->clk));
+               return r / div;
+       }
+}
+EXPORT_SYMBOL_GPL(clk_divider_round_rate);
+
+static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate)
+{
+       struct clk_divider *divider = to_clk_divider(hw);
+       unsigned int div;
+       unsigned long flags = 0;
+       u32 val;
+
+       div = __clk_get_rate(__clk_get_parent(hw->clk)) / rate;
+
+       if (!(divider->flags & CLK_DIVIDER_ONE_BASED))
+               div--;
+
+       if (div > div_mask(divider))
+               div = div_mask(divider);
+
+       if (divider->lock)
+               spin_lock_irqsave(divider->lock, flags);
+
+       val = readl(divider->reg);
+       val &= ~(div_mask(divider) << divider->shift);
+       val |= div << divider->shift;
+       writel(val, divider->reg);
+
+       if (divider->lock)
+               spin_unlock_irqrestore(divider->lock, flags);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(clk_divider_set_rate);
+
+struct clk_ops clk_divider_ops = {
+       .recalc_rate = clk_divider_recalc_rate,
+       .round_rate = clk_divider_round_rate,
+       .set_rate = clk_divider_set_rate,
+};
+EXPORT_SYMBOL_GPL(clk_divider_ops);
+
+struct clk *clk_register_divider(struct device *dev, const char *name,
+               const char *parent_name, unsigned long flags,
+               void __iomem *reg, u8 shift, u8 width,
+               u8 clk_divider_flags, spinlock_t *lock)
+{
+       struct clk_divider *div;
+       struct clk *clk;
+
+       div = kzalloc(sizeof(struct clk_divider), GFP_KERNEL);
+
+       if (!div) {
+               pr_err("%s: could not allocate divider clk\n", __func__);
+               return NULL;
+       }
+
+       /* struct clk_divider assignments */
+       div->reg = reg;
+       div->shift = shift;
+       div->width = width;
+       div->flags = clk_divider_flags;
+       div->lock = lock;
+
+       if (parent_name) {
+               div->parent[0] = kstrdup(parent_name, GFP_KERNEL);
+               if (!div->parent[0])
+                       goto out;
+       }
+
+       clk = clk_register(dev, name,
+                       &clk_divider_ops, &div->hw,
+                       div->parent,
+                       (parent_name ? 1 : 0),
+                       flags);
+       if (clk)
+               return clk;
+
+out:
+       kfree(div->parent[0]);
+       kfree(div);
+
+       return NULL;
+}
diff --git a/drivers/clk/clk-fixed-rate.c b/drivers/clk/clk-fixed-rate.c
new file mode 100644 (file)
index 0000000..90c79fb
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
+ * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd <mturquette@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Fixed rate clock implementation
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/err.h>
+
+/*
+ * DOC: basic fixed-rate clock that cannot gate
+ *
+ * Traits of this clock:
+ * prepare - clk_(un)prepare only ensures parents are prepared
+ * enable - clk_enable only ensures parents are enabled
+ * rate - rate is always a fixed value.  No clk_set_rate support
+ * parent - fixed parent.  No clk_set_parent support
+ */
+
+#define to_clk_fixed_rate(_hw) container_of(_hw, struct clk_fixed_rate, hw)
+
+static unsigned long clk_fixed_rate_recalc_rate(struct clk_hw *hw,
+               unsigned long parent_rate)
+{
+       return to_clk_fixed_rate(hw)->fixed_rate;
+}
+EXPORT_SYMBOL_GPL(clk_fixed_rate_recalc_rate);
+
+struct clk_ops clk_fixed_rate_ops = {
+       .recalc_rate = clk_fixed_rate_recalc_rate,
+};
+EXPORT_SYMBOL_GPL(clk_fixed_rate_ops);
+
+struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
+               const char *parent_name, unsigned long flags,
+               unsigned long fixed_rate)
+{
+       struct clk_fixed_rate *fixed;
+       char **parent_names = NULL;
+       u8 len;
+
+       fixed = kzalloc(sizeof(struct clk_fixed_rate), GFP_KERNEL);
+
+       if (!fixed) {
+               pr_err("%s: could not allocate fixed clk\n", __func__);
+               return ERR_PTR(-ENOMEM);
+       }
+
+       /* struct clk_fixed_rate assignments */
+       fixed->fixed_rate = fixed_rate;
+
+       if (parent_name) {
+               parent_names = kmalloc(sizeof(char *), GFP_KERNEL);
+
+               if (! parent_names)
+                       goto out;
+
+               len = sizeof(char) * strlen(parent_name);
+
+               parent_names[0] = kmalloc(len, GFP_KERNEL);
+
+               if (!parent_names[0])
+                       goto out;
+
+               strncpy(parent_names[0], parent_name, len);
+       }
+
+out:
+       return clk_register(dev, name,
+                       &clk_fixed_rate_ops, &fixed->hw,
+                       parent_names,
+                       (parent_name ? 1 : 0),
+                       flags);
+}
diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
new file mode 100644 (file)
index 0000000..b5902e2
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
+ * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd <mturquette@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Gated clock implementation
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/string.h>
+
+/**
+ * DOC: basic gatable clock which can gate and ungate it's ouput
+ *
+ * Traits of this clock:
+ * prepare - clk_(un)prepare only ensures parent is (un)prepared
+ * enable - clk_enable and clk_disable are functional & control gating
+ * rate - inherits rate from parent.  No clk_set_rate support
+ * parent - fixed parent.  No clk_set_parent support
+ */
+
+#define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw)
+
+static void clk_gate_set_bit(struct clk_gate *gate)
+{
+       u32 reg;
+       unsigned long flags = 0;
+
+       if (gate->lock)
+               spin_lock_irqsave(gate->lock, flags);
+
+       reg = readl(gate->reg);
+       reg |= BIT(gate->bit_idx);
+       writel(reg, gate->reg);
+
+       if (gate->lock)
+               spin_unlock_irqrestore(gate->lock, flags);
+}
+
+static void clk_gate_clear_bit(struct clk_gate *gate)
+{
+       u32 reg;
+       unsigned long flags = 0;
+
+       if (gate->lock)
+               spin_lock_irqsave(gate->lock, flags);
+
+       reg = readl(gate->reg);
+       reg &= ~BIT(gate->bit_idx);
+       writel(reg, gate->reg);
+
+       if (gate->lock)
+               spin_unlock_irqrestore(gate->lock, flags);
+}
+
+static int clk_gate_enable(struct clk_hw *hw)
+{
+       struct clk_gate *gate = to_clk_gate(hw);
+
+       if (gate->flags & CLK_GATE_SET_TO_DISABLE)
+               clk_gate_clear_bit(gate);
+       else
+               clk_gate_set_bit(gate);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(clk_gate_enable);
+
+static void clk_gate_disable(struct clk_hw *hw)
+{
+       struct clk_gate *gate = to_clk_gate(hw);
+
+       if (gate->flags & CLK_GATE_SET_TO_DISABLE)
+               clk_gate_set_bit(gate);
+       else
+               clk_gate_clear_bit(gate);
+}
+EXPORT_SYMBOL_GPL(clk_gate_disable);
+
+static int clk_gate_is_enabled(struct clk_hw *hw)
+{
+       u32 reg;
+       struct clk_gate *gate = to_clk_gate(hw);
+
+       reg = readl(gate->reg);
+
+       /* if a set bit disables this clk, flip it before masking */
+       if (gate->flags & CLK_GATE_SET_TO_DISABLE)
+               reg ^= BIT(gate->bit_idx);
+
+       reg &= BIT(gate->bit_idx);
+
+       return reg ? 1 : 0;
+}
+EXPORT_SYMBOL_GPL(clk_gate_is_enabled);
+
+struct clk_ops clk_gate_ops = {
+       .enable = clk_gate_enable,
+       .disable = clk_gate_disable,
+       .is_enabled = clk_gate_is_enabled,
+};
+EXPORT_SYMBOL_GPL(clk_gate_ops);
+
+struct clk *clk_register_gate(struct device *dev, const char *name,
+               const char *parent_name, unsigned long flags,
+               void __iomem *reg, u8 bit_idx,
+               u8 clk_gate_flags, spinlock_t *lock)
+{
+       struct clk_gate *gate;
+       struct clk *clk;
+
+       gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
+
+       if (!gate) {
+               pr_err("%s: could not allocate gated clk\n", __func__);
+               return NULL;
+       }
+
+       /* struct clk_gate assignments */
+       gate->reg = reg;
+       gate->bit_idx = bit_idx;
+       gate->flags = clk_gate_flags;
+       gate->lock = lock;
+
+       if (parent_name) {
+               gate->parent[0] = kstrdup(parent_name, GFP_KERNEL);
+               if (!gate->parent[0])
+                       goto out;
+       }
+
+       clk = clk_register(dev, name,
+                       &clk_gate_ops, &gate->hw,
+                       gate->parent,
+                       (parent_name ? 1 : 0),
+                       flags);
+       if (clk)
+               return clk;
+out:
+       kfree(gate->parent[0]);
+       kfree(gate);
+
+       return NULL;
+}
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
new file mode 100644 (file)
index 0000000..c71ad1f
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2011 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
+ * Copyright (C) 2011 Richard Zhao, Linaro <richard.zhao@linaro.org>
+ * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd <mturquette@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Simple multiplexer clock implementation
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/err.h>
+
+/*
+ * DOC: basic adjustable multiplexer clock that cannot gate
+ *
+ * Traits of this clock:
+ * prepare - clk_prepare only ensures that parents are prepared
+ * enable - clk_enable only ensures that parents are enabled
+ * rate - rate is only affected by parent switching.  No clk_set_rate support
+ * parent - parent is adjustable through clk_set_parent
+ */
+
+#define to_clk_mux(_hw) container_of(_hw, struct clk_mux, hw)
+
+static u8 clk_mux_get_parent(struct clk_hw *hw)
+{
+       struct clk_mux *mux = to_clk_mux(hw);
+       u32 val;
+
+       /*
+        * FIXME need a mux-specific flag to determine if val is bitwise or numeric
+        * e.g. sys_clkin_ck's clksel field is 3 bits wide, but ranges from 0x1
+        * to 0x7 (index starts at one)
+        * OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so
+        * val = 0x4 really means "bit 2, index starts at bit 0"
+        */
+       val = readl(mux->reg) >> mux->shift;
+       val &= (1 << mux->width) - 1;
+
+       if (val && (mux->flags & CLK_MUX_INDEX_BIT))
+               val = ffs(val) - 1;
+
+       if (val && (mux->flags & CLK_MUX_INDEX_ONE))
+               val--;
+
+       if (val >= __clk_get_num_parents(hw->clk))
+               return -EINVAL;
+
+       return val;
+}
+EXPORT_SYMBOL_GPL(clk_mux_get_parent);
+
+static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+       struct clk_mux *mux = to_clk_mux(hw);
+       u32 val;
+       unsigned long flags = 0;
+
+       if (mux->flags & CLK_MUX_INDEX_BIT)
+               index = (1 << ffs(index));
+
+       if (mux->flags & CLK_MUX_INDEX_ONE)
+               index++;
+
+       if (mux->lock)
+               spin_lock_irqsave(mux->lock, flags);
+
+       val = readl(mux->reg);
+       val &= ~(((1 << mux->width) - 1) << mux->shift);
+       val |= index << mux->shift;
+       writel(val, mux->reg);
+
+       if (mux->lock)
+               spin_unlock_irqrestore(mux->lock, flags);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(clk_mux_set_parent);
+
+struct clk_ops clk_mux_ops = {
+       .get_parent = clk_mux_get_parent,
+       .set_parent = clk_mux_set_parent,
+};
+EXPORT_SYMBOL_GPL(clk_mux_ops);
+
+struct clk *clk_register_mux(struct device *dev, const char *name,
+               char **parent_names, u8 num_parents, unsigned long flags,
+               void __iomem *reg, u8 shift, u8 width,
+               u8 clk_mux_flags, spinlock_t *lock)
+{
+       struct clk_mux *mux;
+
+       mux = kmalloc(sizeof(struct clk_mux), GFP_KERNEL);
+
+       if (!mux) {
+               pr_err("%s: could not allocate mux clk\n", __func__);
+               return ERR_PTR(-ENOMEM);
+       }
+
+       /* struct clk_mux assignments */
+       mux->reg = reg;
+       mux->shift = shift;
+       mux->width = width;
+       mux->flags = clk_mux_flags;
+       mux->lock = lock;
+
+       return clk_register(dev, name, &clk_mux_ops, &mux->hw,
+                       parent_names, num_parents, flags);
+}
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
new file mode 100644 (file)
index 0000000..9cf6f59
--- /dev/null
@@ -0,0 +1,1461 @@
+/*
+ * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
+ * Copyright (C) 2011-2012 Linaro Ltd <mturquette@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Standard functionality for the common clock API.  See Documentation/clk.txt
+ */
+
+#include <linux/clk-private.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+#include <linux/err.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+
+static DEFINE_SPINLOCK(enable_lock);
+static DEFINE_MUTEX(prepare_lock);
+
+static HLIST_HEAD(clk_root_list);
+static HLIST_HEAD(clk_orphan_list);
+static LIST_HEAD(clk_notifier_list);
+
+/***        debugfs support        ***/
+
+#ifdef CONFIG_COMMON_CLK_DEBUG
+#include <linux/debugfs.h>
+
+static struct dentry *rootdir;
+static struct dentry *orphandir;
+static int inited = 0;
+
+/* caller must hold prepare_lock */
+static int clk_debug_create_one(struct clk *clk, struct dentry *pdentry)
+{
+       struct dentry *d;
+       int ret = -ENOMEM;
+
+       if (!clk || !pdentry) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       d = debugfs_create_dir(clk->name, pdentry);
+       if (!d)
+               goto out;
+
+       clk->dentry = d;
+
+       d = debugfs_create_u32("clk_rate", S_IRUGO, clk->dentry,
+                       (u32 *)&clk->rate);
+       if (!d)
+               goto err_out;
+
+       d = debugfs_create_x32("clk_flags", S_IRUGO, clk->dentry,
+                       (u32 *)&clk->flags);
+       if (!d)
+               goto err_out;
+
+       d = debugfs_create_u32("clk_prepare_count", S_IRUGO, clk->dentry,
+                       (u32 *)&clk->prepare_count);
+       if (!d)
+               goto err_out;
+
+       d = debugfs_create_u32("clk_enable_count", S_IRUGO, clk->dentry,
+                       (u32 *)&clk->enable_count);
+       if (!d)
+               goto err_out;
+
+       d = debugfs_create_u32("clk_notifier_count", S_IRUGO, clk->dentry,
+                       (u32 *)&clk->notifier_count);
+       if (!d)
+               goto err_out;
+
+       ret = 0;
+       goto out;
+
+err_out:
+       debugfs_remove(clk->dentry);
+out:
+       return ret;
+}
+
+/* caller must hold prepare_lock */
+static int clk_debug_create_subtree(struct clk *clk, struct dentry *pdentry)
+{
+       struct clk *child;
+       struct hlist_node *tmp;
+       int ret = -EINVAL;;
+
+       if (!clk || !pdentry)
+               goto out;
+
+       ret = clk_debug_create_one(clk, pdentry);
+
+       if (ret)
+               goto out;
+
+       hlist_for_each_entry(child, tmp, &clk->children, child_node)
+               clk_debug_create_subtree(child, clk->dentry);
+
+       ret = 0;
+out:
+       return ret;
+}
+
+/**
+ * clk_debug_register - add a clk node to the debugfs clk tree
+ * @clk: the clk being added to the debugfs clk tree
+ *
+ * Dynamically adds a clk to the debugfs clk tree if debugfs has been
+ * initialized.  Otherwise it bails out early since the debugfs clk tree
+ * will be created lazily by clk_debug_init as part of a late_initcall.
+ *
+ * Caller must hold prepare_lock.  Only clk_init calls this function (so
+ * far) so this is taken care.
+ */
+static int clk_debug_register(struct clk *clk)
+{
+       struct clk *parent;
+       struct dentry *pdentry;
+       int ret = 0;
+
+       if (!inited)
+               goto out;
+
+       parent = clk->parent;
+
+       /*
+        * Check to see if a clk is a root clk.  Also check that it is
+        * safe to add this clk to debugfs
+        */
+       if (!parent)
+               if (clk->flags & CLK_IS_ROOT)
+                       pdentry = rootdir;
+               else
+                       pdentry = orphandir;
+       else
+               if (parent->dentry)
+                       pdentry = parent->dentry;
+               else
+                       goto out;
+
+       ret = clk_debug_create_subtree(clk, pdentry);
+
+out:
+       return ret;
+}
+
+/**
+ * clk_debug_init - lazily create the debugfs clk tree visualization
+ *
+ * clks are often initialized very early during boot before memory can
+ * be dynamically allocated and well before debugfs is setup.
+ * clk_debug_init walks the clk tree hierarchy while holding
+ * prepare_lock and creates the topology as part of a late_initcall,
+ * thus insuring that clks initialized very early will still be
+ * represented in the debugfs clk tree.  This function should only be
+ * called once at boot-time, and all other clks added dynamically will
+ * be done so with clk_debug_register.
+ */
+static int __init clk_debug_init(void)
+{
+       struct clk *clk;
+       struct hlist_node *tmp;
+
+       rootdir = debugfs_create_dir("clk", NULL);
+
+       if (!rootdir)
+               return -ENOMEM;
+
+       orphandir = debugfs_create_dir("orphans", rootdir);
+
+       if (!orphandir)
+               return -ENOMEM;
+
+       mutex_lock(&prepare_lock);
+
+       hlist_for_each_entry(clk, tmp, &clk_root_list, child_node)
+               clk_debug_create_subtree(clk, rootdir);
+
+       hlist_for_each_entry(clk, tmp, &clk_orphan_list, child_node)
+               clk_debug_create_subtree(clk, orphandir);
+
+       inited = 1;
+
+       mutex_unlock(&prepare_lock);
+
+       return 0;
+}
+late_initcall(clk_debug_init);
+#else
+static inline int clk_debug_register(struct clk *clk) { return 0; }
+#endif /* CONFIG_COMMON_CLK_DEBUG */
+
+#ifdef CONFIG_COMMON_CLK_DISABLE_UNUSED
+/* caller must hold prepare_lock */
+static void clk_disable_unused_subtree(struct clk *clk)
+{
+       struct clk *child;
+       struct hlist_node *tmp;
+       unsigned long flags;
+
+       if (!clk)
+               goto out;
+
+       hlist_for_each_entry(child, tmp, &clk->children, child_node)
+               clk_disable_unused_subtree(child);
+
+       spin_lock_irqsave(&enable_lock, flags);
+
+       if (clk->enable_count)
+               goto unlock_out;
+
+       if (clk->flags & CLK_IGNORE_UNUSED)
+               goto unlock_out;
+
+       if (__clk_is_enabled(clk) && clk->ops->disable)
+               clk->ops->disable(clk->hw);
+
+unlock_out:
+       spin_unlock_irqrestore(&enable_lock, flags);
+
+out:
+       return;
+}
+
+static int clk_disable_unused(void)
+{
+       struct clk *clk;
+       struct hlist_node *tmp;
+
+       mutex_lock(&prepare_lock);
+
+       hlist_for_each_entry(clk, tmp, &clk_root_list, child_node)
+               clk_disable_unused_subtree(clk);
+
+       hlist_for_each_entry(clk, tmp, &clk_orphan_list, child_node)
+               clk_disable_unused_subtree(clk);
+
+       mutex_unlock(&prepare_lock);
+
+       return 0;
+}
+late_initcall(clk_disable_unused);
+#else
+static inline int clk_disable_unused(struct clk *clk) { return 0; }
+#endif /* CONFIG_COMMON_CLK_DISABLE_UNUSED */
+
+/***    helper functions   ***/
+
+inline const char *__clk_get_name(struct clk *clk)
+{
+       return !clk ? NULL : clk->name;
+}
+
+inline struct clk_hw *__clk_get_hw(struct clk *clk)
+{
+       return !clk ? NULL : clk->hw;
+}
+
+inline u8 __clk_get_num_parents(struct clk *clk)
+{
+       return !clk ? -EINVAL : clk->num_parents;
+}
+
+inline struct clk *__clk_get_parent(struct clk *clk)
+{
+       return !clk ? NULL : clk->parent;
+}
+
+inline int __clk_get_enable_count(struct clk *clk)
+{
+       return !clk ? -EINVAL : clk->enable_count;
+}
+
+inline int __clk_get_prepare_count(struct clk *clk)
+{
+       return !clk ? -EINVAL : clk->prepare_count;
+}
+
+unsigned long __clk_get_rate(struct clk *clk)
+{
+       unsigned long ret;
+
+       if (!clk) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       ret = clk->rate;
+
+       if (clk->flags & CLK_IS_ROOT)
+               goto out;
+
+       if (!clk->parent)
+               ret = -ENODEV;
+
+out:
+       return ret;
+}
+
+inline unsigned long __clk_get_flags(struct clk *clk)
+{
+       return !clk ? -EINVAL : clk->flags;
+}
+
+int __clk_is_enabled(struct clk *clk)
+{
+       int ret;
+
+       if (!clk)
+               return -EINVAL;
+
+       /*
+        * .is_enabled is only mandatory for clocks that gate
+        * fall back to software usage counter if .is_enabled is missing
+        */
+       if (!clk->ops->is_enabled) {
+               ret = clk->enable_count ? 1 : 0;
+               goto out;
+       }
+
+       ret = clk->ops->is_enabled(clk->hw);
+out:
+       return ret;
+}
+
+static struct clk *__clk_lookup_subtree(const char *name, struct clk *clk)
+{
+       struct clk *child;
+       struct clk *ret;
+       struct hlist_node *tmp;
+
+       if (!strcmp(clk->name, name))
+               return clk;
+
+       hlist_for_each_entry(child, tmp, &clk->children, child_node) {
+               ret = __clk_lookup_subtree(name, child);
+               if (ret)
+                       return ret;
+       }
+
+       return NULL;
+}
+
+struct clk *__clk_lookup(const char *name)
+{
+       struct clk *root_clk;
+       struct clk *ret;
+       struct hlist_node *tmp;
+
+       if (!name)
+               return NULL;
+
+       /* search the 'proper' clk tree first */
+       hlist_for_each_entry(root_clk, tmp, &clk_root_list, child_node) {
+               ret = __clk_lookup_subtree(name, root_clk);
+               if (ret)
+                       return ret;
+       }
+
+       /* if not found, then search the orphan tree */
+       hlist_for_each_entry(root_clk, tmp, &clk_orphan_list, child_node) {
+               ret = __clk_lookup_subtree(name, root_clk);
+               if (ret)
+                       return ret;
+       }
+
+       return NULL;
+}
+
+/***        clk api        ***/
+
+void __clk_unprepare(struct clk *clk)
+{
+       if (!clk)
+               return;
+
+       if (WARN_ON(clk->prepare_count == 0))
+               return;
+
+       if (--clk->prepare_count > 0)
+               return;
+
+       WARN_ON(clk->enable_count > 0);
+
+       if (clk->ops->unprepare)
+               clk->ops->unprepare(clk->hw);
+
+       __clk_unprepare(clk->parent);
+}
+
+/**
+ * clk_unprepare - undo preparation of a clock source
+ * @clk: the clk being unprepare
+ *
+ * clk_unprepare may sleep, which differentiates it from clk_disable.  In a
+ * simple case, clk_unprepare can be used instead of clk_disable to gate a clk
+ * if the operation may sleep.  One example is a clk which is accessed over
+ * I2c.  In the complex case a clk gate operation may require a fast and a slow
+ * part.  It is this reason that clk_unprepare and clk_disable are not mutually
+ * exclusive.  In fact clk_disable must be called before clk_unprepare.
+ */
+void clk_unprepare(struct clk *clk)
+{
+       mutex_lock(&prepare_lock);
+       __clk_unprepare(clk);
+       mutex_unlock(&prepare_lock);
+}
+EXPORT_SYMBOL_GPL(clk_unprepare);
+
+int __clk_prepare(struct clk *clk)
+{
+       int ret = 0;
+
+       if (!clk)
+               return 0;
+
+       if (clk->prepare_count == 0) {
+               ret = __clk_prepare(clk->parent);
+               if (ret)
+                       return ret;
+
+               if (clk->ops->prepare) {
+                       ret = clk->ops->prepare(clk->hw);
+                       if (ret) {
+                               __clk_unprepare(clk->parent);
+                               return ret;
+                       }
+               }
+       }
+
+       clk->prepare_count++;
+
+       return 0;
+}
+
+/**
+ * clk_prepare - prepare a clock source
+ * @clk: the clk being prepared
+ *
+ * clk_prepare may sleep, which differentiates it from clk_enable.  In a simple
+ * case, clk_prepare can be used instead of clk_enable to ungate a clk if the
+ * operation may sleep.  One example is a clk which is accessed over I2c.  In
+ * the complex case a clk ungate operation may require a fast and a slow part.
+ * It is this reason that clk_prepare and clk_enable are not mutually
+ * exclusive.  In fact clk_prepare must be called before clk_enable.
+ * Returns 0 on success, -EERROR otherwise.
+ */
+int clk_prepare(struct clk *clk)
+{
+       int ret;
+
+       mutex_lock(&prepare_lock);
+       ret = __clk_prepare(clk);
+       mutex_unlock(&prepare_lock);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(clk_prepare);
+
+static void __clk_disable(struct clk *clk)
+{
+       if (!clk)
+               return;
+
+       if (WARN_ON(clk->enable_count == 0))
+               return;
+
+       if (--clk->enable_count > 0)
+               return;
+
+       if (clk->ops->disable)
+               clk->ops->disable(clk->hw);
+
+       __clk_disable(clk->parent);
+}
+
+/**
+ * clk_disable - gate a clock
+ * @clk: the clk being gated
+ *
+ * clk_disable must not sleep, which differentiates it from clk_unprepare.  In
+ * a simple case, clk_disable can be used instead of clk_unprepare to gate a
+ * clk if the operation is fast and will never sleep.  One example is a
+ * SoC-internal clk which is controlled via simple register writes.  In the
+ * complex case a clk gate operation may require a fast and a slow part.  It is
+ * this reason that clk_unprepare and clk_disable are not mutually exclusive.
+ * In fact clk_disable must be called before clk_unprepare.
+ */
+void clk_disable(struct clk *clk)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&enable_lock, flags);
+       __clk_disable(clk);
+       spin_unlock_irqrestore(&enable_lock, flags);
+}
+EXPORT_SYMBOL_GPL(clk_disable);
+
+static int __clk_enable(struct clk *clk)
+{
+       int ret = 0;
+
+       if (!clk)
+               return 0;
+
+       if (WARN_ON(clk->prepare_count == 0))
+               return -ESHUTDOWN;
+
+       if (clk->enable_count == 0) {
+               ret = __clk_enable(clk->parent);
+
+               if (ret)
+                       return ret;
+
+               if (clk->ops->enable) {
+                       ret = clk->ops->enable(clk->hw);
+                       if (ret) {
+                               __clk_disable(clk->parent);
+                               return ret;
+                       }
+               }
+       }
+
+       clk->enable_count++;
+       return 0;
+}
+
+/**
+ * clk_enable - ungate a clock
+ * @clk: the clk being ungated
+ *
+ * clk_enable must not sleep, which differentiates it from clk_prepare.  In a
+ * simple case, clk_enable can be used instead of clk_prepare to ungate a clk
+ * if the operation will never sleep.  One example is a SoC-internal clk which
+ * is controlled via simple register writes.  In the complex case a clk ungate
+ * operation may require a fast and a slow part.  It is this reason that
+ * clk_enable and clk_prepare are not mutually exclusive.  In fact clk_prepare
+ * must be called before clk_enable.  Returns 0 on success, -EERROR
+ * otherwise.
+ */
+int clk_enable(struct clk *clk)
+{
+       unsigned long flags;
+       int ret;
+
+       spin_lock_irqsave(&enable_lock, flags);
+       ret = __clk_enable(clk);
+       spin_unlock_irqrestore(&enable_lock, flags);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(clk_enable);
+
+/**
+ * clk_get_rate - return the rate of clk
+ * @clk: the clk whose rate is being returned
+ *
+ * Simply returns the cached rate of the clk.  Does not query the hardware.  If
+ * clk is NULL then returns -EINVAL.
+ */
+unsigned long clk_get_rate(struct clk *clk)
+{
+       unsigned long rate;
+
+       mutex_lock(&prepare_lock);
+       rate = __clk_get_rate(clk);
+       mutex_unlock(&prepare_lock);
+
+       return rate;
+}
+EXPORT_SYMBOL_GPL(clk_get_rate);
+
+/**
+ * __clk_round_rate - round the given rate for a clk
+ * @clk: round the rate of this clock
+ *
+ * Caller must hold prepare_lock.  Useful for clk_ops such as .set_rate
+ */
+unsigned long __clk_round_rate(struct clk *clk, unsigned long rate)
+{
+       unsigned long unused;
+
+       if (!clk)
+               return -EINVAL;
+
+       if (!clk->ops->round_rate)
+               return clk->rate;
+
+       if (clk->flags & CLK_SET_RATE_PARENT)
+               return clk->ops->round_rate(clk->hw, rate, &unused);
+       else
+               return clk->ops->round_rate(clk->hw, rate, NULL);
+}
+
+/**
+ * clk_round_rate - round the given rate for a clk
+ * @clk: the clk for which we are rounding a rate
+ * @rate: the rate which is to be rounded
+ *
+ * Takes in a rate as input and rounds it to a rate that the clk can actually
+ * use which is then returned.  If clk doesn't support round_rate operation
+ * then the parent rate is returned.
+ */
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+       unsigned long ret;
+
+       mutex_lock(&prepare_lock);
+       ret = __clk_round_rate(clk, rate);
+       mutex_unlock(&prepare_lock);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(clk_round_rate);
+
+/**
+ * __clk_notify - call clk notifier chain
+ * @clk: struct clk * that is changing rate
+ * @msg: clk notifier type (see include/linux/clk.h)
+ * @old_rate: old clk rate
+ * @new_rate: new clk rate
+ *
+ * Triggers a notifier call chain on the clk rate-change notification
+ * for 'clk'.  Passes a pointer to the struct clk and the previous
+ * and current rates to the notifier callback.  Intended to be called by
+ * internal clock code only.  Returns NOTIFY_DONE from the last driver
+ * called if all went well, or NOTIFY_STOP or NOTIFY_BAD immediately if
+ * a driver returns that.
+ */
+static int __clk_notify(struct clk *clk, unsigned long msg,
+               unsigned long old_rate, unsigned long new_rate)
+{
+       struct clk_notifier *cn;
+       struct clk_notifier_data cnd;
+       int ret = NOTIFY_DONE;
+
+       cnd.clk = clk;
+       cnd.old_rate = old_rate;
+       cnd.new_rate = new_rate;
+
+       list_for_each_entry(cn, &clk_notifier_list, node) {
+               if (cn->clk == clk) {
+                       ret = srcu_notifier_call_chain(&cn->notifier_head, msg,
+                                       &cnd);
+                       break;
+               }
+       }
+
+       return ret;
+}
+
+/**
+ * __clk_recalc_rates
+ * @clk: first clk in the subtree
+ * @msg: notification type (see include/linux/clk.h)
+ *
+ * Walks the subtree of clks starting with clk and recalculates rates as it
+ * goes.  Note that if a clk does not implement the .recalc_rate callback then
+ * it is assumed that the clock will take on the rate of it's parent.
+ *
+ * clk_recalc_rates also propagates the POST_RATE_CHANGE notification,
+ * if necessary.
+ *
+ * Caller must hold prepare_lock.
+ */
+static void __clk_recalc_rates(struct clk *clk, unsigned long msg)
+{
+       unsigned long old_rate;
+       unsigned long parent_rate = 0;
+       struct hlist_node *tmp;
+       struct clk *child;
+
+       old_rate = clk->rate;
+
+       if (clk->parent)
+               parent_rate = clk->parent->rate;
+
+       if (clk->ops->recalc_rate)
+               clk->rate = clk->ops->recalc_rate(clk->hw, parent_rate);
+       else
+               clk->rate = parent_rate;
+
+       /*
+        * ignore NOTIFY_STOP and NOTIFY_BAD return values for POST_RATE_CHANGE
+        * & ABORT_RATE_CHANGE notifiers
+        */
+       if (clk->notifier_count && msg)
+               __clk_notify(clk, msg, old_rate, clk->rate);
+
+       hlist_for_each_entry(child, tmp, &clk->children, child_node)
+               __clk_recalc_rates(child, msg);
+}
+
+/**
+ * __clk_speculate_rates
+ * @clk: first clk in the subtree
+ * @parent_rate: the "future" rate of clk's parent
+ *
+ * Walks the subtree of clks starting with clk, speculating rates as it
+ * goes and firing off PRE_RATE_CHANGE notifications as necessary.
+ *
+ * Unlike clk_recalc_rates, clk_speculate_rates exists only for sending
+ * pre-rate change notifications and returns early if no clks in the
+ * subtree have subscribed to the notifications.  Note that if a clk does not
+ * implement the .recalc_rate callback then it is assumed that the clock will
+ * take on the rate of it's parent.
+ *
+ * Caller must hold prepare_lock.
+ */
+static int __clk_speculate_rates(struct clk *clk, unsigned long parent_rate)
+{
+       struct hlist_node *tmp;
+       struct clk *child;
+       unsigned long new_rate;
+       int ret = NOTIFY_DONE;
+
+       if (clk->ops->recalc_rate)
+               new_rate = clk->ops->recalc_rate(clk->hw, parent_rate);
+       else
+               new_rate = parent_rate;
+
+       /* abort the rate change if a driver returns NOTIFY_BAD */
+       if (clk->notifier_count)
+               ret = __clk_notify(clk, PRE_RATE_CHANGE, clk->rate, new_rate);
+
+       if (ret == NOTIFY_BAD)
+               goto out;
+
+       hlist_for_each_entry(child, tmp, &clk->children, child_node) {
+               ret = __clk_speculate_rates(child, new_rate);
+               if (ret == NOTIFY_BAD)
+                       break;
+       }
+
+out:
+       return ret;
+}
+
+static void clk_calc_subtree(struct clk *clk, unsigned long new_rate)
+{
+       struct clk *child;
+       struct hlist_node *tmp;
+
+       clk->new_rate = new_rate;
+
+       hlist_for_each_entry(child, tmp, &clk->children, child_node) {
+               if (child->ops->recalc_rate)
+                       child->new_rate = child->ops->recalc_rate(child->hw, new_rate);
+               else
+                       child->new_rate = new_rate;
+               clk_calc_subtree(child, child->new_rate);
+       }
+}
+
+/*
+ * calculate the new rates returning the topmost clock that has to be
+ * changed.
+ */
+static struct clk *clk_calc_new_rates(struct clk *clk, unsigned long rate)
+{
+       struct clk *top = clk;
+       unsigned long best_parent_rate = clk->parent->rate;
+       unsigned long new_rate;
+
+       if (!clk->ops->round_rate && !(clk->flags & CLK_SET_RATE_PARENT)) {
+               clk->new_rate = clk->rate;
+               return NULL;
+       }
+
+       if (!clk->ops->round_rate && (clk->flags & CLK_SET_RATE_PARENT)) {
+               top = clk_calc_new_rates(clk->parent, rate);
+               new_rate = clk->new_rate = clk->parent->new_rate;
+
+               goto out;
+       }
+
+       if (clk->flags & CLK_SET_RATE_PARENT)
+               new_rate = clk->ops->round_rate(clk->hw, rate, &best_parent_rate);
+       else
+               new_rate = clk->ops->round_rate(clk->hw, rate, NULL);
+
+       if (best_parent_rate != clk->parent->rate) {
+               top = clk_calc_new_rates(clk->parent, best_parent_rate);
+
+               goto out;
+       }
+
+out:
+       clk_calc_subtree(clk, new_rate);
+
+       return top;
+}
+
+/*
+ * Notify about rate changes in a subtree. Always walk down the whole tree
+ * so that in case of an error we can walk down the whole tree again and
+ * abort the change.
+ */
+static struct clk *clk_propagate_rate_change(struct clk *clk, unsigned long event)
+{
+       struct hlist_node *tmp;
+       struct clk *child, *fail_clk = NULL;
+       int ret = NOTIFY_DONE;
+
+       if (clk->rate == clk->new_rate)
+               return 0;
+
+       if (clk->notifier_count) {
+               ret = __clk_notify(clk, event, clk->rate, clk->new_rate);
+               if (ret == NOTIFY_BAD)
+                       fail_clk = clk;
+       }
+
+       hlist_for_each_entry(child, tmp, &clk->children, child_node) {
+               clk = clk_propagate_rate_change(child, event);
+               if (clk)
+                       fail_clk = clk;
+       }
+
+       return fail_clk;
+}
+
+/*
+ * walk down a subtree and set the new rates notifying the rate
+ * change on the way
+ */
+static void clk_change_rate(struct clk *clk)
+{
+       struct clk *child;
+       unsigned long old_rate;
+       struct hlist_node *tmp;
+
+       old_rate = clk->rate;
+
+       if (clk->ops->set_rate)
+               clk->ops->set_rate(clk->hw, clk->new_rate);
+
+       if (clk->ops->recalc_rate)
+               clk->rate = clk->ops->recalc_rate(clk->hw,
+                               clk->parent->rate);
+       else
+               clk->rate = clk->parent->rate;
+
+       if (clk->notifier_count && old_rate != clk->rate)
+               __clk_notify(clk, POST_RATE_CHANGE, old_rate, clk->rate);
+
+       hlist_for_each_entry(child, tmp, &clk->children, child_node)
+               clk_change_rate(child);
+}
+
+/**
+ * clk_set_rate - specify a new rate for clk
+ * @clk: the clk whose rate is being changed
+ * @rate: the new rate for clk
+ *
+ * In the simplest case clk_set_rate will only change the rate of clk.
+ *
+ * If clk has the CLK_SET_RATE_GATE flag set and it is enabled this call
+ * will fail; only when the clk is disabled will it be able to change
+ * its rate.
+ *
+ * Setting the CLK_SET_RATE_PARENT flag allows clk_set_rate to
+ * recursively propagate up to clk's parent; whether or not this happens
+ * depends on the outcome of clk's .round_rate implementation.  If
+ * *parent_rate is 0 after calling .round_rate then upstream parent
+ * propagation is ignored.  If *parent_rate comes back with a new rate
+ * for clk's parent then we propagate up to clk's parent and set it's
+ * rate.  Upward propagation will continue until either a clk does not
+ * support the CLK_SET_RATE_PARENT flag or .round_rate stops requesting
+ * changes to clk's parent_rate.  If there is a failure during upstream
+ * propagation then clk_set_rate will unwind and restore each clk's rate
+ * that had been successfully changed.  Afterwards a rate change abort
+ * notification will be propagated downstream, starting from the clk
+ * that failed.
+ *
+ * At the end of all of the rate setting, clk_set_rate internally calls
+ * __clk_recalc_rates and propagates the rate changes downstream,
+ * starting from the highest clk whose rate was changed.  This has the
+ * added benefit of propagating post-rate change notifiers.
+ *
+ * Note that while post-rate change and rate change abort notifications
+ * are guaranteed to be sent to a clk only once per call to
+ * clk_set_rate, pre-change notifications will be sent for every clk
+ * whose rate is changed.  Stacking pre-change notifications is noisy
+ * for the drivers subscribed to them, but this allows drivers to react
+ * to intermediate clk rate changes up until the point where the final
+ * rate is achieved at the end of upstream propagation.
+ *
+ * Returns 0 on success, -EERROR otherwise.
+ */
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+       struct clk *top, *fail_clk;
+       int ret = 0;
+
+       /* prevent racing with updates to the clock topology */
+       mutex_lock(&prepare_lock);
+
+       /* bail early if nothing to do */
+       if (rate == clk->rate)
+               goto out;
+
+       /* calculate new rates and get the topmost changed clock */
+       top = clk_calc_new_rates(clk, rate);
+       if (!top) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       /* notify that we are about to change rates */
+       fail_clk = clk_propagate_rate_change(top, PRE_RATE_CHANGE);
+       if (fail_clk) {
+               pr_warn("%s: failed to set %s rate\n", __func__,
+                               fail_clk->name);
+               clk_propagate_rate_change(top, ABORT_RATE_CHANGE);
+               ret = -EBUSY;
+               goto out;
+       }
+
+       /* change the rates */
+       clk_change_rate(top);
+
+       mutex_unlock(&prepare_lock);
+
+       return 0;
+out:
+       mutex_unlock(&prepare_lock);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(clk_set_rate);
+
+/**
+ * clk_get_parent - return the parent of a clk
+ * @clk: the clk whose parent gets returned
+ *
+ * Simply returns clk->parent.  Returns NULL if clk is NULL.
+ */
+struct clk *clk_get_parent(struct clk *clk)
+{
+       struct clk *parent;
+
+       mutex_lock(&prepare_lock);
+       parent = __clk_get_parent(clk);
+       mutex_unlock(&prepare_lock);
+
+       return parent;
+}
+EXPORT_SYMBOL_GPL(clk_get_parent);
+
+/*
+ * .get_parent is mandatory for clocks with multiple possible parents.  It is
+ * optional for single-parent clocks.  Always call .get_parent if it is
+ * available and WARN if it is missing for multi-parent clocks.
+ *
+ * For single-parent clocks without .get_parent, first check to see if the
+ * .parents array exists, and if so use it to avoid an expensive tree
+ * traversal.  If .parents does not exist then walk the tree with __clk_lookup.
+ */
+static struct clk *__clk_init_parent(struct clk *clk)
+{
+       struct clk *ret = NULL;
+       u8 index;
+
+       /* handle the trivial cases */
+
+       if (!clk->num_parents)
+               goto out;
+
+       if (clk->num_parents == 1) {
+               if (IS_ERR_OR_NULL(clk->parent))
+                       ret = clk->parent = __clk_lookup(clk->parent_names[0]);
+               ret = clk->parent;
+               goto out;
+       }
+
+       if (!clk->ops->get_parent) {
+               WARN(!clk->ops->get_parent,
+                       "%s: multi-parent clocks must implement .get_parent\n",
+                       __func__);
+               goto out;
+       };
+
+       /*
+        * Do our best to cache parent clocks in clk->parents.  This prevents
+        * unnecessary and expensive calls to __clk_lookup.  We don't set
+        * clk->parent here; that is done by the calling function
+        */
+
+       index = clk->ops->get_parent(clk->hw);
+
+       if (!clk->parents)
+               clk->parents =
+                       kmalloc((sizeof(struct clk*) * clk->num_parents),
+                                       GFP_KERNEL);
+
+       if (!clk->parents)
+               ret = __clk_lookup(clk->parent_names[index]);
+       else if (!clk->parents[index])
+               ret = clk->parents[index] =
+                       __clk_lookup(clk->parent_names[index]);
+       else
+               ret = clk->parents[index];
+
+out:
+       return ret;
+}
+
+void __clk_reparent(struct clk *clk, struct clk *new_parent)
+{
+#ifdef CONFIG_COMMON_CLK_DEBUG
+       struct dentry *d;
+       struct dentry *new_parent_d;
+#endif
+
+       if (!clk || !new_parent)
+               return;
+
+       hlist_del(&clk->child_node);
+
+       if (new_parent)
+               hlist_add_head(&clk->child_node, &new_parent->children);
+       else
+               hlist_add_head(&clk->child_node, &clk_orphan_list);
+
+#ifdef CONFIG_COMMON_CLK_DEBUG
+       if (!inited)
+               goto out;
+
+       if (new_parent)
+               new_parent_d = new_parent->dentry;
+       else
+               new_parent_d = orphandir;
+
+       d = debugfs_rename(clk->dentry->d_parent, clk->dentry,
+                       new_parent_d, clk->name);
+       if (d)
+               clk->dentry = d;
+       else
+               pr_debug("%s: failed to rename debugfs entry for %s\n",
+                               __func__, clk->name);
+out:
+#endif
+
+       clk->parent = new_parent;
+
+       __clk_recalc_rates(clk, POST_RATE_CHANGE);
+}
+
+static int __clk_set_parent(struct clk *clk, struct clk *parent)
+{
+       struct clk *old_parent;
+       unsigned long flags;
+       int ret = -EINVAL;
+       u8 i;
+
+       old_parent = clk->parent;
+
+       /* find index of new parent clock using cached parent ptrs */
+       for (i = 0; i < clk->num_parents; i++)
+               if (clk->parents[i] == parent)
+                       break;
+
+       /*
+        * find index of new parent clock using string name comparison
+        * also try to cache the parent to avoid future calls to __clk_lookup
+        */
+       if (i == clk->num_parents)
+               for (i = 0; i < clk->num_parents; i++)
+                       if (!strcmp(clk->parent_names[i], parent->name)) {
+                               clk->parents[i] = __clk_lookup(parent->name);
+                               break;
+                       }
+
+       if (i == clk->num_parents) {
+               pr_debug("%s: clock %s is not a possible parent of clock %s\n",
+                               __func__, parent->name, clk->name);
+               goto out;
+       }
+
+       /* migrate prepare and enable */
+       if (clk->prepare_count)
+               __clk_prepare(parent);
+
+       /* FIXME replace with clk_is_enabled(clk) someday */
+       spin_lock_irqsave(&enable_lock, flags);
+       if (clk->enable_count)
+               __clk_enable(parent);
+       spin_unlock_irqrestore(&enable_lock, flags);
+
+       /* change clock input source */
+       ret = clk->ops->set_parent(clk->hw, i);
+
+       /* clean up old prepare and enable */
+       spin_lock_irqsave(&enable_lock, flags);
+       if (clk->enable_count)
+               __clk_disable(old_parent);
+       spin_unlock_irqrestore(&enable_lock, flags);
+
+       if (clk->prepare_count)
+               __clk_unprepare(old_parent);
+
+out:
+       return ret;
+}
+
+/**
+ * clk_set_parent - switch the parent of a mux clk
+ * @clk: the mux clk whose input we are switching
+ * @parent: the new input to clk
+ *
+ * Re-parent clk to use parent as it's new input source.  If clk has the
+ * CLK_SET_PARENT_GATE flag set then clk must be gated for this
+ * operation to succeed.  After successfully changing clk's parent
+ * clk_set_parent will update the clk topology, sysfs topology and
+ * propagate rate recalculation via __clk_recalc_rates.  Returns 0 on
+ * success, -EERROR otherwise.
+ */
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+       int ret = 0;
+
+       if (!clk || !clk->ops)
+               return -EINVAL;
+
+       if (!clk->ops->set_parent)
+               return -ENOSYS;
+
+       /* prevent racing with updates to the clock topology */
+       mutex_lock(&prepare_lock);
+
+       if (clk->parent == parent)
+               goto out;
+
+       /* propagate PRE_RATE_CHANGE notifications */
+       if (clk->notifier_count)
+               ret = __clk_speculate_rates(clk, parent->rate);
+
+       /* abort if a driver objects */
+       if (ret == NOTIFY_STOP)
+               goto out;
+
+       /* only re-parent if the clock is not in use */
+       if ((clk->flags & CLK_SET_PARENT_GATE) && clk->prepare_count)
+               ret = -EBUSY;
+       else
+               ret = __clk_set_parent(clk, parent);
+
+       /* propagate ABORT_RATE_CHANGE if .set_parent failed */
+       if (ret) {
+               __clk_recalc_rates(clk, ABORT_RATE_CHANGE);
+               goto out;
+       }
+
+       /* propagate rate recalculation downstream */
+       __clk_reparent(clk, parent);
+
+out:
+       mutex_unlock(&prepare_lock);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(clk_set_parent);
+
+/**
+ * __clk_init - initialize the data structures in a struct clk
+ * @dev:       device initializing this clk, placeholder for now
+ * @clk:       clk being initialized
+ *
+ * Initializes the lists in struct clk, queries the hardware for the
+ * parent and rate and sets them both.
+ *
+ * Any struct clk passed into __clk_init must have the following members
+ * populated:
+ *     .name
+ *     .ops
+ *     .hw
+ *     .parent_names
+ *     .num_parents
+ *     .flags
+ *
+ * Essentially, everything that would normally be passed into clk_register is
+ * assumed to be initialized already in __clk_init.  The other members may be
+ * populated, but are optional.
+ *
+ * __clk_init is only exposed via clk-private.h and is intended for use with
+ * very large numbers of clocks that need to be statically initialized.  It is
+ * a layering violation to include clk-private.h from any code which implements
+ * a clock's .ops; as such any statically initialized clock data MUST be in a
+ * separate C file from the logic that implements it's operations.
+ */
+void __clk_init(struct device *dev, struct clk *clk)
+{
+       int i;
+       struct clk *orphan;
+       struct hlist_node *tmp, *tmp2;
+
+       if (!clk)
+               return;
+
+       mutex_lock(&prepare_lock);
+
+       /* check to see if a clock with this name is already registered */
+       if (__clk_lookup(clk->name))
+               goto out;
+
+       /* throw a WARN if any entries in parent_names are NULL */
+       for (i = 0; i < clk->num_parents; i++)
+               WARN(!clk->parent_names[i],
+                               "%s: invalid NULL in %s's .parent_names\n",
+                               __func__, clk->name);
+
+       /*
+        * Allocate an array of struct clk *'s to avoid unnecessary string
+        * look-ups of clk's possible parents.  This can fail for clocks passed
+        * in to clk_init during early boot; thus any access to clk->parents[]
+        * must always check for a NULL pointer and try to populate it if
+        * necessary.
+        *
+        * If clk->parents is not NULL we skip this entire block.  This allows
+        * for clock drivers to statically initialize clk->parents.
+        */
+       if (clk->num_parents && !clk->parents) {
+               clk->parents = kmalloc((sizeof(struct clk*) * clk->num_parents),
+                               GFP_KERNEL);
+               /*
+                * __clk_lookup returns NULL for parents that have not been
+                * clk_init'd; thus any access to clk->parents[] must check
+                * for a NULL pointer.  We can always perform lazy lookups for
+                * missing parents later on.
+                */
+               if (clk->parents)
+                       for (i = 0; i < clk->num_parents; i++)
+                               clk->parents[i] =
+                                       __clk_lookup(clk->parent_names[i]);
+       }
+
+       clk->parent = __clk_init_parent(clk);
+
+       /*
+        * Populate clk->parent if parent has already been __clk_init'd.  If
+        * parent has not yet been __clk_init'd then place clk in the orphan
+        * list.  If clk has set the CLK_IS_ROOT flag then place it in the root
+        * clk list.
+        *
+        * Every time a new clk is clk_init'd then we walk the list of orphan
+        * clocks and re-parent any that are children of the clock currently
+        * being clk_init'd.
+        */
+       if (clk->parent)
+               hlist_add_head(&clk->child_node,
+                               &clk->parent->children);
+       else if (clk->flags & CLK_IS_ROOT)
+               hlist_add_head(&clk->child_node, &clk_root_list);
+       else
+               hlist_add_head(&clk->child_node, &clk_orphan_list);
+
+       /*
+        * Set clk's rate.  The preferred method is to use .recalc_rate.  For
+        * simple clocks and lazy developers the default fallback is to use the
+        * parent's rate.  If a clock doesn't have a parent (or is orphaned)
+        * then rate is set to zero.
+        */
+       if (clk->ops->recalc_rate)
+               clk->rate = clk->ops->recalc_rate(clk->hw,
+                               __clk_get_rate(clk->parent));
+       else if (clk->parent)
+               clk->rate = clk->parent->rate;
+       else
+               clk->rate = 0;
+
+       /*
+        * walk the list of orphan clocks and reparent any that are children of
+        * this clock
+        */
+       hlist_for_each_entry_safe(orphan, tmp, tmp2, &clk_orphan_list, child_node)
+               for (i = 0; i < orphan->num_parents; i++)
+                       if (!strcmp(clk->name, orphan->parent_names[i])) {
+                               __clk_reparent(orphan, clk);
+                               break;
+                       }
+
+       /*
+        * optional platform-specific magic
+        *
+        * The .init callback is not used by any of the basic clock types, but
+        * exists for weird hardware that must perform initialization magic.
+        * Please consider other ways of solving initialization problems before
+        * using this callback, as it's use is discouraged.
+        */
+       if (clk->ops->init)
+               clk->ops->init(clk->hw);
+
+       clk_debug_register(clk);
+
+out:
+       mutex_unlock(&prepare_lock);
+
+       return;
+}
+
+/**
+ * clk_register - allocate a new clock, register it and return an opaque cookie
+ * @dev: device that is registering this clock
+ * @name: clock name
+ * @ops: operations this clock supports
+ * @hw: link to hardware-specific clock data
+ * @parent_names: array of string names for all possible parents
+ * @num_parents: number of possible parents
+ * @flags: framework-level hints and quirks
+ *
+ * clk_register is the primary interface for populating the clock tree with new
+ * clock nodes.  It returns a pointer to the newly allocated struct clk which
+ * cannot be dereferenced by driver code but may be used in conjuction with the
+ * rest of the clock API.
+ */
+struct clk *clk_register(struct device *dev, const char *name,
+               const struct clk_ops *ops, struct clk_hw *hw,
+               char **parent_names, u8 num_parents, unsigned long flags)
+{
+       struct clk *clk;
+
+       clk = kzalloc(sizeof(*clk), GFP_KERNEL);
+       if (!clk)
+               return NULL;
+
+       clk->name = name;
+       clk->ops = ops;
+       clk->hw = hw;
+       clk->flags = flags;
+       clk->parent_names = parent_names;
+       clk->num_parents = num_parents;
+       hw->clk = clk;
+
+       __clk_init(dev, clk);
+
+       return clk;
+}
+EXPORT_SYMBOL_GPL(clk_register);
+
+/***        clk rate change notifiers        ***/
+
+/**
+ * clk_notifier_register - add a clk rate change notifier
+ * @clk: struct clk * to watch
+ * @nb: struct notifier_block * with callback info
+ *
+ * Request notification when clk's rate changes.  This uses an SRCU
+ * notifier because we want it to block and notifier unregistrations are
+ * uncommon.  The callbacks associated with the notifier must not
+ * re-enter into the clk framework by calling any top-level clk APIs;
+ * this will cause a nested prepare_lock mutex.
+ *
+ * Pre-change notifier callbacks will be passed the current, pre-change
+ * rate of the clk via struct clk_notifier_data.old_rate.  The new,
+ * post-change rate of the clk is passed via struct
+ * clk_notifier_data.new_rate.
+ *
+ * Post-change notifiers will pass the now-current, post-change rate of
+ * the clk in both struct clk_notifier_data.old_rate and struct
+ * clk_notifier_data.new_rate.
+ *
+ * Abort-change notifiers are effectively the opposite of pre-change
+ * notifiers: the original pre-change clk rate is passed in via struct
+ * clk_notifier_data.new_rate and the failed post-change rate is passed
+ * in via struct clk_notifier_data.old_rate.
+ *
+ * clk_notifier_register() must be called from non-atomic context.
+ * Returns -EINVAL if called with null arguments, -ENOMEM upon
+ * allocation failure; otherwise, passes along the return value of
+ * srcu_notifier_chain_register().
+ */
+int clk_notifier_register(struct clk *clk, struct notifier_block *nb)
+{
+       struct clk_notifier *cn;
+       int ret = -ENOMEM;
+
+       if (!clk || !nb)
+               return -EINVAL;
+
+       mutex_lock(&prepare_lock);
+
+       /* search the list of notifiers for this clk */
+       list_for_each_entry(cn, &clk_notifier_list, node)
+               if (cn->clk == clk)
+                       break;
+
+       /* if clk wasn't in the notifier list, allocate new clk_notifier */
+       if (cn->clk != clk) {
+               cn = kzalloc(sizeof(struct clk_notifier), GFP_KERNEL);
+               if (!cn)
+                       goto out;
+
+               cn->clk = clk;
+               srcu_init_notifier_head(&cn->notifier_head);
+
+               list_add(&cn->node, &clk_notifier_list);
+       }
+
+       ret = srcu_notifier_chain_register(&cn->notifier_head, nb);
+
+       clk->notifier_count++;
+
+out:
+       mutex_unlock(&prepare_lock);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(clk_notifier_register);
+
+/**
+ * clk_notifier_unregister - remove a clk rate change notifier
+ * @clk: struct clk *
+ * @nb: struct notifier_block * with callback info
+ *
+ * Request no further notification for changes to 'clk' and frees memory
+ * allocated in clk_notifier_register.
+ *
+ * Returns -EINVAL if called with null arguments; otherwise, passes
+ * along the return value of srcu_notifier_chain_unregister().
+ */
+int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb)
+{
+       struct clk_notifier *cn = NULL;
+       int ret = -EINVAL;
+
+       if (!clk || !nb)
+               return -EINVAL;
+
+       mutex_lock(&prepare_lock);
+
+       list_for_each_entry(cn, &clk_notifier_list, node)
+               if (cn->clk == clk)
+                       break;
+
+       if (cn->clk == clk) {
+               ret = srcu_notifier_chain_unregister(&cn->notifier_head, nb);
+
+               clk->notifier_count--;
+
+               /* XXX the notifier code should handle this better */
+               if (!cn->notifier_head.head) {
+                       srcu_cleanup_notifier_head(&cn->notifier_head);
+                       kfree(cn);
+               }
+
+       } else {
+               ret = -ENOENT;
+       }
+
+       mutex_unlock(&prepare_lock);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(clk_notifier_unregister);
index f500201..a22ffa5 100644 (file)
@@ -22,11 +22,11 @@ static struct cpufreq_frequency_table freq_table[] = {
        },
        [1] = {
                .index = 1,
-               .frequency = 300000,
+               .frequency = 400000,
        },
        [2] = {
                .index = 2,
-               .frequency = 600000,
+               .frequency = 800000,
        },
        [3] = {
                /* Used for MAX_OPP, if available */
@@ -113,12 +113,9 @@ static int __cpuinit db8500_cpufreq_init(struct cpufreq_policy *policy)
 
        BUILD_BUG_ON(ARRAY_SIZE(idx2opp) + 1 != ARRAY_SIZE(freq_table));
 
-       if (!prcmu_is_u8400()) {
-               freq_table[1].frequency = 400000;
-               freq_table[2].frequency = 800000;
-               if (prcmu_has_arm_maxopp())
-                       freq_table[3].frequency = 1000000;
-       }
+       if (prcmu_has_arm_maxopp())
+               freq_table[3].frequency = 1000000;
+
        pr_info("db8500-cpufreq : Available frequencies:\n");
        for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++)
                pr_info("  %d Mhz\n", freq_table[i].frequency/1000);
index 67bbb06..17fa04d 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/module.h>
 #include <linux/regulator/consumer.h>
 
-#include <asm/system.h>
 #include <asm/smp_plat.h>
 #include <asm/cpu.h>
 
index cf7e1ee..334cc2f 100644 (file)
@@ -27,7 +27,6 @@
 
 #include <asm/timer.h>         /* Needed for recalibrate_cpu_khz() */
 #include <asm/msr.h>
-#include <asm/system.h>
 #include <asm/cpu_device_id.h>
 
 #ifdef CONFIG_X86_POWERNOW_K7_ACPI
index 5948a21..fdffa1b 100644 (file)
@@ -215,7 +215,7 @@ config EDAC_I7300
 config EDAC_SBRIDGE
        tristate "Intel Sandy-Bridge Integrated MC"
        depends on EDAC_MM_EDAC && PCI && X86_64 && X86_MCE_INTEL
-       depends on EXPERIMENTAL
+       depends on PCI_MMCONFIG && EXPERIMENTAL
        help
          Support for error detection and correction the Intel
          Sandy Bridge Integrated Memory Controller.
index da09cd7..feef773 100644 (file)
@@ -39,7 +39,7 @@ static LIST_HEAD(mc_devices);
 
 #ifdef CONFIG_EDAC_DEBUG
 
-static void edac_mc_dump_channel(struct channel_info *chan)
+static void edac_mc_dump_channel(struct rank_info *chan)
 {
        debugf4("\tchannel = %p\n", chan);
        debugf4("\tchannel->chan_idx = %d\n", chan->chan_idx);
@@ -156,7 +156,7 @@ struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows,
 {
        struct mem_ctl_info *mci;
        struct csrow_info *csi, *csrow;
-       struct channel_info *chi, *chp, *chan;
+       struct rank_info *chi, *chp, *chan;
        void *pvt;
        unsigned size;
        int row, chn;
@@ -181,7 +181,7 @@ struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows,
         * rather than an imaginary chunk of memory located at address 0.
         */
        csi = (struct csrow_info *)(((char *)mci) + ((unsigned long)csi));
-       chi = (struct channel_info *)(((char *)mci) + ((unsigned long)chi));
+       chi = (struct rank_info *)(((char *)mci) + ((unsigned long)chi));
        pvt = sz_pvt ? (((char *)mci) + ((unsigned long)pvt)) : NULL;
 
        /* setup index and various internal pointers */
index 2e23547..d500749 100644 (file)
@@ -49,7 +49,7 @@
 #define                I5100_FERR_NF_MEM_M6ERR_MASK    (1 << 6)
 #define                I5100_FERR_NF_MEM_M5ERR_MASK    (1 << 5)
 #define                I5100_FERR_NF_MEM_M4ERR_MASK    (1 << 4)
-#define                I5100_FERR_NF_MEM_M1ERR_MASK    1
+#define                I5100_FERR_NF_MEM_M1ERR_MASK    (1 << 1)
 #define                I5100_FERR_NF_MEM_ANY_MASK      \
                        (I5100_FERR_NF_MEM_M16ERR_MASK | \
                        I5100_FERR_NF_MEM_M15ERR_MASK | \
@@ -535,23 +535,20 @@ static void i5100_read_log(struct mem_ctl_info *mci, int chan,
 static void i5100_check_error(struct mem_ctl_info *mci)
 {
        struct i5100_priv *priv = mci->pvt_info;
-       u32 dw;
-
+       u32 dw, dw2;
 
        pci_read_config_dword(priv->mc, I5100_FERR_NF_MEM, &dw);
        if (i5100_ferr_nf_mem_any(dw)) {
-               u32 dw2;
 
                pci_read_config_dword(priv->mc, I5100_NERR_NF_MEM, &dw2);
-               if (dw2)
-                       pci_write_config_dword(priv->mc, I5100_NERR_NF_MEM,
-                                              dw2);
-               pci_write_config_dword(priv->mc, I5100_FERR_NF_MEM, dw);
 
                i5100_read_log(mci, i5100_ferr_nf_mem_chan_indx(dw),
                               i5100_ferr_nf_mem_any(dw),
                               i5100_nerr_nf_mem_any(dw2));
+
+               pci_write_config_dword(priv->mc, I5100_NERR_NF_MEM, dw2);
        }
+       pci_write_config_dword(priv->mc, I5100_FERR_NF_MEM, dw);
 }
 
 /* The i5100 chipset will scrub the entire memory once, then
index 67ec962..1869a10 100644 (file)
@@ -735,7 +735,7 @@ static int i5400_get_devices(struct mem_ctl_info *mci, int dev_idx)
 
        /* Attempt to 'get' the MCH register we want */
        pdev = NULL;
-       while (!pvt->branchmap_werrors || !pvt->fsb_error_regs) {
+       while (1) {
                pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
                                      PCI_DEVICE_ID_INTEL_5400_ERR, pdev);
                if (!pdev) {
@@ -743,23 +743,42 @@ static int i5400_get_devices(struct mem_ctl_info *mci, int dev_idx)
                        i5400_printk(KERN_ERR,
                                "'system address,Process Bus' "
                                "device not found:"
-                               "vendor 0x%x device 0x%x ERR funcs "
+                               "vendor 0x%x device 0x%x ERR func 1 "
                                "(broken BIOS?)\n",
                                PCI_VENDOR_ID_INTEL,
                                PCI_DEVICE_ID_INTEL_5400_ERR);
-                       goto error;
+                       return -ENODEV;
                }
 
-               /* Store device 16 funcs 1 and 2 */
-               switch (PCI_FUNC(pdev->devfn)) {
-               case 1:
-                       pvt->branchmap_werrors = pdev;
-                       break;
-               case 2:
-                       pvt->fsb_error_regs = pdev;
+               /* Store device 16 func 1 */
+               if (PCI_FUNC(pdev->devfn) == 1)
                        break;
+       }
+       pvt->branchmap_werrors = pdev;
+
+       pdev = NULL;
+       while (1) {
+               pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
+                                     PCI_DEVICE_ID_INTEL_5400_ERR, pdev);
+               if (!pdev) {
+                       /* End of list, leave */
+                       i5400_printk(KERN_ERR,
+                               "'system address,Process Bus' "
+                               "device not found:"
+                               "vendor 0x%x device 0x%x ERR func 2 "
+                               "(broken BIOS?)\n",
+                               PCI_VENDOR_ID_INTEL,
+                               PCI_DEVICE_ID_INTEL_5400_ERR);
+
+                       pci_dev_put(pvt->branchmap_werrors);
+                       return -ENODEV;
                }
+
+               /* Store device 16 func 2 */
+               if (PCI_FUNC(pdev->devfn) == 2)
+                       break;
        }
+       pvt->fsb_error_regs = pdev;
 
        debugf1("System Address, processor bus- PCI Bus ID: %s  %x:%x\n",
                pci_name(pvt->system_address),
@@ -778,7 +797,10 @@ static int i5400_get_devices(struct mem_ctl_info *mci, int dev_idx)
                        "MC: 'BRANCH 0' device not found:"
                        "vendor 0x%x device 0x%x Func 0 (broken BIOS?)\n",
                        PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5400_FBD0);
-               goto error;
+
+               pci_dev_put(pvt->fsb_error_regs);
+               pci_dev_put(pvt->branchmap_werrors);
+               return -ENODEV;
        }
 
        /* If this device claims to have more than 2 channels then
@@ -796,14 +818,14 @@ static int i5400_get_devices(struct mem_ctl_info *mci, int dev_idx)
                        "(broken BIOS?)\n",
                        PCI_VENDOR_ID_INTEL,
                        PCI_DEVICE_ID_INTEL_5400_FBD1);
-               goto error;
+
+               pci_dev_put(pvt->branch_0);
+               pci_dev_put(pvt->fsb_error_regs);
+               pci_dev_put(pvt->branchmap_werrors);
+               return -ENODEV;
        }
 
        return 0;
-
-error:
-       i5400_put_devices(mci);
-       return -ENODEV;
 }
 
 /*
index fc75706..d427c69 100644 (file)
@@ -184,7 +184,7 @@ struct ppc4xx_ecc_status {
 
 /* Function Prototypes */
 
-static int ppc4xx_edac_probe(struct platform_device *device)
+static int ppc4xx_edac_probe(struct platform_device *device);
 static int ppc4xx_edac_remove(struct platform_device *device);
 
 /* Global Variables */
@@ -1068,7 +1068,7 @@ ppc4xx_edac_mc_init(struct mem_ctl_info *mci,
 
        mci->mod_name           = PPC4XX_EDAC_MODULE_NAME;
        mci->mod_ver            = PPC4XX_EDAC_MODULE_REVISION;
-       mci->ctl_name           = match->compatible,
+       mci->ctl_name           = ppc4xx_edac_match->compatible,
        mci->dev_name           = np->full_name;
 
        /* Initialize callbacks */
index 3a605f7..a203536 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/mmzone.h>
 #include <linux/smp.h>
 #include <linux/bitmap.h>
+#include <linux/math64.h>
 #include <asm/processor.h>
 #include <asm/mce.h>
 
@@ -670,6 +671,7 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
        u32 reg;
        u64 limit, prv = 0;
        u64 tmp_mb;
+       u32 mb, kb;
        u32 rir_way;
 
        /*
@@ -682,8 +684,9 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
        pvt->tolm = GET_TOLM(reg);
        tmp_mb = (1 + pvt->tolm) >> 20;
 
-       debugf0("TOLM: %Lu.%03Lu GB (0x%016Lx)\n",
-               tmp_mb / 1000, tmp_mb % 1000, (u64)pvt->tolm);
+       mb = div_u64_rem(tmp_mb, 1000, &kb);
+       debugf0("TOLM: %u.%03u GB (0x%016Lx)\n",
+               mb, kb, (u64)pvt->tolm);
 
        /* Address range is already 45:25 */
        pci_read_config_dword(pvt->pci_sad1, TOHM,
@@ -691,8 +694,9 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
        pvt->tohm = GET_TOHM(reg);
        tmp_mb = (1 + pvt->tohm) >> 20;
 
-       debugf0("TOHM: %Lu.%03Lu GB (0x%016Lx)",
-               tmp_mb / 1000, tmp_mb % 1000, (u64)pvt->tohm);
+       mb = div_u64_rem(tmp_mb, 1000, &kb);
+       debugf0("TOHM: %u.%03u GB (0x%016Lx)",
+               mb, kb, (u64)pvt->tohm);
 
        /*
         * Step 2) Get SAD range and SAD Interleave list
@@ -714,10 +718,11 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
                        break;
 
                tmp_mb = (limit + 1) >> 20;
-               debugf0("SAD#%d %s up to %Lu.%03Lu GB (0x%016Lx) %s reg=0x%08x\n",
+               mb = div_u64_rem(tmp_mb, 1000, &kb);
+               debugf0("SAD#%d %s up to %u.%03u GB (0x%016Lx) %s reg=0x%08x\n",
                        n_sads,
                        get_dram_attr(reg),
-                       tmp_mb / 1000, tmp_mb % 1000,
+                       mb, kb,
                        ((u64)tmp_mb) << 20L,
                        INTERLEAVE_MODE(reg) ? "Interleave: 8:6" : "Interleave: [8:6]XOR[18:16]",
                        reg);
@@ -747,8 +752,9 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
                        break;
                tmp_mb = (limit + 1) >> 20;
 
-               debugf0("TAD#%d: up to %Lu.%03Lu GB (0x%016Lx), socket interleave %d, memory interleave %d, TGT: %d, %d, %d, %d, reg=0x%08x\n",
-                       n_tads, tmp_mb / 1000, tmp_mb % 1000,
+               mb = div_u64_rem(tmp_mb, 1000, &kb);
+               debugf0("TAD#%d: up to %u.%03u GB (0x%016Lx), socket interleave %d, memory interleave %d, TGT: %d, %d, %d, %d, reg=0x%08x\n",
+                       n_tads, mb, kb,
                        ((u64)tmp_mb) << 20L,
                        (u32)TAD_SOCK(reg),
                        (u32)TAD_CH(reg),
@@ -757,7 +763,7 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
                        (u32)TAD_TGT2(reg),
                        (u32)TAD_TGT3(reg),
                        reg);
-               prv = tmp_mb;
+               prv = limit;
        }
 
        /*
@@ -771,9 +777,10 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
                                              tad_ch_nilv_offset[j],
                                              &reg);
                        tmp_mb = TAD_OFFSET(reg) >> 20;
-                       debugf0("TAD CH#%d, offset #%d: %Lu.%03Lu GB (0x%016Lx), reg=0x%08x\n",
+                       mb = div_u64_rem(tmp_mb, 1000, &kb);
+                       debugf0("TAD CH#%d, offset #%d: %u.%03u GB (0x%016Lx), reg=0x%08x\n",
                                i, j,
-                               tmp_mb / 1000, tmp_mb % 1000,
+                               mb, kb,
                                ((u64)tmp_mb) << 20L,
                                reg);
                }
@@ -795,9 +802,10 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
 
                        tmp_mb = RIR_LIMIT(reg) >> 20;
                        rir_way = 1 << RIR_WAY(reg);
-                       debugf0("CH#%d RIR#%d, limit: %Lu.%03Lu GB (0x%016Lx), way: %d, reg=0x%08x\n",
+                       mb = div_u64_rem(tmp_mb, 1000, &kb);
+                       debugf0("CH#%d RIR#%d, limit: %u.%03u GB (0x%016Lx), way: %d, reg=0x%08x\n",
                                i, j,
-                               tmp_mb / 1000, tmp_mb % 1000,
+                               mb, kb,
                                ((u64)tmp_mb) << 20L,
                                rir_way,
                                reg);
@@ -808,9 +816,10 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
                                                      &reg);
                                tmp_mb = RIR_OFFSET(reg) << 6;
 
-                               debugf0("CH#%d RIR#%d INTL#%d, offset %Lu.%03Lu GB (0x%016Lx), tgt: %d, reg=0x%08x\n",
+                               mb = div_u64_rem(tmp_mb, 1000, &kb);
+                               debugf0("CH#%d RIR#%d INTL#%d, offset %u.%03u GB (0x%016Lx), tgt: %d, reg=0x%08x\n",
                                        i, j, k,
-                                       tmp_mb / 1000, tmp_mb % 1000,
+                                       mb, kb,
                                        ((u64)tmp_mb) << 20L,
                                        (u32)RIR_RNK_TGT(reg),
                                        reg);
@@ -848,6 +857,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
        u8                      ch_way,sck_way;
        u32                     tad_offset;
        u32                     rir_way;
+       u32                     mb, kb;
        u64                     ch_addr, offset, limit, prv = 0;
 
 
@@ -858,7 +868,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
         * range (e. g. VGA addresses). It is unlikely, however, that the
         * memory controller would generate an error on that range.
         */
-       if ((addr > (u64) pvt->tolm) && (addr < (1L << 32))) {
+       if ((addr > (u64) pvt->tolm) && (addr < (1LL << 32))) {
                sprintf(msg, "Error at TOLM area, on addr 0x%08Lx", addr);
                edac_mc_handle_ce_no_info(mci, msg);
                return -EINVAL;
@@ -913,7 +923,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
                addr,
                limit,
                sad_way + 7,
-               INTERLEAVE_MODE(reg) ? "" : "XOR[18:16]");
+               interleave_mode ? "" : "XOR[18:16]");
        if (interleave_mode)
                idx = ((addr >> 6) ^ (addr >> 16)) & 7;
        else
@@ -1053,7 +1063,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
        ch_addr = addr & 0x7f;
        /* Remove socket wayness and remove 6 bits */
        addr >>= 6;
-       addr /= sck_xch;
+       addr = div_u64(addr, sck_xch);
 #if 0
        /* Divide by channel way */
        addr = addr / ch_way;
@@ -1073,10 +1083,10 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
                        continue;
 
                limit = RIR_LIMIT(reg);
-
-               debugf0("RIR#%d, limit: %Lu.%03Lu GB (0x%016Lx), way: %d\n",
+               mb = div_u64_rem(limit >> 20, 1000, &kb);
+               debugf0("RIR#%d, limit: %u.%03u GB (0x%016Lx), way: %d\n",
                        n_rir,
-                       (limit >> 20) / 1000, (limit >> 20) % 1000,
+                       mb, kb,
                        limit,
                        1 << RIR_WAY(reg));
                if  (ch_addr <= limit)
index 22c6df5..2e6b245 100644 (file)
@@ -44,7 +44,6 @@
 #include <linux/wait.h>
 #include <linux/workqueue.h>
 
-#include <asm/system.h>
 
 #include "core.h"
 
index afa7c83..68109e9 100644 (file)
@@ -40,7 +40,6 @@
 
 #include <linux/atomic.h>
 #include <asm/byteorder.h>
-#include <asm/system.h>
 
 #include "core.h"
 
index 255646f..0de8350 100644 (file)
@@ -31,7 +31,6 @@
 
 #include <linux/atomic.h>
 #include <asm/byteorder.h>
-#include <asm/system.h>
 
 #include "core.h"
 
index 187b3f2..2b54600 100644 (file)
@@ -46,7 +46,6 @@
 
 #include <asm/byteorder.h>
 #include <asm/page.h>
-#include <asm/system.h>
 
 #ifdef CONFIG_PPC_PMAC
 #include <asm/pmac_feature.h>
index 000a29f..b7e65d7 100644 (file)
@@ -52,7 +52,6 @@
 #include <linux/workqueue.h>
 
 #include <asm/byteorder.h>
-#include <asm/system.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
index 0409cf3..edadbda 100644 (file)
@@ -236,6 +236,12 @@ config GPIO_MAX732X_IRQ
          Say yes here to enable the max732x to be used as an interrupt
          controller. It requires the driver to be built in the kernel.
 
+config GPIO_MC9S08DZ60
+       bool "MX35 3DS BOARD MC9S08DZ60 GPIO functions"
+       depends on I2C && MACH_MX35_3DS
+       help
+         Select this to enable the MC9S08DZ60 GPIO driver
+
 config GPIO_PCA953X
        tristate "PCA953x, PCA955x, TCA64xx, and MAX7310 I/O ports"
        depends on I2C
@@ -422,6 +428,14 @@ config GPIO_ML_IOH
          Hub) which is for IVI(In-Vehicle Infotainment) use.
          This driver can access the IOH's GPIO device.
 
+config GPIO_SODAVILLE
+       bool "Intel Sodaville GPIO support"
+       depends on X86 && PCI && OF && BROKEN
+       select GPIO_GENERIC
+       select GENERIC_IRQ_CHIP
+       help
+         Say Y here to support Intel Sodaville GPIO.
+
 config GPIO_TIMBERDALE
        bool "Support for timberdale GPIO IP"
        depends on MFD_TIMBERDALE && HAS_IOMEM
index 9a8fb54..007f54b 100644 (file)
@@ -27,6 +27,7 @@ obj-$(CONFIG_GPIO_MAX7300)    += gpio-max7300.o
 obj-$(CONFIG_GPIO_MAX7301)     += gpio-max7301.o
 obj-$(CONFIG_GPIO_MAX732X)     += gpio-max732x.o
 obj-$(CONFIG_GPIO_MC33880)     += gpio-mc33880.o
+obj-$(CONFIG_GPIO_MC9S08DZ60)  += gpio-mc9s08dz60.o
 obj-$(CONFIG_GPIO_MCP23S08)    += gpio-mcp23s08.o
 obj-$(CONFIG_GPIO_ML_IOH)      += gpio-ml-ioh.o
 obj-$(CONFIG_GPIO_MPC5200)     += gpio-mpc5200.o
@@ -46,6 +47,7 @@ obj-$(CONFIG_GPIO_RDC321X)    += gpio-rdc321x.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_SODAVILLE)   += gpio-sodaville.o
 obj-$(CONFIG_GPIO_STMPE)       += gpio-stmpe.o
 obj-$(CONFIG_GPIO_SX150X)      += gpio-sx150x.o
 obj-$(CONFIG_GPIO_TC3589X)     += gpio-tc3589x.o
index df0d595..3d00016 100644 (file)
@@ -313,10 +313,16 @@ static int gpio_to_irq_unbanked(struct gpio_chip *chip, unsigned offset)
                return -ENODEV;
 }
 
-static int gpio_irq_type_unbanked(struct irq_data *d, unsigned trigger)
+static int gpio_irq_type_unbanked(struct irq_data *data, unsigned trigger)
 {
-       struct davinci_gpio_regs __iomem *g = irq2regs(d->irq);
-       u32 mask = (u32) irq_data_get_irq_handler_data(d);
+       struct davinci_gpio_controller *d;
+       struct davinci_gpio_regs __iomem *g;
+       struct davinci_soc_info *soc_info = &davinci_soc_info;
+       u32 mask;
+
+       d = (struct davinci_gpio_controller *)data->handler_data;
+       g = (struct davinci_gpio_regs __iomem *)d->regs;
+       mask = __gpio_mask(data->irq - soc_info->gpio_irq);
 
        if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
                return -EINVAL;
@@ -380,7 +386,7 @@ static int __init davinci_gpio_irq_setup(void)
         * IRQ mux conflicts; gpio_irq_type_unbanked() is only for GPIOs.
         */
        if (soc_info->gpio_unbanked) {
-               static struct irq_chip gpio_irqchip_unbanked;
+               static struct irq_chip_type gpio_unbanked;
 
                /* pass "bank 0" GPIO IRQs to AINTC */
                chips[0].chip.to_irq = gpio_to_irq_unbanked;
@@ -388,9 +394,10 @@ static int __init davinci_gpio_irq_setup(void)
 
                /* AINTC handles mask/unmask; GPIO handles triggering */
                irq = bank_irq;
-               gpio_irqchip_unbanked = *irq_get_chip(irq);
-               gpio_irqchip_unbanked.name = "GPIO-AINTC";
-               gpio_irqchip_unbanked.irq_set_type = gpio_irq_type_unbanked;
+               gpio_unbanked = *container_of(irq_get_chip(irq),
+                                             struct irq_chip_type, chip);
+               gpio_unbanked.chip.name = "GPIO-AINTC";
+               gpio_unbanked.chip.irq_set_type = gpio_irq_type_unbanked;
 
                /* default trigger: both edges */
                g = gpio2regs(0);
@@ -399,9 +406,8 @@ static int __init davinci_gpio_irq_setup(void)
 
                /* set the direct IRQs up to use that irqchip */
                for (gpio = 0; gpio < soc_info->gpio_unbanked; gpio++, irq++) {
-                       irq_set_chip(irq, &gpio_irqchip_unbanked);
-                       irq_set_handler_data(irq, (void *)__gpio_mask(gpio));
-                       irq_set_chip_data(irq, (__force void *)g);
+                       irq_set_chip(irq, &gpio_unbanked.chip);
+                       irq_set_handler_data(irq, &chips[gpio / 32]);
                        irq_set_status_flags(irq, IRQ_TYPE_EDGE_BOTH);
                }
 
index 4ca5642..776b772 100644 (file)
@@ -12,8 +12,6 @@
  *  published by the Free Software Foundation.
  */
 
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
@@ -65,11 +63,6 @@ static void ep93xx_gpio_update_int_params(unsigned port)
                EP93XX_GPIO_REG(int_en_register_offset[port]));
 }
 
-static inline void ep93xx_gpio_int_mask(unsigned line)
-{
-       gpio_int_unmasked[line >> 3] &= ~(1 << (line & 7));
-}
-
 static void ep93xx_gpio_int_debounce(unsigned int irq, bool enable)
 {
        int line = irq_to_gpio(irq);
@@ -212,7 +205,6 @@ static int ep93xx_gpio_irq_type(struct irq_data *d, unsigned int type)
                handler = handle_edge_irq;
                break;
        default:
-               pr_err("failed to set irq type %d for gpio %d\n", type, gpio);
                return -EINVAL;
        }
 
index ddfacc5..61c2d08 100644 (file)
 #define GPO3_PIN_TO_BIT(x)                     (1 << (x))
 #define GPIO012_PIN_IN_SEL(x, y)               (((x) >> (y)) & 1)
 #define GPIO3_PIN_IN_SHIFT(x)                  ((x) == 5 ? 24 : 10 + (x))
-#define GPIO3_PIN_IN_SEL(x, y)                 ((x) >> GPIO3_PIN_IN_SHIFT(y))
+#define GPIO3_PIN_IN_SEL(x, y)                 (((x) >> GPIO3_PIN_IN_SHIFT(y)) & 1)
 #define GPIO3_PIN5_IN_SEL(x)                   (((x) >> 24) & 1)
 #define GPI3_PIN_IN_SEL(x, y)                  (((x) >> (y)) & 1)
+#define GPO3_PIN_IN_SEL(x, y)                  (((x) >> (y)) & 1)
 
 struct gpio_regs {
        void __iomem *inp_state;
+       void __iomem *outp_state;
        void __iomem *outp_set;
        void __iomem *outp_clr;
        void __iomem *dir_set;
@@ -145,6 +147,7 @@ static struct gpio_regs gpio_grp_regs_p2 = {
 
 static struct gpio_regs gpio_grp_regs_p3 = {
        .inp_state      = LPC32XX_GPIO_P3_INP_STATE,
+       .outp_state     = LPC32XX_GPIO_P3_OUTP_STATE,
        .outp_set       = LPC32XX_GPIO_P3_OUTP_SET,
        .outp_clr       = LPC32XX_GPIO_P3_OUTP_CLR,
        .dir_set        = LPC32XX_GPIO_P2_DIR_SET,
@@ -240,6 +243,12 @@ static int __get_gpi_state_p3(struct lpc32xx_gpio_chip *group,
        return GPI3_PIN_IN_SEL(__raw_readl(group->gpio_grp->inp_state), pin);
 }
 
+static int __get_gpo_state_p3(struct lpc32xx_gpio_chip *group,
+       unsigned pin)
+{
+       return GPO3_PIN_IN_SEL(__raw_readl(group->gpio_grp->outp_state), pin);
+}
+
 /*
  * GENERIC_GPIO primitives.
  */
@@ -340,6 +349,13 @@ static void lpc32xx_gpo_set_value(struct gpio_chip *chip, unsigned pin,
        __set_gpo_level_p3(group, pin, value);
 }
 
+static int lpc32xx_gpo_get_value(struct gpio_chip *chip, unsigned pin)
+{
+       struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+
+       return __get_gpo_state_p3(group, pin);
+}
+
 static int lpc32xx_gpio_request(struct gpio_chip *chip, unsigned pin)
 {
        if (pin < chip->ngpio)
@@ -427,6 +443,7 @@ static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = {
                        .label                  = "gpo_p3",
                        .direction_output       = lpc32xx_gpio_dir_out_always,
                        .set                    = lpc32xx_gpo_set_value,
+                       .get                    = lpc32xx_gpo_get_value,
                        .request                = lpc32xx_gpio_request,
                        .base                   = LPC32XX_GPO_P3_GRP,
                        .ngpio                  = LPC32XX_GPO_P3_MAX,
diff --git a/drivers/gpio/gpio-mc9s08dz60.c b/drivers/gpio/gpio-mc9s08dz60.c
new file mode 100644 (file)
index 0000000..2738cc4
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2009-2012 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * Author: Wu Guoxing <b39297@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+
+#define GPIO_GROUP_NUM 2
+#define GPIO_NUM_PER_GROUP 8
+#define GPIO_NUM (GPIO_GROUP_NUM*GPIO_NUM_PER_GROUP)
+
+struct mc9s08dz60 {
+       struct i2c_client *client;
+       struct gpio_chip chip;
+};
+
+static inline struct mc9s08dz60 *to_mc9s08dz60(struct gpio_chip *gc)
+{
+       return container_of(gc, struct mc9s08dz60, chip);
+}
+
+
+static void mc9s_gpio_to_reg_and_bit(int offset, u8 *reg, u8 *bit)
+{
+       *reg = 0x20 + offset / GPIO_NUM_PER_GROUP;
+       *bit = offset % GPIO_NUM_PER_GROUP;
+}
+
+static int mc9s08dz60_get_value(struct gpio_chip *gc, unsigned offset)
+{
+       u8 reg, bit;
+       s32 value;
+       struct mc9s08dz60 *mc9s = to_mc9s08dz60(gc);
+
+       mc9s_gpio_to_reg_and_bit(offset, &reg, &bit);
+       value = i2c_smbus_read_byte_data(mc9s->client, reg);
+
+       return (value >= 0) ? (value >> bit) & 0x1 : 0;
+}
+
+static int mc9s08dz60_set(struct mc9s08dz60 *mc9s, unsigned offset, int val)
+{
+       u8 reg, bit;
+       s32 value;
+
+       mc9s_gpio_to_reg_and_bit(offset, &reg, &bit);
+       value = i2c_smbus_read_byte_data(mc9s->client, reg);
+       if (value >= 0) {
+               if (val)
+                       value |= 1 << bit;
+               else
+                       value &= ~(1 << bit);
+
+               return i2c_smbus_write_byte_data(mc9s->client, reg, value);
+       } else
+               return value;
+
+}
+
+
+static void mc9s08dz60_set_value(struct gpio_chip *gc, unsigned offset, int val)
+{
+       struct mc9s08dz60 *mc9s = to_mc9s08dz60(gc);
+
+       mc9s08dz60_set(mc9s, offset, val);
+}
+
+static int mc9s08dz60_direction_output(struct gpio_chip *gc,
+                                      unsigned offset, int val)
+{
+       struct mc9s08dz60 *mc9s = to_mc9s08dz60(gc);
+
+       return mc9s08dz60_set(mc9s, offset, val);
+}
+
+static int mc9s08dz60_probe(struct i2c_client *client,
+                           const struct i2c_device_id *id)
+{
+       int ret = 0;
+       struct mc9s08dz60 *mc9s;
+
+       mc9s = kzalloc(sizeof(*mc9s), GFP_KERNEL);
+       if (!mc9s)
+               return -ENOMEM;
+
+       mc9s->chip.label = client->name;
+       mc9s->chip.base = -1;
+       mc9s->chip.dev = &client->dev;
+       mc9s->chip.owner = THIS_MODULE;
+       mc9s->chip.ngpio = GPIO_NUM;
+       mc9s->chip.can_sleep = 1;
+       mc9s->chip.get = mc9s08dz60_get_value;
+       mc9s->chip.set = mc9s08dz60_set_value;
+       mc9s->chip.direction_output = mc9s08dz60_direction_output;
+       mc9s->client = client;
+       i2c_set_clientdata(client, mc9s);
+
+       ret = gpiochip_add(&mc9s->chip);
+       if (ret)
+               goto error;
+
+       return 0;
+
+ error:
+       kfree(mc9s);
+       return ret;
+}
+
+static int mc9s08dz60_remove(struct i2c_client *client)
+{
+       struct mc9s08dz60 *mc9s;
+       int ret;
+
+       mc9s = i2c_get_clientdata(client);
+
+       ret = gpiochip_remove(&mc9s->chip);
+       if (!ret)
+               kfree(mc9s);
+
+       return ret;
+
+}
+
+static const struct i2c_device_id mc9s08dz60_id[] = {
+       {"mc9s08dz60", 0},
+       {},
+};
+
+MODULE_DEVICE_TABLE(i2c, mc9s08dz60_id);
+
+static struct i2c_driver mc9s08dz60_i2c_driver = {
+       .driver = {
+               .owner = THIS_MODULE,
+               .name = "mc9s08dz60",
+       },
+       .probe = mc9s08dz60_probe,
+       .remove = mc9s08dz60_remove,
+       .id_table = mc9s08dz60_id,
+};
+
+module_i2c_driver(mc9s08dz60_i2c_driver);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc. "
+               "Wu Guoxing <b39297@freescale.com>");
+MODULE_DESCRIPTION("mc9s08dz60 gpio function on mx35 3ds board");
+MODULE_LICENSE("GPL v2");
index f49bd6f..1adc2ec 100644 (file)
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/io.h>
-#include <linux/slab.h>
+#include <linux/device.h>
 #include <linux/pm_runtime.h>
 #include <linux/pm.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/irqdomain.h>
 
 #include <mach/hardware.h>
 #include <asm/irq.h>
@@ -50,10 +53,10 @@ struct gpio_regs {
 
 struct gpio_bank {
        struct list_head node;
-       unsigned long pbase;
        void __iomem *base;
        u16 irq;
-       u16 virtual_irq_start;
+       int irq_base;
+       struct irq_domain *domain;
        u32 suspend_wakeup;
        u32 saved_wakeup;
        u32 non_wakeup_gpios;
@@ -77,7 +80,6 @@ struct gpio_bank {
        int stride;
        u32 width;
        int context_loss_count;
-       u16 id;
        int power_mode;
        bool workaround_enabled;
 
@@ -91,6 +93,11 @@ struct gpio_bank {
 #define GPIO_BIT(bank, gpio) (1 << GPIO_INDEX(bank, gpio))
 #define GPIO_MOD_CTRL_BIT      BIT(0)
 
+static int irq_to_gpio(struct gpio_bank *bank, unsigned int gpio_irq)
+{
+       return gpio_irq - bank->irq_base + bank->chip.base;
+}
+
 static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input)
 {
        void __iomem *reg = bank->base;
@@ -113,10 +120,13 @@ static void _set_gpio_dataout_reg(struct gpio_bank *bank, int gpio, int enable)
        void __iomem *reg = bank->base;
        u32 l = GPIO_BIT(bank, gpio);
 
-       if (enable)
+       if (enable) {
                reg += bank->regs->set_dataout;
-       else
+               bank->context.dataout |= l;
+       } else {
                reg += bank->regs->clr_dataout;
+               bank->context.dataout &= ~l;
+       }
 
        __raw_writel(l, reg);
 }
@@ -137,25 +147,25 @@ static void _set_gpio_dataout_mask(struct gpio_bank *bank, int gpio, int enable)
        bank->context.dataout = l;
 }
 
-static int _get_gpio_datain(struct gpio_bank *bank, int gpio)
+static int _get_gpio_datain(struct gpio_bank *bank, int offset)
 {
        void __iomem *reg = bank->base + bank->regs->datain;
 
-       return (__raw_readl(reg) & GPIO_BIT(bank, gpio)) != 0;
+       return (__raw_readl(reg) & (1 << offset)) != 0;
 }
 
-static int _get_gpio_dataout(struct gpio_bank *bank, int gpio)
+static int _get_gpio_dataout(struct gpio_bank *bank, int offset)
 {
        void __iomem *reg = bank->base + bank->regs->dataout;
 
-       return (__raw_readl(reg) & GPIO_BIT(bank, gpio)) != 0;
+       return (__raw_readl(reg) & (1 << offset)) != 0;
 }
 
 static inline void _gpio_rmw(void __iomem *base, u32 reg, u32 mask, bool set)
 {
        int l = __raw_readl(base + reg);
 
-       if (set) 
+       if (set)
                l |= mask;
        else
                l &= ~mask;
@@ -238,7 +248,7 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,
 }
 
 static inline void set_gpio_trigger(struct gpio_bank *bank, int gpio,
-                                               int trigger)
+                                               unsigned trigger)
 {
        void __iomem *base = bank->base;
        u32 gpio_bit = 1 << gpio;
@@ -320,7 +330,8 @@ static void _toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio)
 static void _toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio) {}
 #endif
 
-static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
+static int _set_gpio_triggering(struct gpio_bank *bank, int gpio,
+                                                       unsigned trigger)
 {
        void __iomem *reg = bank->base;
        void __iomem *base = bank->base;
@@ -367,7 +378,7 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
 
 static int gpio_irq_type(struct irq_data *d, unsigned type)
 {
-       struct gpio_bank *bank;
+       struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
        unsigned gpio;
        int retval;
        unsigned long flags;
@@ -375,13 +386,11 @@ static int gpio_irq_type(struct irq_data *d, unsigned type)
        if (!cpu_class_is_omap2() && d->irq > IH_MPUIO_BASE)
                gpio = OMAP_MPUIO(d->irq - IH_MPUIO_BASE);
        else
-               gpio = d->irq - IH_GPIO_BASE;
+               gpio = irq_to_gpio(bank, d->irq);
 
        if (type & ~IRQ_TYPE_SENSE_MASK)
                return -EINVAL;
 
-       bank = irq_data_get_irq_chip_data(d);
-
        if (!bank->regs->leveldetect0 &&
                (type & (IRQ_TYPE_LEVEL_LOW|IRQ_TYPE_LEVEL_HIGH)))
                return -EINVAL;
@@ -442,6 +451,7 @@ static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
        if (bank->regs->set_irqenable) {
                reg += bank->regs->set_irqenable;
                l = gpio_mask;
+               bank->context.irqenable1 |= gpio_mask;
        } else {
                reg += bank->regs->irqenable;
                l = __raw_readl(reg);
@@ -449,10 +459,10 @@ static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
                        l &= ~gpio_mask;
                else
                        l |= gpio_mask;
+               bank->context.irqenable1 = l;
        }
 
        __raw_writel(l, reg);
-       bank->context.irqenable1 = l;
 }
 
 static void _disable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
@@ -463,6 +473,7 @@ static void _disable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
        if (bank->regs->clr_irqenable) {
                reg += bank->regs->clr_irqenable;
                l = gpio_mask;
+               bank->context.irqenable1 &= ~gpio_mask;
        } else {
                reg += bank->regs->irqenable;
                l = __raw_readl(reg);
@@ -470,15 +481,18 @@ static void _disable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
                        l |= gpio_mask;
                else
                        l &= ~gpio_mask;
+               bank->context.irqenable1 = l;
        }
 
        __raw_writel(l, reg);
-       bank->context.irqenable1 = l;
 }
 
 static inline void _set_gpio_irqenable(struct gpio_bank *bank, int gpio, int enable)
 {
-       _enable_gpio_irqbank(bank, GPIO_BIT(bank, gpio));
+       if (enable)
+               _enable_gpio_irqbank(bank, GPIO_BIT(bank, gpio));
+       else
+               _disable_gpio_irqbank(bank, GPIO_BIT(bank, gpio));
 }
 
 /*
@@ -495,7 +509,7 @@ static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable)
        unsigned long flags;
 
        if (bank->non_wakeup_gpios & gpio_bit) {
-               dev_err(bank->dev, 
+               dev_err(bank->dev,
                        "Unable to modify wakeup on non-wakeup GPIO%d\n", gpio);
                return -EINVAL;
        }
@@ -506,6 +520,7 @@ static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable)
        else
                bank->suspend_wakeup &= ~gpio_bit;
 
+       __raw_writel(bank->suspend_wakeup, bank->base + bank->regs->wkup_en);
        spin_unlock_irqrestore(&bank->lock, flags);
 
        return 0;
@@ -522,14 +537,10 @@ static void _reset_gpio(struct gpio_bank *bank, int gpio)
 /* Use disable_irq_wake() and enable_irq_wake() functions from drivers */
 static int gpio_wake_enable(struct irq_data *d, unsigned int enable)
 {
-       unsigned int gpio = d->irq - IH_GPIO_BASE;
-       struct gpio_bank *bank;
-       int retval;
-
-       bank = irq_data_get_irq_chip_data(d);
-       retval = _set_gpio_wakeup(bank, gpio, enable);
+       struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
+       unsigned int gpio = irq_to_gpio(bank, d->irq);
 
-       return retval;
+       return _set_gpio_wakeup(bank, gpio, enable);
 }
 
 static int omap_gpio_request(struct gpio_chip *chip, unsigned offset)
@@ -671,13 +682,15 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
                if (!isr)
                        break;
 
-               gpio_irq = bank->virtual_irq_start;
+               gpio_irq = bank->irq_base;
                for (; isr != 0; isr >>= 1, gpio_irq++) {
-                       gpio_index = GPIO_INDEX(bank, irq_to_gpio(gpio_irq));
+                       int gpio = irq_to_gpio(bank, gpio_irq);
 
                        if (!(isr & 1))
                                continue;
 
+                       gpio_index = GPIO_INDEX(bank, gpio);
+
                        /*
                         * Some chips can't respond to both rising and falling
                         * at the same time.  If this irq was requested with
@@ -703,8 +716,8 @@ exit:
 
 static void gpio_irq_shutdown(struct irq_data *d)
 {
-       unsigned int gpio = d->irq - IH_GPIO_BASE;
        struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
+       unsigned int gpio = irq_to_gpio(bank, d->irq);
        unsigned long flags;
 
        spin_lock_irqsave(&bank->lock, flags);
@@ -714,16 +727,16 @@ static void gpio_irq_shutdown(struct irq_data *d)
 
 static void gpio_ack_irq(struct irq_data *d)
 {
-       unsigned int gpio = d->irq - IH_GPIO_BASE;
        struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
+       unsigned int gpio = irq_to_gpio(bank, d->irq);
 
        _clear_gpio_irqstatus(bank, gpio);
 }
 
 static void gpio_mask_irq(struct irq_data *d)
 {
-       unsigned int gpio = d->irq - IH_GPIO_BASE;
        struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
+       unsigned int gpio = irq_to_gpio(bank, d->irq);
        unsigned long flags;
 
        spin_lock_irqsave(&bank->lock, flags);
@@ -734,8 +747,8 @@ static void gpio_mask_irq(struct irq_data *d)
 
 static void gpio_unmask_irq(struct irq_data *d)
 {
-       unsigned int gpio = d->irq - IH_GPIO_BASE;
        struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
+       unsigned int gpio = irq_to_gpio(bank, d->irq);
        unsigned int irq_mask = GPIO_BIT(bank, gpio);
        u32 trigger = irqd_get_trigger_type(d);
        unsigned long flags;
@@ -852,19 +865,15 @@ static int gpio_is_input(struct gpio_bank *bank, int mask)
 static int gpio_get(struct gpio_chip *chip, unsigned offset)
 {
        struct gpio_bank *bank;
-       void __iomem *reg;
-       int gpio;
        u32 mask;
 
-       gpio = chip->base + offset;
        bank = container_of(chip, struct gpio_bank, chip);
-       reg = bank->base;
-       mask = GPIO_BIT(bank, gpio);
+       mask = (1 << offset);
 
        if (gpio_is_input(bank, mask))
-               return _get_gpio_datain(bank, gpio);
+               return _get_gpio_datain(bank, offset);
        else
-               return _get_gpio_dataout(bank, gpio);
+               return _get_gpio_dataout(bank, offset);
 }
 
 static int gpio_output(struct gpio_chip *chip, unsigned offset, int value)
@@ -917,7 +926,7 @@ static int gpio_2irq(struct gpio_chip *chip, unsigned offset)
        struct gpio_bank *bank;
 
        bank = container_of(chip, struct gpio_bank, chip);
-       return bank->virtual_irq_start + offset;
+       return bank->irq_base + offset;
 }
 
 /*---------------------------------------------------------------------*/
@@ -970,7 +979,7 @@ static void omap_gpio_mod_init(struct gpio_bank *bank)
                _gpio_rmw(base, bank->regs->ctrl, 0, 1);
 }
 
-static __init void
+static __devinit void
 omap_mpuio_alloc_gc(struct gpio_bank *bank, unsigned int irq_start,
                    unsigned int num)
 {
@@ -1030,8 +1039,7 @@ static void __devinit omap_gpio_chip_init(struct gpio_bank *bank)
 
        gpiochip_add(&bank->chip);
 
-       for (j = bank->virtual_irq_start;
-                    j < bank->virtual_irq_start + bank->width; j++) {
+       for (j = bank->irq_base; j < bank->irq_base + bank->width; j++) {
                irq_set_lockdep_class(j, &gpio_lock_class);
                irq_set_chip_data(j, bank);
                if (bank->is_mpuio) {
@@ -1046,39 +1054,38 @@ static void __devinit omap_gpio_chip_init(struct gpio_bank *bank)
        irq_set_handler_data(bank->irq, bank);
 }
 
+static const struct of_device_id omap_gpio_match[];
+
 static int __devinit omap_gpio_probe(struct platform_device *pdev)
 {
+       struct device *dev = &pdev->dev;
+       struct device_node *node = dev->of_node;
+       const struct of_device_id *match;
        struct omap_gpio_platform_data *pdata;
        struct resource *res;
        struct gpio_bank *bank;
        int ret = 0;
 
-       if (!pdev->dev.platform_data) {
-               ret = -EINVAL;
-               goto err_exit;
-       }
+       match = of_match_device(of_match_ptr(omap_gpio_match), dev);
+
+       pdata = match ? match->data : dev->platform_data;
+       if (!pdata)
+               return -EINVAL;
 
-       bank = kzalloc(sizeof(struct gpio_bank), GFP_KERNEL);
+       bank = devm_kzalloc(&pdev->dev, sizeof(struct gpio_bank), GFP_KERNEL);
        if (!bank) {
-               dev_err(&pdev->dev, "Memory alloc failed for gpio_bank\n");
-               ret = -ENOMEM;
-               goto err_exit;
+               dev_err(dev, "Memory alloc failed\n");
+               return -ENOMEM;
        }
 
        res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
        if (unlikely(!res)) {
-               dev_err(&pdev->dev, "GPIO Bank %i Invalid IRQ resource\n",
-                               pdev->id);
-               ret = -ENODEV;
-               goto err_free;
+               dev_err(dev, "Invalid IRQ resource\n");
+               return -ENODEV;
        }
 
        bank->irq = res->start;
-       bank->id = pdev->id;
-
-       pdata = pdev->dev.platform_data;
-       bank->virtual_irq_start = pdata->virtual_irq_start;
-       bank->dev = &pdev->dev;
+       bank->dev = dev;
        bank->dbck_flag = pdata->dbck_flag;
        bank->stride = pdata->bank_stride;
        bank->width = pdata->bank_width;
@@ -1087,6 +1094,18 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev)
        bank->loses_context = pdata->loses_context;
        bank->get_context_loss_count = pdata->get_context_loss_count;
        bank->regs = pdata->regs;
+#ifdef CONFIG_OF_GPIO
+       bank->chip.of_node = of_node_get(node);
+#endif
+
+       bank->irq_base = irq_alloc_descs(-1, 0, bank->width, 0);
+       if (bank->irq_base < 0) {
+               dev_err(dev, "Couldn't allocate IRQ numbers\n");
+               return -ENODEV;
+       }
+
+       bank->domain = irq_domain_add_legacy(node, bank->width, bank->irq_base,
+                                            0, &irq_domain_simple_ops, NULL);
 
        if (bank->regs->set_dataout && bank->regs->clr_dataout)
                bank->set_dataout = _set_gpio_dataout_reg;
@@ -1098,18 +1117,20 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev)
        /* Static mapping, never released */
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (unlikely(!res)) {
-               dev_err(&pdev->dev, "GPIO Bank %i Invalid mem resource\n",
-                               pdev->id);
-               ret = -ENODEV;
-               goto err_free;
+               dev_err(dev, "Invalid mem resource\n");
+               return -ENODEV;
        }
 
-       bank->base = ioremap(res->start, resource_size(res));
+       if (!devm_request_mem_region(dev, res->start, resource_size(res),
+                                    pdev->name)) {
+               dev_err(dev, "Region already claimed\n");
+               return -EBUSY;
+       }
+
+       bank->base = devm_ioremap(dev, res->start, resource_size(res));
        if (!bank->base) {
-               dev_err(&pdev->dev, "Could not ioremap gpio bank%i\n",
-                               pdev->id);
-               ret = -ENOMEM;
-               goto err_free;
+               dev_err(dev, "Could not ioremap\n");
+               return -ENOMEM;
        }
 
        platform_set_drvdata(pdev, bank);
@@ -1130,11 +1151,6 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev)
        list_add_tail(&bank->node, &omap_gpio_list);
 
        return ret;
-
-err_free:
-       kfree(bank);
-err_exit:
-       return ret;
 }
 
 #ifdef CONFIG_ARCH_OMAP2PLUS
@@ -1196,8 +1212,30 @@ static int omap_gpio_runtime_suspend(struct device *dev)
        struct gpio_bank *bank = platform_get_drvdata(pdev);
        u32 l1 = 0, l2 = 0;
        unsigned long flags;
+       u32 wake_low, wake_hi;
 
        spin_lock_irqsave(&bank->lock, flags);
+
+       /*
+        * Only edges can generate a wakeup event to the PRCM.
+        *
+        * Therefore, ensure any wake-up capable GPIOs have
+        * edge-detection enabled before going idle to ensure a wakeup
+        * to the PRCM is generated on a GPIO transition. (c.f. 34xx
+        * NDA TRM 25.5.3.1)
+        *
+        * The normal values will be restored upon ->runtime_resume()
+        * by writing back the values saved in bank->context.
+        */
+       wake_low = bank->context.leveldetect0 & bank->context.wake_en;
+       if (wake_low)
+               __raw_writel(wake_low | bank->context.fallingdetect,
+                            bank->base + bank->regs->fallingdetect);
+       wake_hi = bank->context.leveldetect1 & bank->context.wake_en;
+       if (wake_hi)
+               __raw_writel(wake_hi | bank->context.risingdetect,
+                            bank->base + bank->regs->risingdetect);
+
        if (bank->power_mode != OFF_MODE) {
                bank->power_mode = 0;
                goto update_gpio_context_count;
@@ -1207,9 +1245,6 @@ static int omap_gpio_runtime_suspend(struct device *dev)
         * non-wakeup GPIOs.  Otherwise spurious IRQs will be
         * generated.  See OMAP2420 Errata item 1.101.
         */
-       if (!(bank->enabled_non_wakeup_gpios))
-               goto update_gpio_context_count;
-
        bank->saved_datain = __raw_readl(bank->base +
                                                bank->regs->datain);
        l1 = __raw_readl(bank->base + bank->regs->fallingdetect);
@@ -1246,7 +1281,19 @@ static int omap_gpio_runtime_resume(struct device *dev)
 
        spin_lock_irqsave(&bank->lock, flags);
        _gpio_dbck_enable(bank);
-       if (!bank->enabled_non_wakeup_gpios || !bank->workaround_enabled) {
+
+       /*
+        * In ->runtime_suspend(), level-triggered, wakeup-enabled
+        * GPIOs were set to edge trigger also in order to be able to
+        * generate a PRCM wakeup.  Here we restore the
+        * pre-runtime_suspend() values for edge triggering.
+        */
+       __raw_writel(bank->context.fallingdetect,
+                    bank->base + bank->regs->fallingdetect);
+       __raw_writel(bank->context.risingdetect,
+                    bank->base + bank->regs->risingdetect);
+
+       if (!bank->workaround_enabled) {
                spin_unlock_irqrestore(&bank->lock, flags);
                return 0;
        }
@@ -1397,11 +1444,95 @@ static const struct dev_pm_ops gpio_pm_ops = {
                                                                        NULL)
 };
 
+#if defined(CONFIG_OF)
+static struct omap_gpio_reg_offs omap2_gpio_regs = {
+       .revision =             OMAP24XX_GPIO_REVISION,
+       .direction =            OMAP24XX_GPIO_OE,
+       .datain =               OMAP24XX_GPIO_DATAIN,
+       .dataout =              OMAP24XX_GPIO_DATAOUT,
+       .set_dataout =          OMAP24XX_GPIO_SETDATAOUT,
+       .clr_dataout =          OMAP24XX_GPIO_CLEARDATAOUT,
+       .irqstatus =            OMAP24XX_GPIO_IRQSTATUS1,
+       .irqstatus2 =           OMAP24XX_GPIO_IRQSTATUS2,
+       .irqenable =            OMAP24XX_GPIO_IRQENABLE1,
+       .irqenable2 =           OMAP24XX_GPIO_IRQENABLE2,
+       .set_irqenable =        OMAP24XX_GPIO_SETIRQENABLE1,
+       .clr_irqenable =        OMAP24XX_GPIO_CLEARIRQENABLE1,
+       .debounce =             OMAP24XX_GPIO_DEBOUNCE_VAL,
+       .debounce_en =          OMAP24XX_GPIO_DEBOUNCE_EN,
+       .ctrl =                 OMAP24XX_GPIO_CTRL,
+       .wkup_en =              OMAP24XX_GPIO_WAKE_EN,
+       .leveldetect0 =         OMAP24XX_GPIO_LEVELDETECT0,
+       .leveldetect1 =         OMAP24XX_GPIO_LEVELDETECT1,
+       .risingdetect =         OMAP24XX_GPIO_RISINGDETECT,
+       .fallingdetect =        OMAP24XX_GPIO_FALLINGDETECT,
+};
+
+static struct omap_gpio_reg_offs omap4_gpio_regs = {
+       .revision =             OMAP4_GPIO_REVISION,
+       .direction =            OMAP4_GPIO_OE,
+       .datain =               OMAP4_GPIO_DATAIN,
+       .dataout =              OMAP4_GPIO_DATAOUT,
+       .set_dataout =          OMAP4_GPIO_SETDATAOUT,
+       .clr_dataout =          OMAP4_GPIO_CLEARDATAOUT,
+       .irqstatus =            OMAP4_GPIO_IRQSTATUS0,
+       .irqstatus2 =           OMAP4_GPIO_IRQSTATUS1,
+       .irqenable =            OMAP4_GPIO_IRQSTATUSSET0,
+       .irqenable2 =           OMAP4_GPIO_IRQSTATUSSET1,
+       .set_irqenable =        OMAP4_GPIO_IRQSTATUSSET0,
+       .clr_irqenable =        OMAP4_GPIO_IRQSTATUSCLR0,
+       .debounce =             OMAP4_GPIO_DEBOUNCINGTIME,
+       .debounce_en =          OMAP4_GPIO_DEBOUNCENABLE,
+       .ctrl =                 OMAP4_GPIO_CTRL,
+       .wkup_en =              OMAP4_GPIO_IRQWAKEN0,
+       .leveldetect0 =         OMAP4_GPIO_LEVELDETECT0,
+       .leveldetect1 =         OMAP4_GPIO_LEVELDETECT1,
+       .risingdetect =         OMAP4_GPIO_RISINGDETECT,
+       .fallingdetect =        OMAP4_GPIO_FALLINGDETECT,
+};
+
+static struct omap_gpio_platform_data omap2_pdata = {
+       .regs = &omap2_gpio_regs,
+       .bank_width = 32,
+       .dbck_flag = false,
+};
+
+static struct omap_gpio_platform_data omap3_pdata = {
+       .regs = &omap2_gpio_regs,
+       .bank_width = 32,
+       .dbck_flag = true,
+};
+
+static struct omap_gpio_platform_data omap4_pdata = {
+       .regs = &omap4_gpio_regs,
+       .bank_width = 32,
+       .dbck_flag = true,
+};
+
+static const struct of_device_id omap_gpio_match[] = {
+       {
+               .compatible = "ti,omap4-gpio",
+               .data = &omap4_pdata,
+       },
+       {
+               .compatible = "ti,omap3-gpio",
+               .data = &omap3_pdata,
+       },
+       {
+               .compatible = "ti,omap2-gpio",
+               .data = &omap2_pdata,
+       },
+       { },
+};
+MODULE_DEVICE_TABLE(of, omap_gpio_match);
+#endif
+
 static struct platform_driver omap_gpio_driver = {
        .probe          = omap_gpio_probe,
        .driver         = {
                .name   = "omap_gpio",
                .pm     = &gpio_pm_ops,
+               .of_match_table = of_match_ptr(omap_gpio_match),
        },
 };
 
index 77c9cc7..b4b5da4 100644 (file)
@@ -352,7 +352,12 @@ static int pl061_resume(struct device *dev)
        return 0;
 }
 
-static SIMPLE_DEV_PM_OPS(pl061_dev_pm_ops, pl061_suspend, pl061_resume);
+static const struct dev_pm_ops pl061_dev_pm_ops = {
+       .suspend = pl061_suspend,
+       .resume = pl061_resume,
+       .freeze = pl061_suspend,
+       .restore = pl061_resume,
+};
 #endif
 
 static struct amba_id pl061_ids[] = {
index 0a79a11..4627787 100644 (file)
@@ -169,7 +169,7 @@ int s3c24xx_gpio_setpull_1down(struct samsung_gpio_chip *chip,
        return s3c24xx_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_DOWN);
 }
 
-static int exynos4_gpio_setpull(struct samsung_gpio_chip *chip,
+static int exynos_gpio_setpull(struct samsung_gpio_chip *chip,
                                unsigned int off, samsung_gpio_pull_t pull)
 {
        if (pull == S3C_GPIO_PULL_UP)
@@ -178,7 +178,7 @@ static int exynos4_gpio_setpull(struct samsung_gpio_chip *chip,
        return samsung_gpio_setpull_updown(chip, off, pull);
 }
 
-static samsung_gpio_pull_t exynos4_gpio_getpull(struct samsung_gpio_chip *chip,
+static samsung_gpio_pull_t exynos_gpio_getpull(struct samsung_gpio_chip *chip,
                                                unsigned int off)
 {
        samsung_gpio_pull_t pull;
@@ -452,9 +452,9 @@ static struct samsung_gpio_cfg s3c24xx_gpiocfg_banka = {
 };
 #endif
 
-static struct samsung_gpio_cfg exynos4_gpio_cfg = {
-       .set_pull       = exynos4_gpio_setpull,
-       .get_pull       = exynos4_gpio_getpull,
+static struct samsung_gpio_cfg exynos_gpio_cfg = {
+       .set_pull       = exynos_gpio_setpull,
+       .get_pull       = exynos_gpio_getpull,
        .set_config     = samsung_gpio_setcfg_4bit,
        .get_config     = samsung_gpio_getcfg_4bit,
 };
@@ -502,13 +502,13 @@ static struct samsung_gpio_cfg samsung_gpio_cfgs[] = {
                .get_config     = samsung_gpio_getcfg_2bit,
        },
        [8] = {
-               .set_pull       = exynos4_gpio_setpull,
-               .get_pull       = exynos4_gpio_getpull,
+               .set_pull       = exynos_gpio_setpull,
+               .get_pull       = exynos_gpio_getpull,
        },
        [9] = {
                .cfg_eint       = 0x3,
-               .set_pull       = exynos4_gpio_setpull,
-               .get_pull       = exynos4_gpio_getpull,
+               .set_pull       = exynos_gpio_setpull,
+               .get_pull       = exynos_gpio_getpull,
        }
 };
 
@@ -2113,10 +2113,10 @@ static struct samsung_gpio_chip s5pv210_gpios_4bit[] = {
 };
 
 /*
- * Followings are the gpio banks in EXYNOS4210
+ * Followings are the gpio banks in EXYNOS SoCs
  *
  * The 'config' member when left to NULL, is initialized to the default
- * structure samsung_gpio_cfgs[3] in the init function below.
+ * structure exynos_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 samsung_gpio_chip structure
@@ -2331,7 +2331,6 @@ static struct samsung_gpio_chip exynos4_gpios_2[] = {
                        .label  = "GPY6",
                },
        }, {
-               .base   = (S5P_VA_GPIO2 + 0xC00),
                .config = &samsung_gpio_cfgs[9],
                .irq_base = IRQ_EINT(0),
                .chip   = {
@@ -2341,7 +2340,6 @@ static struct samsung_gpio_chip exynos4_gpios_2[] = {
                        .to_irq = samsung_gpiolib_to_irq,
                },
        }, {
-               .base   = (S5P_VA_GPIO2 + 0xC20),
                .config = &samsung_gpio_cfgs[9],
                .irq_base = IRQ_EINT(8),
                .chip   = {
@@ -2351,7 +2349,6 @@ static struct samsung_gpio_chip exynos4_gpios_2[] = {
                        .to_irq = samsung_gpiolib_to_irq,
                },
        }, {
-               .base   = (S5P_VA_GPIO2 + 0xC40),
                .config = &samsung_gpio_cfgs[9],
                .irq_base = IRQ_EINT(16),
                .chip   = {
@@ -2361,7 +2358,6 @@ static struct samsung_gpio_chip exynos4_gpios_2[] = {
                        .to_irq = samsung_gpiolib_to_irq,
                },
        }, {
-               .base   = (S5P_VA_GPIO2 + 0xC60),
                .config = &samsung_gpio_cfgs[9],
                .irq_base = IRQ_EINT(24),
                .chip   = {
@@ -2386,8 +2382,280 @@ static struct samsung_gpio_chip exynos4_gpios_3[] = {
 #endif
 };
 
-#if defined(CONFIG_ARCH_EXYNOS4) && defined(CONFIG_OF)
-static int exynos4_gpio_xlate(struct gpio_chip *gc,
+static struct samsung_gpio_chip exynos5_gpios_1[] = {
+#ifdef CONFIG_ARCH_EXYNOS5
+       {
+               .chip   = {
+                       .base   = EXYNOS5_GPA0(0),
+                       .ngpio  = EXYNOS5_GPIO_A0_NR,
+                       .label  = "GPA0",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS5_GPA1(0),
+                       .ngpio  = EXYNOS5_GPIO_A1_NR,
+                       .label  = "GPA1",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS5_GPA2(0),
+                       .ngpio  = EXYNOS5_GPIO_A2_NR,
+                       .label  = "GPA2",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS5_GPB0(0),
+                       .ngpio  = EXYNOS5_GPIO_B0_NR,
+                       .label  = "GPB0",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS5_GPB1(0),
+                       .ngpio  = EXYNOS5_GPIO_B1_NR,
+                       .label  = "GPB1",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS5_GPB2(0),
+                       .ngpio  = EXYNOS5_GPIO_B2_NR,
+                       .label  = "GPB2",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS5_GPB3(0),
+                       .ngpio  = EXYNOS5_GPIO_B3_NR,
+                       .label  = "GPB3",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS5_GPC0(0),
+                       .ngpio  = EXYNOS5_GPIO_C0_NR,
+                       .label  = "GPC0",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS5_GPC1(0),
+                       .ngpio  = EXYNOS5_GPIO_C1_NR,
+                       .label  = "GPC1",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS5_GPC2(0),
+                       .ngpio  = EXYNOS5_GPIO_C2_NR,
+                       .label  = "GPC2",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS5_GPC3(0),
+                       .ngpio  = EXYNOS5_GPIO_C3_NR,
+                       .label  = "GPC3",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS5_GPD0(0),
+                       .ngpio  = EXYNOS5_GPIO_D0_NR,
+                       .label  = "GPD0",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS5_GPD1(0),
+                       .ngpio  = EXYNOS5_GPIO_D1_NR,
+                       .label  = "GPD1",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS5_GPY0(0),
+                       .ngpio  = EXYNOS5_GPIO_Y0_NR,
+                       .label  = "GPY0",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS5_GPY1(0),
+                       .ngpio  = EXYNOS5_GPIO_Y1_NR,
+                       .label  = "GPY1",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS5_GPY2(0),
+                       .ngpio  = EXYNOS5_GPIO_Y2_NR,
+                       .label  = "GPY2",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS5_GPY3(0),
+                       .ngpio  = EXYNOS5_GPIO_Y3_NR,
+                       .label  = "GPY3",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS5_GPY4(0),
+                       .ngpio  = EXYNOS5_GPIO_Y4_NR,
+                       .label  = "GPY4",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS5_GPY5(0),
+                       .ngpio  = EXYNOS5_GPIO_Y5_NR,
+                       .label  = "GPY5",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS5_GPY6(0),
+                       .ngpio  = EXYNOS5_GPIO_Y6_NR,
+                       .label  = "GPY6",
+               },
+       }, {
+               .config = &samsung_gpio_cfgs[9],
+               .irq_base = IRQ_EINT(0),
+               .chip   = {
+                       .base   = EXYNOS5_GPX0(0),
+                       .ngpio  = EXYNOS5_GPIO_X0_NR,
+                       .label  = "GPX0",
+                       .to_irq = samsung_gpiolib_to_irq,
+               },
+       }, {
+               .config = &samsung_gpio_cfgs[9],
+               .irq_base = IRQ_EINT(8),
+               .chip   = {
+                       .base   = EXYNOS5_GPX1(0),
+                       .ngpio  = EXYNOS5_GPIO_X1_NR,
+                       .label  = "GPX1",
+                       .to_irq = samsung_gpiolib_to_irq,
+               },
+       }, {
+               .config = &samsung_gpio_cfgs[9],
+               .irq_base = IRQ_EINT(16),
+               .chip   = {
+                       .base   = EXYNOS5_GPX2(0),
+                       .ngpio  = EXYNOS5_GPIO_X2_NR,
+                       .label  = "GPX2",
+                       .to_irq = samsung_gpiolib_to_irq,
+               },
+       }, {
+               .config = &samsung_gpio_cfgs[9],
+               .irq_base = IRQ_EINT(24),
+               .chip   = {
+                       .base   = EXYNOS5_GPX3(0),
+                       .ngpio  = EXYNOS5_GPIO_X3_NR,
+                       .label  = "GPX3",
+                       .to_irq = samsung_gpiolib_to_irq,
+               },
+       },
+#endif
+};
+
+static struct samsung_gpio_chip exynos5_gpios_2[] = {
+#ifdef CONFIG_ARCH_EXYNOS5
+       {
+               .chip   = {
+                       .base   = EXYNOS5_GPE0(0),
+                       .ngpio  = EXYNOS5_GPIO_E0_NR,
+                       .label  = "GPE0",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS5_GPE1(0),
+                       .ngpio  = EXYNOS5_GPIO_E1_NR,
+                       .label  = "GPE1",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS5_GPF0(0),
+                       .ngpio  = EXYNOS5_GPIO_F0_NR,
+                       .label  = "GPF0",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS5_GPF1(0),
+                       .ngpio  = EXYNOS5_GPIO_F1_NR,
+                       .label  = "GPF1",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS5_GPG0(0),
+                       .ngpio  = EXYNOS5_GPIO_G0_NR,
+                       .label  = "GPG0",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS5_GPG1(0),
+                       .ngpio  = EXYNOS5_GPIO_G1_NR,
+                       .label  = "GPG1",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS5_GPG2(0),
+                       .ngpio  = EXYNOS5_GPIO_G2_NR,
+                       .label  = "GPG2",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS5_GPH0(0),
+                       .ngpio  = EXYNOS5_GPIO_H0_NR,
+                       .label  = "GPH0",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS5_GPH1(0),
+                       .ngpio  = EXYNOS5_GPIO_H1_NR,
+                       .label  = "GPH1",
+
+               },
+       },
+#endif
+};
+
+static struct samsung_gpio_chip exynos5_gpios_3[] = {
+#ifdef CONFIG_ARCH_EXYNOS5
+       {
+               .chip   = {
+                       .base   = EXYNOS5_GPV0(0),
+                       .ngpio  = EXYNOS5_GPIO_V0_NR,
+                       .label  = "GPV0",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS5_GPV1(0),
+                       .ngpio  = EXYNOS5_GPIO_V1_NR,
+                       .label  = "GPV1",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS5_GPV2(0),
+                       .ngpio  = EXYNOS5_GPIO_V2_NR,
+                       .label  = "GPV2",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS5_GPV3(0),
+                       .ngpio  = EXYNOS5_GPIO_V3_NR,
+                       .label  = "GPV3",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS5_GPV4(0),
+                       .ngpio  = EXYNOS5_GPIO_V4_NR,
+                       .label  = "GPV4",
+               },
+       },
+#endif
+};
+
+static struct samsung_gpio_chip exynos5_gpios_4[] = {
+#ifdef CONFIG_ARCH_EXYNOS5
+       {
+               .chip   = {
+                       .base   = EXYNOS5_GPZ(0),
+                       .ngpio  = EXYNOS5_GPIO_Z_NR,
+                       .label  = "GPZ",
+               },
+       },
+#endif
+};
+
+
+#if defined(CONFIG_ARCH_EXYNOS) && defined(CONFIG_OF)
+static int exynos_gpio_xlate(struct gpio_chip *gc,
                        const struct of_phandle_args *gpiospec, u32 *flags)
 {
        unsigned int pin;
@@ -2413,13 +2681,13 @@ static int exynos4_gpio_xlate(struct gpio_chip *gc,
        return gpiospec->args[0];
 }
 
-static const struct of_device_id exynos4_gpio_dt_match[] __initdata = {
+static const struct of_device_id exynos_gpio_dt_match[] __initdata = {
        { .compatible = "samsung,exynos4-gpio", },
        {}
 };
 
-static __init void exynos4_gpiolib_attach_ofnode(struct samsung_gpio_chip *chip,
-                                                u64 base, u64 offset)
+static __init void exynos_gpiolib_attach_ofnode(struct samsung_gpio_chip *chip,
+                                               u64 base, u64 offset)
 {
        struct gpio_chip *gc =  &chip->chip;
        u64 address;
@@ -2429,28 +2697,29 @@ static __init void exynos4_gpiolib_attach_ofnode(struct samsung_gpio_chip *chip,
 
        address = chip->base ? base + ((u32)chip->base & 0xfff) : base + offset;
        gc->of_node = of_find_matching_node_by_address(NULL,
-                       exynos4_gpio_dt_match, address);
+                       exynos_gpio_dt_match, address);
        if (!gc->of_node) {
                pr_info("gpio: device tree node not found for gpio controller"
                        " with base address %08llx\n", address);
                return;
        }
        gc->of_gpio_n_cells = 4;
-       gc->of_xlate = exynos4_gpio_xlate;
+       gc->of_xlate = exynos_gpio_xlate;
 }
-#elif defined(CONFIG_ARCH_EXYNOS4)
-static __init void exynos4_gpiolib_attach_ofnode(struct samsung_gpio_chip *chip,
-                                                u64 base, u64 offset)
+#elif defined(CONFIG_ARCH_EXYNOS)
+static __init void exynos_gpiolib_attach_ofnode(struct samsung_gpio_chip *chip,
+                                               u64 base, u64 offset)
 {
        return;
 }
-#endif /* defined(CONFIG_ARCH_EXYNOS4) && defined(CONFIG_OF) */
+#endif /* defined(CONFIG_ARCH_EXYNOS) && defined(CONFIG_OF) */
 
 /* TODO: cleanup soc_is_* */
 static __init int samsung_gpiolib_init(void)
 {
        struct samsung_gpio_chip *chip;
        int i, nr_chips;
+       void __iomem *gpio_base1, *gpio_base2, *gpio_base3, *gpio_base4;
        int group = 0;
 
        samsung_gpiolib_set_cfg(samsung_gpio_cfgs, ARRAY_SIZE(samsung_gpio_cfgs));
@@ -2516,66 +2785,200 @@ static __init int samsung_gpiolib_init(void)
                s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
 #endif
        } else if (soc_is_exynos4210()) {
-               group = 0;
+#ifdef CONFIG_CPU_EXYNOS4210
+               void __iomem *gpx_base;
 
                /* gpio part1 */
+               gpio_base1 = ioremap(EXYNOS4_PA_GPIO1, SZ_4K);
+               if (gpio_base1 == NULL) {
+                       pr_err("unable to ioremap for gpio_base1\n");
+                       goto err_ioremap1;
+               }
+
                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->config = &exynos_gpio_cfg;
                                chip->group = group++;
                        }
-#ifdef CONFIG_CPU_EXYNOS4210
-                       exynos4_gpiolib_attach_ofnode(chip,
+                       exynos_gpiolib_attach_ofnode(chip,
                                        EXYNOS4_PA_GPIO1, i * 0x20);
-#endif
                }
-               samsung_gpiolib_add_4bit_chips(exynos4_gpios_1, nr_chips, S5P_VA_GPIO1);
+               samsung_gpiolib_add_4bit_chips(exynos4_gpios_1,
+                                              nr_chips, gpio_base1);
 
                /* gpio part2 */
+               gpio_base2 = ioremap(EXYNOS4_PA_GPIO2, SZ_4K);
+               if (gpio_base2 == NULL) {
+                       pr_err("unable to ioremap for gpio_base2\n");
+                       goto err_ioremap2;
+               }
+
+               /* need to set base address for gpx */
+               chip = &exynos4_gpios_2[16];
+               gpx_base = gpio_base2 + 0xC00;
+               for (i = 0; i < 4; i++, chip++, gpx_base += 0x20)
+                       chip->base = gpx_base;
+
                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->config = &exynos_gpio_cfg;
                                chip->group = group++;
                        }
-#ifdef CONFIG_CPU_EXYNOS4210
-                       exynos4_gpiolib_attach_ofnode(chip,
+                       exynos_gpiolib_attach_ofnode(chip,
                                        EXYNOS4_PA_GPIO2, i * 0x20);
-#endif
                }
-               samsung_gpiolib_add_4bit_chips(exynos4_gpios_2, nr_chips, S5P_VA_GPIO2);
+               samsung_gpiolib_add_4bit_chips(exynos4_gpios_2,
+                                              nr_chips, gpio_base2);
 
                /* gpio part3 */
+               gpio_base3 = ioremap(EXYNOS4_PA_GPIO3, SZ_256);
+               if (gpio_base3 == NULL) {
+                       pr_err("unable to ioremap for gpio_base3\n");
+                       goto err_ioremap3;
+               }
+
                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->config = &exynos_gpio_cfg;
                                chip->group = group++;
                        }
-#ifdef CONFIG_CPU_EXYNOS4210
-                       exynos4_gpiolib_attach_ofnode(chip,
+                       exynos_gpiolib_attach_ofnode(chip,
                                        EXYNOS4_PA_GPIO3, i * 0x20);
-#endif
                }
-               samsung_gpiolib_add_4bit_chips(exynos4_gpios_3, nr_chips, S5P_VA_GPIO3);
+               samsung_gpiolib_add_4bit_chips(exynos4_gpios_3,
+                                              nr_chips, gpio_base3);
 
 #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
+
+#endif /* CONFIG_CPU_EXYNOS4210 */
+       } else if (soc_is_exynos5250()) {
+#ifdef CONFIG_SOC_EXYNOS5250
+               void __iomem *gpx_base;
+
+               /* gpio part1 */
+               gpio_base1 = ioremap(EXYNOS5_PA_GPIO1, SZ_4K);
+               if (gpio_base1 == NULL) {
+                       pr_err("unable to ioremap for gpio_base1\n");
+                       goto err_ioremap1;
+               }
+
+               /* need to set base address for gpx */
+               chip = &exynos5_gpios_1[20];
+               gpx_base = gpio_base1 + 0xC00;
+               for (i = 0; i < 4; i++, chip++, gpx_base += 0x20)
+                       chip->base = gpx_base;
+
+               chip = exynos5_gpios_1;
+               nr_chips = ARRAY_SIZE(exynos5_gpios_1);
+
+               for (i = 0; i < nr_chips; i++, chip++) {
+                       if (!chip->config) {
+                               chip->config = &exynos_gpio_cfg;
+                               chip->group = group++;
+                       }
+                       exynos_gpiolib_attach_ofnode(chip,
+                                       EXYNOS5_PA_GPIO1, i * 0x20);
+               }
+               samsung_gpiolib_add_4bit_chips(exynos5_gpios_1,
+                                              nr_chips, gpio_base1);
+
+               /* gpio part2 */
+               gpio_base2 = ioremap(EXYNOS5_PA_GPIO2, SZ_4K);
+               if (gpio_base2 == NULL) {
+                       pr_err("unable to ioremap for gpio_base2\n");
+                       goto err_ioremap2;
+               }
+
+               chip = exynos5_gpios_2;
+               nr_chips = ARRAY_SIZE(exynos5_gpios_2);
+
+               for (i = 0; i < nr_chips; i++, chip++) {
+                       if (!chip->config) {
+                               chip->config = &exynos_gpio_cfg;
+                               chip->group = group++;
+                       }
+                       exynos_gpiolib_attach_ofnode(chip,
+                                       EXYNOS5_PA_GPIO2, i * 0x20);
+               }
+               samsung_gpiolib_add_4bit_chips(exynos5_gpios_2,
+                                              nr_chips, gpio_base2);
+
+               /* gpio part3 */
+               gpio_base3 = ioremap(EXYNOS5_PA_GPIO3, SZ_4K);
+               if (gpio_base3 == NULL) {
+                       pr_err("unable to ioremap for gpio_base3\n");
+                       goto err_ioremap3;
+               }
+
+               /* need to set base address for gpv */
+               exynos5_gpios_3[0].base = gpio_base3;
+               exynos5_gpios_3[1].base = gpio_base3 + 0x20;
+               exynos5_gpios_3[2].base = gpio_base3 + 0x60;
+               exynos5_gpios_3[3].base = gpio_base3 + 0x80;
+               exynos5_gpios_3[4].base = gpio_base3 + 0xC0;
+
+               chip = exynos5_gpios_3;
+               nr_chips = ARRAY_SIZE(exynos5_gpios_3);
+
+               for (i = 0; i < nr_chips; i++, chip++) {
+                       if (!chip->config) {
+                               chip->config = &exynos_gpio_cfg;
+                               chip->group = group++;
+                       }
+                       exynos_gpiolib_attach_ofnode(chip,
+                                       EXYNOS5_PA_GPIO3, i * 0x20);
+               }
+               samsung_gpiolib_add_4bit_chips(exynos5_gpios_3,
+                                              nr_chips, gpio_base3);
+
+               /* gpio part4 */
+               gpio_base4 = ioremap(EXYNOS5_PA_GPIO4, SZ_4K);
+               if (gpio_base4 == NULL) {
+                       pr_err("unable to ioremap for gpio_base4\n");
+                       goto err_ioremap4;
+               }
+
+               chip = exynos5_gpios_4;
+               nr_chips = ARRAY_SIZE(exynos5_gpios_4);
+
+               for (i = 0; i < nr_chips; i++, chip++) {
+                       if (!chip->config) {
+                               chip->config = &exynos_gpio_cfg;
+                               chip->group = group++;
+                       }
+                       exynos_gpiolib_attach_ofnode(chip,
+                                       EXYNOS5_PA_GPIO4, i * 0x20);
+               }
+               samsung_gpiolib_add_4bit_chips(exynos5_gpios_4,
+                                              nr_chips, gpio_base4);
+#endif /* CONFIG_SOC_EXYNOS5250 */
        } else {
                WARN(1, "Unknown SoC in gpio-samsung, no GPIOs added\n");
                return -ENODEV;
        }
 
        return 0;
+
+err_ioremap4:
+       iounmap(gpio_base3);
+err_ioremap3:
+       iounmap(gpio_base2);
+err_ioremap2:
+       iounmap(gpio_base1);
+err_ioremap1:
+       return -ENOMEM;
 }
 core_initcall(samsung_gpiolib_init);
 
diff --git a/drivers/gpio/gpio-sodaville.c b/drivers/gpio/gpio-sodaville.c
new file mode 100644 (file)
index 0000000..9ba15d3
--- /dev/null
@@ -0,0 +1,302 @@
+/*
+ *  GPIO interface for Intel Sodaville SoCs.
+ *
+ *  Copyright (c) 2010, 2011 Intel Corporation
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License 2 as published
+ *  by the Free Software Foundation.
+ *
+ */
+
+#include <linux/errno.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/of_irq.h>
+#include <linux/basic_mmio_gpio.h>
+
+#define DRV_NAME               "sdv_gpio"
+#define SDV_NUM_PUB_GPIOS      12
+#define PCI_DEVICE_ID_SDV_GPIO 0x2e67
+#define GPIO_BAR               0
+
+#define GPOUTR         0x00
+#define GPOER          0x04
+#define GPINR          0x08
+
+#define GPSTR          0x0c
+#define GPIT1R0                0x10
+#define GPIO_INT       0x14
+#define GPIT1R1                0x18
+
+#define GPMUXCTL       0x1c
+
+struct sdv_gpio_chip_data {
+       int irq_base;
+       void __iomem *gpio_pub_base;
+       struct irq_domain id;
+       struct irq_chip_generic *gc;
+       struct bgpio_chip bgpio;
+};
+
+static int sdv_gpio_pub_set_type(struct irq_data *d, unsigned int type)
+{
+       struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+       struct sdv_gpio_chip_data *sd = gc->private;
+       void __iomem *type_reg;
+       u32 irq_offs = d->irq - sd->irq_base;
+       u32 reg;
+
+       if (irq_offs < 8)
+               type_reg = sd->gpio_pub_base + GPIT1R0;
+       else
+               type_reg = sd->gpio_pub_base + GPIT1R1;
+
+       reg = readl(type_reg);
+
+       switch (type) {
+       case IRQ_TYPE_LEVEL_HIGH:
+               reg &= ~BIT(4 * (irq_offs % 8));
+               break;
+
+       case IRQ_TYPE_LEVEL_LOW:
+               reg |= BIT(4 * (irq_offs % 8));
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       writel(reg, type_reg);
+       return 0;
+}
+
+static irqreturn_t sdv_gpio_pub_irq_handler(int irq, void *data)
+{
+       struct sdv_gpio_chip_data *sd = data;
+       u32 irq_stat = readl(sd->gpio_pub_base + GPSTR);
+
+       irq_stat &= readl(sd->gpio_pub_base + GPIO_INT);
+       if (!irq_stat)
+               return IRQ_NONE;
+
+       while (irq_stat) {
+               u32 irq_bit = __fls(irq_stat);
+
+               irq_stat &= ~BIT(irq_bit);
+               generic_handle_irq(sd->irq_base + irq_bit);
+       }
+
+       return IRQ_HANDLED;
+}
+
+static int sdv_xlate(struct irq_domain *h, struct device_node *node,
+               const u32 *intspec, u32 intsize, irq_hw_number_t *out_hwirq,
+               u32 *out_type)
+{
+       u32 line, type;
+
+       if (node != h->of_node)
+               return -EINVAL;
+
+       if (intsize < 2)
+               return -EINVAL;
+
+       line = *intspec;
+       *out_hwirq = line;
+
+       intspec++;
+       type = *intspec;
+
+       switch (type) {
+       case IRQ_TYPE_LEVEL_LOW:
+       case IRQ_TYPE_LEVEL_HIGH:
+               *out_type = type;
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static struct irq_domain_ops irq_domain_sdv_ops = {
+       .dt_translate   = sdv_xlate,
+};
+
+static __devinit int sdv_register_irqsupport(struct sdv_gpio_chip_data *sd,
+               struct pci_dev *pdev)
+{
+       struct irq_chip_type *ct;
+       int ret;
+
+       sd->irq_base = irq_alloc_descs(-1, 0, SDV_NUM_PUB_GPIOS, -1);
+       if (sd->irq_base < 0)
+               return sd->irq_base;
+
+       /* mask + ACK all interrupt sources */
+       writel(0, sd->gpio_pub_base + GPIO_INT);
+       writel((1 << 11) - 1, sd->gpio_pub_base + GPSTR);
+
+       ret = request_irq(pdev->irq, sdv_gpio_pub_irq_handler, IRQF_SHARED,
+                       "sdv_gpio", sd);
+       if (ret)
+               goto out_free_desc;
+
+       sd->id.irq_base = sd->irq_base;
+       sd->id.of_node = of_node_get(pdev->dev.of_node);
+       sd->id.ops = &irq_domain_sdv_ops;
+
+       /*
+        * This gpio irq controller latches level irqs. Testing shows that if
+        * we unmask & ACK the IRQ before the source of the interrupt is gone
+        * then the interrupt is active again.
+        */
+       sd->gc = irq_alloc_generic_chip("sdv-gpio", 1, sd->irq_base,
+                       sd->gpio_pub_base, handle_fasteoi_irq);
+       if (!sd->gc) {
+               ret = -ENOMEM;
+               goto out_free_irq;
+       }
+
+       sd->gc->private = sd;
+       ct = sd->gc->chip_types;
+       ct->type = IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW;
+       ct->regs.eoi = GPSTR;
+       ct->regs.mask = GPIO_INT;
+       ct->chip.irq_mask = irq_gc_mask_clr_bit;
+       ct->chip.irq_unmask = irq_gc_mask_set_bit;
+       ct->chip.irq_eoi = irq_gc_eoi;
+       ct->chip.irq_set_type = sdv_gpio_pub_set_type;
+
+       irq_setup_generic_chip(sd->gc, IRQ_MSK(SDV_NUM_PUB_GPIOS),
+                       IRQ_GC_INIT_MASK_CACHE, IRQ_NOREQUEST,
+                       IRQ_LEVEL | IRQ_NOPROBE);
+
+       irq_domain_add(&sd->id);
+       return 0;
+out_free_irq:
+       free_irq(pdev->irq, sd);
+out_free_desc:
+       irq_free_descs(sd->irq_base, SDV_NUM_PUB_GPIOS);
+       return ret;
+}
+
+static int __devinit sdv_gpio_probe(struct pci_dev *pdev,
+                                       const struct pci_device_id *pci_id)
+{
+       struct sdv_gpio_chip_data *sd;
+       unsigned long addr;
+       const void *prop;
+       int len;
+       int ret;
+       u32 mux_val;
+
+       sd = kzalloc(sizeof(struct sdv_gpio_chip_data), GFP_KERNEL);
+       if (!sd)
+               return -ENOMEM;
+       ret = pci_enable_device(pdev);
+       if (ret) {
+               dev_err(&pdev->dev, "can't enable device.\n");
+               goto done;
+       }
+
+       ret = pci_request_region(pdev, GPIO_BAR, DRV_NAME);
+       if (ret) {
+               dev_err(&pdev->dev, "can't alloc PCI BAR #%d\n", GPIO_BAR);
+               goto disable_pci;
+       }
+
+       addr = pci_resource_start(pdev, GPIO_BAR);
+       if (!addr)
+               goto release_reg;
+       sd->gpio_pub_base = ioremap(addr, pci_resource_len(pdev, GPIO_BAR));
+
+       prop = of_get_property(pdev->dev.of_node, "intel,muxctl", &len);
+       if (prop && len == 4) {
+               mux_val = of_read_number(prop, 1);
+               writel(mux_val, sd->gpio_pub_base + GPMUXCTL);
+       }
+
+       ret = bgpio_init(&sd->bgpio, &pdev->dev, 4,
+                       sd->gpio_pub_base + GPINR, sd->gpio_pub_base + GPOUTR,
+                       NULL, sd->gpio_pub_base + GPOER, NULL, false);
+       if (ret)
+               goto unmap;
+       sd->bgpio.gc.ngpio = SDV_NUM_PUB_GPIOS;
+
+       ret = gpiochip_add(&sd->bgpio.gc);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "gpiochip_add() failed.\n");
+               goto unmap;
+       }
+
+       ret = sdv_register_irqsupport(sd, pdev);
+       if (ret)
+               goto unmap;
+
+       pci_set_drvdata(pdev, sd);
+       dev_info(&pdev->dev, "Sodaville GPIO driver registered.\n");
+       return 0;
+
+unmap:
+       iounmap(sd->gpio_pub_base);
+release_reg:
+       pci_release_region(pdev, GPIO_BAR);
+disable_pci:
+       pci_disable_device(pdev);
+done:
+       kfree(sd);
+       return ret;
+}
+
+static void sdv_gpio_remove(struct pci_dev *pdev)
+{
+       struct sdv_gpio_chip_data *sd = pci_get_drvdata(pdev);
+
+       irq_domain_del(&sd->id);
+       free_irq(pdev->irq, sd);
+       irq_free_descs(sd->irq_base, SDV_NUM_PUB_GPIOS);
+
+       if (gpiochip_remove(&sd->bgpio.gc))
+               dev_err(&pdev->dev, "gpiochip_remove() failed.\n");
+
+       pci_release_region(pdev, GPIO_BAR);
+       iounmap(sd->gpio_pub_base);
+       pci_disable_device(pdev);
+       kfree(sd);
+}
+
+static struct pci_device_id sdv_gpio_pci_ids[] __devinitdata = {
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_SDV_GPIO) },
+       { 0, },
+};
+
+static struct pci_driver sdv_gpio_driver = {
+       .name = DRV_NAME,
+       .id_table = sdv_gpio_pci_ids,
+       .probe = sdv_gpio_probe,
+       .remove = sdv_gpio_remove,
+};
+
+static int __init sdv_gpio_init(void)
+{
+       return pci_register_driver(&sdv_gpio_driver);
+}
+module_init(sdv_gpio_init);
+
+static void __exit sdv_gpio_exit(void)
+{
+       pci_unregister_driver(&sdv_gpio_driver);
+}
+module_exit(sdv_gpio_exit);
+
+MODULE_AUTHOR("Hans J. Koch <hjk@linutronix.de>");
+MODULE_DESCRIPTION("GPIO interface for Intel Sodaville SoCs");
+MODULE_LICENSE("GPL v2");
index 87a68a8..dce3472 100644 (file)
@@ -54,7 +54,7 @@ static int stmpe_gpio_get(struct gpio_chip *chip, unsigned offset)
        if (ret < 0)
                return ret;
 
-       return ret & mask;
+       return !!(ret & mask);
 }
 
 static void stmpe_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
@@ -307,13 +307,11 @@ static int __devinit stmpe_gpio_probe(struct platform_device *pdev)
        struct stmpe_gpio_platform_data *pdata;
        struct stmpe_gpio *stmpe_gpio;
        int ret;
-       int irq;
+       int irq = 0;
 
        pdata = stmpe->pdata->gpio;
 
        irq = platform_get_irq(pdev, 0);
-       if (irq < 0)
-               return irq;
 
        stmpe_gpio = kzalloc(sizeof(struct stmpe_gpio), GFP_KERNEL);
        if (!stmpe_gpio)
@@ -330,21 +328,28 @@ static int __devinit stmpe_gpio_probe(struct platform_device *pdev)
        stmpe_gpio->chip.dev = &pdev->dev;
        stmpe_gpio->chip.base = pdata ? pdata->gpio_base : -1;
 
-       stmpe_gpio->irq_base = stmpe->irq_base + STMPE_INT_GPIO(0);
+       if (irq >= 0)
+               stmpe_gpio->irq_base = stmpe->irq_base + STMPE_INT_GPIO(0);
+       else
+               dev_info(&pdev->dev,
+                       "device configured in no-irq mode; "
+                       "irqs are not available\n");
 
        ret = stmpe_enable(stmpe, STMPE_BLOCK_GPIO);
        if (ret)
                goto out_free;
 
-       ret = stmpe_gpio_irq_init(stmpe_gpio);
-       if (ret)
-               goto out_disable;
+       if (irq >= 0) {
+               ret = stmpe_gpio_irq_init(stmpe_gpio);
+               if (ret)
+                       goto out_disable;
 
-       ret = request_threaded_irq(irq, NULL, stmpe_gpio_irq, IRQF_ONESHOT,
-                                  "stmpe-gpio", stmpe_gpio);
-       if (ret) {
-               dev_err(&pdev->dev, "unable to get irq: %d\n", ret);
-               goto out_removeirq;
+               ret = request_threaded_irq(irq, NULL, stmpe_gpio_irq,
+                               IRQF_ONESHOT, "stmpe-gpio", stmpe_gpio);
+               if (ret) {
+                       dev_err(&pdev->dev, "unable to get irq: %d\n", ret);
+                       goto out_removeirq;
+               }
        }
 
        ret = gpiochip_add(&stmpe_gpio->chip);
@@ -361,9 +366,11 @@ static int __devinit stmpe_gpio_probe(struct platform_device *pdev)
        return 0;
 
 out_freeirq:
-       free_irq(irq, stmpe_gpio);
+       if (irq >= 0)
+               free_irq(irq, stmpe_gpio);
 out_removeirq:
-       stmpe_gpio_irq_remove(stmpe_gpio);
+       if (irq >= 0)
+               stmpe_gpio_irq_remove(stmpe_gpio);
 out_disable:
        stmpe_disable(stmpe, STMPE_BLOCK_GPIO);
 out_free:
@@ -391,8 +398,10 @@ static int __devexit stmpe_gpio_remove(struct platform_device *pdev)
 
        stmpe_disable(stmpe, STMPE_BLOCK_GPIO);
 
-       free_irq(irq, stmpe_gpio);
-       stmpe_gpio_irq_remove(stmpe_gpio);
+       if (irq >= 0) {
+               free_irq(irq, stmpe_gpio);
+               stmpe_gpio_irq_remove(stmpe_gpio);
+       }
        platform_set_drvdata(pdev, NULL);
        kfree(stmpe_gpio);
 
index 6f17671..32de670 100644 (file)
@@ -109,11 +109,13 @@ void tegra_gpio_enable(int gpio)
 {
        tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 1);
 }
+EXPORT_SYMBOL_GPL(tegra_gpio_enable);
 
 void tegra_gpio_disable(int gpio)
 {
        tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 0);
 }
+EXPORT_SYMBOL_GPL(tegra_gpio_disable);
 
 static void tegra_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 {
@@ -459,7 +461,7 @@ static int __init tegra_gpio_init(void)
 }
 postcore_initcall(tegra_gpio_init);
 
-void __init tegra_gpio_config(struct tegra_gpio_table *table, int num)
+void tegra_gpio_config(struct tegra_gpio_table *table, int num)
 {
        int i;
 
index 91f45b9..7eef648 100644 (file)
@@ -69,6 +69,7 @@ static int tps65910_gpio_input(struct gpio_chip *gc, unsigned offset)
 void tps65910_gpio_init(struct tps65910 *tps65910, int gpio_base)
 {
        int ret;
+       struct tps65910_board *board_data;
 
        if (!gpio_base)
                return;
@@ -80,10 +81,10 @@ void tps65910_gpio_init(struct tps65910 *tps65910, int gpio_base)
 
        switch(tps65910_chip_id(tps65910)) {
        case TPS65910:
-               tps65910->gpio.ngpio    = 6;
+               tps65910->gpio.ngpio    = TPS65910_NUM_GPIO;
                break;
        case TPS65911:
-               tps65910->gpio.ngpio    = 9;
+               tps65910->gpio.ngpio    = TPS65911_NUM_GPIO;
                break;
        default:
                return;
@@ -95,6 +96,21 @@ void tps65910_gpio_init(struct tps65910 *tps65910, int gpio_base)
        tps65910->gpio.set              = tps65910_gpio_set;
        tps65910->gpio.get              = tps65910_gpio_get;
 
+       /* Configure sleep control for gpios */
+       board_data = dev_get_platdata(tps65910->dev);
+       if (board_data) {
+               int i;
+               for (i = 0; i < tps65910->gpio.ngpio; ++i) {
+                       if (board_data->en_gpio_sleep[i]) {
+                               ret = tps65910_set_bits(tps65910,
+                                       TPS65910_GPIO0 + i, GPIO_SLEEP_MASK);
+                               if (ret < 0)
+                                       dev_warn(tps65910->dev,
+                                               "GPIO Sleep setting failed\n");
+                       }
+               }
+       }
+
        ret = gpiochip_add(&tps65910->gpio);
 
        if (ret)
index b8b4f22..94256fe 100644 (file)
@@ -32,6 +32,8 @@
 #include <linux/irq.h>
 #include <linux/gpio.h>
 #include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/irqdomain.h>
 
 #include <linux/i2c/twl.h>
 
@@ -256,7 +258,8 @@ static int twl_request(struct gpio_chip *chip, unsigned offset)
                 * and vMMC2 power supplies based on card presence.
                 */
                pdata = chip->dev->platform_data;
-               value |= pdata->mmc_cd & 0x03;
+               if (pdata)
+                       value |= pdata->mmc_cd & 0x03;
 
                status = gpio_twl4030_write(REG_GPIO_CTRL, value);
        }
@@ -395,59 +398,70 @@ static int gpio_twl4030_remove(struct platform_device *pdev);
 static int __devinit gpio_twl4030_probe(struct platform_device *pdev)
 {
        struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data;
-       int ret;
+       struct device_node *node = pdev->dev.of_node;
+       int ret, irq_base;
 
        /* maybe setup IRQs */
-       if (pdata->irq_base) {
-               if (is_module()) {
-                       dev_err(&pdev->dev,
-                               "can't dispatch IRQs from modules\n");
-                       goto no_irqs;
-               }
-               ret = twl4030_sih_setup(TWL4030_MODULE_GPIO);
-               if (ret < 0)
-                       return ret;
-               WARN_ON(ret != pdata->irq_base);
-               twl4030_gpio_irq_base = ret;
+       if (is_module()) {
+               dev_err(&pdev->dev, "can't dispatch IRQs from modules\n");
+               goto no_irqs;
+       }
+
+       irq_base = irq_alloc_descs(-1, 0, TWL4030_GPIO_MAX, 0);
+       if (irq_base < 0) {
+               dev_err(&pdev->dev, "Failed to alloc irq_descs\n");
+               return irq_base;
        }
 
+       irq_domain_add_legacy(node, TWL4030_GPIO_MAX, irq_base, 0,
+                             &irq_domain_simple_ops, NULL);
+
+       ret = twl4030_sih_setup(&pdev->dev, TWL4030_MODULE_GPIO, irq_base);
+       if (ret < 0)
+               return ret;
+
+       twl4030_gpio_irq_base = irq_base;
+
 no_irqs:
-       /*
-        * NOTE:  boards may waste power if they don't set pullups
-        * and pulldowns correctly ... default for non-ULPI pins is
-        * pulldown, and some other pins may have external pullups
-        * or pulldowns.  Careful!
-        */
-       ret = gpio_twl4030_pulls(pdata->pullups, pdata->pulldowns);
-       if (ret)
-               dev_dbg(&pdev->dev, "pullups %.05x %.05x --> %d\n",
-                               pdata->pullups, pdata->pulldowns,
-                               ret);
-
-       ret = gpio_twl4030_debounce(pdata->debounce, pdata->mmc_cd);
-       if (ret)
-               dev_dbg(&pdev->dev, "debounce %.03x %.01x --> %d\n",
-                               pdata->debounce, pdata->mmc_cd,
-                               ret);
-
-       twl_gpiochip.base = pdata->gpio_base;
+       twl_gpiochip.base = -1;
        twl_gpiochip.ngpio = TWL4030_GPIO_MAX;
        twl_gpiochip.dev = &pdev->dev;
 
-       /* NOTE: we assume VIBRA_CTL.VIBRA_EN, in MODULE_AUDIO_VOICE,
-        * is (still) clear if use_leds is set.
-        */
-       if (pdata->use_leds)
-               twl_gpiochip.ngpio += 2;
+       if (pdata) {
+               twl_gpiochip.base = pdata->gpio_base;
+
+               /*
+                * NOTE:  boards may waste power if they don't set pullups
+                * and pulldowns correctly ... default for non-ULPI pins is
+                * pulldown, and some other pins may have external pullups
+                * or pulldowns.  Careful!
+                */
+               ret = gpio_twl4030_pulls(pdata->pullups, pdata->pulldowns);
+               if (ret)
+                       dev_dbg(&pdev->dev, "pullups %.05x %.05x --> %d\n",
+                                       pdata->pullups, pdata->pulldowns,
+                                       ret);
+
+               ret = gpio_twl4030_debounce(pdata->debounce, pdata->mmc_cd);
+               if (ret)
+                       dev_dbg(&pdev->dev, "debounce %.03x %.01x --> %d\n",
+                                       pdata->debounce, pdata->mmc_cd,
+                                       ret);
+
+               /*
+                * NOTE: we assume VIBRA_CTL.VIBRA_EN, in MODULE_AUDIO_VOICE,
+                * is (still) clear if use_leds is set.
+                */
+               if (pdata->use_leds)
+                       twl_gpiochip.ngpio += 2;
+       }
 
        ret = gpiochip_add(&twl_gpiochip);
        if (ret < 0) {
-               dev_err(&pdev->dev,
-                               "could not register gpiochip, %d\n",
-                               ret);
+               dev_err(&pdev->dev, "could not register gpiochip, %d\n", ret);
                twl_gpiochip.ngpio = 0;
                gpio_twl4030_remove(pdev);
-       } else if (pdata->setup) {
+       } else if (pdata && pdata->setup) {
                int status;
 
                status = pdata->setup(&pdev->dev,
@@ -465,7 +479,7 @@ static int gpio_twl4030_remove(struct platform_device *pdev)
        struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data;
        int status;
 
-       if (pdata->teardown) {
+       if (pdata && pdata->teardown) {
                status = pdata->teardown(&pdev->dev,
                                pdata->gpio_base, TWL4030_GPIO_MAX);
                if (status) {
@@ -486,12 +500,21 @@ static int gpio_twl4030_remove(struct platform_device *pdev)
        return -EIO;
 }
 
+static const struct of_device_id twl_gpio_match[] = {
+       { .compatible = "ti,twl4030-gpio", },
+       { },
+};
+MODULE_DEVICE_TABLE(of, twl_gpio_match);
+
 /* Note:  this hardware lives inside an I2C-based multi-function device. */
 MODULE_ALIAS("platform:twl4030_gpio");
 
 static struct platform_driver gpio_twl4030_driver = {
-       .driver.name    = "twl4030_gpio",
-       .driver.owner   = THIS_MODULE,
+       .driver = {
+               .name   = "twl4030_gpio",
+               .owner  = THIS_MODULE,
+               .of_match_table = of_match_ptr(twl_gpio_match),
+       },
        .probe          = gpio_twl4030_probe,
        .remove         = gpio_twl4030_remove,
 };
index 17fdf4b..5a75510 100644 (file)
@@ -58,6 +58,8 @@ struct gpio_desc {
 #define FLAG_TRIG_FALL 5       /* trigger on falling edge */
 #define FLAG_TRIG_RISE 6       /* trigger on rising edge */
 #define FLAG_ACTIVE_LOW        7       /* sysfs value has active low */
+#define FLAG_OPEN_DRAIN        8       /* Gpio is open drain type */
+#define FLAG_OPEN_SOURCE 9     /* Gpio is open source type */
 
 #define ID_SHIFT       16      /* add new flags before this one */
 
@@ -873,6 +875,7 @@ void gpio_unexport(unsigned gpio)
 {
        struct gpio_desc        *desc;
        int                     status = 0;
+       struct device           *dev = NULL;
 
        if (!gpio_is_valid(gpio)) {
                status = -EINVAL;
@@ -884,19 +887,20 @@ void gpio_unexport(unsigned gpio)
        desc = &gpio_desc[gpio];
 
        if (test_bit(FLAG_EXPORT, &desc->flags)) {
-               struct device   *dev = NULL;
 
                dev = class_find_device(&gpio_class, NULL, desc, match_export);
                if (dev) {
                        gpio_setup_irq(desc, dev, 0);
                        clear_bit(FLAG_EXPORT, &desc->flags);
-                       put_device(dev);
-                       device_unregister(dev);
                } else
                        status = -ENODEV;
        }
 
        mutex_unlock(&sysfs_lock);
+       if (dev) {
+               device_unregister(dev);
+               put_device(dev);
+       }
 done:
        if (status)
                pr_debug("%s: gpio%d status %d\n", __func__, gpio, status);
@@ -1150,8 +1154,9 @@ EXPORT_SYMBOL_GPL(gpiochip_remove);
  * non-zero, this function will return to the caller and not iterate over any
  * more gpio_chips.
  */
-struct gpio_chip *gpiochip_find(void *data,
-                               int (*match)(struct gpio_chip *chip, void *data))
+struct gpio_chip *gpiochip_find(const void *data,
+                               int (*match)(struct gpio_chip *chip,
+                                            const void *data))
 {
        struct gpio_chip *chip = NULL;
        unsigned long flags;
@@ -1261,6 +1266,8 @@ void gpio_free(unsigned gpio)
                module_put(desc->chip->owner);
                clear_bit(FLAG_ACTIVE_LOW, &desc->flags);
                clear_bit(FLAG_REQUESTED, &desc->flags);
+               clear_bit(FLAG_OPEN_DRAIN, &desc->flags);
+               clear_bit(FLAG_OPEN_SOURCE, &desc->flags);
        } else
                WARN_ON(extra_checks);
 
@@ -1282,6 +1289,12 @@ int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
        if (err)
                return err;
 
+       if (flags & GPIOF_OPEN_DRAIN)
+               set_bit(FLAG_OPEN_DRAIN, &gpio_desc[gpio].flags);
+
+       if (flags & GPIOF_OPEN_SOURCE)
+               set_bit(FLAG_OPEN_SOURCE, &gpio_desc[gpio].flags);
+
        if (flags & GPIOF_DIR_IN)
                err = gpio_direction_input(gpio);
        else
@@ -1431,6 +1444,14 @@ int gpio_direction_output(unsigned gpio, int value)
        struct gpio_desc        *desc = &gpio_desc[gpio];
        int                     status = -EINVAL;
 
+       /* Open drain pin should not be driven to 1 */
+       if (value && test_bit(FLAG_OPEN_DRAIN,  &desc->flags))
+               return gpio_direction_input(gpio);
+
+       /* Open source pin should not be driven to 0 */
+       if (!value && test_bit(FLAG_OPEN_SOURCE,  &desc->flags))
+               return gpio_direction_input(gpio);
+
        spin_lock_irqsave(&gpio_lock, flags);
 
        if (!gpio_is_valid(gpio))
@@ -1560,6 +1581,7 @@ int __gpio_get_value(unsigned gpio)
        int value;
 
        chip = gpio_to_chip(gpio);
+       /* Should be using gpio_get_value_cansleep() */
        WARN_ON(chip->can_sleep);
        value = chip->get ? chip->get(chip, gpio - chip->base) : 0;
        trace_gpio_value(gpio, 1, value);
@@ -1567,6 +1589,57 @@ int __gpio_get_value(unsigned gpio)
 }
 EXPORT_SYMBOL_GPL(__gpio_get_value);
 
+/*
+ *  _gpio_set_open_drain_value() - Set the open drain gpio's value.
+ * @gpio: Gpio whose state need to be set.
+ * @chip: Gpio chip.
+ * @value: Non-zero for setting it HIGH otherise it will set to LOW.
+ */
+static void _gpio_set_open_drain_value(unsigned gpio,
+                       struct gpio_chip *chip, int value)
+{
+       int err = 0;
+       if (value) {
+               err = chip->direction_input(chip, gpio - chip->base);
+               if (!err)
+                       clear_bit(FLAG_IS_OUT, &gpio_desc[gpio].flags);
+       } else {
+               err = chip->direction_output(chip, gpio - chip->base, 0);
+               if (!err)
+                       set_bit(FLAG_IS_OUT, &gpio_desc[gpio].flags);
+       }
+       trace_gpio_direction(gpio, value, err);
+       if (err < 0)
+               pr_err("%s: Error in set_value for open drain gpio%d err %d\n",
+                                       __func__, gpio, err);
+}
+
+/*
+ *  _gpio_set_open_source() - Set the open source gpio's value.
+ * @gpio: Gpio whose state need to be set.
+ * @chip: Gpio chip.
+ * @value: Non-zero for setting it HIGH otherise it will set to LOW.
+ */
+static void _gpio_set_open_source_value(unsigned gpio,
+                       struct gpio_chip *chip, int value)
+{
+       int err = 0;
+       if (value) {
+               err = chip->direction_output(chip, gpio - chip->base, 1);
+               if (!err)
+                       set_bit(FLAG_IS_OUT, &gpio_desc[gpio].flags);
+       } else {
+               err = chip->direction_input(chip, gpio - chip->base);
+               if (!err)
+                       clear_bit(FLAG_IS_OUT, &gpio_desc[gpio].flags);
+       }
+       trace_gpio_direction(gpio, !value, err);
+       if (err < 0)
+               pr_err("%s: Error in set_value for open source gpio%d err %d\n",
+                                       __func__, gpio, err);
+}
+
+
 /**
  * __gpio_set_value() - assign a gpio's value
  * @gpio: gpio whose value will be assigned
@@ -1581,9 +1654,15 @@ void __gpio_set_value(unsigned gpio, int value)
        struct gpio_chip        *chip;
 
        chip = gpio_to_chip(gpio);
+       /* Should be using gpio_set_value_cansleep() */
        WARN_ON(chip->can_sleep);
        trace_gpio_value(gpio, 0, value);
-       chip->set(chip, gpio - chip->base, value);
+       if (test_bit(FLAG_OPEN_DRAIN,  &gpio_desc[gpio].flags))
+               _gpio_set_open_drain_value(gpio, chip, value);
+       else if (test_bit(FLAG_OPEN_SOURCE,  &gpio_desc[gpio].flags))
+               _gpio_set_open_source_value(gpio, chip, value);
+       else
+               chip->set(chip, gpio - chip->base, value);
 }
 EXPORT_SYMBOL_GPL(__gpio_set_value);
 
@@ -1650,7 +1729,12 @@ void gpio_set_value_cansleep(unsigned gpio, int value)
        might_sleep_if(extra_checks);
        chip = gpio_to_chip(gpio);
        trace_gpio_value(gpio, 0, value);
-       chip->set(chip, gpio - chip->base, value);
+       if (test_bit(FLAG_OPEN_DRAIN,  &gpio_desc[gpio].flags))
+               _gpio_set_open_drain_value(gpio, chip, value);
+       else if (test_bit(FLAG_OPEN_SOURCE,  &gpio_desc[gpio].flags))
+               _gpio_set_open_source_value(gpio, chip, value);
+       else
+               chip->set(chip, gpio - chip->base, value);
 }
 EXPORT_SYMBOL_GPL(gpio_set_value_cansleep);
 
index 4c2cb4a..5675d93 100644 (file)
@@ -244,7 +244,6 @@ static int mdfld_dsi_connector_set_property(struct drm_connector *connector,
                                uint64_t value)
 {
        struct drm_encoder *encoder = connector->encoder;
-       struct backlight_device *psb_bd;
 
        if (!strcmp(property->name, "scaling mode") && encoder) {
                struct psb_intel_crtc *psb_crtc =
@@ -301,11 +300,15 @@ static int mdfld_dsi_connector_set_property(struct drm_connector *connector,
                                                                        value))
                        goto set_prop_error;
                else {
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+                       struct backlight_device *psb_bd;
+
                        psb_bd = mdfld_get_backlight_device();
                        if (psb_bd) {
                                psb_bd->props.brightness = value;
                                mdfld_set_brightness(psb_bd);
                        }
+#endif
                }
        }
 set_prop_done:
index 8f510fd..fa86035 100644 (file)
@@ -654,10 +654,13 @@ nouveau_connector_detect_depth(struct drm_connector *connector)
        if (nv_connector->edid && connector->display_info.bpc)
                return;
 
-       /* if not, we're out of options unless we're LVDS, default to 6bpc */
-       connector->display_info.bpc = 6;
-       if (nv_encoder->dcb->type != OUTPUT_LVDS)
+       /* if not, we're out of options unless we're LVDS, default to 8bpc */
+       if (nv_encoder->dcb->type != OUTPUT_LVDS) {
+               connector->display_info.bpc = 8;
                return;
+       }
+
+       connector->display_info.bpc = 6;
 
        /* LVDS: panel straps */
        if (bios->fp_no_ddc) {
index 8f4f914..e2be95a 100644 (file)
@@ -315,8 +315,8 @@ nouveau_i2c_init(struct drm_device *dev)
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nvbios *bios = &dev_priv->vbios;
        struct nouveau_i2c_chan *port;
+       u8 version = 0x00, entries, recordlen;
        u8 *i2c, *entry, legacy[2][4] = {};
-       u8 version, entries, recordlen;
        int ret, i;
 
        INIT_LIST_HEAD(&dev_priv->i2c_ports);
@@ -346,12 +346,12 @@ nouveau_i2c_init(struct drm_device *dev)
                if (i2c[7]) legacy[1][1] = i2c[7];
        }
 
-       if (i2c && version >= 0x30) {
+       if (version >= 0x30) {
                entry     = i2c[1] + i2c;
                entries   = i2c[2];
                recordlen = i2c[3];
        } else
-       if (i2c) {
+       if (version) {
                entry     = i2c;
                entries   = 16;
                recordlen = 4;
index a3ae91f..a4886b3 100644 (file)
@@ -852,7 +852,7 @@ nouveau_card_init(struct drm_device *dev)
        if (ret)
                goto out_pm;
 
-       if (!dev_priv->noaccel) {
+       if (dev_priv->eng[NVOBJ_ENGINE_GR]) {
                ret = nouveau_card_channel_init(dev);
                if (ret)
                        goto out_fence;
index 083b3ea..b5ff1f7 100644 (file)
@@ -588,8 +588,8 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
                if (encoder->crtc == crtc) {
                        radeon_encoder = to_radeon_encoder(encoder);
                        connector = radeon_get_connector_for_encoder(encoder);
-                       if (connector && connector->display_info.bpc)
-                               bpc = connector->display_info.bpc;
+                       /* if (connector && connector->display_info.bpc)
+                               bpc = connector->display_info.bpc; */
                        encoder_mode = atombios_get_encoder_mode(encoder);
                        is_duallink = radeon_dig_monitor_is_duallink(encoder, mode->clock);
                        if ((radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) ||
@@ -965,7 +965,9 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode
                struct radeon_connector_atom_dig *dig_connector =
                        radeon_connector->con_priv;
                int dp_clock;
-               bpc = connector->display_info.bpc;
+
+               /* if (connector->display_info.bpc)
+                       bpc = connector->display_info.bpc; */
 
                switch (encoder_mode) {
                case ATOM_ENCODER_MODE_DP_MST:
index 6c62be2..c57d856 100644 (file)
@@ -405,10 +405,13 @@ static void dp_get_adjust_train(u8 link_status[DP_LINK_STATUS_SIZE],
 /* get bpc from the EDID */
 static int convert_bpc_to_bpp(int bpc)
 {
+#if 0
        if (bpc == 0)
                return 24;
        else
                return bpc * 3;
+#endif
+       return 24;
 }
 
 /* get the max pix clock supported by the link rate and lane num */
index 468b874..e607c4d 100644 (file)
@@ -541,7 +541,7 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mo
                dp_clock = dig_connector->dp_clock;
                dp_lane_count = dig_connector->dp_lane_count;
                hpd_id = radeon_connector->hpd.hpd;
-               bpc = connector->display_info.bpc;
+               /* bpc = connector->display_info.bpc; */
        }
 
        /* no dig encoder assigned */
@@ -1159,7 +1159,7 @@ atombios_external_encoder_setup(struct drm_encoder *encoder,
                dp_lane_count = dig_connector->dp_lane_count;
                connector_object_id =
                        (radeon_connector->connector_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
-               bpc = connector->display_info.bpc;
+               /* bpc = connector->display_info.bpc; */
        }
 
        memset(&args, 0, sizeof(args));
index a58b37a..70089d3 100644 (file)
@@ -80,6 +80,9 @@ struct evergreen_cs_track {
        bool                    cb_dirty;
        bool                    db_dirty;
        bool                    streamout_dirty;
+       u32                     htile_offset;
+       u32                     htile_surface;
+       struct radeon_bo        *htile_bo;
 };
 
 static u32 evergreen_cs_get_aray_mode(u32 tiling_flags)
@@ -144,6 +147,9 @@ static void evergreen_cs_track_init(struct evergreen_cs_track *track)
        track->db_s_read_bo = NULL;
        track->db_s_write_bo = NULL;
        track->db_dirty = true;
+       track->htile_bo = NULL;
+       track->htile_offset = 0xFFFFFFFF;
+       track->htile_surface = 0;
 
        for (i = 0; i < 4; i++) {
                track->vgt_strmout_size[i] = 0;
@@ -444,6 +450,62 @@ static int evergreen_cs_track_validate_cb(struct radeon_cs_parser *p, unsigned i
        return 0;
 }
 
+static int evergreen_cs_track_validate_htile(struct radeon_cs_parser *p,
+                                               unsigned nbx, unsigned nby)
+{
+       struct evergreen_cs_track *track = p->track;
+       unsigned long size;
+
+       if (track->htile_bo == NULL) {
+               dev_warn(p->dev, "%s:%d htile enabled without htile surface 0x%08x\n",
+                               __func__, __LINE__, track->db_z_info);
+               return -EINVAL;
+       }
+
+       if (G_028ABC_LINEAR(track->htile_surface)) {
+               /* pitch must be 16 htiles aligned == 16 * 8 pixel aligned */
+               nbx = round_up(nbx, 16 * 8);
+               /* height is npipes htiles aligned == npipes * 8 pixel aligned */
+               nby = round_up(nby, track->npipes * 8);
+       } else {
+               switch (track->npipes) {
+               case 8:
+                       nbx = round_up(nbx, 64 * 8);
+                       nby = round_up(nby, 64 * 8);
+                       break;
+               case 4:
+                       nbx = round_up(nbx, 64 * 8);
+                       nby = round_up(nby, 32 * 8);
+                       break;
+               case 2:
+                       nbx = round_up(nbx, 32 * 8);
+                       nby = round_up(nby, 32 * 8);
+                       break;
+               case 1:
+                       nbx = round_up(nbx, 32 * 8);
+                       nby = round_up(nby, 16 * 8);
+                       break;
+               default:
+                       dev_warn(p->dev, "%s:%d invalid num pipes %d\n",
+                                       __func__, __LINE__, track->npipes);
+                       return -EINVAL;
+               }
+       }
+       /* compute number of htile */
+       nbx = nbx / 8;
+       nby = nby / 8;
+       size = nbx * nby * 4;
+       size += track->htile_offset;
+
+       if (size > radeon_bo_size(track->htile_bo)) {
+               dev_warn(p->dev, "%s:%d htile surface too small %ld for %ld (%d %d)\n",
+                               __func__, __LINE__, radeon_bo_size(track->htile_bo),
+                               size, nbx, nby);
+               return -EINVAL;
+       }
+       return 0;
+}
+
 static int evergreen_cs_track_validate_stencil(struct radeon_cs_parser *p)
 {
        struct evergreen_cs_track *track = p->track;
@@ -530,6 +592,14 @@ static int evergreen_cs_track_validate_stencil(struct radeon_cs_parser *p)
                return -EINVAL;
        }
 
+       /* hyperz */
+       if (G_028040_TILE_SURFACE_ENABLE(track->db_z_info)) {
+               r = evergreen_cs_track_validate_htile(p, surf.nbx, surf.nby);
+               if (r) {
+                       return r;
+               }
+       }
+
        return 0;
 }
 
@@ -617,6 +687,14 @@ static int evergreen_cs_track_validate_depth(struct radeon_cs_parser *p)
                return -EINVAL;
        }
 
+       /* hyperz */
+       if (G_028040_TILE_SURFACE_ENABLE(track->db_z_info)) {
+               r = evergreen_cs_track_validate_htile(p, surf.nbx, surf.nby);
+               if (r) {
+                       return r;
+               }
+       }
+
        return 0;
 }
 
@@ -850,7 +928,7 @@ static int evergreen_cs_track_check(struct radeon_cs_parser *p)
                                return r;
                }
                /* Check depth buffer */
-               if (G_028800_Z_WRITE_ENABLE(track->db_depth_control)) {
+               if (G_028800_Z_ENABLE(track->db_depth_control)) {
                        r = evergreen_cs_track_validate_depth(p);
                        if (r)
                                return r;
@@ -1616,6 +1694,23 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
                track->cb_color_bo[tmp] = reloc->robj;
                track->cb_dirty = true;
                break;
+       case DB_HTILE_DATA_BASE:
+               r = evergreen_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       dev_warn(p->dev, "bad SET_CONTEXT_REG "
+                                       "0x%04X\n", reg);
+                       return -EINVAL;
+               }
+               track->htile_offset = radeon_get_ib_value(p, idx);
+               ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+               track->htile_bo = reloc->robj;
+               track->db_dirty = true;
+               break;
+       case DB_HTILE_SURFACE:
+               /* 8x8 only */
+               track->htile_surface = radeon_get_ib_value(p, idx);
+               track->db_dirty = true;
+               break;
        case CB_IMMED0_BASE:
        case CB_IMMED1_BASE:
        case CB_IMMED2_BASE:
@@ -1628,7 +1723,6 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
        case CB_IMMED9_BASE:
        case CB_IMMED10_BASE:
        case CB_IMMED11_BASE:
-       case DB_HTILE_DATA_BASE:
        case SQ_PGM_START_FS:
        case SQ_PGM_START_ES:
        case SQ_PGM_START_VS:
index eb5708c..b4eefc3 100644 (file)
 #define   G_028008_SLICE_MAX(x)                        (((x) >> 13) & 0x7FF)
 #define   C_028008_SLICE_MAX                           0xFF001FFF
 #define DB_HTILE_DATA_BASE                             0x28014
+#define DB_HTILE_SURFACE                               0x28abc
+#define   S_028ABC_HTILE_WIDTH(x)                      (((x) & 0x1) << 0)
+#define   G_028ABC_HTILE_WIDTH(x)                      (((x) >> 0) & 0x1)
+#define   C_028ABC_HTILE_WIDTH                         0xFFFFFFFE
+#define   S_028ABC_HTILE_HEIGHT(x)                      (((x) & 0x1) << 1)
+#define   G_028ABC_HTILE_HEIGHT(x)                      (((x) >> 1) & 0x1)
+#define   C_028ABC_HTILE_HEIGHT                         0xFFFFFFFD
+#define   G_028ABC_LINEAR(x)                           (((x) >> 2) & 0x1)
 #define DB_Z_INFO                                      0x28040
 #       define Z_ARRAY_MODE(x)                          ((x) << 4)
 #       define DB_TILE_SPLIT(x)                         (((x) & 0x7) << 8)
index 0ec3f20..b8e12af 100644 (file)
@@ -78,6 +78,9 @@ struct r600_cs_track {
        bool                    cb_dirty;
        bool                    db_dirty;
        bool                    streamout_dirty;
+       struct radeon_bo        *htile_bo;
+       u64                     htile_offset;
+       u32                     htile_surface;
 };
 
 #define FMT_8_BIT(fmt, vc)   [fmt] = { 1, 1, 1, vc, CHIP_R600 }
@@ -321,6 +324,9 @@ static void r600_cs_track_init(struct r600_cs_track *track)
        track->db_depth_size_idx = 0;
        track->db_depth_control = 0xFFFFFFFF;
        track->db_dirty = true;
+       track->htile_bo = NULL;
+       track->htile_offset = 0xFFFFFFFF;
+       track->htile_surface = 0;
 
        for (i = 0; i < 4; i++) {
                track->vgt_strmout_size[i] = 0;
@@ -455,12 +461,256 @@ static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
        return 0;
 }
 
+static int r600_cs_track_validate_db(struct radeon_cs_parser *p)
+{
+       struct r600_cs_track *track = p->track;
+       u32 nviews, bpe, ntiles, size, slice_tile_max, tmp;
+       u32 height_align, pitch_align, depth_align;
+       u32 pitch = 8192;
+       u32 height = 8192;
+       u64 base_offset, base_align;
+       struct array_mode_checker array_check;
+       int array_mode;
+       volatile u32 *ib = p->ib->ptr;
+
+
+       if (track->db_bo == NULL) {
+               dev_warn(p->dev, "z/stencil with no depth buffer\n");
+               return -EINVAL;
+       }
+       switch (G_028010_FORMAT(track->db_depth_info)) {
+       case V_028010_DEPTH_16:
+               bpe = 2;
+               break;
+       case V_028010_DEPTH_X8_24:
+       case V_028010_DEPTH_8_24:
+       case V_028010_DEPTH_X8_24_FLOAT:
+       case V_028010_DEPTH_8_24_FLOAT:
+       case V_028010_DEPTH_32_FLOAT:
+               bpe = 4;
+               break;
+       case V_028010_DEPTH_X24_8_32_FLOAT:
+               bpe = 8;
+               break;
+       default:
+               dev_warn(p->dev, "z/stencil with invalid format %d\n", G_028010_FORMAT(track->db_depth_info));
+               return -EINVAL;
+       }
+       if ((track->db_depth_size & 0xFFFFFC00) == 0xFFFFFC00) {
+               if (!track->db_depth_size_idx) {
+                       dev_warn(p->dev, "z/stencil buffer size not set\n");
+                       return -EINVAL;
+               }
+               tmp = radeon_bo_size(track->db_bo) - track->db_offset;
+               tmp = (tmp / bpe) >> 6;
+               if (!tmp) {
+                       dev_warn(p->dev, "z/stencil buffer too small (0x%08X %d %d %ld)\n",
+                                       track->db_depth_size, bpe, track->db_offset,
+                                       radeon_bo_size(track->db_bo));
+                       return -EINVAL;
+               }
+               ib[track->db_depth_size_idx] = S_028000_SLICE_TILE_MAX(tmp - 1) | (track->db_depth_size & 0x3FF);
+       } else {
+               size = radeon_bo_size(track->db_bo);
+               /* pitch in pixels */
+               pitch = (G_028000_PITCH_TILE_MAX(track->db_depth_size) + 1) * 8;
+               slice_tile_max = G_028000_SLICE_TILE_MAX(track->db_depth_size) + 1;
+               slice_tile_max *= 64;
+               height = slice_tile_max / pitch;
+               if (height > 8192)
+                       height = 8192;
+               base_offset = track->db_bo_mc + track->db_offset;
+               array_mode = G_028010_ARRAY_MODE(track->db_depth_info);
+               array_check.array_mode = array_mode;
+               array_check.group_size = track->group_size;
+               array_check.nbanks = track->nbanks;
+               array_check.npipes = track->npipes;
+               array_check.nsamples = track->nsamples;
+               array_check.blocksize = bpe;
+               if (r600_get_array_mode_alignment(&array_check,
+                                       &pitch_align, &height_align, &depth_align, &base_align)) {
+                       dev_warn(p->dev, "%s invalid tiling %d (0x%08X)\n", __func__,
+                                       G_028010_ARRAY_MODE(track->db_depth_info),
+                                       track->db_depth_info);
+                       return -EINVAL;
+               }
+               switch (array_mode) {
+               case V_028010_ARRAY_1D_TILED_THIN1:
+                       /* don't break userspace */
+                       height &= ~0x7;
+                       break;
+               case V_028010_ARRAY_2D_TILED_THIN1:
+                       break;
+               default:
+                       dev_warn(p->dev, "%s invalid tiling %d (0x%08X)\n", __func__,
+                                       G_028010_ARRAY_MODE(track->db_depth_info),
+                                       track->db_depth_info);
+                       return -EINVAL;
+               }
+
+               if (!IS_ALIGNED(pitch, pitch_align)) {
+                       dev_warn(p->dev, "%s:%d db pitch (%d, 0x%x, %d) invalid\n",
+                                       __func__, __LINE__, pitch, pitch_align, array_mode);
+                       return -EINVAL;
+               }
+               if (!IS_ALIGNED(height, height_align)) {
+                       dev_warn(p->dev, "%s:%d db height (%d, 0x%x, %d) invalid\n",
+                                       __func__, __LINE__, height, height_align, array_mode);
+                       return -EINVAL;
+               }
+               if (!IS_ALIGNED(base_offset, base_align)) {
+                       dev_warn(p->dev, "%s offset 0x%llx, 0x%llx, %d not aligned\n", __func__,
+                                       base_offset, base_align, array_mode);
+                       return -EINVAL;
+               }
+
+               ntiles = G_028000_SLICE_TILE_MAX(track->db_depth_size) + 1;
+               nviews = G_028004_SLICE_MAX(track->db_depth_view) + 1;
+               tmp = ntiles * bpe * 64 * nviews;
+               if ((tmp + track->db_offset) > radeon_bo_size(track->db_bo)) {
+                       dev_warn(p->dev, "z/stencil buffer (%d) too small (0x%08X %d %d %d -> %u have %lu)\n",
+                                       array_mode,
+                                       track->db_depth_size, ntiles, nviews, bpe, tmp + track->db_offset,
+                                       radeon_bo_size(track->db_bo));
+                       return -EINVAL;
+               }
+       }
+
+       /* hyperz */
+       if (G_028010_TILE_SURFACE_ENABLE(track->db_depth_info)) {
+               unsigned long size;
+               unsigned nbx, nby;
+
+               if (track->htile_bo == NULL) {
+                       dev_warn(p->dev, "%s:%d htile enabled without htile surface 0x%08x\n",
+                                __func__, __LINE__, track->db_depth_info);
+                       return -EINVAL;
+               }
+               if ((track->db_depth_size & 0xFFFFFC00) == 0xFFFFFC00) {
+                       dev_warn(p->dev, "%s:%d htile can't be enabled with bogus db_depth_size 0x%08x\n",
+                                __func__, __LINE__, track->db_depth_size);
+                       return -EINVAL;
+               }
+
+               nbx = pitch;
+               nby = height;
+               if (G_028D24_LINEAR(track->htile_surface)) {
+                       /* nbx must be 16 htiles aligned == 16 * 8 pixel aligned */
+                       nbx = round_up(nbx, 16 * 8);
+                       /* nby is npipes htiles aligned == npipes * 8 pixel aligned */
+                       nby = round_up(nby, track->npipes * 8);
+               } else {
+                       /* htile widht & nby (8 or 4) make 2 bits number */
+                       tmp = track->htile_surface & 3;
+                       /* align is htile align * 8, htile align vary according to
+                        * number of pipe and tile width and nby
+                        */
+                       switch (track->npipes) {
+                       case 8:
+                               switch (tmp) {
+                               case 3: /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/
+                                       nbx = round_up(nbx, 64 * 8);
+                                       nby = round_up(nby, 64 * 8);
+                                       break;
+                               case 2: /* HTILE_WIDTH = 4 & HTILE_HEIGHT = 8*/
+                               case 1: /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 4*/
+                                       nbx = round_up(nbx, 64 * 8);
+                                       nby = round_up(nby, 32 * 8);
+                                       break;
+                               case 0: /* HTILE_WIDTH = 4 & HTILE_HEIGHT = 4*/
+                                       nbx = round_up(nbx, 32 * 8);
+                                       nby = round_up(nby, 32 * 8);
+                                       break;
+                               default:
+                                       return -EINVAL;
+                               }
+                               break;
+                       case 4:
+                               switch (tmp) {
+                               case 3: /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/
+                                       nbx = round_up(nbx, 64 * 8);
+                                       nby = round_up(nby, 32 * 8);
+                                       break;
+                               case 2: /* HTILE_WIDTH = 4 & HTILE_HEIGHT = 8*/
+                               case 1: /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 4*/
+                                       nbx = round_up(nbx, 32 * 8);
+                                       nby = round_up(nby, 32 * 8);
+                                       break;
+                               case 0: /* HTILE_WIDTH = 4 & HTILE_HEIGHT = 4*/
+                                       nbx = round_up(nbx, 32 * 8);
+                                       nby = round_up(nby, 16 * 8);
+                                       break;
+                               default:
+                                       return -EINVAL;
+                               }
+                               break;
+                       case 2:
+                               switch (tmp) {
+                               case 3: /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/
+                                       nbx = round_up(nbx, 32 * 8);
+                                       nby = round_up(nby, 32 * 8);
+                                       break;
+                               case 2: /* HTILE_WIDTH = 4 & HTILE_HEIGHT = 8*/
+                               case 1: /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 4*/
+                                       nbx = round_up(nbx, 32 * 8);
+                                       nby = round_up(nby, 16 * 8);
+                                       break;
+                               case 0: /* HTILE_WIDTH = 4 & HTILE_HEIGHT = 4*/
+                                       nbx = round_up(nbx, 16 * 8);
+                                       nby = round_up(nby, 16 * 8);
+                                       break;
+                               default:
+                                       return -EINVAL;
+                               }
+                               break;
+                       case 1:
+                               switch (tmp) {
+                               case 3: /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/
+                                       nbx = round_up(nbx, 32 * 8);
+                                       nby = round_up(nby, 16 * 8);
+                                       break;
+                               case 2: /* HTILE_WIDTH = 4 & HTILE_HEIGHT = 8*/
+                               case 1: /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 4*/
+                                       nbx = round_up(nbx, 16 * 8);
+                                       nby = round_up(nby, 16 * 8);
+                                       break;
+                               case 0: /* HTILE_WIDTH = 4 & HTILE_HEIGHT = 4*/
+                                       nbx = round_up(nbx, 16 * 8);
+                                       nby = round_up(nby, 8 * 8);
+                                       break;
+                               default:
+                                       return -EINVAL;
+                               }
+                               break;
+                       default:
+                               dev_warn(p->dev, "%s:%d invalid num pipes %d\n",
+                                        __func__, __LINE__, track->npipes);
+                               return -EINVAL;
+                       }
+               }
+               /* compute number of htile */
+               nbx = G_028D24_HTILE_WIDTH(track->htile_surface) ? nbx / 8 : nbx / 4;
+               nby = G_028D24_HTILE_HEIGHT(track->htile_surface) ? nby / 8 : nby / 4;
+               size = nbx * nby * 4;
+               size += track->htile_offset;
+
+               if (size > radeon_bo_size(track->htile_bo)) {
+                       dev_warn(p->dev, "%s:%d htile surface too small %ld for %ld (%d %d)\n",
+                                __func__, __LINE__, radeon_bo_size(track->htile_bo),
+                                size, nbx, nby);
+                       return -EINVAL;
+               }
+       }
+
+       track->db_dirty = false;
+       return 0;
+}
+
 static int r600_cs_track_check(struct radeon_cs_parser *p)
 {
        struct r600_cs_track *track = p->track;
        u32 tmp;
        int r, i;
-       volatile u32 *ib = p->ib->ptr;
 
        /* on legacy kernel we don't perform advanced check */
        if (p->rdev == NULL)
@@ -513,124 +763,14 @@ static int r600_cs_track_check(struct radeon_cs_parser *p)
                track->cb_dirty = false;
        }
 
-       if (track->db_dirty) {
-               /* Check depth buffer */
-               if (G_028800_STENCIL_ENABLE(track->db_depth_control) ||
-                       G_028800_Z_ENABLE(track->db_depth_control)) {
-                       u32 nviews, bpe, ntiles, size, slice_tile_max;
-                       u32 height, height_align, pitch, pitch_align, depth_align;
-                       u64 base_offset, base_align;
-                       struct array_mode_checker array_check;
-                       int array_mode;
-
-                       if (track->db_bo == NULL) {
-                               dev_warn(p->dev, "z/stencil with no depth buffer\n");
-                               return -EINVAL;
-                       }
-                       if (G_028010_TILE_SURFACE_ENABLE(track->db_depth_info)) {
-                               dev_warn(p->dev, "this kernel doesn't support z/stencil htile\n");
-                               return -EINVAL;
-                       }
-                       switch (G_028010_FORMAT(track->db_depth_info)) {
-                       case V_028010_DEPTH_16:
-                               bpe = 2;
-                               break;
-                       case V_028010_DEPTH_X8_24:
-                       case V_028010_DEPTH_8_24:
-                       case V_028010_DEPTH_X8_24_FLOAT:
-                       case V_028010_DEPTH_8_24_FLOAT:
-                       case V_028010_DEPTH_32_FLOAT:
-                               bpe = 4;
-                               break;
-                       case V_028010_DEPTH_X24_8_32_FLOAT:
-                               bpe = 8;
-                               break;
-                       default:
-                               dev_warn(p->dev, "z/stencil with invalid format %d\n", G_028010_FORMAT(track->db_depth_info));
-                               return -EINVAL;
-                       }
-                       if ((track->db_depth_size & 0xFFFFFC00) == 0xFFFFFC00) {
-                               if (!track->db_depth_size_idx) {
-                                       dev_warn(p->dev, "z/stencil buffer size not set\n");
-                                       return -EINVAL;
-                               }
-                               tmp = radeon_bo_size(track->db_bo) - track->db_offset;
-                               tmp = (tmp / bpe) >> 6;
-                               if (!tmp) {
-                                       dev_warn(p->dev, "z/stencil buffer too small (0x%08X %d %d %ld)\n",
-                                                       track->db_depth_size, bpe, track->db_offset,
-                                                       radeon_bo_size(track->db_bo));
-                                       return -EINVAL;
-                               }
-                               ib[track->db_depth_size_idx] = S_028000_SLICE_TILE_MAX(tmp - 1) | (track->db_depth_size & 0x3FF);
-                       } else {
-                               size = radeon_bo_size(track->db_bo);
-                               /* pitch in pixels */
-                               pitch = (G_028000_PITCH_TILE_MAX(track->db_depth_size) + 1) * 8;
-                               slice_tile_max = G_028000_SLICE_TILE_MAX(track->db_depth_size) + 1;
-                               slice_tile_max *= 64;
-                               height = slice_tile_max / pitch;
-                               if (height > 8192)
-                                       height = 8192;
-                               base_offset = track->db_bo_mc + track->db_offset;
-                               array_mode = G_028010_ARRAY_MODE(track->db_depth_info);
-                               array_check.array_mode = array_mode;
-                               array_check.group_size = track->group_size;
-                               array_check.nbanks = track->nbanks;
-                               array_check.npipes = track->npipes;
-                               array_check.nsamples = track->nsamples;
-                               array_check.blocksize = bpe;
-                               if (r600_get_array_mode_alignment(&array_check,
-                                                                 &pitch_align, &height_align, &depth_align, &base_align)) {
-                                       dev_warn(p->dev, "%s invalid tiling %d (0x%08X)\n", __func__,
-                                                G_028010_ARRAY_MODE(track->db_depth_info),
-                                                track->db_depth_info);
-                                       return -EINVAL;
-                               }
-                               switch (array_mode) {
-                               case V_028010_ARRAY_1D_TILED_THIN1:
-                                       /* don't break userspace */
-                                       height &= ~0x7;
-                                       break;
-                               case V_028010_ARRAY_2D_TILED_THIN1:
-                                       break;
-                               default:
-                                       dev_warn(p->dev, "%s invalid tiling %d (0x%08X)\n", __func__,
-                                                G_028010_ARRAY_MODE(track->db_depth_info),
-                                                track->db_depth_info);
-                                       return -EINVAL;
-                               }
-
-                               if (!IS_ALIGNED(pitch, pitch_align)) {
-                                       dev_warn(p->dev, "%s:%d db pitch (%d, 0x%x, %d) invalid\n",
-                                                __func__, __LINE__, pitch, pitch_align, array_mode);
-                                       return -EINVAL;
-                               }
-                               if (!IS_ALIGNED(height, height_align)) {
-                                       dev_warn(p->dev, "%s:%d db height (%d, 0x%x, %d) invalid\n",
-                                                __func__, __LINE__, height, height_align, array_mode);
-                                       return -EINVAL;
-                               }
-                               if (!IS_ALIGNED(base_offset, base_align)) {
-                                       dev_warn(p->dev, "%s offset[%d] 0x%llx, 0x%llx, %d not aligned\n", __func__, i,
-                                                base_offset, base_align, array_mode);
-                                       return -EINVAL;
-                               }
-
-                               ntiles = G_028000_SLICE_TILE_MAX(track->db_depth_size) + 1;
-                               nviews = G_028004_SLICE_MAX(track->db_depth_view) + 1;
-                               tmp = ntiles * bpe * 64 * nviews;
-                               if ((tmp + track->db_offset) > radeon_bo_size(track->db_bo)) {
-                                       dev_warn(p->dev, "z/stencil buffer (%d) too small (0x%08X %d %d %d -> %u have %lu)\n",
-                                                array_mode,
-                                                track->db_depth_size, ntiles, nviews, bpe, tmp + track->db_offset,
-                                                radeon_bo_size(track->db_bo));
-                                       return -EINVAL;
-                               }
-                       }
-               }
-               track->db_dirty = false;
+       /* Check depth buffer */
+       if (track->db_dirty && (G_028800_STENCIL_ENABLE(track->db_depth_control) ||
+               G_028800_Z_ENABLE(track->db_depth_control))) {
+               r = r600_cs_track_validate_db(p);
+               if (r)
+                       return r;
        }
+
        return 0;
 }
 
@@ -1244,6 +1384,21 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
                track->db_dirty = true;
                break;
        case DB_HTILE_DATA_BASE:
+               r = r600_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       dev_warn(p->dev, "bad SET_CONTEXT_REG "
+                                       "0x%04X\n", reg);
+                       return -EINVAL;
+               }
+               track->htile_offset = radeon_get_ib_value(p, idx) << 8;
+               ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+               track->htile_bo = reloc->robj;
+               track->db_dirty = true;
+               break;
+       case DB_HTILE_SURFACE:
+               track->htile_surface = radeon_get_ib_value(p, idx);
+               track->db_dirty = true;
+               break;
        case SQ_PGM_START_FS:
        case SQ_PGM_START_ES:
        case SQ_PGM_START_VS:
index 3568a2e..59f9c99 100644 (file)
 #define                PREZ_MUST_WAIT_FOR_POSTZ_DONE                   (1 << 31)
 #define        DB_DEPTH_BASE                                   0x2800C
 #define        DB_HTILE_DATA_BASE                              0x28014
+#define        DB_HTILE_SURFACE                                0x28D24
+#define   S_028D24_HTILE_WIDTH(x)                      (((x) & 0x1) << 0)
+#define   G_028D24_HTILE_WIDTH(x)                      (((x) >> 0) & 0x1)
+#define   C_028D24_HTILE_WIDTH                         0xFFFFFFFE
+#define   S_028D24_HTILE_HEIGHT(x)                      (((x) & 0x1) << 1)
+#define   G_028D24_HTILE_HEIGHT(x)                      (((x) >> 1) & 0x1)
+#define   C_028D24_HTILE_HEIGHT                         0xFFFFFFFD
+#define   G_028D24_LINEAR(x)                           (((x) >> 2) & 0x1)
 #define        DB_WATERMARKS                                   0x9838
 #define                DEPTH_FREE(x)                                   ((x) << 0)
 #define                DEPTH_FLUSH(x)                                  ((x) << 5)
index 91541e6..6f70158 100644 (file)
@@ -233,7 +233,17 @@ int radeon_bo_pin_restricted(struct radeon_bo *bo, u32 domain, u64 max_offset,
                bo->pin_count++;
                if (gpu_addr)
                        *gpu_addr = radeon_bo_gpu_offset(bo);
-               WARN_ON_ONCE(max_offset != 0);
+
+               if (max_offset != 0) {
+                       u64 domain_start;
+
+                       if (domain == RADEON_GEM_DOMAIN_VRAM)
+                               domain_start = bo->rdev->mc.vram_start;
+                       else
+                               domain_start = bo->rdev->mc.gtt_start;
+                       WARN_ON_ONCE((*gpu_addr - domain_start) > max_offset);
+               }
+
                return 0;
        }
        radeon_ttm_placement_from_domain(bo, domain);
index aea63c4..0f656b1 100644 (file)
@@ -509,7 +509,6 @@ cayman 0x9400
 0x00028AA8 IA_MULTI_VGT_PARAM
 0x00028AB4 VGT_REUSE_OFF
 0x00028AB8 VGT_VTX_CNT_EN
-0x00028ABC DB_HTILE_SURFACE
 0x00028AC0 DB_SRESULTS_COMPARE_STATE0
 0x00028AC4 DB_SRESULTS_COMPARE_STATE1
 0x00028AC8 DB_PRELOAD_CONTROL
index 77c3720..b912a37 100644 (file)
@@ -519,7 +519,6 @@ evergreen 0x9400
 0x00028AA4 VGT_INSTANCE_STEP_RATE_1
 0x00028AB4 VGT_REUSE_OFF
 0x00028AB8 VGT_VTX_CNT_EN
-0x00028ABC DB_HTILE_SURFACE
 0x00028AC0 DB_SRESULTS_COMPARE_STATE0
 0x00028AC4 DB_SRESULTS_COMPARE_STATE1
 0x00028AC8 DB_PRELOAD_CONTROL
index 626c24e..5e659b0 100644 (file)
@@ -713,7 +713,6 @@ r600 0x9400
 0x0000A710 TD_VS_SAMPLER17_BORDER_RED
 0x00009508 TA_CNTL_AUX
 0x0002802C DB_DEPTH_CLEAR
-0x00028D24 DB_HTILE_SURFACE
 0x00028D34 DB_PREFETCH_LIMIT
 0x00028D30 DB_PRELOAD_CONTROL
 0x00028D0C DB_RENDER_CONTROL
index 8305d29..519ce8b 100644 (file)
@@ -53,8 +53,8 @@
 static const unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END };
 
 /* Insmod parameters */
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
        __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
index 6c6b240..ce86c5e 100644 (file)
@@ -59,7 +59,7 @@ static int mc13783_adc_read(struct device *dev,
 
        ret = mc13xxx_adc_do_conversion(priv->mc13xxx,
                        MC13XXX_ADC_MODE_MULT_CHAN,
-                       channel, sample);
+                       channel, 0, 0, sample);
        if (ret)
                return ret;
 
index 834e49d..d6b0bdd 100644 (file)
@@ -71,8 +71,8 @@ MODULE_PARM_DESC(timeout,
        "Watchdog timeout in minutes. 2<= timeout <=255 (default="
                                __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
        "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
index acba1c6..7f0b832 100644 (file)
@@ -15,7 +15,8 @@
 
     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.
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+    MA 02110-1301 USA.
  * ------------------------------------------------------------------------- */
 
 /* With some changes from Frodo Looijaard <frodol@dds.nl>, Kyösti Mälkki
@@ -111,7 +112,7 @@ static int sclhi(struct i2c_algo_bit_data *adap)
                                break;
                        return -ETIMEDOUT;
                }
-               cond_resched();
+               cpu_relax();
        }
 #ifdef DEBUG
        if (jiffies != start && i2c_debug >= 3)
index beb9ffe..73133b1 100644 (file)
@@ -15,7 +15,8 @@
  *
  *  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.
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ *  MA 02110-1301 USA.
  */
 
 #include <linux/kernel.h>
index 5eebf56..5c23795 100644 (file)
@@ -16,7 +16,8 @@
  *
  *  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.
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ *  MA 02110-1301 USA.
  *
  * With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and
  * Frodo Looijaard <frodol@dds.nl>, and also from Martin Bailey
index 5263a9e..1ec703e 100644 (file)
@@ -16,7 +16,8 @@
 
     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.          */
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+    MA 02110-1301 USA.                                                 */
 /* --------------------------------------------------------------------        */
 
 /* With some changes from Frodo Looijaard <frodol@dds.nl> */
index 71c1b0a..d2c5095 100644 (file)
@@ -103,6 +103,7 @@ config I2C_I801
            Patsburg (PCH)
            DH89xxCC (PCH)
            Panther Point (PCH)
+           Lynx Point (PCH)
 
          This driver can also be built as a module.  If so, the module
          will be called i2c-i801.
index 8679648..ed9f48d 100644 (file)
@@ -19,7 +19,6 @@
 
 #include <mach/hardware.h>
 #include <asm/hardware/ioc.h>
-#include <asm/system.h>
 
 #define FORCE_ONES     0xdc
 #define SCL            0x02
index a651779..c0330a4 100644 (file)
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/platform_device.h>
-
-#include <asm/gpio.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/of_i2c.h>
+
+struct i2c_gpio_private_data {
+       struct i2c_adapter adap;
+       struct i2c_algo_bit_data bit_data;
+       struct i2c_gpio_platform_data pdata;
+};
 
 /* Toggle SDA by changing the direction of the pin */
 static void i2c_gpio_setsda_dir(void *data, int state)
@@ -78,24 +85,62 @@ static int i2c_gpio_getscl(void *data)
        return gpio_get_value(pdata->scl_pin);
 }
 
+static int __devinit of_i2c_gpio_probe(struct device_node *np,
+                            struct i2c_gpio_platform_data *pdata)
+{
+       u32 reg;
+
+       if (of_gpio_count(np) < 2)
+               return -ENODEV;
+
+       pdata->sda_pin = of_get_gpio(np, 0);
+       pdata->scl_pin = of_get_gpio(np, 1);
+
+       if (!gpio_is_valid(pdata->sda_pin) || !gpio_is_valid(pdata->scl_pin)) {
+               pr_err("%s: invalid GPIO pins, sda=%d/scl=%d\n",
+                      np->full_name, pdata->sda_pin, pdata->scl_pin);
+               return -ENODEV;
+       }
+
+       of_property_read_u32(np, "i2c-gpio,delay-us", &pdata->udelay);
+
+       if (!of_property_read_u32(np, "i2c-gpio,timeout-ms", &reg))
+               pdata->timeout = msecs_to_jiffies(reg);
+
+       pdata->sda_is_open_drain =
+               of_property_read_bool(np, "i2c-gpio,sda-open-drain");
+       pdata->scl_is_open_drain =
+               of_property_read_bool(np, "i2c-gpio,scl-open-drain");
+       pdata->scl_is_output_only =
+               of_property_read_bool(np, "i2c-gpio,scl-output-only");
+
+       return 0;
+}
+
 static int __devinit i2c_gpio_probe(struct platform_device *pdev)
 {
+       struct i2c_gpio_private_data *priv;
        struct i2c_gpio_platform_data *pdata;
        struct i2c_algo_bit_data *bit_data;
        struct i2c_adapter *adap;
        int ret;
 
-       pdata = pdev->dev.platform_data;
-       if (!pdata)
-               return -ENXIO;
-
-       ret = -ENOMEM;
-       adap = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
-       if (!adap)
-               goto err_alloc_adap;
-       bit_data = kzalloc(sizeof(struct i2c_algo_bit_data), GFP_KERNEL);
-       if (!bit_data)
-               goto err_alloc_bit_data;
+       priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+       adap = &priv->adap;
+       bit_data = &priv->bit_data;
+       pdata = &priv->pdata;
+
+       if (pdev->dev.of_node) {
+               ret = of_i2c_gpio_probe(pdev->dev.of_node, pdata);
+               if (ret)
+                       return ret;
+       } else {
+               if (!pdev->dev.platform_data)
+                       return -ENXIO;
+               memcpy(pdata, pdev->dev.platform_data, sizeof(*pdata));
+       }
 
        ret = gpio_request(pdata->sda_pin, "sda");
        if (ret)
@@ -143,6 +188,7 @@ static int __devinit i2c_gpio_probe(struct platform_device *pdev)
        adap->algo_data = bit_data;
        adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
        adap->dev.parent = &pdev->dev;
+       adap->dev.of_node = pdev->dev.of_node;
 
        /*
         * If "dev->id" is negative we consider it as zero.
@@ -154,7 +200,9 @@ static int __devinit i2c_gpio_probe(struct platform_device *pdev)
        if (ret)
                goto err_add_bus;
 
-       platform_set_drvdata(pdev, adap);
+       of_i2c_register_devices(adap);
+
+       platform_set_drvdata(pdev, priv);
 
        dev_info(&pdev->dev, "using pins %u (SDA) and %u (SCL%s)\n",
                 pdata->sda_pin, pdata->scl_pin,
@@ -168,34 +216,40 @@ err_add_bus:
 err_request_scl:
        gpio_free(pdata->sda_pin);
 err_request_sda:
-       kfree(bit_data);
-err_alloc_bit_data:
-       kfree(adap);
-err_alloc_adap:
        return ret;
 }
 
 static int __devexit i2c_gpio_remove(struct platform_device *pdev)
 {
+       struct i2c_gpio_private_data *priv;
        struct i2c_gpio_platform_data *pdata;
        struct i2c_adapter *adap;
 
-       adap = platform_get_drvdata(pdev);
-       pdata = pdev->dev.platform_data;
+       priv = platform_get_drvdata(pdev);
+       adap = &priv->adap;
+       pdata = &priv->pdata;
 
        i2c_del_adapter(adap);
        gpio_free(pdata->scl_pin);
        gpio_free(pdata->sda_pin);
-       kfree(adap->algo_data);
-       kfree(adap);
 
        return 0;
 }
 
+#if defined(CONFIG_OF)
+static const struct of_device_id i2c_gpio_dt_ids[] = {
+       { .compatible = "i2c-gpio", },
+       { /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, i2c_gpio_dt_ids);
+#endif
+
 static struct platform_driver i2c_gpio_driver = {
        .driver         = {
                .name   = "i2c-gpio",
                .owner  = THIS_MODULE,
+               .of_match_table = of_match_ptr(i2c_gpio_dt_ids),
        },
        .probe          = i2c_gpio_probe,
        .remove         = __devexit_p(i2c_gpio_remove),
index 5d2e281..ae2945a 100644 (file)
@@ -2,7 +2,7 @@
     Copyright (c) 1998 - 2002  Frodo Looijaard <frodol@dds.nl>,
     Philip Edelbrock <phil@netroedge.com>, and Mark D. Studebaker
     <mdsxyz123@yahoo.com>
-    Copyright (C) 2007, 2008   Jean Delvare <khali@linux-fr.org>
+    Copyright (C) 2007 - 2012  Jean Delvare <khali@linux-fr.org>
     Copyright (C) 2010         Intel Corporation,
                                David Woodhouse <dwmw2@infradead.org>
 
@@ -51,6 +51,7 @@
   Patsburg (PCH) IDF    0x1d72     32     hard     yes     yes     yes
   DH89xxCC (PCH)        0x2330     32     hard     yes     yes     yes
   Panther Point (PCH)   0x1e22     32     hard     yes     yes     yes
+  Lynx Point (PCH)      0x8c22     32     hard     yes     yes     yes
 
   Features supported by this driver:
   Software PEC                     no
 #define SMBHSTCNT_KILL         2
 
 /* Other settings */
-#define MAX_TIMEOUT            100
+#define MAX_RETRIES            400
 #define ENABLE_INT9            0       /* set to 0x01 to enable - untested */
 
 /* I801 command constants */
 #define PCI_DEVICE_ID_INTEL_PANTHERPOINT_SMBUS 0x1e22
 #define PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS     0x2330
 #define PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS        0x3b30
+#define PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS    0x8c22
 
 struct i801_priv {
        struct i2c_adapter adapter;
@@ -215,7 +217,7 @@ static int i801_check_post(struct i801_priv *priv, int status, int timeout)
                dev_dbg(&priv->pci_dev->dev, "Terminating the current operation\n");
                outb_p(inb_p(SMBHSTCNT(priv)) | SMBHSTCNT_KILL,
                       SMBHSTCNT(priv));
-               msleep(1);
+               usleep_range(1000, 2000);
                outb_p(inb_p(SMBHSTCNT(priv)) & (~SMBHSTCNT_KILL),
                       SMBHSTCNT(priv));
 
@@ -272,11 +274,11 @@ static int i801_transaction(struct i801_priv *priv, int xact)
 
        /* We will always wait for a fraction of a second! */
        do {
-               msleep(1);
+               usleep_range(250, 500);
                status = inb_p(SMBHSTSTS(priv));
-       } while ((status & SMBHSTSTS_HOST_BUSY) && (timeout++ < MAX_TIMEOUT));
+       } while ((status & SMBHSTSTS_HOST_BUSY) && (timeout++ < MAX_RETRIES));
 
-       result = i801_check_post(priv, status, timeout > MAX_TIMEOUT);
+       result = i801_check_post(priv, status, timeout > MAX_RETRIES);
        if (result < 0)
                return result;
 
@@ -291,12 +293,12 @@ static void i801_wait_hwpec(struct i801_priv *priv)
        int status;
 
        do {
-               msleep(1);
+               usleep_range(250, 500);
                status = inb_p(SMBHSTSTS(priv));
        } while ((!(status & SMBHSTSTS_INTR))
-                && (timeout++ < MAX_TIMEOUT));
+                && (timeout++ < MAX_RETRIES));
 
-       if (timeout > MAX_TIMEOUT)
+       if (timeout > MAX_RETRIES)
                dev_dbg(&priv->pci_dev->dev, "PEC Timeout!\n");
 
        outb_p(status, SMBHSTSTS(priv));
@@ -380,12 +382,12 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv,
                /* We will always wait for a fraction of a second! */
                timeout = 0;
                do {
-                       msleep(1);
+                       usleep_range(250, 500);
                        status = inb_p(SMBHSTSTS(priv));
                } while ((!(status & SMBHSTSTS_BYTE_DONE))
-                        && (timeout++ < MAX_TIMEOUT));
+                        && (timeout++ < MAX_RETRIES));
 
-               result = i801_check_post(priv, status, timeout > MAX_TIMEOUT);
+               result = i801_check_post(priv, status, timeout > MAX_RETRIES);
                if (result < 0)
                        return result;
 
@@ -633,6 +635,7 @@ static DEFINE_PCI_DEVICE_TABLE(i801_ids) = {
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF2) },
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS) },
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PANTHERPOINT_SMBUS) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS) },
        { 0, }
 };
 
index 6561d27..f90a605 100644 (file)
@@ -47,7 +47,7 @@
 #define SMBBLKDAT      (0x20 + sch_smba)
 
 /* Other settings */
-#define MAX_TIMEOUT    500
+#define MAX_RETRIES    5000
 
 /* I2C constants */
 #define SCH_QUICK              0x00
@@ -68,7 +68,7 @@ static int sch_transaction(void)
 {
        int temp;
        int result = 0;
-       int timeout = 0;
+       int retries = 0;
 
        dev_dbg(&sch_adapter.dev, "Transaction (pre): CNT=%02x, CMD=%02x, "
                "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb(SMBHSTCNT),
@@ -100,12 +100,12 @@ static int sch_transaction(void)
        outb(inb(SMBHSTCNT) | 0x10, SMBHSTCNT);
 
        do {
-               msleep(1);
+               usleep_range(100, 200);
                temp = inb(SMBHSTSTS) & 0x0f;
-       } while ((temp & 0x08) && (timeout++ < MAX_TIMEOUT));
+       } while ((temp & 0x08) && (retries++ < MAX_RETRIES));
 
        /* If the SMBus is still busy, we give up */
-       if (timeout > MAX_TIMEOUT) {
+       if (retries > MAX_RETRIES) {
                dev_err(&sch_adapter.dev, "SMBus Timeout!\n");
                result = -ETIMEDOUT;
        }
index 10274ff..f24cc64 100644 (file)
@@ -13,7 +13,8 @@
  *
  * 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.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA.
  */
 
 #include <linux/kernel.h>
index e9c1893..feb7dc3 100644 (file)
@@ -14,7 +14,8 @@
 
     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.               */
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+    MA 02110-1301 USA.                                                      */
 /* ------------------------------------------------------------------------- */
 
 /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi>.
index 9f9c57f..18a8fd2 100644 (file)
@@ -13,7 +13,8 @@
  *
  * 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.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA.
  */
 
 #include <linux/rwsem.h>
index 10e7f1e..4504832 100644 (file)
@@ -17,7 +17,8 @@
 
     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.
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+    MA 02110-1301 USA.
 */
 
 /* Note that this is a complete rewrite of Simon Vogl's i2c-dev module.
index f61ccc1..9836d08 100644 (file)
@@ -16,7 +16,8 @@
  *
  * 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.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA.
  */
 
 #include <linux/kernel.h>
index ed699c5..e0df9b6 100644 (file)
@@ -393,18 +393,7 @@ static struct i2c_driver pca9541_driver = {
        .id_table = pca9541_id,
 };
 
-static int __init pca9541_init(void)
-{
-       return i2c_add_driver(&pca9541_driver);
-}
-
-static void __exit pca9541_exit(void)
-{
-       i2c_del_driver(&pca9541_driver);
-}
-
-module_init(pca9541_init);
-module_exit(pca9541_exit);
+module_i2c_driver(pca9541_driver);
 
 MODULE_AUTHOR("Guenter Roeck <guenter.roeck@ericsson.com>");
 MODULE_DESCRIPTION("PCA9541 I2C master selector driver");
index 6f89536..0e37ef2 100644 (file)
@@ -284,18 +284,7 @@ static struct i2c_driver pca954x_driver = {
        .id_table       = pca954x_id,
 };
 
-static int __init pca954x_init(void)
-{
-       return i2c_add_driver(&pca954x_driver);
-}
-
-static void __exit pca954x_exit(void)
-{
-       i2c_del_driver(&pca954x_driver);
-}
-
-module_init(pca954x_init);
-module_exit(pca954x_exit);
+module_i2c_driver(pca954x_driver);
 
 MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>");
 MODULE_DESCRIPTION("PCA954x I2C mux/switch driver");
index d2f3db3..28e344e 100644 (file)
@@ -41,7 +41,6 @@
 #include <linux/major.h>
 #include <linux/delay.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
index 8bbfe55..e03f4f1 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/blkdev.h>
 #include <linux/ide.h>
 #include <linux/init.h>
-#include <asm/system.h>
 #include <asm/io.h>
 
 #define DRV_NAME "qd65xx"
index 9a3fbfc..fd05f48 100644 (file)
@@ -42,7 +42,6 @@
  */
 
 
-#include <asm/system.h>
 #include "ehca_classes.h"
 #include "ehca_tools.h"
 #include "ehca_qes.h"
index c24ec2d..26043cc 100644 (file)
@@ -13,7 +13,6 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <asm/io.h>
-#include <asm/system.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/joystick.h>
index 0bc8620..24044da 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/interrupt.h>
 #include <linux/mutex.h>
 
-#include <asm/system.h>
 #include <asm/amigahw.h>
 #include <asm/amigaints.h>
 
index f2e0cbc..f9ce183 100644 (file)
@@ -105,6 +105,8 @@ static int __devinit pm860x_onkey_probe(struct platform_device *pdev)
        }
 
        platform_set_drvdata(pdev, info);
+       device_init_wakeup(&pdev->dev, 1);
+
        return 0;
 
 out_irq:
@@ -129,10 +131,34 @@ static int __devexit pm860x_onkey_remove(struct platform_device *pdev)
        return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int pm860x_onkey_suspend(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
+
+       if (device_may_wakeup(dev))
+               chip->wakeup_flag |= 1 << PM8607_IRQ_ONKEY;
+       return 0;
+}
+static int pm860x_onkey_resume(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
+
+       if (device_may_wakeup(dev))
+               chip->wakeup_flag &= ~(1 << PM8607_IRQ_ONKEY);
+       return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(pm860x_onkey_pm_ops, pm860x_onkey_suspend, pm860x_onkey_resume);
+
 static struct platform_driver pm860x_onkey_driver = {
        .driver         = {
                .name   = "88pm860x-onkey",
                .owner  = THIS_MODULE,
+               .pm     = &pm860x_onkey_pm_ops,
        },
        .probe          = pm860x_onkey_probe,
        .remove         = __devexit_p(pm860x_onkey_remove),
index ff5f61a..5fa9934 100644 (file)
@@ -25,7 +25,6 @@
 
 #include <asm/irq.h>
 #include <asm/setup.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/amigahw.h>
 #include <asm/amigaints.h>
index 5c4a692..d1c4323 100644 (file)
@@ -47,7 +47,6 @@
 
 #include <asm/irq.h>
 #include <asm/setup.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/atarihw.h>
 #include <asm/atarikb.h>
index be33160..09a0899 100644 (file)
@@ -71,7 +71,6 @@
 #include <linux/slab.h>
 #include <linux/hil.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 /* Machine-specific abstraction */
 
index 558200e..61da763 100644 (file)
@@ -21,7 +21,6 @@
 
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/ip32/mace.h>
 #include <asm/ip32/ip32_ints.h>
 
index 58b2244..2af5df6 100644 (file)
@@ -38,7 +38,6 @@
 
 #include <mach/hardware.h>
 #include <asm/hardware/iomd.h>
-#include <asm/system.h>
 
 MODULE_AUTHOR("Vojtech Pavlik, Russell King");
 MODULE_DESCRIPTION("Acorn RiscPC PS/2 keyboard controller driver");
index 5ebabe3..3897667 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/spinlock.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include <asm/hardware/sa1111.h>
 
index ede0274..48dc5b0 100644 (file)
@@ -39,6 +39,7 @@ struct mc13783_ts_priv {
        struct delayed_work work;
        struct workqueue_struct *workq;
        unsigned int sample[4];
+       struct mc13xxx_ts_platform_data *touch;
 };
 
 static irqreturn_t mc13783_ts_handler(int irq, void *data)
@@ -125,7 +126,9 @@ static void mc13783_ts_work(struct work_struct *work)
        unsigned int channel = 12;
 
        if (mc13xxx_adc_do_conversion(priv->mc13xxx,
-                               mode, channel, priv->sample) == 0)
+                               mode, channel,
+                               priv->touch->ato, priv->touch->atox,
+                               priv->sample) == 0)
                mc13783_ts_report_sample(priv);
 }
 
@@ -179,6 +182,12 @@ static int __init mc13783_ts_probe(struct platform_device *pdev)
        INIT_DELAYED_WORK(&priv->work, mc13783_ts_work);
        priv->mc13xxx = dev_get_drvdata(pdev->dev.parent);
        priv->idev = idev;
+       priv->touch = dev_get_platdata(&pdev->dev);
+       if (!priv->touch) {
+               dev_err(&pdev->dev, "missing platform data\n");
+               ret = -ENODEV;
+               goto err_free_mem;
+       }
 
        /*
         * We need separate workqueue because mc13783_adc_do_conversion
index 44b50cc..c21353d 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/serial.h>
 #include <linux/major.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ciscode.h>
index 33e3c94..c644557 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
index fe254e7..a8c4d3f 100644 (file)
@@ -44,7 +44,6 @@
 #include <linux/timer.h>
 #include <linux/ioport.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
index 68f5049..f0dfc0c 100644 (file)
@@ -44,7 +44,6 @@
 #include <linux/timer.h>
 #include <linux/ioport.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
index bfe9428..4deac45 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/timer.h>
 #include <linux/ioport.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
index 7f3c54d..c59e8d2 100644 (file)
@@ -69,7 +69,6 @@
 #include <linux/signal.h>      /* used in new tty drivers */
 #include <linux/bitops.h>
 
-#include <asm/system.h>
 #include <asm/byteorder.h>
 #include <asm/types.h>
 
index 682911f..a18e639 100644 (file)
@@ -36,7 +36,6 @@
 
 #include <linux/isdnif.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 
 
index 4ca0062..5b61aaf 100644 (file)
@@ -114,6 +114,27 @@ static inline int __blink_ctl_mask(int port)
        return ret;
 }
 
+static int led_power_set(struct pm860x_chip *chip, int port, int on)
+{
+       int ret = -EINVAL;
+
+       switch (port) {
+       case PM8606_LED1_RED:
+       case PM8606_LED1_GREEN:
+       case PM8606_LED1_BLUE:
+               ret = on ? pm8606_osc_enable(chip, RGB1_ENABLE) :
+                       pm8606_osc_disable(chip, RGB1_ENABLE);
+               break;
+       case PM8606_LED2_RED:
+       case PM8606_LED2_GREEN:
+       case PM8606_LED2_BLUE:
+               ret = on ? pm8606_osc_enable(chip, RGB2_ENABLE) :
+                       pm8606_osc_disable(chip, RGB2_ENABLE);
+               break;
+       }
+       return ret;
+}
+
 static void pm860x_led_work(struct work_struct *work)
 {
 
@@ -126,6 +147,7 @@ static void pm860x_led_work(struct work_struct *work)
        chip = led->chip;
        mutex_lock(&led->lock);
        if ((led->current_brightness == 0) && led->brightness) {
+               led_power_set(chip, led->port, 1);
                if (led->iset) {
                        pm860x_set_bits(led->i2c, __led_off(led->port),
                                        LED_CURRENT_MASK, led->iset);
@@ -149,6 +171,7 @@ static void pm860x_led_work(struct work_struct *work)
                                        LED_CURRENT_MASK, 0);
                        mask = __blink_ctl_mask(led->port);
                        pm860x_set_bits(led->i2c, PM8606_WLED3B, mask, 0);
+                       led_power_set(chip, led->port, 0);
                }
        }
        led->current_brightness = led->brightness;
index b6ef8f5..87de8d9 100644 (file)
@@ -14,7 +14,6 @@
 #include <asm/pgtable.h>
 #include <asm/hydra.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
 
index c60d025..fc71723 100644 (file)
@@ -29,7 +29,6 @@
 #include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/sections.h>
 
 #undef DEBUG
index 0ff92c2..97cfc5a 100644 (file)
 #include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/sections.h>
 #include <asm/macio.h>
 
index 46c4e95..3b4a157 100644 (file)
@@ -41,7 +41,6 @@
 #include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/sections.h>
 #include <asm/macio.h>
 
index 971bc95..86511c5 100644 (file)
@@ -26,7 +26,6 @@
 #include <asm/mac_via.h>
 #endif
 #include <asm/io.h>
-#include <asm/system.h>
 #include <linux/init.h>
 
 static volatile unsigned char __iomem *via;
index c9570fc..3725f08 100644 (file)
@@ -34,7 +34,6 @@
 #include <asm/macintosh.h>
 #include <asm/macints.h>
 #include <asm/mac_via.h>
-#include <asm/system.h>
 
 static volatile unsigned char *via;
 
index 6cccd60..22b8ce4 100644 (file)
@@ -50,7 +50,6 @@
 #include <asm/machdep.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/sections.h>
 #include <asm/irq.h>
 #include <asm/pmac_feature.h>
index aeb30d0..a00ee41 100644 (file)
@@ -37,7 +37,6 @@
 #include <asm/mac_via.h>
 
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/uaccess.h>
 
index 647c6ad..4d6a90a 100644 (file)
@@ -18,7 +18,6 @@
 #include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/sections.h>
 #include <asm/pmac_low_i2c.h>
 
index 30e6195..04067e0 100644 (file)
 #include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/sections.h>
 #include <asm/smu.h>
 
index 749d174..fc13d0f 100644 (file)
 #include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/sections.h>
 #include <asm/smu.h>
 
index 3442732..a9430ed 100644 (file)
@@ -41,7 +41,6 @@
 #include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/sections.h>
 #include <asm/smu.h>
 
index 43137b4..3c2be51 100644 (file)
@@ -18,7 +18,6 @@
 #include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/sections.h>
 #include <asm/smu.h>
 
index 3c19350..1cc4e49 100644 (file)
@@ -18,7 +18,6 @@
 #include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/sections.h>
 #include <asm/smu.h>
 
index faa4741..10f122a 100644 (file)
@@ -277,8 +277,8 @@ config DM_MIRROR
          needed for live data migration tools such as 'pvmove'.
 
 config DM_RAID
-       tristate "RAID 1/4/5/6 target (EXPERIMENTAL)"
-       depends on BLK_DEV_DM && EXPERIMENTAL
+       tristate "RAID 1/4/5/6 target"
+       depends on BLK_DEV_DM
        select MD_RAID1
        select MD_RAID456
        select BLK_DEV_MD
@@ -359,8 +359,8 @@ config DM_DELAY
        If unsure, say N.
 
 config DM_UEVENT
-       bool "DM uevents (EXPERIMENTAL)"
-       depends on BLK_DEV_DM && EXPERIMENTAL
+       bool "DM uevents"
+       depends on BLK_DEV_DM
        ---help---
        Generate udev events for DM events.
 
@@ -370,4 +370,24 @@ config DM_FLAKEY
        ---help---
          A target that intermittently fails I/O for debugging purposes.
 
+config DM_VERITY
+       tristate "Verity target support (EXPERIMENTAL)"
+       depends on BLK_DEV_DM && EXPERIMENTAL
+       select CRYPTO
+       select CRYPTO_HASH
+       select DM_BUFIO
+       ---help---
+         This device-mapper target creates a read-only device that
+         transparently validates the data on one underlying device against
+         a pre-generated tree of cryptographic checksums stored on a second
+         device.
+
+         You'll need to activate the digests you're going to use in the
+         cryptoapi configuration.
+
+         To compile this code as a module, choose M here: the module will
+         be called dm-verity.
+
+         If unsure, say N.
+
 endif # MD
index 046860c..8b2e0df 100644 (file)
@@ -42,6 +42,7 @@ obj-$(CONFIG_DM_LOG_USERSPACE)        += dm-log-userspace.o
 obj-$(CONFIG_DM_ZERO)          += dm-zero.o
 obj-$(CONFIG_DM_RAID)  += dm-raid.o
 obj-$(CONFIG_DM_THIN_PROVISIONING)     += dm-thin-pool.o
+obj-$(CONFIG_DM_VERITY)                += dm-verity.o
 
 ifeq ($(CONFIG_DM_UEVENT),y)
 dm-mod-objs                    += dm-uevent.o
index b6e58c7..cc06a1e 100644 (file)
@@ -578,7 +578,7 @@ static void write_endio(struct bio *bio, int error)
        struct dm_buffer *b = container_of(bio, struct dm_buffer, bio);
 
        b->write_error = error;
-       if (error) {
+       if (unlikely(error)) {
                struct dm_bufio_client *c = b->c;
                (void)cmpxchg(&c->async_write_error, 0, error);
        }
@@ -697,13 +697,20 @@ static void __wait_for_free_buffer(struct dm_bufio_client *c)
        dm_bufio_lock(c);
 }
 
+enum new_flag {
+       NF_FRESH = 0,
+       NF_READ = 1,
+       NF_GET = 2,
+       NF_PREFETCH = 3
+};
+
 /*
  * Allocate a new buffer. If the allocation is not possible, wait until
  * some other thread frees a buffer.
  *
  * May drop the lock and regain it.
  */
-static struct dm_buffer *__alloc_buffer_wait_no_callback(struct dm_bufio_client *c)
+static struct dm_buffer *__alloc_buffer_wait_no_callback(struct dm_bufio_client *c, enum new_flag nf)
 {
        struct dm_buffer *b;
 
@@ -726,6 +733,9 @@ static struct dm_buffer *__alloc_buffer_wait_no_callback(struct dm_bufio_client
                                return b;
                }
 
+               if (nf == NF_PREFETCH)
+                       return NULL;
+
                if (!list_empty(&c->reserved_buffers)) {
                        b = list_entry(c->reserved_buffers.next,
                                       struct dm_buffer, lru_list);
@@ -743,9 +753,12 @@ static struct dm_buffer *__alloc_buffer_wait_no_callback(struct dm_bufio_client
        }
 }
 
-static struct dm_buffer *__alloc_buffer_wait(struct dm_bufio_client *c)
+static struct dm_buffer *__alloc_buffer_wait(struct dm_bufio_client *c, enum new_flag nf)
 {
-       struct dm_buffer *b = __alloc_buffer_wait_no_callback(c);
+       struct dm_buffer *b = __alloc_buffer_wait_no_callback(c, nf);
+
+       if (!b)
+               return NULL;
 
        if (c->alloc_callback)
                c->alloc_callback(b);
@@ -865,32 +878,23 @@ static struct dm_buffer *__find(struct dm_bufio_client *c, sector_t block)
  * Getting a buffer
  *--------------------------------------------------------------*/
 
-enum new_flag {
-       NF_FRESH = 0,
-       NF_READ = 1,
-       NF_GET = 2
-};
-
 static struct dm_buffer *__bufio_new(struct dm_bufio_client *c, sector_t block,
-                                    enum new_flag nf, struct dm_buffer **bp,
-                                    int *need_submit)
+                                    enum new_flag nf, int *need_submit)
 {
        struct dm_buffer *b, *new_b = NULL;
 
        *need_submit = 0;
 
        b = __find(c, block);
-       if (b) {
-               b->hold_count++;
-               __relink_lru(b, test_bit(B_DIRTY, &b->state) ||
-                            test_bit(B_WRITING, &b->state));
-               return b;
-       }
+       if (b)
+               goto found_buffer;
 
        if (nf == NF_GET)
                return NULL;
 
-       new_b = __alloc_buffer_wait(c);
+       new_b = __alloc_buffer_wait(c, nf);
+       if (!new_b)
+               return NULL;
 
        /*
         * We've had a period where the mutex was unlocked, so need to
@@ -899,10 +903,7 @@ static struct dm_buffer *__bufio_new(struct dm_bufio_client *c, sector_t block,
        b = __find(c, block);
        if (b) {
                __free_buffer_wake(new_b);
-               b->hold_count++;
-               __relink_lru(b, test_bit(B_DIRTY, &b->state) ||
-                            test_bit(B_WRITING, &b->state));
-               return b;
+               goto found_buffer;
        }
 
        __check_watermark(c);
@@ -922,6 +923,24 @@ static struct dm_buffer *__bufio_new(struct dm_bufio_client *c, sector_t block,
        *need_submit = 1;
 
        return b;
+
+found_buffer:
+       if (nf == NF_PREFETCH)
+               return NULL;
+       /*
+        * Note: it is essential that we don't wait for the buffer to be
+        * read if dm_bufio_get function is used. Both dm_bufio_get and
+        * dm_bufio_prefetch can be used in the driver request routine.
+        * If the user called both dm_bufio_prefetch and dm_bufio_get on
+        * the same buffer, it would deadlock if we waited.
+        */
+       if (nf == NF_GET && unlikely(test_bit(B_READING, &b->state)))
+               return NULL;
+
+       b->hold_count++;
+       __relink_lru(b, test_bit(B_DIRTY, &b->state) ||
+                    test_bit(B_WRITING, &b->state));
+       return b;
 }
 
 /*
@@ -956,10 +975,10 @@ static void *new_read(struct dm_bufio_client *c, sector_t block,
        struct dm_buffer *b;
 
        dm_bufio_lock(c);
-       b = __bufio_new(c, block, nf, bp, &need_submit);
+       b = __bufio_new(c, block, nf, &need_submit);
        dm_bufio_unlock(c);
 
-       if (!b || IS_ERR(b))
+       if (!b)
                return b;
 
        if (need_submit)
@@ -1005,13 +1024,47 @@ void *dm_bufio_new(struct dm_bufio_client *c, sector_t block,
 }
 EXPORT_SYMBOL_GPL(dm_bufio_new);
 
+void dm_bufio_prefetch(struct dm_bufio_client *c,
+                      sector_t block, unsigned n_blocks)
+{
+       struct blk_plug plug;
+
+       blk_start_plug(&plug);
+       dm_bufio_lock(c);
+
+       for (; n_blocks--; block++) {
+               int need_submit;
+               struct dm_buffer *b;
+               b = __bufio_new(c, block, NF_PREFETCH, &need_submit);
+               if (unlikely(b != NULL)) {
+                       dm_bufio_unlock(c);
+
+                       if (need_submit)
+                               submit_io(b, READ, b->block, read_endio);
+                       dm_bufio_release(b);
+
+                       dm_bufio_cond_resched();
+
+                       if (!n_blocks)
+                               goto flush_plug;
+                       dm_bufio_lock(c);
+               }
+
+       }
+
+       dm_bufio_unlock(c);
+
+flush_plug:
+       blk_finish_plug(&plug);
+}
+EXPORT_SYMBOL_GPL(dm_bufio_prefetch);
+
 void dm_bufio_release(struct dm_buffer *b)
 {
        struct dm_bufio_client *c = b->c;
 
        dm_bufio_lock(c);
 
-       BUG_ON(test_bit(B_READING, &b->state));
        BUG_ON(!b->hold_count);
 
        b->hold_count--;
@@ -1024,6 +1077,7 @@ void dm_bufio_release(struct dm_buffer *b)
                 * invalid buffer.
                 */
                if ((b->read_error || b->write_error) &&
+                   !test_bit(B_READING, &b->state) &&
                    !test_bit(B_WRITING, &b->state) &&
                    !test_bit(B_DIRTY, &b->state)) {
                        __unlink_buffer(b);
@@ -1041,6 +1095,8 @@ void dm_bufio_mark_buffer_dirty(struct dm_buffer *b)
 
        dm_bufio_lock(c);
 
+       BUG_ON(test_bit(B_READING, &b->state));
+
        if (!test_and_set_bit(B_DIRTY, &b->state))
                __relink_lru(b, LIST_DIRTY);
 
index 5c4c3a0..b142946 100644 (file)
@@ -63,6 +63,14 @@ void *dm_bufio_new(struct dm_bufio_client *c, sector_t block,
                   struct dm_buffer **bp);
 
 /*
+ * Prefetch the specified blocks to the cache.
+ * The function starts to read the blocks and returns without waiting for
+ * I/O to finish.
+ */
+void dm_bufio_prefetch(struct dm_bufio_client *c,
+                      sector_t block, unsigned n_blocks);
+
+/*
  * Release a reference obtained with dm_bufio_{read,get,new}. The data
  * pointer and dm_buffer pointer is no longer valid after this call.
  */
index db6b516..3f06df5 100644 (file)
@@ -176,7 +176,6 @@ struct crypt_config {
 
 #define MIN_IOS        16
 #define MIN_POOL_PAGES 32
-#define MIN_BIO_PAGES  8
 
 static struct kmem_cache *_crypt_io_pool;
 
@@ -848,12 +847,11 @@ static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned size,
                }
 
                /*
-                * if additional pages cannot be allocated without waiting,
-                * return a partially allocated bio, the caller will then try
-                * to allocate additional bios while submitting this partial bio
+                * If additional pages cannot be allocated without waiting,
+                * return a partially-allocated bio.  The caller will then try
+                * to allocate more bios while submitting this partial bio.
                 */
-               if (i == (MIN_BIO_PAGES - 1))
-                       gfp_mask = (gfp_mask | __GFP_NOWARN) & ~__GFP_WAIT;
+               gfp_mask = (gfp_mask | __GFP_NOWARN) & ~__GFP_WAIT;
 
                len = (size > PAGE_SIZE) ? PAGE_SIZE : size;
 
@@ -1046,16 +1044,14 @@ static void kcryptd_queue_io(struct dm_crypt_io *io)
        queue_work(cc->io_queue, &io->work);
 }
 
-static void kcryptd_crypt_write_io_submit(struct dm_crypt_io *io,
-                                         int error, int async)
+static void kcryptd_crypt_write_io_submit(struct dm_crypt_io *io, int async)
 {
        struct bio *clone = io->ctx.bio_out;
        struct crypt_config *cc = io->target->private;
 
-       if (unlikely(error < 0)) {
+       if (unlikely(io->error < 0)) {
                crypt_free_buffer_pages(cc, clone);
                bio_put(clone);
-               io->error = -EIO;
                crypt_dec_pending(io);
                return;
        }
@@ -1106,12 +1102,16 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io)
                sector += bio_sectors(clone);
 
                crypt_inc_pending(io);
+
                r = crypt_convert(cc, &io->ctx);
+               if (r < 0)
+                       io->error = -EIO;
+
                crypt_finished = atomic_dec_and_test(&io->ctx.pending);
 
                /* Encryption was already finished, submit io now */
                if (crypt_finished) {
-                       kcryptd_crypt_write_io_submit(io, r, 0);
+                       kcryptd_crypt_write_io_submit(io, 0);
 
                        /*
                         * If there was an error, do not try next fragments.
@@ -1162,11 +1162,8 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io)
        crypt_dec_pending(io);
 }
 
-static void kcryptd_crypt_read_done(struct dm_crypt_io *io, int error)
+static void kcryptd_crypt_read_done(struct dm_crypt_io *io)
 {
-       if (unlikely(error < 0))
-               io->error = -EIO;
-
        crypt_dec_pending(io);
 }
 
@@ -1181,9 +1178,11 @@ static void kcryptd_crypt_read_convert(struct dm_crypt_io *io)
                           io->sector);
 
        r = crypt_convert(cc, &io->ctx);
+       if (r < 0)
+               io->error = -EIO;
 
        if (atomic_dec_and_test(&io->ctx.pending))
-               kcryptd_crypt_read_done(io, r);
+               kcryptd_crypt_read_done(io);
 
        crypt_dec_pending(io);
 }
@@ -1204,15 +1203,18 @@ static void kcryptd_async_done(struct crypto_async_request *async_req,
        if (!error && cc->iv_gen_ops && cc->iv_gen_ops->post)
                error = cc->iv_gen_ops->post(cc, iv_of_dmreq(cc, dmreq), dmreq);
 
+       if (error < 0)
+               io->error = -EIO;
+
        mempool_free(req_of_dmreq(cc, dmreq), cc->req_pool);
 
        if (!atomic_dec_and_test(&ctx->pending))
                return;
 
        if (bio_data_dir(io->base_bio) == READ)
-               kcryptd_crypt_read_done(io, error);
+               kcryptd_crypt_read_done(io);
        else
-               kcryptd_crypt_write_io_submit(io, error, 1);
+               kcryptd_crypt_write_io_submit(io, 1);
 }
 
 static void kcryptd_crypt(struct work_struct *work)
@@ -1413,6 +1415,7 @@ static int crypt_ctr_cipher(struct dm_target *ti,
        char *tmp, *cipher, *chainmode, *ivmode, *ivopts, *keycount;
        char *cipher_api = NULL;
        int cpu, ret = -EINVAL;
+       char dummy;
 
        /* Convert to crypto api definition? */
        if (strchr(cipher_in, '(')) {
@@ -1434,7 +1437,7 @@ static int crypt_ctr_cipher(struct dm_target *ti,
 
        if (!keycount)
                cc->tfms_count = 1;
-       else if (sscanf(keycount, "%u", &cc->tfms_count) != 1 ||
+       else if (sscanf(keycount, "%u%c", &cc->tfms_count, &dummy) != 1 ||
                 !is_power_of_2(cc->tfms_count)) {
                ti->error = "Bad cipher key count specification";
                return -EINVAL;
@@ -1579,6 +1582,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
        int ret;
        struct dm_arg_set as;
        const char *opt_string;
+       char dummy;
 
        static struct dm_arg _args[] = {
                {0, 1, "Invalid number of feature args"},
@@ -1636,7 +1640,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
        }
 
        ret = -EINVAL;
-       if (sscanf(argv[2], "%llu", &tmpll) != 1) {
+       if (sscanf(argv[2], "%llu%c", &tmpll, &dummy) != 1) {
                ti->error = "Invalid iv_offset sector";
                goto bad;
        }
@@ -1647,7 +1651,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
                goto bad;
        }
 
-       if (sscanf(argv[4], "%llu", &tmpll) != 1) {
+       if (sscanf(argv[4], "%llu%c", &tmpll, &dummy) != 1) {
                ti->error = "Invalid device sector";
                goto bad;
        }
index f18375d..2dc22dd 100644 (file)
@@ -131,6 +131,7 @@ static int delay_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 {
        struct delay_c *dc;
        unsigned long long tmpll;
+       char dummy;
 
        if (argc != 3 && argc != 6) {
                ti->error = "requires exactly 3 or 6 arguments";
@@ -145,13 +146,13 @@ static int delay_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 
        dc->reads = dc->writes = 0;
 
-       if (sscanf(argv[1], "%llu", &tmpll) != 1) {
+       if (sscanf(argv[1], "%llu%c", &tmpll, &dummy) != 1) {
                ti->error = "Invalid device sector";
                goto bad;
        }
        dc->start_read = tmpll;
 
-       if (sscanf(argv[2], "%u", &dc->read_delay) != 1) {
+       if (sscanf(argv[2], "%u%c", &dc->read_delay, &dummy) != 1) {
                ti->error = "Invalid delay";
                goto bad;
        }
@@ -166,13 +167,13 @@ static int delay_ctr(struct dm_target *ti, unsigned int argc, char **argv)
        if (argc == 3)
                goto out;
 
-       if (sscanf(argv[4], "%llu", &tmpll) != 1) {
+       if (sscanf(argv[4], "%llu%c", &tmpll, &dummy) != 1) {
                ti->error = "Invalid write device sector";
                goto bad_dev_read;
        }
        dc->start_write = tmpll;
 
-       if (sscanf(argv[5], "%u", &dc->write_delay) != 1) {
+       if (sscanf(argv[5], "%u%c", &dc->write_delay, &dummy) != 1) {
                ti->error = "Invalid write delay";
                goto bad_dev_read;
        }
index 042e719..aa70f7d 100644 (file)
@@ -283,7 +283,7 @@ int dm_exception_store_init(void)
        return 0;
 
 persistent_fail:
-       dm_persistent_snapshot_exit();
+       dm_transient_snapshot_exit();
 transient_fail:
        return r;
 }
index b280c43..ac49c01 100644 (file)
@@ -160,6 +160,7 @@ static int flakey_ctr(struct dm_target *ti, unsigned int argc, char **argv)
        unsigned long long tmpll;
        struct dm_arg_set as;
        const char *devname;
+       char dummy;
 
        as.argc = argc;
        as.argv = argv;
@@ -178,7 +179,7 @@ static int flakey_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 
        devname = dm_shift_arg(&as);
 
-       if (sscanf(dm_shift_arg(&as), "%llu", &tmpll) != 1) {
+       if (sscanf(dm_shift_arg(&as), "%llu%c", &tmpll, &dummy) != 1) {
                ti->error = "Invalid device sector";
                goto bad;
        }
index 1ce84ed..a1a3e6d 100644 (file)
@@ -880,6 +880,7 @@ static int dev_set_geometry(struct dm_ioctl *param, size_t param_size)
        struct hd_geometry geometry;
        unsigned long indata[4];
        char *geostr = (char *) param + param->data_start;
+       char dummy;
 
        md = find_device(param);
        if (!md)
@@ -891,8 +892,8 @@ static int dev_set_geometry(struct dm_ioctl *param, size_t param_size)
                goto out;
        }
 
-       x = sscanf(geostr, "%lu %lu %lu %lu", indata,
-                  indata + 1, indata + 2, indata + 3);
+       x = sscanf(geostr, "%lu %lu %lu %lu%c", indata,
+                  indata + 1, indata + 2, indata + 3, &dummy);
 
        if (x != 4) {
                DMWARN("Unable to interpret geometry settings.");
index 9728839..3639eea 100644 (file)
@@ -29,6 +29,7 @@ static int linear_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 {
        struct linear_c *lc;
        unsigned long long tmp;
+       char dummy;
 
        if (argc != 2) {
                ti->error = "Invalid argument count";
@@ -41,7 +42,7 @@ static int linear_ctr(struct dm_target *ti, unsigned int argc, char **argv)
                return -ENOMEM;
        }
 
-       if (sscanf(argv[1], "%llu", &tmp) != 1) {
+       if (sscanf(argv[1], "%llu%c", &tmp, &dummy) != 1) {
                ti->error = "dm-linear: Invalid device sector";
                goto bad;
        }
index 3b52bb7..65ebaeb 100644 (file)
@@ -369,6 +369,7 @@ static int create_log_context(struct dm_dirty_log *log, struct dm_target *ti,
        unsigned int region_count;
        size_t bitset_size, buf_size;
        int r;
+       char dummy;
 
        if (argc < 1 || argc > 2) {
                DMWARN("wrong number of arguments to dirty region log");
@@ -387,7 +388,7 @@ static int create_log_context(struct dm_dirty_log *log, struct dm_target *ti,
                }
        }
 
-       if (sscanf(argv[0], "%u", &region_size) != 1 ||
+       if (sscanf(argv[0], "%u%c", &region_size, &dummy) != 1 ||
            !_check_region_size(ti, region_size)) {
                DMWARN("invalid region size %s", argv[0]);
                return -EINVAL;
index 801d92d..922a338 100644 (file)
@@ -226,6 +226,27 @@ static void free_multipath(struct multipath *m)
        kfree(m);
 }
 
+static int set_mapinfo(struct multipath *m, union map_info *info)
+{
+       struct dm_mpath_io *mpio;
+
+       mpio = mempool_alloc(m->mpio_pool, GFP_ATOMIC);
+       if (!mpio)
+               return -ENOMEM;
+
+       memset(mpio, 0, sizeof(*mpio));
+       info->ptr = mpio;
+
+       return 0;
+}
+
+static void clear_mapinfo(struct multipath *m, union map_info *info)
+{
+       struct dm_mpath_io *mpio = info->ptr;
+
+       info->ptr = NULL;
+       mempool_free(mpio, m->mpio_pool);
+}
 
 /*-----------------------------------------------
  * Path selection
@@ -341,13 +362,14 @@ static int __must_push_back(struct multipath *m)
 }
 
 static int map_io(struct multipath *m, struct request *clone,
-                 struct dm_mpath_io *mpio, unsigned was_queued)
+                 union map_info *map_context, unsigned was_queued)
 {
        int r = DM_MAPIO_REMAPPED;
        size_t nr_bytes = blk_rq_bytes(clone);
        unsigned long flags;
        struct pgpath *pgpath;
        struct block_device *bdev;
+       struct dm_mpath_io *mpio = map_context->ptr;
 
        spin_lock_irqsave(&m->lock, flags);
 
@@ -423,7 +445,6 @@ static void dispatch_queued_ios(struct multipath *m)
 {
        int r;
        unsigned long flags;
-       struct dm_mpath_io *mpio;
        union map_info *info;
        struct request *clone, *n;
        LIST_HEAD(cl);
@@ -436,16 +457,15 @@ static void dispatch_queued_ios(struct multipath *m)
                list_del_init(&clone->queuelist);
 
                info = dm_get_rq_mapinfo(clone);
-               mpio = info->ptr;
 
-               r = map_io(m, clone, mpio, 1);
+               r = map_io(m, clone, info, 1);
                if (r < 0) {
-                       mempool_free(mpio, m->mpio_pool);
+                       clear_mapinfo(m, info);
                        dm_kill_unmapped_request(clone, r);
                } else if (r == DM_MAPIO_REMAPPED)
                        dm_dispatch_request(clone);
                else if (r == DM_MAPIO_REQUEUE) {
-                       mempool_free(mpio, m->mpio_pool);
+                       clear_mapinfo(m, info);
                        dm_requeue_unmapped_request(clone);
                }
        }
@@ -908,20 +928,16 @@ static int multipath_map(struct dm_target *ti, struct request *clone,
                         union map_info *map_context)
 {
        int r;
-       struct dm_mpath_io *mpio;
        struct multipath *m = (struct multipath *) ti->private;
 
-       mpio = mempool_alloc(m->mpio_pool, GFP_ATOMIC);
-       if (!mpio)
+       if (set_mapinfo(m, map_context) < 0)
                /* ENOMEM, requeue */
                return DM_MAPIO_REQUEUE;
-       memset(mpio, 0, sizeof(*mpio));
 
-       map_context->ptr = mpio;
        clone->cmd_flags |= REQ_FAILFAST_TRANSPORT;
-       r = map_io(m, clone, mpio, 0);
+       r = map_io(m, clone, map_context, 0);
        if (r < 0 || r == DM_MAPIO_REQUEUE)
-               mempool_free(mpio, m->mpio_pool);
+               clear_mapinfo(m, map_context);
 
        return r;
 }
@@ -1054,8 +1070,9 @@ static int switch_pg_num(struct multipath *m, const char *pgstr)
        struct priority_group *pg;
        unsigned pgnum;
        unsigned long flags;
+       char dummy;
 
-       if (!pgstr || (sscanf(pgstr, "%u", &pgnum) != 1) || !pgnum ||
+       if (!pgstr || (sscanf(pgstr, "%u%c", &pgnum, &dummy) != 1) || !pgnum ||
            (pgnum > m->nr_priority_groups)) {
                DMWARN("invalid PG number supplied to switch_pg_num");
                return -EINVAL;
@@ -1085,8 +1102,9 @@ static int bypass_pg_num(struct multipath *m, const char *pgstr, int bypassed)
 {
        struct priority_group *pg;
        unsigned pgnum;
+       char dummy;
 
-       if (!pgstr || (sscanf(pgstr, "%u", &pgnum) != 1) || !pgnum ||
+       if (!pgstr || (sscanf(pgstr, "%u%c", &pgnum, &dummy) != 1) || !pgnum ||
            (pgnum > m->nr_priority_groups)) {
                DMWARN("invalid PG number supplied to bypass_pg");
                return -EINVAL;
@@ -1261,13 +1279,15 @@ static int multipath_end_io(struct dm_target *ti, struct request *clone,
        struct path_selector *ps;
        int r;
 
+       BUG_ON(!mpio);
+
        r  = do_end_io(m, clone, error, mpio);
        if (pgpath) {
                ps = &pgpath->pg->ps;
                if (ps->type->end_io)
                        ps->type->end_io(ps, &pgpath->path, mpio->nr_bytes);
        }
-       mempool_free(mpio, m->mpio_pool);
+       clear_mapinfo(m, map_context);
 
        return r;
 }
index 03a837a..3941fae 100644 (file)
@@ -112,6 +112,7 @@ static int ql_add_path(struct path_selector *ps, struct dm_path *path,
        struct selector *s = ps->context;
        struct path_info *pi;
        unsigned repeat_count = QL_MIN_IO;
+       char dummy;
 
        /*
         * Arguments: [<repeat_count>]
@@ -123,7 +124,7 @@ static int ql_add_path(struct path_selector *ps, struct dm_path *path,
                return -EINVAL;
        }
 
-       if ((argc == 1) && (sscanf(argv[0], "%u", &repeat_count) != 1)) {
+       if ((argc == 1) && (sscanf(argv[0], "%u%c", &repeat_count, &dummy) != 1)) {
                *error = "queue-length ps: invalid repeat count";
                return -EINVAL;
        }
index c5a875d..b0ba524 100644 (file)
@@ -604,7 +604,9 @@ static int read_disk_sb(struct md_rdev *rdev, int size)
                return 0;
 
        if (!sync_page_io(rdev, 0, size, rdev->sb_page, READ, 1)) {
-               DMERR("Failed to read device superblock");
+               DMERR("Failed to read superblock of device at position %d",
+                     rdev->raid_disk);
+               set_bit(Faulty, &rdev->flags);
                return -EINVAL;
        }
 
@@ -855,9 +857,25 @@ static int super_validate(struct mddev *mddev, struct md_rdev *rdev)
 static int analyse_superblocks(struct dm_target *ti, struct raid_set *rs)
 {
        int ret;
+       unsigned redundancy = 0;
+       struct raid_dev *dev;
        struct md_rdev *rdev, *freshest;
        struct mddev *mddev = &rs->md;
 
+       switch (rs->raid_type->level) {
+       case 1:
+               redundancy = rs->md.raid_disks - 1;
+               break;
+       case 4:
+       case 5:
+       case 6:
+               redundancy = rs->raid_type->parity_devs;
+               break;
+       default:
+               ti->error = "Unknown RAID type";
+               return -EINVAL;
+       }
+
        freshest = NULL;
        rdev_for_each(rdev, mddev) {
                if (!rdev->meta_bdev)
@@ -872,6 +890,37 @@ static int analyse_superblocks(struct dm_target *ti, struct raid_set *rs)
                case 0:
                        break;
                default:
+                       dev = container_of(rdev, struct raid_dev, rdev);
+                       if (redundancy--) {
+                               if (dev->meta_dev)
+                                       dm_put_device(ti, dev->meta_dev);
+
+                               dev->meta_dev = NULL;
+                               rdev->meta_bdev = NULL;
+
+                               if (rdev->sb_page)
+                                       put_page(rdev->sb_page);
+
+                               rdev->sb_page = NULL;
+
+                               rdev->sb_loaded = 0;
+
+                               /*
+                                * We might be able to salvage the data device
+                                * even though the meta device has failed.  For
+                                * now, we behave as though '- -' had been
+                                * set for this device in the table.
+                                */
+                               if (dev->data_dev)
+                                       dm_put_device(ti, dev->data_dev);
+
+                               dev->data_dev = NULL;
+                               rdev->bdev = NULL;
+
+                               list_del(&rdev->same_set);
+
+                               continue;
+                       }
                        ti->error = "Failed to load superblock";
                        return ret;
                }
@@ -1214,7 +1263,7 @@ static void raid_resume(struct dm_target *ti)
 
 static struct target_type raid_target = {
        .name = "raid",
-       .version = {1, 1, 0},
+       .version = {1, 2, 0},
        .module = THIS_MODULE,
        .ctr = raid_ctr,
        .dtr = raid_dtr,
index 9bfd057..d039de8 100644 (file)
@@ -924,8 +924,9 @@ static int get_mirror(struct mirror_set *ms, struct dm_target *ti,
                      unsigned int mirror, char **argv)
 {
        unsigned long long offset;
+       char dummy;
 
-       if (sscanf(argv[1], "%llu", &offset) != 1) {
+       if (sscanf(argv[1], "%llu%c", &offset, &dummy) != 1) {
                ti->error = "Invalid offset";
                return -EINVAL;
        }
@@ -953,13 +954,14 @@ static struct dm_dirty_log *create_dirty_log(struct dm_target *ti,
 {
        unsigned param_count;
        struct dm_dirty_log *dl;
+       char dummy;
 
        if (argc < 2) {
                ti->error = "Insufficient mirror log arguments";
                return NULL;
        }
 
-       if (sscanf(argv[1], "%u", &param_count) != 1) {
+       if (sscanf(argv[1], "%u%c", &param_count, &dummy) != 1) {
                ti->error = "Invalid mirror log argument count";
                return NULL;
        }
@@ -986,13 +988,14 @@ static int parse_features(struct mirror_set *ms, unsigned argc, char **argv,
 {
        unsigned num_features;
        struct dm_target *ti = ms->ti;
+       char dummy;
 
        *args_used = 0;
 
        if (!argc)
                return 0;
 
-       if (sscanf(argv[0], "%u", &num_features) != 1) {
+       if (sscanf(argv[0], "%u%c", &num_features, &dummy) != 1) {
                ti->error = "Invalid number of features";
                return -EINVAL;
        }
@@ -1036,6 +1039,7 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv)
        unsigned int nr_mirrors, m, args_used;
        struct mirror_set *ms;
        struct dm_dirty_log *dl;
+       char dummy;
 
        dl = create_dirty_log(ti, argc, argv, &args_used);
        if (!dl)
@@ -1044,7 +1048,7 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv)
        argv += args_used;
        argc -= args_used;
 
-       if (!argc || sscanf(argv[0], "%u", &nr_mirrors) != 1 ||
+       if (!argc || sscanf(argv[0], "%u%c", &nr_mirrors, &dummy) != 1 ||
            nr_mirrors < 2 || nr_mirrors > DM_KCOPYD_MAX_REGIONS + 1) {
                ti->error = "Invalid number of mirrors";
                dm_dirty_log_destroy(dl);
index 27f1d42..6ab1192 100644 (file)
@@ -114,6 +114,7 @@ static int rr_add_path(struct path_selector *ps, struct dm_path *path,
        struct selector *s = (struct selector *) ps->context;
        struct path_info *pi;
        unsigned repeat_count = RR_MIN_IO;
+       char dummy;
 
        if (argc > 1) {
                *error = "round-robin ps: incorrect number of arguments";
@@ -121,7 +122,7 @@ static int rr_add_path(struct path_selector *ps, struct dm_path *path,
        }
 
        /* First path argument is number of I/Os before switching path */
-       if ((argc == 1) && (sscanf(argv[0], "%u", &repeat_count) != 1)) {
+       if ((argc == 1) && (sscanf(argv[0], "%u%c", &repeat_count, &dummy) != 1)) {
                *error = "round-robin ps: invalid repeat count";
                return -EINVAL;
        }
index 59883bd..9df8f6b 100644 (file)
@@ -110,6 +110,7 @@ static int st_add_path(struct path_selector *ps, struct dm_path *path,
        struct path_info *pi;
        unsigned repeat_count = ST_MIN_IO;
        unsigned relative_throughput = 1;
+       char dummy;
 
        /*
         * Arguments: [<repeat_count> [<relative_throughput>]]
@@ -128,13 +129,13 @@ static int st_add_path(struct path_selector *ps, struct dm_path *path,
                return -EINVAL;
        }
 
-       if (argc && (sscanf(argv[0], "%u", &repeat_count) != 1)) {
+       if (argc && (sscanf(argv[0], "%u%c", &repeat_count, &dummy) != 1)) {
                *error = "service-time ps: invalid repeat count";
                return -EINVAL;
        }
 
        if ((argc == 2) &&
-           (sscanf(argv[1], "%u", &relative_throughput) != 1 ||
+           (sscanf(argv[1], "%u%c", &relative_throughput, &dummy) != 1 ||
             relative_throughput > ST_MAX_RELATIVE_THROUGHPUT)) {
                *error = "service-time ps: invalid relative_throughput value";
                return -EINVAL;
index 3d80cf0..35c94ff 100644 (file)
@@ -75,8 +75,9 @@ static int get_stripe(struct dm_target *ti, struct stripe_c *sc,
                      unsigned int stripe, char **argv)
 {
        unsigned long long start;
+       char dummy;
 
-       if (sscanf(argv[1], "%llu", &start) != 1)
+       if (sscanf(argv[1], "%llu%c", &start, &dummy) != 1)
                return -EINVAL;
 
        if (dm_get_device(ti, argv[0], dm_table_get_mode(ti->table),
index 63cc542..2e227fb 100644 (file)
@@ -268,8 +268,7 @@ void dm_table_destroy(struct dm_table *t)
        vfree(t->highs);
 
        /* free the device list */
-       if (t->devices.next != &t->devices)
-               free_devices(&t->devices);
+       free_devices(&t->devices);
 
        dm_free_md_mempools(t->mempools);
 
@@ -464,10 +463,11 @@ int dm_get_device(struct dm_target *ti, const char *path, fmode_t mode,
        struct dm_dev_internal *dd;
        unsigned int major, minor;
        struct dm_table *t = ti->table;
+       char dummy;
 
        BUG_ON(!t);
 
-       if (sscanf(path, "%u:%u", &major, &minor) == 2) {
+       if (sscanf(path, "%u:%u%c", &major, &minor, &dummy) == 2) {
                /* Extract the major/minor numbers */
                dev = MKDEV(major, minor);
                if (MAJOR(dev) != major || MINOR(dev) != minor)
@@ -842,9 +842,10 @@ static int validate_next_arg(struct dm_arg *arg, struct dm_arg_set *arg_set,
                             unsigned *value, char **error, unsigned grouped)
 {
        const char *arg_str = dm_shift_arg(arg_set);
+       char dummy;
 
        if (!arg_str ||
-           (sscanf(arg_str, "%u", value) != 1) ||
+           (sscanf(arg_str, "%u%c", value, &dummy) != 1) ||
            (*value < arg->min) ||
            (*value > arg->max) ||
            (grouped && arg_set->argc < *value)) {
index 237571a..737d388 100644 (file)
@@ -614,7 +614,7 @@ static int __commit_transaction(struct dm_pool_metadata *pmd)
        if (r < 0)
                goto out;
 
-       r = dm_sm_root_size(pmd->metadata_sm, &data_len);
+       r = dm_sm_root_size(pmd->data_sm, &data_len);
        if (r < 0)
                goto out;
 
@@ -713,6 +713,9 @@ struct dm_pool_metadata *dm_pool_metadata_open(struct block_device *bdev,
        if (r)
                goto bad;
 
+       if (bdev_size > THIN_METADATA_MAX_SECTORS)
+               bdev_size = THIN_METADATA_MAX_SECTORS;
+
        disk_super = dm_block_data(sblock);
        disk_super->magic = cpu_to_le64(THIN_SUPERBLOCK_MAGIC);
        disk_super->version = cpu_to_le32(THIN_VERSION);
index 859c168..ed4725e 100644 (file)
 
 #define THIN_METADATA_BLOCK_SIZE 4096
 
+/*
+ * The metadata device is currently limited in size.
+ *
+ * We have one block of index, which can hold 255 index entries.  Each
+ * index entry contains allocation info about 16k metadata blocks.
+ */
+#define THIN_METADATA_MAX_SECTORS (255 * (1 << 14) * (THIN_METADATA_BLOCK_SIZE / (1 << SECTOR_SHIFT)))
+
+/*
+ * A metadata device larger than 16GB triggers a warning.
+ */
+#define THIN_METADATA_MAX_SECTORS_WARNING (16 * (1024 * 1024 * 1024 >> SECTOR_SHIFT))
+
 /*----------------------------------------------------------------*/
 
 struct dm_pool_metadata;
index c308757..213ae32 100644 (file)
@@ -23,6 +23,7 @@
 #define DEFERRED_SET_SIZE 64
 #define MAPPING_POOL_SIZE 1024
 #define PRISON_CELLS 1024
+#define COMMIT_PERIOD HZ
 
 /*
  * The block size of the device holding pool data must be
 #define DATA_DEV_BLOCK_SIZE_MAX_SECTORS (1024 * 1024 * 1024 >> SECTOR_SHIFT)
 
 /*
- * The metadata device is currently limited in size.  The limitation is
- * checked lower down in dm-space-map-metadata, but we also check it here
- * so we can fail early.
- *
- * We have one block of index, which can hold 255 index entries.  Each
- * index entry contains allocation info about 16k metadata blocks.
- */
-#define METADATA_DEV_MAX_SECTORS (255 * (1 << 14) * (THIN_METADATA_BLOCK_SIZE / (1 << SECTOR_SHIFT)))
-
-/*
  * Device id is restricted to 24 bits.
  */
 #define MAX_DEV_ID ((1 << 24) - 1)
@@ -72,7 +63,7 @@
  * missed out if the io covers the block. (schedule_copy).
  *
  * iv) insert the new mapping into the origin's btree
- * (process_prepared_mappings).  This act of inserting breaks some
+ * (process_prepared_mapping).  This act of inserting breaks some
  * sharing of btree nodes between the two devices.  Breaking sharing only
  * effects the btree of that specific device.  Btrees for the other
  * devices that share the block never change.  The btree for the origin
@@ -124,7 +115,7 @@ struct cell {
        struct hlist_node list;
        struct bio_prison *prison;
        struct cell_key key;
-       unsigned count;
+       struct bio *holder;
        struct bio_list bios;
 };
 
@@ -220,54 +211,59 @@ static struct cell *__search_bucket(struct hlist_head *bucket,
  * This may block if a new cell needs allocating.  You must ensure that
  * cells will be unlocked even if the calling thread is blocked.
  *
- * Returns the number of entries in the cell prior to the new addition
- * or < 0 on failure.
+ * Returns 1 if the cell was already held, 0 if @inmate is the new holder.
  */
 static int bio_detain(struct bio_prison *prison, struct cell_key *key,
                      struct bio *inmate, struct cell **ref)
 {
-       int r;
+       int r = 1;
        unsigned long flags;
        uint32_t hash = hash_key(prison, key);
-       struct cell *uninitialized_var(cell), *cell2 = NULL;
+       struct cell *cell, *cell2;
 
        BUG_ON(hash > prison->nr_buckets);
 
        spin_lock_irqsave(&prison->lock, flags);
+
        cell = __search_bucket(prison->cells + hash, key);
+       if (cell) {
+               bio_list_add(&cell->bios, inmate);
+               goto out;
+       }
 
-       if (!cell) {
-               /*
-                * Allocate a new cell
-                */
-               spin_unlock_irqrestore(&prison->lock, flags);
-               cell2 = mempool_alloc(prison->cell_pool, GFP_NOIO);
-               spin_lock_irqsave(&prison->lock, flags);
+       /*
+        * Allocate a new cell
+        */
+       spin_unlock_irqrestore(&prison->lock, flags);
+       cell2 = mempool_alloc(prison->cell_pool, GFP_NOIO);
+       spin_lock_irqsave(&prison->lock, flags);
 
-               /*
-                * We've been unlocked, so we have to double check that
-                * nobody else has inserted this cell in the meantime.
-                */
-               cell = __search_bucket(prison->cells + hash, key);
+       /*
+        * We've been unlocked, so we have to double check that
+        * nobody else has inserted this cell in the meantime.
+        */
+       cell = __search_bucket(prison->cells + hash, key);
+       if (cell) {
+               mempool_free(cell2, prison->cell_pool);
+               bio_list_add(&cell->bios, inmate);
+               goto out;
+       }
 
-               if (!cell) {
-                       cell = cell2;
-                       cell2 = NULL;
+       /*
+        * Use new cell.
+        */
+       cell = cell2;
 
-                       cell->prison = prison;
-                       memcpy(&cell->key, key, sizeof(cell->key));
-                       cell->count = 0;
-                       bio_list_init(&cell->bios);
-                       hlist_add_head(&cell->list, prison->cells + hash);
-               }
-       }
+       cell->prison = prison;
+       memcpy(&cell->key, key, sizeof(cell->key));
+       cell->holder = inmate;
+       bio_list_init(&cell->bios);
+       hlist_add_head(&cell->list, prison->cells + hash);
 
-       r = cell->count++;
-       bio_list_add(&cell->bios, inmate);
-       spin_unlock_irqrestore(&prison->lock, flags);
+       r = 0;
 
-       if (cell2)
-               mempool_free(cell2, prison->cell_pool);
+out:
+       spin_unlock_irqrestore(&prison->lock, flags);
 
        *ref = cell;
 
@@ -283,8 +279,8 @@ static void __cell_release(struct cell *cell, struct bio_list *inmates)
 
        hlist_del(&cell->list);
 
-       if (inmates)
-               bio_list_merge(inmates, &cell->bios);
+       bio_list_add(inmates, cell->holder);
+       bio_list_merge(inmates, &cell->bios);
 
        mempool_free(cell, prison->cell_pool);
 }
@@ -305,22 +301,44 @@ static void cell_release(struct cell *cell, struct bio_list *bios)
  * bio may be in the cell.  This function releases the cell, and also does
  * a sanity check.
  */
+static void __cell_release_singleton(struct cell *cell, struct bio *bio)
+{
+       hlist_del(&cell->list);
+       BUG_ON(cell->holder != bio);
+       BUG_ON(!bio_list_empty(&cell->bios));
+}
+
 static void cell_release_singleton(struct cell *cell, struct bio *bio)
 {
-       struct bio_prison *prison = cell->prison;
-       struct bio_list bios;
-       struct bio *b;
        unsigned long flags;
-
-       bio_list_init(&bios);
+       struct bio_prison *prison = cell->prison;
 
        spin_lock_irqsave(&prison->lock, flags);
-       __cell_release(cell, &bios);
+       __cell_release_singleton(cell, bio);
        spin_unlock_irqrestore(&prison->lock, flags);
+}
+
+/*
+ * Sometimes we don't want the holder, just the additional bios.
+ */
+static void __cell_release_no_holder(struct cell *cell, struct bio_list *inmates)
+{
+       struct bio_prison *prison = cell->prison;
+
+       hlist_del(&cell->list);
+       bio_list_merge(inmates, &cell->bios);
 
-       b = bio_list_pop(&bios);
-       BUG_ON(b != bio);
-       BUG_ON(!bio_list_empty(&bios));
+       mempool_free(cell, prison->cell_pool);
+}
+
+static void cell_release_no_holder(struct cell *cell, struct bio_list *inmates)
+{
+       unsigned long flags;
+       struct bio_prison *prison = cell->prison;
+
+       spin_lock_irqsave(&prison->lock, flags);
+       __cell_release_no_holder(cell, inmates);
+       spin_unlock_irqrestore(&prison->lock, flags);
 }
 
 static void cell_error(struct cell *cell)
@@ -471,6 +489,13 @@ static void build_virtual_key(struct dm_thin_device *td, dm_block_t b,
  * devices.
  */
 struct new_mapping;
+
+struct pool_features {
+       unsigned zero_new_blocks:1;
+       unsigned discard_enabled:1;
+       unsigned discard_passdown:1;
+};
+
 struct pool {
        struct list_head list;
        struct dm_target *ti;   /* Only set if a pool target is bound */
@@ -484,7 +509,7 @@ struct pool {
        dm_block_t offset_mask;
        dm_block_t low_water_blocks;
 
-       unsigned zero_new_blocks:1;
+       struct pool_features pf;
        unsigned low_water_triggered:1; /* A dm event has been sent */
        unsigned no_free_space:1;       /* A -ENOSPC warning has been issued */
 
@@ -493,17 +518,21 @@ struct pool {
 
        struct workqueue_struct *wq;
        struct work_struct worker;
+       struct delayed_work waker;
 
        unsigned ref_count;
+       unsigned long last_commit_jiffies;
 
        spinlock_t lock;
        struct bio_list deferred_bios;
        struct bio_list deferred_flush_bios;
        struct list_head prepared_mappings;
+       struct list_head prepared_discards;
 
        struct bio_list retry_on_resume_list;
 
-       struct deferred_set ds; /* FIXME: move to thin_c */
+       struct deferred_set shared_read_ds;
+       struct deferred_set all_io_ds;
 
        struct new_mapping *next_mapping;
        mempool_t *mapping_pool;
@@ -521,7 +550,7 @@ struct pool_c {
        struct dm_target_callbacks callbacks;
 
        dm_block_t low_water_blocks;
-       unsigned zero_new_blocks:1;
+       struct pool_features pf;
 };
 
 /*
@@ -529,6 +558,7 @@ struct pool_c {
  */
 struct thin_c {
        struct dm_dev *pool_dev;
+       struct dm_dev *origin_dev;
        dm_thin_id dev_id;
 
        struct pool *pool;
@@ -597,6 +627,13 @@ static struct pool *__pool_table_lookup_metadata_dev(struct block_device *md_dev
 
 /*----------------------------------------------------------------*/
 
+struct endio_hook {
+       struct thin_c *tc;
+       struct deferred_entry *shared_read_entry;
+       struct deferred_entry *all_io_entry;
+       struct new_mapping *overwrite_mapping;
+};
+
 static void __requeue_bio_list(struct thin_c *tc, struct bio_list *master)
 {
        struct bio *bio;
@@ -607,7 +644,8 @@ static void __requeue_bio_list(struct thin_c *tc, struct bio_list *master)
        bio_list_init(master);
 
        while ((bio = bio_list_pop(&bios))) {
-               if (dm_get_mapinfo(bio)->ptr == tc)
+               struct endio_hook *h = dm_get_mapinfo(bio)->ptr;
+               if (h->tc == tc)
                        bio_endio(bio, DM_ENDIO_REQUEUE);
                else
                        bio_list_add(master, bio);
@@ -646,14 +684,16 @@ static void remap(struct thin_c *tc, struct bio *bio, dm_block_t block)
                (bio->bi_sector & pool->offset_mask);
 }
 
-static void remap_and_issue(struct thin_c *tc, struct bio *bio,
-                           dm_block_t block)
+static void remap_to_origin(struct thin_c *tc, struct bio *bio)
+{
+       bio->bi_bdev = tc->origin_dev->bdev;
+}
+
+static void issue(struct thin_c *tc, struct bio *bio)
 {
        struct pool *pool = tc->pool;
        unsigned long flags;
 
-       remap(tc, bio, block);
-
        /*
         * Batch together any FUA/FLUSH bios we find and then issue
         * a single commit for them in process_deferred_bios().
@@ -666,6 +706,19 @@ static void remap_and_issue(struct thin_c *tc, struct bio *bio,
                generic_make_request(bio);
 }
 
+static void remap_to_origin_and_issue(struct thin_c *tc, struct bio *bio)
+{
+       remap_to_origin(tc, bio);
+       issue(tc, bio);
+}
+
+static void remap_and_issue(struct thin_c *tc, struct bio *bio,
+                           dm_block_t block)
+{
+       remap(tc, bio, block);
+       issue(tc, bio);
+}
+
 /*
  * wake_worker() is used when new work is queued and when pool_resume is
  * ready to continue deferred IO processing.
@@ -680,21 +733,17 @@ static void wake_worker(struct pool *pool)
 /*
  * Bio endio functions.
  */
-struct endio_hook {
-       struct thin_c *tc;
-       bio_end_io_t *saved_bi_end_io;
-       struct deferred_entry *entry;
-};
-
 struct new_mapping {
        struct list_head list;
 
-       int prepared;
+       unsigned quiesced:1;
+       unsigned prepared:1;
+       unsigned pass_discard:1;
 
        struct thin_c *tc;
        dm_block_t virt_block;
        dm_block_t data_block;
-       struct cell *cell;
+       struct cell *cell, *cell2;
        int err;
 
        /*
@@ -711,7 +760,7 @@ static void __maybe_add_mapping(struct new_mapping *m)
 {
        struct pool *pool = m->tc->pool;
 
-       if (list_empty(&m->list) && m->prepared) {
+       if (m->quiesced && m->prepared) {
                list_add(&m->list, &pool->prepared_mappings);
                wake_worker(pool);
        }
@@ -734,7 +783,8 @@ static void copy_complete(int read_err, unsigned long write_err, void *context)
 static void overwrite_endio(struct bio *bio, int err)
 {
        unsigned long flags;
-       struct new_mapping *m = dm_get_mapinfo(bio)->ptr;
+       struct endio_hook *h = dm_get_mapinfo(bio)->ptr;
+       struct new_mapping *m = h->overwrite_mapping;
        struct pool *pool = m->tc->pool;
 
        m->err = err;
@@ -745,31 +795,6 @@ static void overwrite_endio(struct bio *bio, int err)
        spin_unlock_irqrestore(&pool->lock, flags);
 }
 
-static void shared_read_endio(struct bio *bio, int err)
-{
-       struct list_head mappings;
-       struct new_mapping *m, *tmp;
-       struct endio_hook *h = dm_get_mapinfo(bio)->ptr;
-       unsigned long flags;
-       struct pool *pool = h->tc->pool;
-
-       bio->bi_end_io = h->saved_bi_end_io;
-       bio_endio(bio, err);
-
-       INIT_LIST_HEAD(&mappings);
-       ds_dec(h->entry, &mappings);
-
-       spin_lock_irqsave(&pool->lock, flags);
-       list_for_each_entry_safe(m, tmp, &mappings, list) {
-               list_del(&m->list);
-               INIT_LIST_HEAD(&m->list);
-               __maybe_add_mapping(m);
-       }
-       spin_unlock_irqrestore(&pool->lock, flags);
-
-       mempool_free(h, pool->endio_hook_pool);
-}
-
 /*----------------------------------------------------------------*/
 
 /*
@@ -800,21 +825,16 @@ static void cell_defer(struct thin_c *tc, struct cell *cell,
  * Same as cell_defer above, except it omits one particular detainee,
  * a write bio that covers the block and has already been processed.
  */
-static void cell_defer_except(struct thin_c *tc, struct cell *cell,
-                             struct bio *exception)
+static void cell_defer_except(struct thin_c *tc, struct cell *cell)
 {
        struct bio_list bios;
-       struct bio *bio;
        struct pool *pool = tc->pool;
        unsigned long flags;
 
        bio_list_init(&bios);
-       cell_release(cell, &bios);
 
        spin_lock_irqsave(&pool->lock, flags);
-       while ((bio = bio_list_pop(&bios)))
-               if (bio != exception)
-                       bio_list_add(&pool->deferred_bios, bio);
+       cell_release_no_holder(cell, &pool->deferred_bios);
        spin_unlock_irqrestore(&pool->lock, flags);
 
        wake_worker(pool);
@@ -854,7 +874,7 @@ static void process_prepared_mapping(struct new_mapping *m)
         * the bios in the cell.
         */
        if (bio) {
-               cell_defer_except(tc, m->cell, bio);
+               cell_defer_except(tc, m->cell);
                bio_endio(bio, 0);
        } else
                cell_defer(tc, m->cell, m->data_block);
@@ -863,7 +883,30 @@ static void process_prepared_mapping(struct new_mapping *m)
        mempool_free(m, tc->pool->mapping_pool);
 }
 
-static void process_prepared_mappings(struct pool *pool)
+static void process_prepared_discard(struct new_mapping *m)
+{
+       int r;
+       struct thin_c *tc = m->tc;
+
+       r = dm_thin_remove_block(tc->td, m->virt_block);
+       if (r)
+               DMERR("dm_thin_remove_block() failed");
+
+       /*
+        * Pass the discard down to the underlying device?
+        */
+       if (m->pass_discard)
+               remap_and_issue(tc, m->bio, m->data_block);
+       else
+               bio_endio(m->bio, 0);
+
+       cell_defer_except(tc, m->cell);
+       cell_defer_except(tc, m->cell2);
+       mempool_free(m, tc->pool->mapping_pool);
+}
+
+static void process_prepared(struct pool *pool, struct list_head *head,
+                            void (*fn)(struct new_mapping *))
 {
        unsigned long flags;
        struct list_head maps;
@@ -871,21 +914,27 @@ static void process_prepared_mappings(struct pool *pool)
 
        INIT_LIST_HEAD(&maps);
        spin_lock_irqsave(&pool->lock, flags);
-       list_splice_init(&pool->prepared_mappings, &maps);
+       list_splice_init(head, &maps);
        spin_unlock_irqrestore(&pool->lock, flags);
 
        list_for_each_entry_safe(m, tmp, &maps, list)
-               process_prepared_mapping(m);
+               fn(m);
 }
 
 /*
  * Deferred bio jobs.
  */
-static int io_overwrites_block(struct pool *pool, struct bio *bio)
+static int io_overlaps_block(struct pool *pool, struct bio *bio)
 {
-       return ((bio_data_dir(bio) == WRITE) &&
-               !(bio->bi_sector & pool->offset_mask)) &&
+       return !(bio->bi_sector & pool->offset_mask) &&
                (bio->bi_size == (pool->sectors_per_block << SECTOR_SHIFT));
+
+}
+
+static int io_overwrites_block(struct pool *pool, struct bio *bio)
+{
+       return (bio_data_dir(bio) == WRITE) &&
+               io_overlaps_block(pool, bio);
 }
 
 static void save_and_set_endio(struct bio *bio, bio_end_io_t **save,
@@ -917,7 +966,8 @@ static struct new_mapping *get_next_mapping(struct pool *pool)
 }
 
 static void schedule_copy(struct thin_c *tc, dm_block_t virt_block,
-                         dm_block_t data_origin, dm_block_t data_dest,
+                         struct dm_dev *origin, dm_block_t data_origin,
+                         dm_block_t data_dest,
                          struct cell *cell, struct bio *bio)
 {
        int r;
@@ -925,6 +975,7 @@ static void schedule_copy(struct thin_c *tc, dm_block_t virt_block,
        struct new_mapping *m = get_next_mapping(pool);
 
        INIT_LIST_HEAD(&m->list);
+       m->quiesced = 0;
        m->prepared = 0;
        m->tc = tc;
        m->virt_block = virt_block;
@@ -933,7 +984,8 @@ static void schedule_copy(struct thin_c *tc, dm_block_t virt_block,
        m->err = 0;
        m->bio = NULL;
 
-       ds_add_work(&pool->ds, &m->list);
+       if (!ds_add_work(&pool->shared_read_ds, &m->list))
+               m->quiesced = 1;
 
        /*
         * IO to pool_dev remaps to the pool target's data_dev.
@@ -942,14 +994,15 @@ static void schedule_copy(struct thin_c *tc, dm_block_t virt_block,
         * bio immediately. Otherwise we use kcopyd to clone the data first.
         */
        if (io_overwrites_block(pool, bio)) {
+               struct endio_hook *h = dm_get_mapinfo(bio)->ptr;
+               h->overwrite_mapping = m;
                m->bio = bio;
                save_and_set_endio(bio, &m->saved_bi_end_io, overwrite_endio);
-               dm_get_mapinfo(bio)->ptr = m;
                remap_and_issue(tc, bio, data_dest);
        } else {
                struct dm_io_region from, to;
 
-               from.bdev = tc->pool_dev->bdev;
+               from.bdev = origin->bdev;
                from.sector = data_origin * pool->sectors_per_block;
                from.count = pool->sectors_per_block;
 
@@ -967,6 +1020,22 @@ static void schedule_copy(struct thin_c *tc, dm_block_t virt_block,
        }
 }
 
+static void schedule_internal_copy(struct thin_c *tc, dm_block_t virt_block,
+                                  dm_block_t data_origin, dm_block_t data_dest,
+                                  struct cell *cell, struct bio *bio)
+{
+       schedule_copy(tc, virt_block, tc->pool_dev,
+                     data_origin, data_dest, cell, bio);
+}
+
+static void schedule_external_copy(struct thin_c *tc, dm_block_t virt_block,
+                                  dm_block_t data_dest,
+                                  struct cell *cell, struct bio *bio)
+{
+       schedule_copy(tc, virt_block, tc->origin_dev,
+                     virt_block, data_dest, cell, bio);
+}
+
 static void schedule_zero(struct thin_c *tc, dm_block_t virt_block,
                          dm_block_t data_block, struct cell *cell,
                          struct bio *bio)
@@ -975,6 +1044,7 @@ static void schedule_zero(struct thin_c *tc, dm_block_t virt_block,
        struct new_mapping *m = get_next_mapping(pool);
 
        INIT_LIST_HEAD(&m->list);
+       m->quiesced = 1;
        m->prepared = 0;
        m->tc = tc;
        m->virt_block = virt_block;
@@ -988,13 +1058,14 @@ static void schedule_zero(struct thin_c *tc, dm_block_t virt_block,
         * zeroing pre-existing data, we can issue the bio immediately.
         * Otherwise we use kcopyd to zero the data first.
         */
-       if (!pool->zero_new_blocks)
+       if (!pool->pf.zero_new_blocks)
                process_prepared_mapping(m);
 
        else if (io_overwrites_block(pool, bio)) {
+               struct endio_hook *h = dm_get_mapinfo(bio)->ptr;
+               h->overwrite_mapping = m;
                m->bio = bio;
                save_and_set_endio(bio, &m->saved_bi_end_io, overwrite_endio);
-               dm_get_mapinfo(bio)->ptr = m;
                remap_and_issue(tc, bio, data_block);
 
        } else {
@@ -1081,7 +1152,8 @@ static int alloc_data_block(struct thin_c *tc, dm_block_t *result)
  */
 static void retry_on_resume(struct bio *bio)
 {
-       struct thin_c *tc = dm_get_mapinfo(bio)->ptr;
+       struct endio_hook *h = dm_get_mapinfo(bio)->ptr;
+       struct thin_c *tc = h->tc;
        struct pool *pool = tc->pool;
        unsigned long flags;
 
@@ -1102,6 +1174,86 @@ static void no_space(struct cell *cell)
                retry_on_resume(bio);
 }
 
+static void process_discard(struct thin_c *tc, struct bio *bio)
+{
+       int r;
+       struct pool *pool = tc->pool;
+       struct cell *cell, *cell2;
+       struct cell_key key, key2;
+       dm_block_t block = get_bio_block(tc, bio);
+       struct dm_thin_lookup_result lookup_result;
+       struct new_mapping *m;
+
+       build_virtual_key(tc->td, block, &key);
+       if (bio_detain(tc->pool->prison, &key, bio, &cell))
+               return;
+
+       r = dm_thin_find_block(tc->td, block, 1, &lookup_result);
+       switch (r) {
+       case 0:
+               /*
+                * Check nobody is fiddling with this pool block.  This can
+                * happen if someone's in the process of breaking sharing
+                * on this block.
+                */
+               build_data_key(tc->td, lookup_result.block, &key2);
+               if (bio_detain(tc->pool->prison, &key2, bio, &cell2)) {
+                       cell_release_singleton(cell, bio);
+                       break;
+               }
+
+               if (io_overlaps_block(pool, bio)) {
+                       /*
+                        * IO may still be going to the destination block.  We must
+                        * quiesce before we can do the removal.
+                        */
+                       m = get_next_mapping(pool);
+                       m->tc = tc;
+                       m->pass_discard = (!lookup_result.shared) & pool->pf.discard_passdown;
+                       m->virt_block = block;
+                       m->data_block = lookup_result.block;
+                       m->cell = cell;
+                       m->cell2 = cell2;
+                       m->err = 0;
+                       m->bio = bio;
+
+                       if (!ds_add_work(&pool->all_io_ds, &m->list)) {
+                               list_add(&m->list, &pool->prepared_discards);
+                               wake_worker(pool);
+                       }
+               } else {
+                       /*
+                        * This path is hit if people are ignoring
+                        * limits->discard_granularity.  It ignores any
+                        * part of the discard that is in a subsequent
+                        * block.
+                        */
+                       sector_t offset = bio->bi_sector - (block << pool->block_shift);
+                       unsigned remaining = (pool->sectors_per_block - offset) << 9;
+                       bio->bi_size = min(bio->bi_size, remaining);
+
+                       cell_release_singleton(cell, bio);
+                       cell_release_singleton(cell2, bio);
+                       remap_and_issue(tc, bio, lookup_result.block);
+               }
+               break;
+
+       case -ENODATA:
+               /*
+                * It isn't provisioned, just forget it.
+                */
+               cell_release_singleton(cell, bio);
+               bio_endio(bio, 0);
+               break;
+
+       default:
+               DMERR("discard: find block unexpectedly returned %d", r);
+               cell_release_singleton(cell, bio);
+               bio_io_error(bio);
+               break;
+       }
+}
+
 static void break_sharing(struct thin_c *tc, struct bio *bio, dm_block_t block,
                          struct cell_key *key,
                          struct dm_thin_lookup_result *lookup_result,
@@ -1113,8 +1265,8 @@ static void break_sharing(struct thin_c *tc, struct bio *bio, dm_block_t block,
        r = alloc_data_block(tc, &data_block);
        switch (r) {
        case 0:
-               schedule_copy(tc, block, lookup_result->block,
-                             data_block, cell, bio);
+               schedule_internal_copy(tc, block, lookup_result->block,
+                                      data_block, cell, bio);
                break;
 
        case -ENOSPC:
@@ -1147,13 +1299,9 @@ static void process_shared_bio(struct thin_c *tc, struct bio *bio,
        if (bio_data_dir(bio) == WRITE)
                break_sharing(tc, bio, block, &key, lookup_result, cell);
        else {
-               struct endio_hook *h;
-               h = mempool_alloc(pool->endio_hook_pool, GFP_NOIO);
+               struct endio_hook *h = dm_get_mapinfo(bio)->ptr;
 
-               h->tc = tc;
-               h->entry = ds_inc(&pool->ds);
-               save_and_set_endio(bio, &h->saved_bi_end_io, shared_read_endio);
-               dm_get_mapinfo(bio)->ptr = h;
+               h->shared_read_entry = ds_inc(&pool->shared_read_ds);
 
                cell_release_singleton(cell, bio);
                remap_and_issue(tc, bio, lookup_result->block);
@@ -1188,7 +1336,10 @@ static void provision_block(struct thin_c *tc, struct bio *bio, dm_block_t block
        r = alloc_data_block(tc, &data_block);
        switch (r) {
        case 0:
-               schedule_zero(tc, block, data_block, cell, bio);
+               if (tc->origin_dev)
+                       schedule_external_copy(tc, block, data_block, cell, bio);
+               else
+                       schedule_zero(tc, block, data_block, cell, bio);
                break;
 
        case -ENOSPC:
@@ -1239,16 +1390,27 @@ static void process_bio(struct thin_c *tc, struct bio *bio)
                break;
 
        case -ENODATA:
-               provision_block(tc, bio, block, cell);
+               if (bio_data_dir(bio) == READ && tc->origin_dev) {
+                       cell_release_singleton(cell, bio);
+                       remap_to_origin_and_issue(tc, bio);
+               } else
+                       provision_block(tc, bio, block, cell);
                break;
 
        default:
                DMERR("dm_thin_find_block() failed, error = %d", r);
+               cell_release_singleton(cell, bio);
                bio_io_error(bio);
                break;
        }
 }
 
+static int need_commit_due_to_time(struct pool *pool)
+{
+       return jiffies < pool->last_commit_jiffies ||
+              jiffies > pool->last_commit_jiffies + COMMIT_PERIOD;
+}
+
 static void process_deferred_bios(struct pool *pool)
 {
        unsigned long flags;
@@ -1264,7 +1426,9 @@ static void process_deferred_bios(struct pool *pool)
        spin_unlock_irqrestore(&pool->lock, flags);
 
        while ((bio = bio_list_pop(&bios))) {
-               struct thin_c *tc = dm_get_mapinfo(bio)->ptr;
+               struct endio_hook *h = dm_get_mapinfo(bio)->ptr;
+               struct thin_c *tc = h->tc;
+
                /*
                 * If we've got no free new_mapping structs, and processing
                 * this bio might require one, we pause until there are some
@@ -1277,7 +1441,11 @@ static void process_deferred_bios(struct pool *pool)
 
                        break;
                }
-               process_bio(tc, bio);
+
+               if (bio->bi_rw & REQ_DISCARD)
+                       process_discard(tc, bio);
+               else
+                       process_bio(tc, bio);
        }
 
        /*
@@ -1290,7 +1458,7 @@ static void process_deferred_bios(struct pool *pool)
        bio_list_init(&pool->deferred_flush_bios);
        spin_unlock_irqrestore(&pool->lock, flags);
 
-       if (bio_list_empty(&bios))
+       if (bio_list_empty(&bios) && !need_commit_due_to_time(pool))
                return;
 
        r = dm_pool_commit_metadata(pool->pmd);
@@ -1301,6 +1469,7 @@ static void process_deferred_bios(struct pool *pool)
                        bio_io_error(bio);
                return;
        }
+       pool->last_commit_jiffies = jiffies;
 
        while ((bio = bio_list_pop(&bios)))
                generic_make_request(bio);
@@ -1310,10 +1479,22 @@ static void do_worker(struct work_struct *ws)
 {
        struct pool *pool = container_of(ws, struct pool, worker);
 
-       process_prepared_mappings(pool);
+       process_prepared(pool, &pool->prepared_mappings, process_prepared_mapping);
+       process_prepared(pool, &pool->prepared_discards, process_prepared_discard);
        process_deferred_bios(pool);
 }
 
+/*
+ * We want to commit periodically so that not too much
+ * unwritten data builds up.
+ */
+static void do_waker(struct work_struct *ws)
+{
+       struct pool *pool = container_of(to_delayed_work(ws), struct pool, waker);
+       wake_worker(pool);
+       queue_delayed_work(pool->wq, &pool->waker, COMMIT_PERIOD);
+}
+
 /*----------------------------------------------------------------*/
 
 /*
@@ -1335,6 +1516,19 @@ static void thin_defer_bio(struct thin_c *tc, struct bio *bio)
        wake_worker(pool);
 }
 
+static struct endio_hook *thin_hook_bio(struct thin_c *tc, struct bio *bio)
+{
+       struct pool *pool = tc->pool;
+       struct endio_hook *h = mempool_alloc(pool->endio_hook_pool, GFP_NOIO);
+
+       h->tc = tc;
+       h->shared_read_entry = NULL;
+       h->all_io_entry = bio->bi_rw & REQ_DISCARD ? NULL : ds_inc(&pool->all_io_ds);
+       h->overwrite_mapping = NULL;
+
+       return h;
+}
+
 /*
  * Non-blocking function called from the thin target's map function.
  */
@@ -1347,12 +1541,8 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio,
        struct dm_thin_device *td = tc->td;
        struct dm_thin_lookup_result result;
 
-       /*
-        * Save the thin context for easy access from the deferred bio later.
-        */
-       map_context->ptr = tc;
-
-       if (bio->bi_rw & (REQ_FLUSH | REQ_FUA)) {
+       map_context->ptr = thin_hook_bio(tc, bio);
+       if (bio->bi_rw & (REQ_DISCARD | REQ_FLUSH | REQ_FUA)) {
                thin_defer_bio(tc, bio);
                return DM_MAPIO_SUBMITTED;
        }
@@ -1434,7 +1624,7 @@ static int bind_control_target(struct pool *pool, struct dm_target *ti)
 
        pool->ti = ti;
        pool->low_water_blocks = pt->low_water_blocks;
-       pool->zero_new_blocks = pt->zero_new_blocks;
+       pool->pf = pt->pf;
 
        return 0;
 }
@@ -1448,6 +1638,14 @@ static void unbind_control_target(struct pool *pool, struct dm_target *ti)
 /*----------------------------------------------------------------
  * Pool creation
  *--------------------------------------------------------------*/
+/* Initialize pool features. */
+static void pool_features_init(struct pool_features *pf)
+{
+       pf->zero_new_blocks = 1;
+       pf->discard_enabled = 1;
+       pf->discard_passdown = 1;
+}
+
 static void __pool_destroy(struct pool *pool)
 {
        __pool_table_remove(pool);
@@ -1495,7 +1693,7 @@ static struct pool *pool_create(struct mapped_device *pool_md,
        pool->block_shift = ffs(block_size) - 1;
        pool->offset_mask = block_size - 1;
        pool->low_water_blocks = 0;
-       pool->zero_new_blocks = 1;
+       pool_features_init(&pool->pf);
        pool->prison = prison_create(PRISON_CELLS);
        if (!pool->prison) {
                *error = "Error creating pool's bio prison";
@@ -1523,14 +1721,17 @@ static struct pool *pool_create(struct mapped_device *pool_md,
        }
 
        INIT_WORK(&pool->worker, do_worker);
+       INIT_DELAYED_WORK(&pool->waker, do_waker);
        spin_lock_init(&pool->lock);
        bio_list_init(&pool->deferred_bios);
        bio_list_init(&pool->deferred_flush_bios);
        INIT_LIST_HEAD(&pool->prepared_mappings);
+       INIT_LIST_HEAD(&pool->prepared_discards);
        pool->low_water_triggered = 0;
        pool->no_free_space = 0;
        bio_list_init(&pool->retry_on_resume_list);
-       ds_init(&pool->ds);
+       ds_init(&pool->shared_read_ds);
+       ds_init(&pool->all_io_ds);
 
        pool->next_mapping = NULL;
        pool->mapping_pool =
@@ -1549,6 +1750,7 @@ static struct pool *pool_create(struct mapped_device *pool_md,
                goto bad_endio_hook_pool;
        }
        pool->ref_count = 1;
+       pool->last_commit_jiffies = jiffies;
        pool->pool_md = pool_md;
        pool->md_dev = metadata_dev;
        __pool_table_insert(pool);
@@ -1588,7 +1790,8 @@ static void __pool_dec(struct pool *pool)
 
 static struct pool *__pool_find(struct mapped_device *pool_md,
                                struct block_device *metadata_dev,
-                               unsigned long block_size, char **error)
+                               unsigned long block_size, char **error,
+                               int *created)
 {
        struct pool *pool = __pool_table_lookup_metadata_dev(metadata_dev);
 
@@ -1604,8 +1807,10 @@ static struct pool *__pool_find(struct mapped_device *pool_md,
                                return ERR_PTR(-EINVAL);
                        __pool_inc(pool);
 
-               } else
+               } else {
                        pool = pool_create(pool_md, metadata_dev, block_size, error);
+                       *created = 1;
+               }
        }
 
        return pool;
@@ -1629,10 +1834,6 @@ static void pool_dtr(struct dm_target *ti)
        mutex_unlock(&dm_thin_pool_table.mutex);
 }
 
-struct pool_features {
-       unsigned zero_new_blocks:1;
-};
-
 static int parse_pool_features(struct dm_arg_set *as, struct pool_features *pf,
                               struct dm_target *ti)
 {
@@ -1641,7 +1842,7 @@ static int parse_pool_features(struct dm_arg_set *as, struct pool_features *pf,
        const char *arg_name;
 
        static struct dm_arg _args[] = {
-               {0, 1, "Invalid number of pool feature arguments"},
+               {0, 3, "Invalid number of pool feature arguments"},
        };
 
        /*
@@ -1661,6 +1862,12 @@ static int parse_pool_features(struct dm_arg_set *as, struct pool_features *pf,
                if (!strcasecmp(arg_name, "skip_block_zeroing")) {
                        pf->zero_new_blocks = 0;
                        continue;
+               } else if (!strcasecmp(arg_name, "ignore_discard")) {
+                       pf->discard_enabled = 0;
+                       continue;
+               } else if (!strcasecmp(arg_name, "no_discard_passdown")) {
+                       pf->discard_passdown = 0;
+                       continue;
                }
 
                ti->error = "Unrecognised pool feature requested";
@@ -1678,10 +1885,12 @@ static int parse_pool_features(struct dm_arg_set *as, struct pool_features *pf,
  *
  * Optional feature arguments are:
  *          skip_block_zeroing: skips the zeroing of newly-provisioned blocks.
+ *          ignore_discard: disable discard
+ *          no_discard_passdown: don't pass discards down to the data device
  */
 static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
 {
-       int r;
+       int r, pool_created = 0;
        struct pool_c *pt;
        struct pool *pool;
        struct pool_features pf;
@@ -1691,6 +1900,7 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
        dm_block_t low_water_blocks;
        struct dm_dev *metadata_dev;
        sector_t metadata_dev_size;
+       char b[BDEVNAME_SIZE];
 
        /*
         * FIXME Remove validation from scope of lock.
@@ -1712,11 +1922,9 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
        }
 
        metadata_dev_size = i_size_read(metadata_dev->bdev->bd_inode) >> SECTOR_SHIFT;
-       if (metadata_dev_size > METADATA_DEV_MAX_SECTORS) {
-               ti->error = "Metadata device is too large";
-               r = -EINVAL;
-               goto out_metadata;
-       }
+       if (metadata_dev_size > THIN_METADATA_MAX_SECTORS_WARNING)
+               DMWARN("Metadata device %s is larger than %u sectors: excess space will not be used.",
+                      bdevname(metadata_dev->bdev, b), THIN_METADATA_MAX_SECTORS);
 
        r = dm_get_device(ti, argv[1], FMODE_READ | FMODE_WRITE, &data_dev);
        if (r) {
@@ -1742,8 +1950,7 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
        /*
         * Set default pool features.
         */
-       memset(&pf, 0, sizeof(pf));
-       pf.zero_new_blocks = 1;
+       pool_features_init(&pf);
 
        dm_consume_args(&as, 4);
        r = parse_pool_features(&as, &pf, ti);
@@ -1757,20 +1964,58 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
        }
 
        pool = __pool_find(dm_table_get_md(ti->table), metadata_dev->bdev,
-                          block_size, &ti->error);
+                          block_size, &ti->error, &pool_created);
        if (IS_ERR(pool)) {
                r = PTR_ERR(pool);
                goto out_free_pt;
        }
 
+       /*
+        * 'pool_created' reflects whether this is the first table load.
+        * Top level discard support is not allowed to be changed after
+        * initial load.  This would require a pool reload to trigger thin
+        * device changes.
+        */
+       if (!pool_created && pf.discard_enabled != pool->pf.discard_enabled) {
+               ti->error = "Discard support cannot be disabled once enabled";
+               r = -EINVAL;
+               goto out_flags_changed;
+       }
+
+       /*
+        * If discard_passdown was enabled verify that the data device
+        * supports discards.  Disable discard_passdown if not; otherwise
+        * -EOPNOTSUPP will be returned.
+        */
+       if (pf.discard_passdown) {
+               struct request_queue *q = bdev_get_queue(data_dev->bdev);
+               if (!q || !blk_queue_discard(q)) {
+                       DMWARN("Discard unsupported by data device: Disabling discard passdown.");
+                       pf.discard_passdown = 0;
+               }
+       }
+
        pt->pool = pool;
        pt->ti = ti;
        pt->metadata_dev = metadata_dev;
        pt->data_dev = data_dev;
        pt->low_water_blocks = low_water_blocks;
-       pt->zero_new_blocks = pf.zero_new_blocks;
+       pt->pf = pf;
        ti->num_flush_requests = 1;
-       ti->num_discard_requests = 0;
+       /*
+        * Only need to enable discards if the pool should pass
+        * them down to the data device.  The thin device's discard
+        * processing will cause mappings to be removed from the btree.
+        */
+       if (pf.discard_enabled && pf.discard_passdown) {
+               ti->num_discard_requests = 1;
+               /*
+                * Setting 'discards_supported' circumvents the normal
+                * stacking of discard limits (this keeps the pool and
+                * thin devices' discard limits consistent).
+                */
+               ti->discards_supported = 1;
+       }
        ti->private = pt;
 
        pt->callbacks.congested_fn = pool_is_congested;
@@ -1780,6 +2025,8 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
 
        return 0;
 
+out_flags_changed:
+       __pool_dec(pool);
 out_free_pt:
        kfree(pt);
 out:
@@ -1878,7 +2125,7 @@ static void pool_resume(struct dm_target *ti)
        __requeue_bios(pool);
        spin_unlock_irqrestore(&pool->lock, flags);
 
-       wake_worker(pool);
+       do_waker(&pool->waker.work);
 }
 
 static void pool_postsuspend(struct dm_target *ti)
@@ -1887,6 +2134,7 @@ static void pool_postsuspend(struct dm_target *ti)
        struct pool_c *pt = ti->private;
        struct pool *pool = pt->pool;
 
+       cancel_delayed_work(&pool->waker);
        flush_workqueue(pool->wq);
 
        r = dm_pool_commit_metadata(pool->pmd);
@@ -2067,7 +2315,7 @@ static int pool_message(struct dm_target *ti, unsigned argc, char **argv)
 static int pool_status(struct dm_target *ti, status_type_t type,
                       char *result, unsigned maxlen)
 {
-       int r;
+       int r, count;
        unsigned sz = 0;
        uint64_t transaction_id;
        dm_block_t nr_free_blocks_data;
@@ -2130,10 +2378,19 @@ static int pool_status(struct dm_target *ti, status_type_t type,
                       (unsigned long)pool->sectors_per_block,
                       (unsigned long long)pt->low_water_blocks);
 
-               DMEMIT("%u ", !pool->zero_new_blocks);
+               count = !pool->pf.zero_new_blocks + !pool->pf.discard_enabled +
+                       !pool->pf.discard_passdown;
+               DMEMIT("%u ", count);
 
-               if (!pool->zero_new_blocks)
+               if (!pool->pf.zero_new_blocks)
                        DMEMIT("skip_block_zeroing ");
+
+               if (!pool->pf.discard_enabled)
+                       DMEMIT("ignore_discard ");
+
+               if (!pool->pf.discard_passdown)
+                       DMEMIT("no_discard_passdown ");
+
                break;
        }
 
@@ -2162,6 +2419,21 @@ static int pool_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
        return min(max_size, q->merge_bvec_fn(q, bvm, biovec));
 }
 
+static void set_discard_limits(struct pool *pool, struct queue_limits *limits)
+{
+       /*
+        * FIXME: these limits may be incompatible with the pool's data device
+        */
+       limits->max_discard_sectors = pool->sectors_per_block;
+
+       /*
+        * This is just a hint, and not enforced.  We have to cope with
+        * bios that overlap 2 blocks.
+        */
+       limits->discard_granularity = pool->sectors_per_block << SECTOR_SHIFT;
+       limits->discard_zeroes_data = pool->pf.zero_new_blocks;
+}
+
 static void pool_io_hints(struct dm_target *ti, struct queue_limits *limits)
 {
        struct pool_c *pt = ti->private;
@@ -2169,13 +2441,15 @@ static void pool_io_hints(struct dm_target *ti, struct queue_limits *limits)
 
        blk_limits_io_min(limits, 0);
        blk_limits_io_opt(limits, pool->sectors_per_block << SECTOR_SHIFT);
+       if (pool->pf.discard_enabled)
+               set_discard_limits(pool, limits);
 }
 
 static struct target_type pool_target = {
        .name = "thin-pool",
        .features = DM_TARGET_SINGLETON | DM_TARGET_ALWAYS_WRITEABLE |
                    DM_TARGET_IMMUTABLE,
-       .version = {1, 0, 0},
+       .version = {1, 1, 0},
        .module = THIS_MODULE,
        .ctr = pool_ctr,
        .dtr = pool_dtr,
@@ -2202,6 +2476,8 @@ static void thin_dtr(struct dm_target *ti)
        __pool_dec(tc->pool);
        dm_pool_close_thin_device(tc->td);
        dm_put_device(ti, tc->pool_dev);
+       if (tc->origin_dev)
+               dm_put_device(ti, tc->origin_dev);
        kfree(tc);
 
        mutex_unlock(&dm_thin_pool_table.mutex);
@@ -2210,21 +2486,25 @@ static void thin_dtr(struct dm_target *ti)
 /*
  * Thin target parameters:
  *
- * <pool_dev> <dev_id>
+ * <pool_dev> <dev_id> [origin_dev]
  *
  * pool_dev: the path to the pool (eg, /dev/mapper/my_pool)
  * dev_id: the internal device identifier
+ * origin_dev: a device external to the pool that should act as the origin
+ *
+ * If the pool device has discards disabled, they get disabled for the thin
+ * device as well.
  */
 static int thin_ctr(struct dm_target *ti, unsigned argc, char **argv)
 {
        int r;
        struct thin_c *tc;
-       struct dm_dev *pool_dev;
+       struct dm_dev *pool_dev, *origin_dev;
        struct mapped_device *pool_md;
 
        mutex_lock(&dm_thin_pool_table.mutex);
 
-       if (argc != 2) {
+       if (argc != 2 && argc != 3) {
                ti->error = "Invalid argument count";
                r = -EINVAL;
                goto out_unlock;
@@ -2237,6 +2517,15 @@ static int thin_ctr(struct dm_target *ti, unsigned argc, char **argv)
                goto out_unlock;
        }
 
+       if (argc == 3) {
+               r = dm_get_device(ti, argv[2], FMODE_READ, &origin_dev);
+               if (r) {
+                       ti->error = "Error opening origin device";
+                       goto bad_origin_dev;
+               }
+               tc->origin_dev = origin_dev;
+       }
+
        r = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), &pool_dev);
        if (r) {
                ti->error = "Error opening pool device";
@@ -2273,8 +2562,12 @@ static int thin_ctr(struct dm_target *ti, unsigned argc, char **argv)
 
        ti->split_io = tc->pool->sectors_per_block;
        ti->num_flush_requests = 1;
-       ti->num_discard_requests = 0;
-       ti->discards_supported = 0;
+
+       /* In case the pool supports discards, pass them on. */
+       if (tc->pool->pf.discard_enabled) {
+               ti->discards_supported = 1;
+               ti->num_discard_requests = 1;
+       }
 
        dm_put(pool_md);
 
@@ -2289,6 +2582,9 @@ bad_pool_lookup:
 bad_common:
        dm_put_device(ti, tc->pool_dev);
 bad_pool_dev:
+       if (tc->origin_dev)
+               dm_put_device(ti, tc->origin_dev);
+bad_origin_dev:
        kfree(tc);
 out_unlock:
        mutex_unlock(&dm_thin_pool_table.mutex);
@@ -2299,11 +2595,46 @@ out_unlock:
 static int thin_map(struct dm_target *ti, struct bio *bio,
                    union map_info *map_context)
 {
-       bio->bi_sector -= ti->begin;
+       bio->bi_sector = dm_target_offset(ti, bio->bi_sector);
 
        return thin_bio_map(ti, bio, map_context);
 }
 
+static int thin_endio(struct dm_target *ti,
+                     struct bio *bio, int err,
+                     union map_info *map_context)
+{
+       unsigned long flags;
+       struct endio_hook *h = map_context->ptr;
+       struct list_head work;
+       struct new_mapping *m, *tmp;
+       struct pool *pool = h->tc->pool;
+
+       if (h->shared_read_entry) {
+               INIT_LIST_HEAD(&work);
+               ds_dec(h->shared_read_entry, &work);
+
+               spin_lock_irqsave(&pool->lock, flags);
+               list_for_each_entry_safe(m, tmp, &work, list) {
+                       list_del(&m->list);
+                       m->quiesced = 1;
+                       __maybe_add_mapping(m);
+               }
+               spin_unlock_irqrestore(&pool->lock, flags);
+       }
+
+       if (h->all_io_entry) {
+               INIT_LIST_HEAD(&work);
+               ds_dec(h->all_io_entry, &work);
+               list_for_each_entry_safe(m, tmp, &work, list)
+                       list_add(&m->list, &pool->prepared_discards);
+       }
+
+       mempool_free(h, pool->endio_hook_pool);
+
+       return 0;
+}
+
 static void thin_postsuspend(struct dm_target *ti)
 {
        if (dm_noflush_suspending(ti))
@@ -2347,6 +2678,8 @@ static int thin_status(struct dm_target *ti, status_type_t type,
                        DMEMIT("%s %lu",
                               format_dev_t(buf, tc->pool_dev->bdev->bd_dev),
                               (unsigned long) tc->dev_id);
+                       if (tc->origin_dev)
+                               DMEMIT(" %s", format_dev_t(buf, tc->origin_dev->bdev->bd_dev));
                        break;
                }
        }
@@ -2377,18 +2710,21 @@ static int thin_iterate_devices(struct dm_target *ti,
 static void thin_io_hints(struct dm_target *ti, struct queue_limits *limits)
 {
        struct thin_c *tc = ti->private;
+       struct pool *pool = tc->pool;
 
        blk_limits_io_min(limits, 0);
-       blk_limits_io_opt(limits, tc->pool->sectors_per_block << SECTOR_SHIFT);
+       blk_limits_io_opt(limits, pool->sectors_per_block << SECTOR_SHIFT);
+       set_discard_limits(pool, limits);
 }
 
 static struct target_type thin_target = {
        .name = "thin",
-       .version = {1, 0, 0},
+       .version = {1, 1, 0},
        .module = THIS_MODULE,
        .ctr = thin_ctr,
        .dtr = thin_dtr,
        .map = thin_map,
+       .end_io = thin_endio,
        .postsuspend = thin_postsuspend,
        .status = thin_status,
        .iterate_devices = thin_iterate_devices,
diff --git a/drivers/md/dm-verity.c b/drivers/md/dm-verity.c
new file mode 100644 (file)
index 0000000..fa365d3
--- /dev/null
@@ -0,0 +1,913 @@
+/*
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * Author: Mikulas Patocka <mpatocka@redhat.com>
+ *
+ * Based on Chromium dm-verity driver (C) 2011 The Chromium OS Authors
+ *
+ * This file is released under the GPLv2.
+ *
+ * In the file "/sys/module/dm_verity/parameters/prefetch_cluster" you can set
+ * default prefetch value. Data are read in "prefetch_cluster" chunks from the
+ * hash device. Setting this greatly improves performance when data and hash
+ * are on the same disk on different partitions on devices with poor random
+ * access behavior.
+ */
+
+#include "dm-bufio.h"
+
+#include <linux/module.h>
+#include <linux/device-mapper.h>
+#include <crypto/hash.h>
+
+#define DM_MSG_PREFIX                  "verity"
+
+#define DM_VERITY_IO_VEC_INLINE                16
+#define DM_VERITY_MEMPOOL_SIZE         4
+#define DM_VERITY_DEFAULT_PREFETCH_SIZE        262144
+
+#define DM_VERITY_MAX_LEVELS           63
+
+static unsigned dm_verity_prefetch_cluster = DM_VERITY_DEFAULT_PREFETCH_SIZE;
+
+module_param_named(prefetch_cluster, dm_verity_prefetch_cluster, uint, S_IRUGO | S_IWUSR);
+
+struct dm_verity {
+       struct dm_dev *data_dev;
+       struct dm_dev *hash_dev;
+       struct dm_target *ti;
+       struct dm_bufio_client *bufio;
+       char *alg_name;
+       struct crypto_shash *tfm;
+       u8 *root_digest;        /* digest of the root block */
+       u8 *salt;               /* salt: its size is salt_size */
+       unsigned salt_size;
+       sector_t data_start;    /* data offset in 512-byte sectors */
+       sector_t hash_start;    /* hash start in blocks */
+       sector_t data_blocks;   /* the number of data blocks */
+       sector_t hash_blocks;   /* the number of hash blocks */
+       unsigned char data_dev_block_bits;      /* log2(data blocksize) */
+       unsigned char hash_dev_block_bits;      /* log2(hash blocksize) */
+       unsigned char hash_per_block_bits;      /* log2(hashes in hash block) */
+       unsigned char levels;   /* the number of tree levels */
+       unsigned char version;
+       unsigned digest_size;   /* digest size for the current hash algorithm */
+       unsigned shash_descsize;/* the size of temporary space for crypto */
+       int hash_failed;        /* set to 1 if hash of any block failed */
+
+       mempool_t *io_mempool;  /* mempool of struct dm_verity_io */
+       mempool_t *vec_mempool; /* mempool of bio vector */
+
+       struct workqueue_struct *verify_wq;
+
+       /* starting blocks for each tree level. 0 is the lowest level. */
+       sector_t hash_level_block[DM_VERITY_MAX_LEVELS];
+};
+
+struct dm_verity_io {
+       struct dm_verity *v;
+       struct bio *bio;
+
+       /* original values of bio->bi_end_io and bio->bi_private */
+       bio_end_io_t *orig_bi_end_io;
+       void *orig_bi_private;
+
+       sector_t block;
+       unsigned n_blocks;
+
+       /* saved bio vector */
+       struct bio_vec *io_vec;
+       unsigned io_vec_size;
+
+       struct work_struct work;
+
+       /* A space for short vectors; longer vectors are allocated separately. */
+       struct bio_vec io_vec_inline[DM_VERITY_IO_VEC_INLINE];
+
+       /*
+        * Three variably-size fields follow this struct:
+        *
+        * u8 hash_desc[v->shash_descsize];
+        * u8 real_digest[v->digest_size];
+        * u8 want_digest[v->digest_size];
+        *
+        * To access them use: io_hash_desc(), io_real_digest() and io_want_digest().
+        */
+};
+
+static struct shash_desc *io_hash_desc(struct dm_verity *v, struct dm_verity_io *io)
+{
+       return (struct shash_desc *)(io + 1);
+}
+
+static u8 *io_real_digest(struct dm_verity *v, struct dm_verity_io *io)
+{
+       return (u8 *)(io + 1) + v->shash_descsize;
+}
+
+static u8 *io_want_digest(struct dm_verity *v, struct dm_verity_io *io)
+{
+       return (u8 *)(io + 1) + v->shash_descsize + v->digest_size;
+}
+
+/*
+ * Auxiliary structure appended to each dm-bufio buffer. If the value
+ * hash_verified is nonzero, hash of the block has been verified.
+ *
+ * The variable hash_verified is set to 0 when allocating the buffer, then
+ * it can be changed to 1 and it is never reset to 0 again.
+ *
+ * There is no lock around this value, a race condition can at worst cause
+ * that multiple processes verify the hash of the same buffer simultaneously
+ * and write 1 to hash_verified simultaneously.
+ * This condition is harmless, so we don't need locking.
+ */
+struct buffer_aux {
+       int hash_verified;
+};
+
+/*
+ * Initialize struct buffer_aux for a freshly created buffer.
+ */
+static void dm_bufio_alloc_callback(struct dm_buffer *buf)
+{
+       struct buffer_aux *aux = dm_bufio_get_aux_data(buf);
+
+       aux->hash_verified = 0;
+}
+
+/*
+ * Translate input sector number to the sector number on the target device.
+ */
+static sector_t verity_map_sector(struct dm_verity *v, sector_t bi_sector)
+{
+       return v->data_start + dm_target_offset(v->ti, bi_sector);
+}
+
+/*
+ * Return hash position of a specified block at a specified tree level
+ * (0 is the lowest level).
+ * The lowest "hash_per_block_bits"-bits of the result denote hash position
+ * inside a hash block. The remaining bits denote location of the hash block.
+ */
+static sector_t verity_position_at_level(struct dm_verity *v, sector_t block,
+                                        int level)
+{
+       return block >> (level * v->hash_per_block_bits);
+}
+
+static void verity_hash_at_level(struct dm_verity *v, sector_t block, int level,
+                                sector_t *hash_block, unsigned *offset)
+{
+       sector_t position = verity_position_at_level(v, block, level);
+       unsigned idx;
+
+       *hash_block = v->hash_level_block[level] + (position >> v->hash_per_block_bits);
+
+       if (!offset)
+               return;
+
+       idx = position & ((1 << v->hash_per_block_bits) - 1);
+       if (!v->version)
+               *offset = idx * v->digest_size;
+       else
+               *offset = idx << (v->hash_dev_block_bits - v->hash_per_block_bits);
+}
+
+/*
+ * Verify hash of a metadata block pertaining to the specified data block
+ * ("block" argument) at a specified level ("level" argument).
+ *
+ * On successful return, io_want_digest(v, io) contains the hash value for
+ * a lower tree level or for the data block (if we're at the lowest leve).
+ *
+ * If "skip_unverified" is true, unverified buffer is skipped and 1 is returned.
+ * If "skip_unverified" is false, unverified buffer is hashed and verified
+ * against current value of io_want_digest(v, io).
+ */
+static int verity_verify_level(struct dm_verity_io *io, sector_t block,
+                              int level, bool skip_unverified)
+{
+       struct dm_verity *v = io->v;
+       struct dm_buffer *buf;
+       struct buffer_aux *aux;
+       u8 *data;
+       int r;
+       sector_t hash_block;
+       unsigned offset;
+
+       verity_hash_at_level(v, block, level, &hash_block, &offset);
+
+       data = dm_bufio_read(v->bufio, hash_block, &buf);
+       if (unlikely(IS_ERR(data)))
+               return PTR_ERR(data);
+
+       aux = dm_bufio_get_aux_data(buf);
+
+       if (!aux->hash_verified) {
+               struct shash_desc *desc;
+               u8 *result;
+
+               if (skip_unverified) {
+                       r = 1;
+                       goto release_ret_r;
+               }
+
+               desc = io_hash_desc(v, io);
+               desc->tfm = v->tfm;
+               desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
+               r = crypto_shash_init(desc);
+               if (r < 0) {
+                       DMERR("crypto_shash_init failed: %d", r);
+                       goto release_ret_r;
+               }
+
+               if (likely(v->version >= 1)) {
+                       r = crypto_shash_update(desc, v->salt, v->salt_size);
+                       if (r < 0) {
+                               DMERR("crypto_shash_update failed: %d", r);
+                               goto release_ret_r;
+                       }
+               }
+
+               r = crypto_shash_update(desc, data, 1 << v->hash_dev_block_bits);
+               if (r < 0) {
+                       DMERR("crypto_shash_update failed: %d", r);
+                       goto release_ret_r;
+               }
+
+               if (!v->version) {
+                       r = crypto_shash_update(desc, v->salt, v->salt_size);
+                       if (r < 0) {
+                               DMERR("crypto_shash_update failed: %d", r);
+                               goto release_ret_r;
+                       }
+               }
+
+               result = io_real_digest(v, io);
+               r = crypto_shash_final(desc, result);
+               if (r < 0) {
+                       DMERR("crypto_shash_final failed: %d", r);
+                       goto release_ret_r;
+               }
+               if (unlikely(memcmp(result, io_want_digest(v, io), v->digest_size))) {
+                       DMERR_LIMIT("metadata block %llu is corrupted",
+                               (unsigned long long)hash_block);
+                       v->hash_failed = 1;
+                       r = -EIO;
+                       goto release_ret_r;
+               } else
+                       aux->hash_verified = 1;
+       }
+
+       data += offset;
+
+       memcpy(io_want_digest(v, io), data, v->digest_size);
+
+       dm_bufio_release(buf);
+       return 0;
+
+release_ret_r:
+       dm_bufio_release(buf);
+
+       return r;
+}
+
+/*
+ * Verify one "dm_verity_io" structure.
+ */
+static int verity_verify_io(struct dm_verity_io *io)
+{
+       struct dm_verity *v = io->v;
+       unsigned b;
+       int i;
+       unsigned vector = 0, offset = 0;
+
+       for (b = 0; b < io->n_blocks; b++) {
+               struct shash_desc *desc;
+               u8 *result;
+               int r;
+               unsigned todo;
+
+               if (likely(v->levels)) {
+                       /*
+                        * First, we try to get the requested hash for
+                        * the current block. If the hash block itself is
+                        * verified, zero is returned. If it isn't, this
+                        * function returns 0 and we fall back to whole
+                        * chain verification.
+                        */
+                       int r = verity_verify_level(io, io->block + b, 0, true);
+                       if (likely(!r))
+                               goto test_block_hash;
+                       if (r < 0)
+                               return r;
+               }
+
+               memcpy(io_want_digest(v, io), v->root_digest, v->digest_size);
+
+               for (i = v->levels - 1; i >= 0; i--) {
+                       int r = verity_verify_level(io, io->block + b, i, false);
+                       if (unlikely(r))
+                               return r;
+               }
+
+test_block_hash:
+               desc = io_hash_desc(v, io);
+               desc->tfm = v->tfm;
+               desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
+               r = crypto_shash_init(desc);
+               if (r < 0) {
+                       DMERR("crypto_shash_init failed: %d", r);
+                       return r;
+               }
+
+               if (likely(v->version >= 1)) {
+                       r = crypto_shash_update(desc, v->salt, v->salt_size);
+                       if (r < 0) {
+                               DMERR("crypto_shash_update failed: %d", r);
+                               return r;
+                       }
+               }
+
+               todo = 1 << v->data_dev_block_bits;
+               do {
+                       struct bio_vec *bv;
+                       u8 *page;
+                       unsigned len;
+
+                       BUG_ON(vector >= io->io_vec_size);
+                       bv = &io->io_vec[vector];
+                       page = kmap_atomic(bv->bv_page);
+                       len = bv->bv_len - offset;
+                       if (likely(len >= todo))
+                               len = todo;
+                       r = crypto_shash_update(desc,
+                                       page + bv->bv_offset + offset, len);
+                       kunmap_atomic(page);
+                       if (r < 0) {
+                               DMERR("crypto_shash_update failed: %d", r);
+                               return r;
+                       }
+                       offset += len;
+                       if (likely(offset == bv->bv_len)) {
+                               offset = 0;
+                               vector++;
+                       }
+                       todo -= len;
+               } while (todo);
+
+               if (!v->version) {
+                       r = crypto_shash_update(desc, v->salt, v->salt_size);
+                       if (r < 0) {
+                               DMERR("crypto_shash_update failed: %d", r);
+                               return r;
+                       }
+               }
+
+               result = io_real_digest(v, io);
+               r = crypto_shash_final(desc, result);
+               if (r < 0) {
+                       DMERR("crypto_shash_final failed: %d", r);
+                       return r;
+               }
+               if (unlikely(memcmp(result, io_want_digest(v, io), v->digest_size))) {
+                       DMERR_LIMIT("data block %llu is corrupted",
+                               (unsigned long long)(io->block + b));
+                       v->hash_failed = 1;
+                       return -EIO;
+               }
+       }
+       BUG_ON(vector != io->io_vec_size);
+       BUG_ON(offset);
+
+       return 0;
+}
+
+/*
+ * End one "io" structure with a given error.
+ */
+static void verity_finish_io(struct dm_verity_io *io, int error)
+{
+       struct bio *bio = io->bio;
+       struct dm_verity *v = io->v;
+
+       bio->bi_end_io = io->orig_bi_end_io;
+       bio->bi_private = io->orig_bi_private;
+
+       if (io->io_vec != io->io_vec_inline)
+               mempool_free(io->io_vec, v->vec_mempool);
+
+       mempool_free(io, v->io_mempool);
+
+       bio_endio(bio, error);
+}
+
+static void verity_work(struct work_struct *w)
+{
+       struct dm_verity_io *io = container_of(w, struct dm_verity_io, work);
+
+       verity_finish_io(io, verity_verify_io(io));
+}
+
+static void verity_end_io(struct bio *bio, int error)
+{
+       struct dm_verity_io *io = bio->bi_private;
+
+       if (error) {
+               verity_finish_io(io, error);
+               return;
+       }
+
+       INIT_WORK(&io->work, verity_work);
+       queue_work(io->v->verify_wq, &io->work);
+}
+
+/*
+ * Prefetch buffers for the specified io.
+ * The root buffer is not prefetched, it is assumed that it will be cached
+ * all the time.
+ */
+static void verity_prefetch_io(struct dm_verity *v, struct dm_verity_io *io)
+{
+       int i;
+
+       for (i = v->levels - 2; i >= 0; i--) {
+               sector_t hash_block_start;
+               sector_t hash_block_end;
+               verity_hash_at_level(v, io->block, i, &hash_block_start, NULL);
+               verity_hash_at_level(v, io->block + io->n_blocks - 1, i, &hash_block_end, NULL);
+               if (!i) {
+                       unsigned cluster = *(volatile unsigned *)&dm_verity_prefetch_cluster;
+
+                       cluster >>= v->data_dev_block_bits;
+                       if (unlikely(!cluster))
+                               goto no_prefetch_cluster;
+
+                       if (unlikely(cluster & (cluster - 1)))
+                               cluster = 1 << (fls(cluster) - 1);
+
+                       hash_block_start &= ~(sector_t)(cluster - 1);
+                       hash_block_end |= cluster - 1;
+                       if (unlikely(hash_block_end >= v->hash_blocks))
+                               hash_block_end = v->hash_blocks - 1;
+               }
+no_prefetch_cluster:
+               dm_bufio_prefetch(v->bufio, hash_block_start,
+                                 hash_block_end - hash_block_start + 1);
+       }
+}
+
+/*
+ * Bio map function. It allocates dm_verity_io structure and bio vector and
+ * fills them. Then it issues prefetches and the I/O.
+ */
+static int verity_map(struct dm_target *ti, struct bio *bio,
+                     union map_info *map_context)
+{
+       struct dm_verity *v = ti->private;
+       struct dm_verity_io *io;
+
+       bio->bi_bdev = v->data_dev->bdev;
+       bio->bi_sector = verity_map_sector(v, bio->bi_sector);
+
+       if (((unsigned)bio->bi_sector | bio_sectors(bio)) &
+           ((1 << (v->data_dev_block_bits - SECTOR_SHIFT)) - 1)) {
+               DMERR_LIMIT("unaligned io");
+               return -EIO;
+       }
+
+       if ((bio->bi_sector + bio_sectors(bio)) >>
+           (v->data_dev_block_bits - SECTOR_SHIFT) > v->data_blocks) {
+               DMERR_LIMIT("io out of range");
+               return -EIO;
+       }
+
+       if (bio_data_dir(bio) == WRITE)
+               return -EIO;
+
+       io = mempool_alloc(v->io_mempool, GFP_NOIO);
+       io->v = v;
+       io->bio = bio;
+       io->orig_bi_end_io = bio->bi_end_io;
+       io->orig_bi_private = bio->bi_private;
+       io->block = bio->bi_sector >> (v->data_dev_block_bits - SECTOR_SHIFT);
+       io->n_blocks = bio->bi_size >> v->data_dev_block_bits;
+
+       bio->bi_end_io = verity_end_io;
+       bio->bi_private = io;
+       io->io_vec_size = bio->bi_vcnt - bio->bi_idx;
+       if (io->io_vec_size < DM_VERITY_IO_VEC_INLINE)
+               io->io_vec = io->io_vec_inline;
+       else
+               io->io_vec = mempool_alloc(v->vec_mempool, GFP_NOIO);
+       memcpy(io->io_vec, bio_iovec(bio),
+              io->io_vec_size * sizeof(struct bio_vec));
+
+       verity_prefetch_io(v, io);
+
+       generic_make_request(bio);
+
+       return DM_MAPIO_SUBMITTED;
+}
+
+/*
+ * Status: V (valid) or C (corruption found)
+ */
+static int verity_status(struct dm_target *ti, status_type_t type,
+                        char *result, unsigned maxlen)
+{
+       struct dm_verity *v = ti->private;
+       unsigned sz = 0;
+       unsigned x;
+
+       switch (type) {
+       case STATUSTYPE_INFO:
+               DMEMIT("%c", v->hash_failed ? 'C' : 'V');
+               break;
+       case STATUSTYPE_TABLE:
+               DMEMIT("%u %s %s %u %u %llu %llu %s ",
+                       v->version,
+                       v->data_dev->name,
+                       v->hash_dev->name,
+                       1 << v->data_dev_block_bits,
+                       1 << v->hash_dev_block_bits,
+                       (unsigned long long)v->data_blocks,
+                       (unsigned long long)v->hash_start,
+                       v->alg_name
+                       );
+               for (x = 0; x < v->digest_size; x++)
+                       DMEMIT("%02x", v->root_digest[x]);
+               DMEMIT(" ");
+               if (!v->salt_size)
+                       DMEMIT("-");
+               else
+                       for (x = 0; x < v->salt_size; x++)
+                               DMEMIT("%02x", v->salt[x]);
+               break;
+       }
+
+       return 0;
+}
+
+static int verity_ioctl(struct dm_target *ti, unsigned cmd,
+                       unsigned long arg)
+{
+       struct dm_verity *v = ti->private;
+       int r = 0;
+
+       if (v->data_start ||
+           ti->len != i_size_read(v->data_dev->bdev->bd_inode) >> SECTOR_SHIFT)
+               r = scsi_verify_blk_ioctl(NULL, cmd);
+
+       return r ? : __blkdev_driver_ioctl(v->data_dev->bdev, v->data_dev->mode,
+                                    cmd, arg);
+}
+
+static int verity_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
+                       struct bio_vec *biovec, int max_size)
+{
+       struct dm_verity *v = ti->private;
+       struct request_queue *q = bdev_get_queue(v->data_dev->bdev);
+
+       if (!q->merge_bvec_fn)
+               return max_size;
+
+       bvm->bi_bdev = v->data_dev->bdev;
+       bvm->bi_sector = verity_map_sector(v, bvm->bi_sector);
+
+       return min(max_size, q->merge_bvec_fn(q, bvm, biovec));
+}
+
+static int verity_iterate_devices(struct dm_target *ti,
+                                 iterate_devices_callout_fn fn, void *data)
+{
+       struct dm_verity *v = ti->private;
+
+       return fn(ti, v->data_dev, v->data_start, ti->len, data);
+}
+
+static void verity_io_hints(struct dm_target *ti, struct queue_limits *limits)
+{
+       struct dm_verity *v = ti->private;
+
+       if (limits->logical_block_size < 1 << v->data_dev_block_bits)
+               limits->logical_block_size = 1 << v->data_dev_block_bits;
+
+       if (limits->physical_block_size < 1 << v->data_dev_block_bits)
+               limits->physical_block_size = 1 << v->data_dev_block_bits;
+
+       blk_limits_io_min(limits, limits->logical_block_size);
+}
+
+static void verity_dtr(struct dm_target *ti)
+{
+       struct dm_verity *v = ti->private;
+
+       if (v->verify_wq)
+               destroy_workqueue(v->verify_wq);
+
+       if (v->vec_mempool)
+               mempool_destroy(v->vec_mempool);
+
+       if (v->io_mempool)
+               mempool_destroy(v->io_mempool);
+
+       if (v->bufio)
+               dm_bufio_client_destroy(v->bufio);
+
+       kfree(v->salt);
+       kfree(v->root_digest);
+
+       if (v->tfm)
+               crypto_free_shash(v->tfm);
+
+       kfree(v->alg_name);
+
+       if (v->hash_dev)
+               dm_put_device(ti, v->hash_dev);
+
+       if (v->data_dev)
+               dm_put_device(ti, v->data_dev);
+
+       kfree(v);
+}
+
+/*
+ * Target parameters:
+ *     <version>       The current format is version 1.
+ *                     Vsn 0 is compatible with original Chromium OS releases.
+ *     <data device>
+ *     <hash device>
+ *     <data block size>
+ *     <hash block size>
+ *     <the number of data blocks>
+ *     <hash start block>
+ *     <algorithm>
+ *     <digest>
+ *     <salt>          Hex string or "-" if no salt.
+ */
+static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv)
+{
+       struct dm_verity *v;
+       unsigned num;
+       unsigned long long num_ll;
+       int r;
+       int i;
+       sector_t hash_position;
+       char dummy;
+
+       v = kzalloc(sizeof(struct dm_verity), GFP_KERNEL);
+       if (!v) {
+               ti->error = "Cannot allocate verity structure";
+               return -ENOMEM;
+       }
+       ti->private = v;
+       v->ti = ti;
+
+       if ((dm_table_get_mode(ti->table) & ~FMODE_READ)) {
+               ti->error = "Device must be readonly";
+               r = -EINVAL;
+               goto bad;
+       }
+
+       if (argc != 10) {
+               ti->error = "Invalid argument count: exactly 10 arguments required";
+               r = -EINVAL;
+               goto bad;
+       }
+
+       if (sscanf(argv[0], "%d%c", &num, &dummy) != 1 ||
+           num < 0 || num > 1) {
+               ti->error = "Invalid version";
+               r = -EINVAL;
+               goto bad;
+       }
+       v->version = num;
+
+       r = dm_get_device(ti, argv[1], FMODE_READ, &v->data_dev);
+       if (r) {
+               ti->error = "Data device lookup failed";
+               goto bad;
+       }
+
+       r = dm_get_device(ti, argv[2], FMODE_READ, &v->hash_dev);
+       if (r) {
+               ti->error = "Data device lookup failed";
+               goto bad;
+       }
+
+       if (sscanf(argv[3], "%u%c", &num, &dummy) != 1 ||
+           !num || (num & (num - 1)) ||
+           num < bdev_logical_block_size(v->data_dev->bdev) ||
+           num > PAGE_SIZE) {
+               ti->error = "Invalid data device block size";
+               r = -EINVAL;
+               goto bad;
+       }
+       v->data_dev_block_bits = ffs(num) - 1;
+
+       if (sscanf(argv[4], "%u%c", &num, &dummy) != 1 ||
+           !num || (num & (num - 1)) ||
+           num < bdev_logical_block_size(v->hash_dev->bdev) ||
+           num > INT_MAX) {
+               ti->error = "Invalid hash device block size";
+               r = -EINVAL;
+               goto bad;
+       }
+       v->hash_dev_block_bits = ffs(num) - 1;
+
+       if (sscanf(argv[5], "%llu%c", &num_ll, &dummy) != 1 ||
+           num_ll << (v->data_dev_block_bits - SECTOR_SHIFT) !=
+           (sector_t)num_ll << (v->data_dev_block_bits - SECTOR_SHIFT)) {
+               ti->error = "Invalid data blocks";
+               r = -EINVAL;
+               goto bad;
+       }
+       v->data_blocks = num_ll;
+
+       if (ti->len > (v->data_blocks << (v->data_dev_block_bits - SECTOR_SHIFT))) {
+               ti->error = "Data device is too small";
+               r = -EINVAL;
+               goto bad;
+       }
+
+       if (sscanf(argv[6], "%llu%c", &num_ll, &dummy) != 1 ||
+           num_ll << (v->hash_dev_block_bits - SECTOR_SHIFT) !=
+           (sector_t)num_ll << (v->hash_dev_block_bits - SECTOR_SHIFT)) {
+               ti->error = "Invalid hash start";
+               r = -EINVAL;
+               goto bad;
+       }
+       v->hash_start = num_ll;
+
+       v->alg_name = kstrdup(argv[7], GFP_KERNEL);
+       if (!v->alg_name) {
+               ti->error = "Cannot allocate algorithm name";
+               r = -ENOMEM;
+               goto bad;
+       }
+
+       v->tfm = crypto_alloc_shash(v->alg_name, 0, 0);
+       if (IS_ERR(v->tfm)) {
+               ti->error = "Cannot initialize hash function";
+               r = PTR_ERR(v->tfm);
+               v->tfm = NULL;
+               goto bad;
+       }
+       v->digest_size = crypto_shash_digestsize(v->tfm);
+       if ((1 << v->hash_dev_block_bits) < v->digest_size * 2) {
+               ti->error = "Digest size too big";
+               r = -EINVAL;
+               goto bad;
+       }
+       v->shash_descsize =
+               sizeof(struct shash_desc) + crypto_shash_descsize(v->tfm);
+
+       v->root_digest = kmalloc(v->digest_size, GFP_KERNEL);
+       if (!v->root_digest) {
+               ti->error = "Cannot allocate root digest";
+               r = -ENOMEM;
+               goto bad;
+       }
+       if (strlen(argv[8]) != v->digest_size * 2 ||
+           hex2bin(v->root_digest, argv[8], v->digest_size)) {
+               ti->error = "Invalid root digest";
+               r = -EINVAL;
+               goto bad;
+       }
+
+       if (strcmp(argv[9], "-")) {
+               v->salt_size = strlen(argv[9]) / 2;
+               v->salt = kmalloc(v->salt_size, GFP_KERNEL);
+               if (!v->salt) {
+                       ti->error = "Cannot allocate salt";
+                       r = -ENOMEM;
+                       goto bad;
+               }
+               if (strlen(argv[9]) != v->salt_size * 2 ||
+                   hex2bin(v->salt, argv[9], v->salt_size)) {
+                       ti->error = "Invalid salt";
+                       r = -EINVAL;
+                       goto bad;
+               }
+       }
+
+       v->hash_per_block_bits =
+               fls((1 << v->hash_dev_block_bits) / v->digest_size) - 1;
+
+       v->levels = 0;
+       if (v->data_blocks)
+               while (v->hash_per_block_bits * v->levels < 64 &&
+                      (unsigned long long)(v->data_blocks - 1) >>
+                      (v->hash_per_block_bits * v->levels))
+                       v->levels++;
+
+       if (v->levels > DM_VERITY_MAX_LEVELS) {
+               ti->error = "Too many tree levels";
+               r = -E2BIG;
+               goto bad;
+       }
+
+       hash_position = v->hash_start;
+       for (i = v->levels - 1; i >= 0; i--) {
+               sector_t s;
+               v->hash_level_block[i] = hash_position;
+               s = verity_position_at_level(v, v->data_blocks, i);
+               s = (s >> v->hash_per_block_bits) +
+                   !!(s & ((1 << v->hash_per_block_bits) - 1));
+               if (hash_position + s < hash_position) {
+                       ti->error = "Hash device offset overflow";
+                       r = -E2BIG;
+                       goto bad;
+               }
+               hash_position += s;
+       }
+       v->hash_blocks = hash_position;
+
+       v->bufio = dm_bufio_client_create(v->hash_dev->bdev,
+               1 << v->hash_dev_block_bits, 1, sizeof(struct buffer_aux),
+               dm_bufio_alloc_callback, NULL);
+       if (IS_ERR(v->bufio)) {
+               ti->error = "Cannot initialize dm-bufio";
+               r = PTR_ERR(v->bufio);
+               v->bufio = NULL;
+               goto bad;
+       }
+
+       if (dm_bufio_get_device_size(v->bufio) < v->hash_blocks) {
+               ti->error = "Hash device is too small";
+               r = -E2BIG;
+               goto bad;
+       }
+
+       v->io_mempool = mempool_create_kmalloc_pool(DM_VERITY_MEMPOOL_SIZE,
+         sizeof(struct dm_verity_io) + v->shash_descsize + v->digest_size * 2);
+       if (!v->io_mempool) {
+               ti->error = "Cannot allocate io mempool";
+               r = -ENOMEM;
+               goto bad;
+       }
+
+       v->vec_mempool = mempool_create_kmalloc_pool(DM_VERITY_MEMPOOL_SIZE,
+                                       BIO_MAX_PAGES * sizeof(struct bio_vec));
+       if (!v->vec_mempool) {
+               ti->error = "Cannot allocate vector mempool";
+               r = -ENOMEM;
+               goto bad;
+       }
+
+       /* WQ_UNBOUND greatly improves performance when running on ramdisk */
+       v->verify_wq = alloc_workqueue("kverityd", WQ_CPU_INTENSIVE | WQ_MEM_RECLAIM | WQ_UNBOUND, num_online_cpus());
+       if (!v->verify_wq) {
+               ti->error = "Cannot allocate workqueue";
+               r = -ENOMEM;
+               goto bad;
+       }
+
+       return 0;
+
+bad:
+       verity_dtr(ti);
+
+       return r;
+}
+
+static struct target_type verity_target = {
+       .name           = "verity",
+       .version        = {1, 0, 0},
+       .module         = THIS_MODULE,
+       .ctr            = verity_ctr,
+       .dtr            = verity_dtr,
+       .map            = verity_map,
+       .status         = verity_status,
+       .ioctl          = verity_ioctl,
+       .merge          = verity_merge,
+       .iterate_devices = verity_iterate_devices,
+       .io_hints       = verity_io_hints,
+};
+
+static int __init dm_verity_init(void)
+{
+       int r;
+
+       r = dm_register_target(&verity_target);
+       if (r < 0)
+               DMERR("register failed %d", r);
+
+       return r;
+}
+
+static void __exit dm_verity_exit(void)
+{
+       dm_unregister_target(&verity_target);
+}
+
+module_init(dm_verity_init);
+module_exit(dm_verity_exit);
+
+MODULE_AUTHOR("Mikulas Patocka <mpatocka@redhat.com>");
+MODULE_AUTHOR("Mandeep Baines <msb@chromium.org>");
+MODULE_AUTHOR("Will Drewry <wad@chromium.org>");
+MODULE_DESCRIPTION(DM_NAME " target for transparent disk integrity checking");
+MODULE_LICENSE("GPL");
index b89c548..e24143c 100644 (file)
@@ -1016,6 +1016,7 @@ static void __map_bio(struct dm_target *ti, struct bio *clone,
                /*
                 * Store bio_set for cleanup.
                 */
+               clone->bi_end_io = NULL;
                clone->bi_private = md->bs;
                bio_put(clone);
                free_tio(md, tio);
index d279c76..5709bfe 100644 (file)
@@ -108,12 +108,9 @@ static inline void *value_base(struct node *n)
        return &n->keys[le32_to_cpu(n->header.max_entries)];
 }
 
-/*
- * FIXME: Now that value size is stored in node we don't need the third parm.
- */
-static inline void *value_ptr(struct node *n, uint32_t index, size_t value_size)
+static inline void *value_ptr(struct node *n, uint32_t index)
 {
-       BUG_ON(value_size != le32_to_cpu(n->header.value_size));
+       uint32_t value_size = le32_to_cpu(n->header.value_size);
        return value_base(n) + (value_size * index);
 }
 
index 023fbc2..aa71e23 100644 (file)
@@ -61,20 +61,20 @@ static void node_shift(struct node *n, int shift)
        if (shift < 0) {
                shift = -shift;
                BUG_ON(shift > nr_entries);
-               BUG_ON((void *) key_ptr(n, shift) >= value_ptr(n, shift, value_size));
+               BUG_ON((void *) key_ptr(n, shift) >= value_ptr(n, shift));
                memmove(key_ptr(n, 0),
                        key_ptr(n, shift),
                        (nr_entries - shift) * sizeof(__le64));
-               memmove(value_ptr(n, 0, value_size),
-                       value_ptr(n, shift, value_size),
+               memmove(value_ptr(n, 0),
+                       value_ptr(n, shift),
                        (nr_entries - shift) * value_size);
        } else {
                BUG_ON(nr_entries + shift > le32_to_cpu(n->header.max_entries));
                memmove(key_ptr(n, shift),
                        key_ptr(n, 0),
                        nr_entries * sizeof(__le64));
-               memmove(value_ptr(n, shift, value_size),
-                       value_ptr(n, 0, value_size),
+               memmove(value_ptr(n, shift),
+                       value_ptr(n, 0),
                        nr_entries * value_size);
        }
 }
@@ -91,16 +91,16 @@ static void node_copy(struct node *left, struct node *right, int shift)
                memcpy(key_ptr(left, nr_left),
                       key_ptr(right, 0),
                       shift * sizeof(__le64));
-               memcpy(value_ptr(left, nr_left, value_size),
-                      value_ptr(right, 0, value_size),
+               memcpy(value_ptr(left, nr_left),
+                      value_ptr(right, 0),
                       shift * value_size);
        } else {
                BUG_ON(shift > le32_to_cpu(right->header.max_entries));
                memcpy(key_ptr(right, 0),
                       key_ptr(left, nr_left - shift),
                       shift * sizeof(__le64));
-               memcpy(value_ptr(right, 0, value_size),
-                      value_ptr(left, nr_left - shift, value_size),
+               memcpy(value_ptr(right, 0),
+                      value_ptr(left, nr_left - shift),
                       shift * value_size);
        }
 }
@@ -120,26 +120,17 @@ static void delete_at(struct node *n, unsigned index)
                        key_ptr(n, index + 1),
                        nr_to_copy * sizeof(__le64));
 
-               memmove(value_ptr(n, index, value_size),
-                       value_ptr(n, index + 1, value_size),
+               memmove(value_ptr(n, index),
+                       value_ptr(n, index + 1),
                        nr_to_copy * value_size);
        }
 
        n->header.nr_entries = cpu_to_le32(nr_entries - 1);
 }
 
-static unsigned del_threshold(struct node *n)
-{
-       return le32_to_cpu(n->header.max_entries) / 3;
-}
-
 static unsigned merge_threshold(struct node *n)
 {
-       /*
-        * The extra one is because we know we're potentially going to
-        * delete an entry.
-        */
-       return 2 * (le32_to_cpu(n->header.max_entries) / 3) + 1;
+       return le32_to_cpu(n->header.max_entries) / 3;
 }
 
 struct child {
@@ -175,7 +166,7 @@ static int init_child(struct dm_btree_info *info, struct node *parent,
        if (inc)
                inc_children(info->tm, result->n, &le64_type);
 
-       *((__le64 *) value_ptr(parent, index, sizeof(__le64))) =
+       *((__le64 *) value_ptr(parent, index)) =
                cpu_to_le64(dm_block_location(result->block));
 
        return 0;
@@ -188,6 +179,15 @@ static int exit_child(struct dm_btree_info *info, struct child *c)
 
 static void shift(struct node *left, struct node *right, int count)
 {
+       uint32_t nr_left = le32_to_cpu(left->header.nr_entries);
+       uint32_t nr_right = le32_to_cpu(right->header.nr_entries);
+       uint32_t max_entries = le32_to_cpu(left->header.max_entries);
+       uint32_t r_max_entries = le32_to_cpu(right->header.max_entries);
+
+       BUG_ON(max_entries != r_max_entries);
+       BUG_ON(nr_left - count > max_entries);
+       BUG_ON(nr_right + count > max_entries);
+
        if (!count)
                return;
 
@@ -199,13 +199,8 @@ static void shift(struct node *left, struct node *right, int count)
                node_shift(right, count);
        }
 
-       left->header.nr_entries =
-               cpu_to_le32(le32_to_cpu(left->header.nr_entries) - count);
-       BUG_ON(le32_to_cpu(left->header.nr_entries) > le32_to_cpu(left->header.max_entries));
-
-       right->header.nr_entries =
-               cpu_to_le32(le32_to_cpu(right->header.nr_entries) + count);
-       BUG_ON(le32_to_cpu(right->header.nr_entries) > le32_to_cpu(right->header.max_entries));
+       left->header.nr_entries = cpu_to_le32(nr_left - count);
+       right->header.nr_entries = cpu_to_le32(nr_right + count);
 }
 
 static void __rebalance2(struct dm_btree_info *info, struct node *parent,
@@ -215,8 +210,9 @@ static void __rebalance2(struct dm_btree_info *info, struct node *parent,
        struct node *right = r->n;
        uint32_t nr_left = le32_to_cpu(left->header.nr_entries);
        uint32_t nr_right = le32_to_cpu(right->header.nr_entries);
+       unsigned threshold = 2 * merge_threshold(left) + 1;
 
-       if (nr_left + nr_right <= merge_threshold(left)) {
+       if (nr_left + nr_right < threshold) {
                /*
                 * Merge
                 */
@@ -234,9 +230,6 @@ static void __rebalance2(struct dm_btree_info *info, struct node *parent,
                 * Rebalance.
                 */
                unsigned target_left = (nr_left + nr_right) / 2;
-               unsigned shift_ = nr_left - target_left;
-               BUG_ON(le32_to_cpu(left->header.max_entries) <= nr_left - shift_);
-               BUG_ON(le32_to_cpu(right->header.max_entries) <= nr_right + shift_);
                shift(left, right, nr_left - target_left);
                *key_ptr(parent, r->index) = right->keys[0];
        }
@@ -272,6 +265,84 @@ static int rebalance2(struct shadow_spine *s, struct dm_btree_info *info,
        return exit_child(info, &right);
 }
 
+/*
+ * We dump as many entries from center as possible into left, then the rest
+ * in right, then rebalance2.  This wastes some cpu, but I want something
+ * simple atm.
+ */
+static void delete_center_node(struct dm_btree_info *info, struct node *parent,
+                              struct child *l, struct child *c, struct child *r,
+                              struct node *left, struct node *center, struct node *right,
+                              uint32_t nr_left, uint32_t nr_center, uint32_t nr_right)
+{
+       uint32_t max_entries = le32_to_cpu(left->header.max_entries);
+       unsigned shift = min(max_entries - nr_left, nr_center);
+
+       BUG_ON(nr_left + shift > max_entries);
+       node_copy(left, center, -shift);
+       left->header.nr_entries = cpu_to_le32(nr_left + shift);
+
+       if (shift != nr_center) {
+               shift = nr_center - shift;
+               BUG_ON((nr_right + shift) > max_entries);
+               node_shift(right, shift);
+               node_copy(center, right, shift);
+               right->header.nr_entries = cpu_to_le32(nr_right + shift);
+       }
+       *key_ptr(parent, r->index) = right->keys[0];
+
+       delete_at(parent, c->index);
+       r->index--;
+
+       dm_tm_dec(info->tm, dm_block_location(c->block));
+       __rebalance2(info, parent, l, r);
+}
+
+/*
+ * Redistributes entries among 3 sibling nodes.
+ */
+static void redistribute3(struct dm_btree_info *info, struct node *parent,
+                         struct child *l, struct child *c, struct child *r,
+                         struct node *left, struct node *center, struct node *right,
+                         uint32_t nr_left, uint32_t nr_center, uint32_t nr_right)
+{
+       int s;
+       uint32_t max_entries = le32_to_cpu(left->header.max_entries);
+       unsigned target = (nr_left + nr_center + nr_right) / 3;
+       BUG_ON(target > max_entries);
+
+       if (nr_left < nr_right) {
+               s = nr_left - target;
+
+               if (s < 0 && nr_center < -s) {
+                       /* not enough in central node */
+                       shift(left, center, nr_center);
+                       s = nr_center - target;
+                       shift(left, right, s);
+                       nr_right += s;
+               } else
+                       shift(left, center, s);
+
+               shift(center, right, target - nr_right);
+
+       } else {
+               s = target - nr_right;
+               if (s > 0 && nr_center < s) {
+                       /* not enough in central node */
+                       shift(center, right, nr_center);
+                       s = target - nr_center;
+                       shift(left, right, s);
+                       nr_left -= s;
+               } else
+                       shift(center, right, s);
+
+               shift(left, center, nr_left - target);
+       }
+
+       *key_ptr(parent, c->index) = center->keys[0];
+       *key_ptr(parent, r->index) = right->keys[0];
+}
+
 static void __rebalance3(struct dm_btree_info *info, struct node *parent,
                         struct child *l, struct child *c, struct child *r)
 {
@@ -282,62 +353,18 @@ static void __rebalance3(struct dm_btree_info *info, struct node *parent,
        uint32_t nr_left = le32_to_cpu(left->header.nr_entries);
        uint32_t nr_center = le32_to_cpu(center->header.nr_entries);
        uint32_t nr_right = le32_to_cpu(right->header.nr_entries);
-       uint32_t max_entries = le32_to_cpu(left->header.max_entries);
 
-       unsigned target;
+       unsigned threshold = merge_threshold(left) * 4 + 1;
 
        BUG_ON(left->header.max_entries != center->header.max_entries);
        BUG_ON(center->header.max_entries != right->header.max_entries);
 
-       if (((nr_left + nr_center + nr_right) / 2) < merge_threshold(center)) {
-               /*
-                * Delete center node:
-                *
-                * We dump as many entries from center as possible into
-                * left, then the rest in right, then rebalance2.  This
-                * wastes some cpu, but I want something simple atm.
-                */
-               unsigned shift = min(max_entries - nr_left, nr_center);
-
-               BUG_ON(nr_left + shift > max_entries);
-               node_copy(left, center, -shift);
-               left->header.nr_entries = cpu_to_le32(nr_left + shift);
-
-               if (shift != nr_center) {
-                       shift = nr_center - shift;
-                       BUG_ON((nr_right + shift) >= max_entries);
-                       node_shift(right, shift);
-                       node_copy(center, right, shift);
-                       right->header.nr_entries = cpu_to_le32(nr_right + shift);
-               }
-               *key_ptr(parent, r->index) = right->keys[0];
-
-               delete_at(parent, c->index);
-               r->index--;
-
-               dm_tm_dec(info->tm, dm_block_location(c->block));
-               __rebalance2(info, parent, l, r);
-
-               return;
-       }
-
-       /*
-        * Rebalance
-        */
-       target = (nr_left + nr_center + nr_right) / 3;
-       BUG_ON(target > max_entries);
-
-       /*
-        * Adjust the left node
-        */
-       shift(left, center, nr_left - target);
-
-       /*
-        * Adjust the right node
-        */
-       shift(center, right, target - nr_right);
-       *key_ptr(parent, c->index) = center->keys[0];
-       *key_ptr(parent, r->index) = right->keys[0];
+       if ((nr_left + nr_center + nr_right) < threshold)
+               delete_center_node(info, parent, l, c, r, left, center, right,
+                                  nr_left, nr_center, nr_right);
+       else
+               redistribute3(info, parent, l, c, r, left, center, right,
+                             nr_left, nr_center, nr_right);
 }
 
 static int rebalance3(struct shadow_spine *s, struct dm_btree_info *info,
@@ -441,9 +468,6 @@ static int rebalance_children(struct shadow_spine *s,
        if (r)
                return r;
 
-       if (child_entries > del_threshold(n))
-               return 0;
-
        has_left_sibling = i > 0;
        has_right_sibling = i < (le32_to_cpu(n->header.nr_entries) - 1);
 
@@ -496,7 +520,7 @@ static int remove_raw(struct shadow_spine *s, struct dm_btree_info *info,
                 */
                if (shadow_has_parent(s)) {
                        __le64 location = cpu_to_le64(dm_block_location(shadow_current(s)));
-                       memcpy(value_ptr(dm_block_data(shadow_parent(s)), i, sizeof(__le64)),
+                       memcpy(value_ptr(dm_block_data(shadow_parent(s)), i),
                               &location, sizeof(__le64));
                }
 
@@ -553,7 +577,7 @@ int dm_btree_remove(struct dm_btree_info *info, dm_block_t root,
 
                if (info->value_type.dec)
                        info->value_type.dec(info->value_type.context,
-                                            value_ptr(n, index, info->value_type.size));
+                                            value_ptr(n, index));
 
                delete_at(n, index);
        }
index bd1e7ff..d12b2cc 100644 (file)
@@ -74,8 +74,7 @@ void inc_children(struct dm_transaction_manager *tm, struct node *n,
                        dm_tm_inc(tm, value64(n, i));
        else if (vt->inc)
                for (i = 0; i < nr_entries; i++)
-                       vt->inc(vt->context,
-                               value_ptr(n, i, vt->size));
+                       vt->inc(vt->context, value_ptr(n, i));
 }
 
 static int insert_at(size_t value_size, struct node *node, unsigned index,
@@ -281,7 +280,7 @@ int dm_btree_del(struct dm_btree_info *info, dm_block_t root)
 
                                for (i = 0; i < f->nr_children; i++)
                                        info->value_type.dec(info->value_type.context,
-                                                            value_ptr(f->n, i, info->value_type.size));
+                                                            value_ptr(f->n, i));
                        }
                        f->current_child = f->nr_children;
                }
@@ -320,7 +319,7 @@ static int btree_lookup_raw(struct ro_spine *s, dm_block_t block, uint64_t key,
        } while (!(flags & LEAF_NODE));
 
        *result_key = le64_to_cpu(ro_node(s)->keys[i]);
-       memcpy(v, value_ptr(ro_node(s), i, value_size), value_size);
+       memcpy(v, value_ptr(ro_node(s), i), value_size);
 
        return 0;
 }
@@ -432,7 +431,7 @@ static int btree_split_sibling(struct shadow_spine *s, dm_block_t root,
 
        size = le32_to_cpu(ln->header.flags) & INTERNAL_NODE ?
                sizeof(uint64_t) : s->info->value_type.size;
-       memcpy(value_ptr(rn, 0, size), value_ptr(ln, nr_left, size),
+       memcpy(value_ptr(rn, 0), value_ptr(ln, nr_left),
               size * nr_right);
 
        /*
@@ -443,7 +442,7 @@ static int btree_split_sibling(struct shadow_spine *s, dm_block_t root,
        pn = dm_block_data(parent);
        location = cpu_to_le64(dm_block_location(left));
        __dm_bless_for_disk(&location);
-       memcpy_disk(value_ptr(pn, parent_index, sizeof(__le64)),
+       memcpy_disk(value_ptr(pn, parent_index),
                    &location, sizeof(__le64));
 
        location = cpu_to_le64(dm_block_location(right));
@@ -529,8 +528,8 @@ static int btree_split_beneath(struct shadow_spine *s, uint64_t key)
 
        size = le32_to_cpu(pn->header.flags) & INTERNAL_NODE ?
                sizeof(__le64) : s->info->value_type.size;
-       memcpy(value_ptr(ln, 0, size), value_ptr(pn, 0, size), nr_left * size);
-       memcpy(value_ptr(rn, 0, size), value_ptr(pn, nr_left, size),
+       memcpy(value_ptr(ln, 0), value_ptr(pn, 0), nr_left * size);
+       memcpy(value_ptr(rn, 0), value_ptr(pn, nr_left),
               nr_right * size);
 
        /* new_parent should just point to l and r now */
@@ -545,12 +544,12 @@ static int btree_split_beneath(struct shadow_spine *s, uint64_t key)
        val = cpu_to_le64(dm_block_location(left));
        __dm_bless_for_disk(&val);
        pn->keys[0] = ln->keys[0];
-       memcpy_disk(value_ptr(pn, 0, sizeof(__le64)), &val, sizeof(__le64));
+       memcpy_disk(value_ptr(pn, 0), &val, sizeof(__le64));
 
        val = cpu_to_le64(dm_block_location(right));
        __dm_bless_for_disk(&val);
        pn->keys[1] = rn->keys[0];
-       memcpy_disk(value_ptr(pn, 1, sizeof(__le64)), &val, sizeof(__le64));
+       memcpy_disk(value_ptr(pn, 1), &val, sizeof(__le64));
 
        /*
         * rejig the spine.  This is ugly, since it knows too
@@ -595,7 +594,7 @@ static int btree_insert_raw(struct shadow_spine *s, dm_block_t root,
                        __le64 location = cpu_to_le64(dm_block_location(shadow_current(s)));
 
                        __dm_bless_for_disk(&location);
-                       memcpy_disk(value_ptr(dm_block_data(shadow_parent(s)), i, sizeof(uint64_t)),
+                       memcpy_disk(value_ptr(dm_block_data(shadow_parent(s)), i),
                                    &location, sizeof(__le64));
                }
 
@@ -710,12 +709,12 @@ static int insert(struct dm_btree_info *info, dm_block_t root,
                    (!info->value_type.equal ||
                     !info->value_type.equal(
                             info->value_type.context,
-                            value_ptr(n, index, info->value_type.size),
+                            value_ptr(n, index),
                             value))) {
                        info->value_type.dec(info->value_type.context,
-                                            value_ptr(n, index, info->value_type.size));
+                                            value_ptr(n, index));
                }
-               memcpy_disk(value_ptr(n, index, info->value_type.size),
+               memcpy_disk(value_ptr(n, index),
                            value, info->value_type.size);
        }
 
index df2494c..ff3beed 100644 (file)
@@ -405,8 +405,6 @@ int sm_ll_insert(struct ll_disk *ll, dm_block_t b,
                if (r < 0)
                        return r;
 
-#if 0
-               /* FIXME: dm_btree_remove doesn't handle this yet */
                if (old > 2) {
                        r = dm_btree_remove(&ll->ref_count_info,
                                            ll->ref_count_root,
@@ -414,7 +412,6 @@ int sm_ll_insert(struct ll_disk *ll, dm_block_t b,
                        if (r)
                                return r;
                }
-#endif
 
        } else {
                __le32 le_rc = cpu_to_le32(ref_count);
index e4b5c03..73970cd 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/ioctl.h>
 #include <linux/wait.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include "dmxdev.h"
 
 static int debug;
index 864b627..e24ec53 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/workqueue.h>
 
 #include <asm/page.h>
-#include <asm/system.h>
 
 #include <dvb_demux.h>
 
index 6ecbcf6..4bd8bd5 100644 (file)
@@ -53,7 +53,6 @@
 #include <asm/unaligned.h>
 #include <asm/byteorder.h>
 
-#include <asm/system.h>
 
 #include <linux/dvb/frontend.h>
 
index 421cf73..f6b52d5 100644 (file)
@@ -40,7 +40,6 @@
 #include <linux/string.h>
 #include <linux/types.h>
 #include <linux/uaccess.h>
-#include <asm/system.h>
 
 #include <media/media-devnode.h>
 
index f767df9..2e22002 100644 (file)
@@ -54,7 +54,6 @@
 #include <linux/mutex.h>
 #include <linux/slab.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/byteorder.h>
 
 #include <linux/dvb/video.h>
index 5c6100f..1baec83 100644 (file)
@@ -55,7 +55,6 @@
 #include <linux/spi/spi.h>
 #endif
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
 #include <asm/div64.h>
index 041804b..70bec54 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/kmod.h>
 #include <linux/slab.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 
 #include <media/v4l2-common.h>
 #include <media/v4l2-device.h>
index c8ed7b6..1d31d72 100644 (file)
@@ -57,7 +57,6 @@
 #include <linux/scatterlist.h>
 
 #include <asm/dma.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <linux/atomic.h>
 
index 17dfe9b..87bd5ba 100644 (file)
@@ -503,6 +503,101 @@ static void device_irq_exit(struct pm860x_chip *chip)
                free_irq(chip->core_irq, chip);
 }
 
+int pm8606_osc_enable(struct pm860x_chip *chip, unsigned short client)
+{
+       int ret = -EIO;
+       struct i2c_client *i2c = (chip->id == CHIP_PM8606) ?
+               chip->client : chip->companion;
+
+       dev_dbg(chip->dev, "%s(B): client=0x%x\n", __func__, client);
+       dev_dbg(chip->dev, "%s(B): vote=0x%x status=%d\n",
+                       __func__, chip->osc_vote,
+                       chip->osc_status);
+
+       mutex_lock(&chip->osc_lock);
+       /* Update voting status */
+       chip->osc_vote |= client;
+       /* If reference group is off - turn on*/
+       if (chip->osc_status != PM8606_REF_GP_OSC_ON) {
+               chip->osc_status = PM8606_REF_GP_OSC_UNKNOWN;
+               /* Enable Reference group Vsys */
+               if (pm860x_set_bits(i2c, PM8606_VSYS,
+                               PM8606_VSYS_EN, PM8606_VSYS_EN))
+                       goto out;
+
+               /*Enable Internal Oscillator */
+               if (pm860x_set_bits(i2c, PM8606_MISC,
+                               PM8606_MISC_OSC_EN, PM8606_MISC_OSC_EN))
+                       goto out;
+               /* Update status (only if writes succeed) */
+               chip->osc_status = PM8606_REF_GP_OSC_ON;
+       }
+       mutex_unlock(&chip->osc_lock);
+
+       dev_dbg(chip->dev, "%s(A): vote=0x%x status=%d ret=%d\n",
+                       __func__, chip->osc_vote,
+                       chip->osc_status, ret);
+       return 0;
+out:
+       mutex_unlock(&chip->osc_lock);
+       return ret;
+}
+EXPORT_SYMBOL(pm8606_osc_enable);
+
+int pm8606_osc_disable(struct pm860x_chip *chip, unsigned short client)
+{
+       int ret = -EIO;
+       struct i2c_client *i2c = (chip->id == CHIP_PM8606) ?
+               chip->client : chip->companion;
+
+       dev_dbg(chip->dev, "%s(B): client=0x%x\n", __func__, client);
+       dev_dbg(chip->dev, "%s(B): vote=0x%x status=%d\n",
+                       __func__, chip->osc_vote,
+                       chip->osc_status);
+
+       mutex_lock(&chip->osc_lock);
+       /*Update voting status */
+       chip->osc_vote &= ~(client);
+       /* If reference group is off and this is the last client to release
+        * - turn off */
+       if ((chip->osc_status != PM8606_REF_GP_OSC_OFF) &&
+                       (chip->osc_vote == REF_GP_NO_CLIENTS)) {
+               chip->osc_status = PM8606_REF_GP_OSC_UNKNOWN;
+               /* Disable Reference group Vsys */
+               if (pm860x_set_bits(i2c, PM8606_VSYS, PM8606_VSYS_EN, 0))
+                       goto out;
+               /* Disable Internal Oscillator */
+               if (pm860x_set_bits(i2c, PM8606_MISC, PM8606_MISC_OSC_EN, 0))
+                       goto out;
+               chip->osc_status = PM8606_REF_GP_OSC_OFF;
+       }
+       mutex_unlock(&chip->osc_lock);
+
+       dev_dbg(chip->dev, "%s(A): vote=0x%x status=%d ret=%d\n",
+                       __func__, chip->osc_vote,
+                       chip->osc_status, ret);
+       return 0;
+out:
+       mutex_unlock(&chip->osc_lock);
+       return ret;
+}
+EXPORT_SYMBOL(pm8606_osc_disable);
+
+static void __devinit device_osc_init(struct i2c_client *i2c)
+{
+       struct pm860x_chip *chip = i2c_get_clientdata(i2c);
+
+       mutex_init(&chip->osc_lock);
+       /* init portofino reference group voting and status */
+       /* Disable Reference group Vsys */
+       pm860x_set_bits(i2c, PM8606_VSYS, PM8606_VSYS_EN, 0);
+       /* Disable Internal Oscillator */
+       pm860x_set_bits(i2c, PM8606_MISC, PM8606_MISC_OSC_EN, 0);
+
+       chip->osc_vote = REF_GP_NO_CLIENTS;
+       chip->osc_status = PM8606_REF_GP_OSC_OFF;
+}
+
 static void __devinit device_bk_init(struct pm860x_chip *chip,
                                     struct pm860x_platform_data *pdata)
 {
@@ -767,6 +862,15 @@ out:
        return;
 }
 
+static void __devinit device_8606_init(struct pm860x_chip *chip,
+                                      struct i2c_client *i2c,
+                                      struct pm860x_platform_data *pdata)
+{
+       device_osc_init(i2c);
+       device_bk_init(chip, pdata);
+       device_led_init(chip, pdata);
+}
+
 int __devinit pm860x_device_init(struct pm860x_chip *chip,
                       struct pm860x_platform_data *pdata)
 {
@@ -774,8 +878,7 @@ int __devinit pm860x_device_init(struct pm860x_chip *chip,
 
        switch (chip->id) {
        case CHIP_PM8606:
-               device_bk_init(chip, pdata);
-               device_led_init(chip, pdata);
+               device_8606_init(chip, chip->client, pdata);
                break;
        case CHIP_PM8607:
                device_8607_init(chip, chip->client, pdata);
@@ -785,8 +888,7 @@ int __devinit pm860x_device_init(struct pm860x_chip *chip,
        if (chip->companion) {
                switch (chip->id) {
                case CHIP_PM8607:
-                       device_bk_init(chip, pdata);
-                       device_led_init(chip, pdata);
+                       device_8606_init(chip, chip->companion, pdata);
                        break;
                case CHIP_PM8606:
                        device_8607_init(chip, chip->companion, pdata);
index f93dd95..b2cfdc4 100644 (file)
@@ -334,10 +334,35 @@ static int __devexit pm860x_remove(struct i2c_client *client)
        return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int pm860x_suspend(struct device *dev)
+{
+       struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+       struct pm860x_chip *chip = i2c_get_clientdata(client);
+
+       if (device_may_wakeup(dev) && chip->wakeup_flag)
+               enable_irq_wake(chip->core_irq);
+       return 0;
+}
+
+static int pm860x_resume(struct device *dev)
+{
+       struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+       struct pm860x_chip *chip = i2c_get_clientdata(client);
+
+       if (device_may_wakeup(dev) && chip->wakeup_flag)
+               disable_irq_wake(chip->core_irq);
+       return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(pm860x_pm_ops, pm860x_suspend, pm860x_resume);
+
 static struct i2c_driver pm860x_driver = {
        .driver = {
                .name   = "88PM860x",
                .owner  = THIS_MODULE,
+               .pm     = &pm860x_pm_ops,
        },
        .probe          = pm860x_probe,
        .remove         = __devexit_p(pm860x_remove),
index 243e0c6..29f463c 100644 (file)
@@ -143,6 +143,21 @@ config TPS6507X
          This driver can also be built as a module.  If so, the module
          will be called tps6507x.
 
+config MFD_TPS65217
+       tristate "TPS65217 Power Management / White LED chips"
+       depends on I2C
+       select MFD_CORE
+       select REGMAP_I2C
+       help
+         If you say yes here you get support for the TPS65217 series of
+         Power Management / White LED chips.
+         These include voltage regulators, lithium ion/polymer battery
+         charger, wled and other features that are often used in portable
+         devices.
+
+         This driver can also be built as a module.  If so, the module
+         will be called tps65217.
+
 config MFD_TPS6586X
        bool "TPS6586x Power Management chips"
        depends on I2C=y && GPIOLIB && GENERIC_HARDIRQS
@@ -162,6 +177,7 @@ config MFD_TPS65910
        depends on I2C=y && GPIOLIB
        select MFD_CORE
        select GPIO_TPS65910
+       select REGMAP_I2C
        help
          if you say yes here you get support for the TPS65910 series of
          Power Management chips.
@@ -171,7 +187,7 @@ config MFD_TPS65912
        depends on GPIOLIB
 
 config MFD_TPS65912_I2C
-       bool "TPS95612 Power Management chip with I2C"
+       bool "TPS65912 Power Management chip with I2C"
        select MFD_CORE
        select MFD_TPS65912
        depends on I2C=y && GPIOLIB
@@ -400,7 +416,7 @@ config MFD_MAX8997
        depends on I2C=y && GENERIC_HARDIRQS
        select MFD_CORE
        help
-         Say yes here to support for Maxim Semiconductor MAX8998/8966.
+         Say yes here to support for Maxim Semiconductor MAX8997/8966.
          This is a Power Management IC with RTC, Flash, Fuel Gauge, Haptic,
          MUIC controls on chip.
          This driver provides common support for accessing the device;
@@ -812,6 +828,18 @@ config MFD_PM8XXX_IRQ
 config TPS65911_COMPARATOR
        tristate
 
+config MFD_TPS65090
+       bool "TPS65090 Power Management chips"
+       depends on I2C=y && GENERIC_HARDIRQS
+       select MFD_CORE
+       select REGMAP_I2C
+       help
+         If you say yes here you get support for the TPS65090 series of
+         Power Management chips.
+         This driver provides common support for accessing the device,
+         additional drivers must be enabled in order to use the
+         functionality of the device.
+
 config MFD_AAT2870_CORE
        bool "Support for the AnalogicTech AAT2870"
        select MFD_CORE
@@ -831,6 +859,28 @@ config MFD_INTEL_MSIC
          Passage) chip. This chip embeds audio, battery, GPIO, etc.
          devices used in Intel Medfield platforms.
 
+config MFD_RC5T583
+       bool "Ricoh RC5T583 Power Management system device"
+       depends on I2C=y && GENERIC_HARDIRQS
+       select MFD_CORE
+       select REGMAP_I2C
+       help
+         Select this option to get support for the RICOH583 Power
+         Management system device.
+         This driver provides common support for accessing the device
+         through i2c interface. The device supports multiple sub-devices
+         like GPIO, interrupts, RTC, LDO and DCDC regulators, onkey.
+         Additional drivers must be enabled in order to use the
+         different functionality of the device.
+
+config MFD_ANATOP
+       bool "Support for Freescale i.MX on-chip ANATOP controller"
+       depends on SOC_IMX6Q
+       help
+         Select this option to enable Freescale i.MX on-chip ANATOP
+         MFD controller. This controller embeds regulator and
+         thermal devices for Freescale i.MX platforms.
+
 endmenu
 endif
 
index b953bab..05fa538 100644 (file)
@@ -38,6 +38,7 @@ obj-$(CONFIG_MFD_WM8994)      += wm8994-core.o wm8994-irq.o wm8994-regmap.o
 obj-$(CONFIG_TPS6105X)         += tps6105x.o
 obj-$(CONFIG_TPS65010)         += tps65010.o
 obj-$(CONFIG_TPS6507X)         += tps6507x.o
+obj-$(CONFIG_MFD_TPS65217)     += tps65217.o
 obj-$(CONFIG_MFD_TPS65910)     += tps65910.o tps65910-irq.o
 tps65912-objs                   := tps65912-core.o tps65912-irq.o
 obj-$(CONFIG_MFD_TPS65912)     += tps65912.o
@@ -109,6 +110,9 @@ obj-$(CONFIG_MFD_OMAP_USB_HOST)     += omap-usb-host.o
 obj-$(CONFIG_MFD_PM8921_CORE)  += pm8921-core.o
 obj-$(CONFIG_MFD_PM8XXX_IRQ)   += pm8xxx-irq.o
 obj-$(CONFIG_TPS65911_COMPARATOR)      += tps65911-comparator.o
+obj-$(CONFIG_MFD_TPS65090)     += tps65090.o
 obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o
 obj-$(CONFIG_MFD_INTEL_MSIC)   += intel_msic.o
+obj-$(CONFIG_MFD_RC5T583)      += rc5t583.o rc5t583-irq.o
 obj-$(CONFIG_MFD_S5M_CORE)     += s5m-core.o s5m-irq.o
+obj-$(CONFIG_MFD_ANATOP)       += anatop-mfd.o
index d295941..1f08704 100644 (file)
@@ -32,6 +32,7 @@
 #define AB8500_IT_SOURCE6_REG          0x05
 #define AB8500_IT_SOURCE7_REG          0x06
 #define AB8500_IT_SOURCE8_REG          0x07
+#define AB9540_IT_SOURCE13_REG         0x0C
 #define AB8500_IT_SOURCE19_REG         0x12
 #define AB8500_IT_SOURCE20_REG         0x13
 #define AB8500_IT_SOURCE21_REG         0x14
@@ -53,6 +54,7 @@
 #define AB8500_IT_LATCH9_REG           0x28
 #define AB8500_IT_LATCH10_REG          0x29
 #define AB8500_IT_LATCH12_REG          0x2B
+#define AB9540_IT_LATCH13_REG          0x2C
 #define AB8500_IT_LATCH19_REG          0x32
 #define AB8500_IT_LATCH20_REG          0x33
 #define AB8500_IT_LATCH21_REG          0x34
 #define AB8500_IT_MASK24_REG           0x57
 
 #define AB8500_REV_REG                 0x80
+#define AB8500_IC_NAME_REG             0x82
 #define AB8500_SWITCH_OFF_STATUS       0x00
 
 #define AB8500_TURN_ON_STATUS          0x00
 
+#define AB9540_MODEM_CTRL2_REG                 0x23
+#define AB9540_MODEM_CTRL2_SWDBBRSTN_BIT       BIT(2)
+
 /*
  * Map interrupt numbers to the LATCH and MASK register offsets, Interrupt
- * numbers are indexed into this array with (num / 8).
+ * numbers are indexed into this array with (num / 8). The interupts are
+ * defined in linux/mfd/ab8500.h
  *
  * This is one off from the register names, i.e. AB8500_IT_MASK1_REG is at
  * offset 0.
  */
+/* AB8500 support */
 static const int ab8500_irq_regoffset[AB8500_NUM_IRQ_REGS] = {
        0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21,
 };
 
+/* AB9540 support */
+static const int ab9540_irq_regoffset[AB9540_NUM_IRQ_REGS] = {
+       0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21, 12, 13, 24,
+};
+
+static const char ab8500_version_str[][7] = {
+       [AB8500_VERSION_AB8500] = "AB8500",
+       [AB8500_VERSION_AB8505] = "AB8505",
+       [AB8500_VERSION_AB9540] = "AB9540",
+       [AB8500_VERSION_AB8540] = "AB8540",
+};
+
 static int ab8500_get_chip_id(struct device *dev)
 {
        struct ab8500 *ab8500;
@@ -127,9 +147,7 @@ static int set_register_interruptible(struct ab8500 *ab8500, u8 bank,
 
        dev_vdbg(ab8500->dev, "wr: addr %#x <= %#x\n", addr, data);
 
-       ret = mutex_lock_interruptible(&ab8500->lock);
-       if (ret)
-               return ret;
+       mutex_lock(&ab8500->lock);
 
        ret = ab8500->write(ab8500, addr, data);
        if (ret < 0)
@@ -156,9 +174,7 @@ static int get_register_interruptible(struct ab8500 *ab8500, u8 bank,
         * bank on higher 8 bits and reg in lower */
        u16 addr = ((u16)bank) << 8 | reg;
 
-       ret = mutex_lock_interruptible(&ab8500->lock);
-       if (ret)
-               return ret;
+       mutex_lock(&ab8500->lock);
 
        ret = ab8500->read(ab8500, addr);
        if (ret < 0)
@@ -185,31 +201,38 @@ static int mask_and_set_register_interruptible(struct ab8500 *ab8500, u8 bank,
        u8 reg, u8 bitmask, u8 bitvalues)
 {
        int ret;
-       u8 data;
        /* put the u8 bank and u8 reg together into a an u16.
         * bank on higher 8 bits and reg in lower */
        u16 addr = ((u16)bank) << 8 | reg;
 
-       ret = mutex_lock_interruptible(&ab8500->lock);
-       if (ret)
-               return ret;
+       mutex_lock(&ab8500->lock);
 
-       ret = ab8500->read(ab8500, addr);
-       if (ret < 0) {
-               dev_err(ab8500->dev, "failed to read reg %#x: %d\n",
-                       addr, ret);
-               goto out;
-       }
+       if (ab8500->write_masked == NULL) {
+               u8 data;
 
-       data = (u8)ret;
-       data = (~bitmask & data) | (bitmask & bitvalues);
+               ret = ab8500->read(ab8500, addr);
+               if (ret < 0) {
+                       dev_err(ab8500->dev, "failed to read reg %#x: %d\n",
+                               addr, ret);
+                       goto out;
+               }
 
-       ret = ab8500->write(ab8500, addr, data);
-       if (ret < 0)
-               dev_err(ab8500->dev, "failed to write reg %#x: %d\n",
-                       addr, ret);
+               data = (u8)ret;
+               data = (~bitmask & data) | (bitmask & bitvalues);
+
+               ret = ab8500->write(ab8500, addr, data);
+               if (ret < 0)
+                       dev_err(ab8500->dev, "failed to write reg %#x: %d\n",
+                               addr, ret);
 
-       dev_vdbg(ab8500->dev, "mask: addr %#x => data %#x\n", addr, data);
+               dev_vdbg(ab8500->dev, "mask: addr %#x => data %#x\n", addr,
+                       data);
+               goto out;
+       }
+       ret = ab8500->write_masked(ab8500, addr, bitmask, bitvalues);
+       if (ret < 0)
+               dev_err(ab8500->dev, "failed to modify reg %#x: %d\n", addr,
+                       ret);
 out:
        mutex_unlock(&ab8500->lock);
        return ret;
@@ -248,7 +271,7 @@ static void ab8500_irq_sync_unlock(struct irq_data *data)
        struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
        int i;
 
-       for (i = 0; i < AB8500_NUM_IRQ_REGS; i++) {
+       for (i = 0; i < ab8500->mask_size; i++) {
                u8 old = ab8500->oldmask[i];
                u8 new = ab8500->mask[i];
                int reg;
@@ -256,14 +279,17 @@ static void ab8500_irq_sync_unlock(struct irq_data *data)
                if (new == old)
                        continue;
 
-               /* Interrupt register 12 doesn't exist prior to version 2.0 */
-               if (ab8500_irq_regoffset[i] == 11 &&
-                       ab8500->chip_id < AB8500_CUT2P0)
+               /*
+                * Interrupt register 12 doesn't exist prior to AB8500 version
+                * 2.0
+                */
+               if (ab8500->irq_reg_offset[i] == 11 &&
+                       is_ab8500_1p1_or_earlier(ab8500))
                        continue;
 
                ab8500->oldmask[i] = new;
 
-               reg = AB8500_IT_MASK1_REG + ab8500_irq_regoffset[i];
+               reg = AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i];
                set_register_interruptible(ab8500, AB8500_INTERRUPT, reg, new);
        }
 
@@ -306,13 +332,16 @@ static irqreturn_t ab8500_irq(int irq, void *dev)
 
        dev_vdbg(ab8500->dev, "interrupt\n");
 
-       for (i = 0; i < AB8500_NUM_IRQ_REGS; i++) {
-               int regoffset = ab8500_irq_regoffset[i];
+       for (i = 0; i < ab8500->mask_size; i++) {
+               int regoffset = ab8500->irq_reg_offset[i];
                int status;
                u8 value;
 
-               /* Interrupt register 12 doesn't exist prior to version 2.0 */
-               if (regoffset == 11 && ab8500->chip_id < AB8500_CUT2P0)
+               /*
+                * Interrupt register 12 doesn't exist prior to AB8500 version
+                * 2.0
+                */
+               if (regoffset == 11 && is_ab8500_1p1_or_earlier(ab8500))
                        continue;
 
                status = get_register_interruptible(ab8500, AB8500_INTERRUPT,
@@ -336,8 +365,16 @@ static int ab8500_irq_init(struct ab8500 *ab8500)
 {
        int base = ab8500->irq_base;
        int irq;
+       int num_irqs;
+
+       if (is_ab9540(ab8500))
+               num_irqs = AB9540_NR_IRQS;
+       else if (is_ab8505(ab8500))
+               num_irqs = AB8505_NR_IRQS;
+       else
+               num_irqs = AB8500_NR_IRQS;
 
-       for (irq = base; irq < base + AB8500_NR_IRQS; irq++) {
+       for (irq = base; irq < base + num_irqs; irq++) {
                irq_set_chip_data(irq, ab8500);
                irq_set_chip_and_handler(irq, &ab8500_irq_chip,
                                         handle_simple_irq);
@@ -356,8 +393,16 @@ static void ab8500_irq_remove(struct ab8500 *ab8500)
 {
        int base = ab8500->irq_base;
        int irq;
+       int num_irqs;
 
-       for (irq = base; irq < base + AB8500_NR_IRQS; irq++) {
+       if (is_ab9540(ab8500))
+               num_irqs = AB9540_NR_IRQS;
+       else if (is_ab8505(ab8500))
+               num_irqs = AB8505_NR_IRQS;
+       else
+               num_irqs = AB8500_NR_IRQS;
+
+       for (irq = base; irq < base + num_irqs; irq++) {
 #ifdef CONFIG_ARM
                set_irq_flags(irq, 0);
 #endif
@@ -366,6 +411,7 @@ static void ab8500_irq_remove(struct ab8500 *ab8500)
        }
 }
 
+/* AB8500 GPIO Resources */
 static struct resource __devinitdata ab8500_gpio_resources[] = {
        {
                .name   = "GPIO_INT6",
@@ -375,6 +421,28 @@ static struct resource __devinitdata ab8500_gpio_resources[] = {
        }
 };
 
+/* AB9540 GPIO Resources */
+static struct resource __devinitdata ab9540_gpio_resources[] = {
+       {
+               .name   = "GPIO_INT6",
+               .start  = AB8500_INT_GPIO6R,
+               .end    = AB8500_INT_GPIO41F,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .name   = "GPIO_INT14",
+               .start  = AB9540_INT_GPIO50R,
+               .end    = AB9540_INT_GPIO54R,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .name   = "GPIO_INT15",
+               .start  = AB9540_INT_GPIO50F,
+               .end    = AB9540_INT_GPIO54F,
+               .flags  = IORESOURCE_IRQ,
+       }
+};
+
 static struct resource __devinitdata ab8500_gpadc_resources[] = {
        {
                .name   = "HW_CONV_END",
@@ -491,12 +559,6 @@ static struct resource __devinitdata ab8500_charger_resources[] = {
                .flags = IORESOURCE_IRQ,
        },
        {
-               .name = "USB_CHARGE_DET_DONE",
-               .start = AB8500_INT_USB_CHG_DET_DONE,
-               .end = AB8500_INT_USB_CHG_DET_DONE,
-               .flags = IORESOURCE_IRQ,
-       },
-       {
                .name = "VBUS_OVV",
                .start = AB8500_INT_VBUS_OVV,
                .end = AB8500_INT_VBUS_OVV,
@@ -534,14 +596,8 @@ static struct resource __devinitdata ab8500_charger_resources[] = {
        },
        {
                .name = "USB_CHARGER_NOT_OKR",
-               .start = AB8500_INT_USB_CHARGER_NOT_OK,
-               .end = AB8500_INT_USB_CHARGER_NOT_OK,
-               .flags = IORESOURCE_IRQ,
-       },
-       {
-               .name = "USB_CHARGER_NOT_OKF",
-               .start = AB8500_INT_USB_CHARGER_NOT_OKF,
-               .end = AB8500_INT_USB_CHARGER_NOT_OKF,
+               .start = AB8500_INT_USB_CHARGER_NOT_OKR,
+               .end = AB8500_INT_USB_CHARGER_NOT_OKR,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -616,6 +672,12 @@ static struct resource __devinitdata ab8500_fg_resources[] = {
                .end = AB8500_INT_CC_INT_CALIB,
                .flags = IORESOURCE_IRQ,
        },
+       {
+               .name = "CCEOC",
+               .start = AB8500_INT_CCEOC,
+               .end = AB8500_INT_CCEOC,
+               .flags = IORESOURCE_IRQ,
+       },
 };
 
 static struct resource __devinitdata ab8500_chargalg_resources[] = {};
@@ -630,8 +692,8 @@ static struct resource __devinitdata ab8500_debug_resources[] = {
        },
        {
                .name   = "IRQ_LAST",
-               .start  = AB8500_INT_USB_CHARGER_NOT_OKF,
-               .end    = AB8500_INT_USB_CHARGER_NOT_OKF,
+               .start  = AB8500_INT_XTAL32K_KO,
+               .end    = AB8500_INT_XTAL32K_KO,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -691,7 +753,7 @@ static struct resource __devinitdata ab8500_temp_resources[] = {
        },
 };
 
-static struct mfd_cell __devinitdata ab8500_devs[] = {
+static struct mfd_cell __devinitdata abx500_common_devs[] = {
 #ifdef CONFIG_DEBUG_FS
        {
                .name = "ab8500-debug",
@@ -706,11 +768,6 @@ static struct mfd_cell __devinitdata ab8500_devs[] = {
                .name = "ab8500-regulator",
        },
        {
-               .name = "ab8500-gpio",
-               .num_resources = ARRAY_SIZE(ab8500_gpio_resources),
-               .resources = ab8500_gpio_resources,
-       },
-       {
                .name = "ab8500-gpadc",
                .num_resources = ARRAY_SIZE(ab8500_gpadc_resources),
                .resources = ab8500_gpadc_resources,
@@ -748,11 +805,7 @@ static struct mfd_cell __devinitdata ab8500_devs[] = {
        {
                .name = "ab8500-codec",
        },
-       {
-               .name = "ab8500-usb",
-               .num_resources = ARRAY_SIZE(ab8500_usb_resources),
-               .resources = ab8500_usb_resources,
-       },
+
        {
                .name = "ab8500-poweron-key",
                .num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
@@ -781,6 +834,32 @@ static struct mfd_cell __devinitdata ab8500_devs[] = {
        },
 };
 
+static struct mfd_cell __devinitdata ab8500_devs[] = {
+       {
+               .name = "ab8500-gpio",
+               .num_resources = ARRAY_SIZE(ab8500_gpio_resources),
+               .resources = ab8500_gpio_resources,
+       },
+       {
+               .name = "ab8500-usb",
+               .num_resources = ARRAY_SIZE(ab8500_usb_resources),
+               .resources = ab8500_usb_resources,
+       },
+};
+
+static struct mfd_cell __devinitdata ab9540_devs[] = {
+       {
+               .name = "ab8500-gpio",
+               .num_resources = ARRAY_SIZE(ab9540_gpio_resources),
+               .resources = ab9540_gpio_resources,
+       },
+       {
+               .name = "ab9540-usb",
+               .num_resources = ARRAY_SIZE(ab8500_usb_resources),
+               .resources = ab8500_usb_resources,
+       },
+};
+
 static ssize_t show_chip_id(struct device *dev,
                                struct device_attribute *attr, char *buf)
 {
@@ -842,9 +921,64 @@ static ssize_t show_turn_on_status(struct device *dev,
        return sprintf(buf, "%#x\n", value);
 }
 
+static ssize_t show_ab9540_dbbrstn(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct ab8500 *ab8500;
+       int ret;
+       u8 value;
+
+       ab8500 = dev_get_drvdata(dev);
+
+       ret = get_register_interruptible(ab8500, AB8500_REGU_CTRL2,
+               AB9540_MODEM_CTRL2_REG, &value);
+       if (ret < 0)
+               return ret;
+
+       return sprintf(buf, "%d\n",
+                       (value & AB9540_MODEM_CTRL2_SWDBBRSTN_BIT) ? 1 : 0);
+}
+
+static ssize_t store_ab9540_dbbrstn(struct device *dev,
+       struct device_attribute *attr, const char *buf, size_t count)
+{
+       struct ab8500 *ab8500;
+       int ret = count;
+       int err;
+       u8 bitvalues;
+
+       ab8500 = dev_get_drvdata(dev);
+
+       if (count > 0) {
+               switch (buf[0]) {
+               case '0':
+                       bitvalues = 0;
+                       break;
+               case '1':
+                       bitvalues = AB9540_MODEM_CTRL2_SWDBBRSTN_BIT;
+                       break;
+               default:
+                       goto exit;
+               }
+
+               err = mask_and_set_register_interruptible(ab8500,
+                       AB8500_REGU_CTRL2, AB9540_MODEM_CTRL2_REG,
+                       AB9540_MODEM_CTRL2_SWDBBRSTN_BIT, bitvalues);
+               if (err)
+                       dev_info(ab8500->dev,
+                               "Failed to set DBBRSTN %c, err %#x\n",
+                               buf[0], err);
+       }
+
+exit:
+       return ret;
+}
+
 static DEVICE_ATTR(chip_id, S_IRUGO, show_chip_id, NULL);
 static DEVICE_ATTR(switch_off_status, S_IRUGO, show_switch_off_status, NULL);
 static DEVICE_ATTR(turn_on_status, S_IRUGO, show_turn_on_status, NULL);
+static DEVICE_ATTR(dbbrstn, S_IRUGO | S_IWUSR,
+                       show_ab9540_dbbrstn, store_ab9540_dbbrstn);
 
 static struct attribute *ab8500_sysfs_entries[] = {
        &dev_attr_chip_id.attr,
@@ -853,11 +987,23 @@ static struct attribute *ab8500_sysfs_entries[] = {
        NULL,
 };
 
+static struct attribute *ab9540_sysfs_entries[] = {
+       &dev_attr_chip_id.attr,
+       &dev_attr_switch_off_status.attr,
+       &dev_attr_turn_on_status.attr,
+       &dev_attr_dbbrstn.attr,
+       NULL,
+};
+
 static struct attribute_group ab8500_attr_group = {
        .attrs  = ab8500_sysfs_entries,
 };
 
-int __devinit ab8500_init(struct ab8500 *ab8500)
+static struct attribute_group ab9540_attr_group = {
+       .attrs  = ab9540_sysfs_entries,
+};
+
+int __devinit ab8500_init(struct ab8500 *ab8500, enum ab8500_version version)
 {
        struct ab8500_platform_data *plat = dev_get_platdata(ab8500->dev);
        int ret;
@@ -870,25 +1016,45 @@ int __devinit ab8500_init(struct ab8500 *ab8500)
        mutex_init(&ab8500->lock);
        mutex_init(&ab8500->irq_lock);
 
+       if (version != AB8500_VERSION_UNDEFINED)
+               ab8500->version = version;
+       else {
+               ret = get_register_interruptible(ab8500, AB8500_MISC,
+                       AB8500_IC_NAME_REG, &value);
+               if (ret < 0)
+                       return ret;
+
+               ab8500->version = value;
+       }
+
        ret = get_register_interruptible(ab8500, AB8500_MISC,
                AB8500_REV_REG, &value);
        if (ret < 0)
                return ret;
 
-       switch (value) {
-       case AB8500_CUT1P0:
-       case AB8500_CUT1P1:
-       case AB8500_CUT2P0:
-       case AB8500_CUT3P0:
-       case AB8500_CUT3P3:
-               dev_info(ab8500->dev, "detected chip, revision: %#x\n", value);
-               break;
-       default:
-               dev_err(ab8500->dev, "unknown chip, revision: %#x\n", value);
-               return -EINVAL;
-       }
        ab8500->chip_id = value;
 
+       dev_info(ab8500->dev, "detected chip, %s rev. %1x.%1x\n",
+                       ab8500_version_str[ab8500->version],
+                       ab8500->chip_id >> 4,
+                       ab8500->chip_id & 0x0F);
+
+       /* Configure AB8500 or AB9540 IRQ */
+       if (is_ab9540(ab8500) || is_ab8505(ab8500)) {
+               ab8500->mask_size = AB9540_NUM_IRQ_REGS;
+               ab8500->irq_reg_offset = ab9540_irq_regoffset;
+       } else {
+               ab8500->mask_size = AB8500_NUM_IRQ_REGS;
+               ab8500->irq_reg_offset = ab8500_irq_regoffset;
+       }
+       ab8500->mask = kzalloc(ab8500->mask_size, GFP_KERNEL);
+       if (!ab8500->mask)
+               return -ENOMEM;
+       ab8500->oldmask = kzalloc(ab8500->mask_size, GFP_KERNEL);
+       if (!ab8500->oldmask) {
+               ret = -ENOMEM;
+               goto out_freemask;
+       }
        /*
         * ab8500 has switched off due to (SWITCH_OFF_STATUS):
         * 0x01 Swoff bit programming
@@ -911,30 +1077,33 @@ int __devinit ab8500_init(struct ab8500 *ab8500)
                plat->init(ab8500);
 
        /* Clear and mask all interrupts */
-       for (i = 0; i < AB8500_NUM_IRQ_REGS; i++) {
-               /* Interrupt register 12 doesn't exist prior to version 2.0 */
-               if (ab8500_irq_regoffset[i] == 11 &&
-                       ab8500->chip_id < AB8500_CUT2P0)
+       for (i = 0; i < ab8500->mask_size; i++) {
+               /*
+                * Interrupt register 12 doesn't exist prior to AB8500 version
+                * 2.0
+                */
+               if (ab8500->irq_reg_offset[i] == 11 &&
+                               is_ab8500_1p1_or_earlier(ab8500))
                        continue;
 
                get_register_interruptible(ab8500, AB8500_INTERRUPT,
-                       AB8500_IT_LATCH1_REG + ab8500_irq_regoffset[i],
+                       AB8500_IT_LATCH1_REG + ab8500->irq_reg_offset[i],
                        &value);
                set_register_interruptible(ab8500, AB8500_INTERRUPT,
-                       AB8500_IT_MASK1_REG + ab8500_irq_regoffset[i], 0xff);
+                       AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i], 0xff);
        }
 
        ret = abx500_register_ops(ab8500->dev, &ab8500_ops);
        if (ret)
-               return ret;
+               goto out_freeoldmask;
 
-       for (i = 0; i < AB8500_NUM_IRQ_REGS; i++)
+       for (i = 0; i < ab8500->mask_size; i++)
                ab8500->mask[i] = ab8500->oldmask[i] = 0xff;
 
        if (ab8500->irq_base) {
                ret = ab8500_irq_init(ab8500);
                if (ret)
-                       return ret;
+                       goto out_freeoldmask;
 
                ret = request_threaded_irq(ab8500->irq, NULL, ab8500_irq,
                                           IRQF_ONESHOT | IRQF_NO_SUSPEND,
@@ -943,17 +1112,34 @@ int __devinit ab8500_init(struct ab8500 *ab8500)
                        goto out_removeirq;
        }
 
-       ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs,
-                             ARRAY_SIZE(ab8500_devs), NULL,
+       ret = mfd_add_devices(ab8500->dev, 0, abx500_common_devs,
+                             ARRAY_SIZE(abx500_common_devs), NULL,
                              ab8500->irq_base);
+
        if (ret)
                goto out_freeirq;
 
-       ret = sysfs_create_group(&ab8500->dev->kobj, &ab8500_attr_group);
+       if (is_ab9540(ab8500))
+               ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs,
+                             ARRAY_SIZE(ab9540_devs), NULL,
+                             ab8500->irq_base);
+       else
+               ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs,
+                             ARRAY_SIZE(ab9540_devs), NULL,
+                             ab8500->irq_base);
        if (ret)
-               dev_err(ab8500->dev, "error creating sysfs entries\n");
+               goto out_freeirq;
 
-       return ret;
+       if (is_ab9540(ab8500))
+               ret = sysfs_create_group(&ab8500->dev->kobj,
+                                       &ab9540_attr_group);
+       else
+               ret = sysfs_create_group(&ab8500->dev->kobj,
+                                       &ab8500_attr_group);
+       if (ret)
+               dev_err(ab8500->dev, "error creating sysfs entries\n");
+       else
+               return ret;
 
 out_freeirq:
        if (ab8500->irq_base)
@@ -961,18 +1147,27 @@ out_freeirq:
 out_removeirq:
        if (ab8500->irq_base)
                ab8500_irq_remove(ab8500);
+out_freeoldmask:
+       kfree(ab8500->oldmask);
+out_freemask:
+       kfree(ab8500->mask);
 
        return ret;
 }
 
 int __devexit ab8500_exit(struct ab8500 *ab8500)
 {
-       sysfs_remove_group(&ab8500->dev->kobj, &ab8500_attr_group);
+       if (is_ab9540(ab8500))
+               sysfs_remove_group(&ab8500->dev->kobj, &ab9540_attr_group);
+       else
+               sysfs_remove_group(&ab8500->dev->kobj, &ab8500_attr_group);
        mfd_remove_devices(ab8500->dev);
        if (ab8500->irq_base) {
                free_irq(ab8500->irq, ab8500);
                ab8500_irq_remove(ab8500);
        }
+       kfree(ab8500->oldmask);
+       kfree(ab8500->mask);
 
        return 0;
 }
index 087fecd..b83045f 100644 (file)
@@ -11,7 +11,7 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/mfd/abx500/ab8500.h>
-#include <linux/mfd/db8500-prcmu.h>
+#include <linux/mfd/dbx500-prcmu.h>
 
 static int ab8500_i2c_write(struct ab8500 *ab8500, u16 addr, u8 data)
 {
@@ -23,6 +23,18 @@ static int ab8500_i2c_write(struct ab8500 *ab8500, u16 addr, u8 data)
        return ret;
 }
 
+static int ab8500_i2c_write_masked(struct ab8500 *ab8500, u16 addr, u8 mask,
+       u8 data)
+{
+       int ret;
+
+       ret = prcmu_abb_write_masked((u8)(addr >> 8), (u8)(addr & 0xFF), &data,
+               &mask, 1);
+       if (ret < 0)
+               dev_err(ab8500->dev, "prcmu i2c error %d\n", ret);
+       return ret;
+}
+
 static int ab8500_i2c_read(struct ab8500 *ab8500, u16 addr)
 {
        int ret;
@@ -38,6 +50,7 @@ static int ab8500_i2c_read(struct ab8500 *ab8500, u16 addr)
 
 static int __devinit ab8500_i2c_probe(struct platform_device *plf)
 {
+       const struct platform_device_id *platid = platform_get_device_id(plf);
        struct ab8500 *ab8500;
        struct resource *resource;
        int ret;
@@ -58,13 +71,15 @@ static int __devinit ab8500_i2c_probe(struct platform_device *plf)
 
        ab8500->read = ab8500_i2c_read;
        ab8500->write = ab8500_i2c_write;
+       ab8500->write_masked = ab8500_i2c_write_masked;
 
        platform_set_drvdata(plf, ab8500);
 
-       ret = ab8500_init(ab8500);
+       ret = ab8500_init(ab8500, platid->driver_data);
        if (ret)
                kfree(ab8500);
 
+
        return ret;
 }
 
@@ -78,13 +93,22 @@ static int __devexit ab8500_i2c_remove(struct platform_device *plf)
        return 0;
 }
 
+static const struct platform_device_id ab8500_id[] = {
+       { "ab8500-i2c", AB8500_VERSION_AB8500 },
+       { "ab8505-i2c", AB8500_VERSION_AB8505 },
+       { "ab9540-i2c", AB8500_VERSION_AB9540 },
+       { "ab8540-i2c", AB8500_VERSION_AB8540 },
+       { }
+};
+
 static struct platform_driver ab8500_i2c_driver = {
        .driver = {
                .name = "ab8500-i2c",
                .owner = THIS_MODULE,
        },
        .probe  = ab8500_i2c_probe,
-       .remove = __devexit_p(ab8500_i2c_remove)
+       .remove = __devexit_p(ab8500_i2c_remove),
+       .id_table = ab8500_id,
 };
 
 static int __init ab8500_i2c_init(void)
diff --git a/drivers/mfd/anatop-mfd.c b/drivers/mfd/anatop-mfd.c
new file mode 100644 (file)
index 0000000..2af4248
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * Anatop MFD driver
+ *
+ * Copyright (C) 2012 Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
+ * Copyright (C) 2012 Linaro
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/mfd/anatop.h>
+
+u32 anatop_get_bits(struct anatop *adata, u32 addr, int bit_shift,
+                   int bit_width)
+{
+       u32 val, mask;
+
+       if (bit_width == 32)
+               mask = ~0;
+       else
+               mask = (1 << bit_width) - 1;
+
+       val = readl(adata->ioreg + addr);
+       val = (val >> bit_shift) & mask;
+
+       return val;
+}
+EXPORT_SYMBOL_GPL(anatop_get_bits);
+
+void anatop_set_bits(struct anatop *adata, u32 addr, int bit_shift,
+                    int bit_width, u32 data)
+{
+       u32 val, mask;
+
+       if (bit_width == 32)
+               mask = ~0;
+       else
+               mask = (1 << bit_width) - 1;
+
+       spin_lock(&adata->reglock);
+       val = readl(adata->ioreg + addr) & ~(mask << bit_shift);
+       writel((data << bit_shift) | val, adata->ioreg + addr);
+       spin_unlock(&adata->reglock);
+}
+EXPORT_SYMBOL_GPL(anatop_set_bits);
+
+static const struct of_device_id of_anatop_match[] = {
+       { .compatible = "fsl,imx6q-anatop", },
+       { },
+};
+
+static int __devinit of_anatop_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct device_node *np = dev->of_node;
+       void *ioreg;
+       struct anatop *drvdata;
+
+       ioreg = of_iomap(np, 0);
+       if (!ioreg)
+               return -EADDRNOTAVAIL;
+       drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
+       if (!drvdata)
+               return -ENOMEM;
+       drvdata->ioreg = ioreg;
+       spin_lock_init(&drvdata->reglock);
+       platform_set_drvdata(pdev, drvdata);
+       of_platform_populate(np, of_anatop_match, NULL, dev);
+
+       return 0;
+}
+
+static int __devexit of_anatop_remove(struct platform_device *pdev)
+{
+       struct anatop *drvdata;
+       drvdata = platform_get_drvdata(pdev);
+       iounmap(drvdata->ioreg);
+
+       return 0;
+}
+
+static struct platform_driver anatop_of_driver = {
+       .driver = {
+               .name = "anatop-mfd",
+               .owner = THIS_MODULE,
+               .of_match_table = of_anatop_match,
+       },
+       .probe          = of_anatop_probe,
+       .remove         = of_anatop_remove,
+};
+
+static int __init anatop_init(void)
+{
+       return platform_driver_register(&anatop_of_driver);
+}
+postcore_initcall(anatop_init);
+
+static void __exit anatop_exit(void)
+{
+       platform_driver_unregister(&anatop_of_driver);
+}
+module_exit(anatop_exit);
+
+MODULE_AUTHOR("Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>");
+MODULE_DESCRIPTION("ANATOP MFD driver");
+MODULE_LICENSE("GPL v2");
index b85bbd7..1895cf9 100644 (file)
@@ -525,6 +525,11 @@ static void asic3_gpio_set(struct gpio_chip *chip,
        return;
 }
 
+static int asic3_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+       return (offset < ASIC3_NUM_GPIOS) ? IRQ_BOARD_START + offset : -ENXIO;
+}
+
 static __init int asic3_gpio_probe(struct platform_device *pdev,
                                   u16 *gpio_config, int num)
 {
@@ -976,6 +981,7 @@ static int __init asic3_probe(struct platform_device *pdev)
        asic->gpio.set = asic3_gpio_set;
        asic->gpio.direction_input = asic3_gpio_direction_input;
        asic->gpio.direction_output = asic3_gpio_direction_output;
+       asic->gpio.to_irq = asic3_gpio_to_irq;
 
        ret = asic3_gpio_probe(pdev,
                               pdata->gpio_config,
index 5ddde2a..7ff313f 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/input.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
-#include <linux/mutex.h>
 #include <linux/mfd/core.h>
 #include <linux/slab.h>
 #include <linux/module.h>
@@ -647,8 +646,6 @@ int __devinit da9052_device_init(struct da9052 *da9052, u8 chip_id)
        struct irq_desc *desc;
        int ret;
 
-       mutex_init(&da9052->io_lock);
-
        if (pdata && pdata->init != NULL)
                pdata->init(da9052);
 
index 44b97c7..36b88e3 100644 (file)
@@ -74,24 +74,27 @@ static int __devinit da9052_i2c_probe(struct i2c_client *client,
 
        ret = da9052_i2c_enable_multiwrite(da9052);
        if (ret < 0)
-               goto err;
+               goto err_regmap;
 
        ret = da9052_device_init(da9052, id->driver_data);
        if (ret != 0)
-               goto err;
+               goto err_regmap;
 
        return 0;
 
+err_regmap:
+       regmap_exit(da9052->regmap);
 err:
        kfree(da9052);
        return ret;
 }
 
-static int da9052_i2c_remove(struct i2c_client *client)
+static int __devexit da9052_i2c_remove(struct i2c_client *client)
 {
        struct da9052 *da9052 = i2c_get_clientdata(client);
 
        da9052_device_exit(da9052);
+       regmap_exit(da9052->regmap);
        kfree(da9052);
 
        return 0;
@@ -107,7 +110,7 @@ static struct i2c_device_id da9052_i2c_id[] = {
 
 static struct i2c_driver da9052_i2c_driver = {
        .probe = da9052_i2c_probe,
-       .remove = da9052_i2c_remove,
+       .remove = __devexit_p(da9052_i2c_remove),
        .id_table = da9052_i2c_id,
        .driver = {
                .name = "da9052",
index cdbc7ca..6faf149 100644 (file)
@@ -21,7 +21,7 @@
 
 #include <linux/mfd/da9052/da9052.h>
 
-static int da9052_spi_probe(struct spi_device *spi)
+static int __devinit da9052_spi_probe(struct spi_device *spi)
 {
        int ret;
        const struct spi_device_id *id = spi_get_device_id(spi);
@@ -52,20 +52,23 @@ static int da9052_spi_probe(struct spi_device *spi)
 
        ret = da9052_device_init(da9052, id->driver_data);
        if (ret != 0)
-               goto err;
+               goto err_regmap;
 
        return 0;
 
+err_regmap:
+       regmap_exit(da9052->regmap);
 err:
        kfree(da9052);
        return ret;
 }
 
-static int da9052_spi_remove(struct spi_device *spi)
+static int __devexit da9052_spi_remove(struct spi_device *spi)
 {
        struct da9052 *da9052 = dev_get_drvdata(&spi->dev);
 
        da9052_device_exit(da9052);
+       regmap_exit(da9052->regmap);
        kfree(da9052);
 
        return 0;
index af8e0ef..ebc1e86 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/mfd/dbx500-prcmu.h>
 #include <linux/regulator/db8500-prcmu.h>
 #include <linux/regulator/machine.h>
+#include <asm/hardware/gic.h>
 #include <mach/hardware.h>
 #include <mach/irqs.h>
 #include <mach/db8500-regs.h>
 /* Offset for the firmware version within the TCPM */
 #define PRCMU_FW_VERSION_OFFSET 0xA4
 
-/* PRCMU project numbers, defined by PRCMU FW */
-#define PRCMU_PROJECT_ID_8500V1_0 1
-#define PRCMU_PROJECT_ID_8500V2_0 2
-#define PRCMU_PROJECT_ID_8400V2_0 3
-
 /* Index of different voltages to be used when accessing AVSData */
 #define PRCM_AVS_BASE          0x2FC
 #define PRCM_AVS_VBB_RET       (PRCM_AVS_BASE + 0x0)
 #define PRCM_REQ_MB1_ARM_OPP                   (PRCM_REQ_MB1 + 0x0)
 #define PRCM_REQ_MB1_APE_OPP                   (PRCM_REQ_MB1 + 0x1)
 #define PRCM_REQ_MB1_PLL_ON_OFF                        (PRCM_REQ_MB1 + 0x4)
+#define PLL_SOC0_OFF   0x1
+#define PLL_SOC0_ON    0x2
 #define PLL_SOC1_OFF   0x4
 #define PLL_SOC1_ON    0x8
 
 #define WAKEUP_BIT_GPIO7 BIT(30)
 #define WAKEUP_BIT_GPIO8 BIT(31)
 
+static struct {
+       bool valid;
+       struct prcmu_fw_version version;
+} fw_info;
+
 /*
  * This vector maps irq numbers to the bits in the bit field used in
  * communication with the PRCMU firmware.
@@ -341,11 +344,13 @@ static struct {
  * mb1_transfer - state needed for mailbox 1 communication.
  * @lock:      The transaction lock.
  * @work:      The transaction completion structure.
+ * @ape_opp:   The current APE OPP.
  * @ack:       Reply ("acknowledge") data.
  */
 static struct {
        struct mutex lock;
        struct completion work;
+       u8 ape_opp;
        struct {
                u8 header;
                u8 arm_opp;
@@ -413,79 +418,102 @@ static struct {
 static atomic_t ac_wake_req_state = ATOMIC_INIT(0);
 
 /* Spinlocks */
+static DEFINE_SPINLOCK(prcmu_lock);
 static DEFINE_SPINLOCK(clkout_lock);
-static DEFINE_SPINLOCK(gpiocr_lock);
 
 /* Global var to runtime determine TCDM base for v2 or v1 */
 static __iomem void *tcdm_base;
 
 struct clk_mgt {
-       unsigned int offset;
+       void __iomem *reg;
        u32 pllsw;
+       int branch;
+       bool clk38div;
+};
+
+enum {
+       PLL_RAW,
+       PLL_FIX,
+       PLL_DIV
 };
 
 static DEFINE_SPINLOCK(clk_mgt_lock);
 
-#define CLK_MGT_ENTRY(_name)[PRCMU_##_name] = { (PRCM_##_name##_MGT_OFF), 0 }
+#define CLK_MGT_ENTRY(_name, _branch, _clk38div)[PRCMU_##_name] = \
+       { (PRCM_##_name##_MGT), 0 , _branch, _clk38div}
 struct clk_mgt clk_mgt[PRCMU_NUM_REG_CLOCKS] = {
-       CLK_MGT_ENTRY(SGACLK),
-       CLK_MGT_ENTRY(UARTCLK),
-       CLK_MGT_ENTRY(MSP02CLK),
-       CLK_MGT_ENTRY(MSP1CLK),
-       CLK_MGT_ENTRY(I2CCLK),
-       CLK_MGT_ENTRY(SDMMCCLK),
-       CLK_MGT_ENTRY(SLIMCLK),
-       CLK_MGT_ENTRY(PER1CLK),
-       CLK_MGT_ENTRY(PER2CLK),
-       CLK_MGT_ENTRY(PER3CLK),
-       CLK_MGT_ENTRY(PER5CLK),
-       CLK_MGT_ENTRY(PER6CLK),
-       CLK_MGT_ENTRY(PER7CLK),
-       CLK_MGT_ENTRY(LCDCLK),
-       CLK_MGT_ENTRY(BMLCLK),
-       CLK_MGT_ENTRY(HSITXCLK),
-       CLK_MGT_ENTRY(HSIRXCLK),
-       CLK_MGT_ENTRY(HDMICLK),
-       CLK_MGT_ENTRY(APEATCLK),
-       CLK_MGT_ENTRY(APETRACECLK),
-       CLK_MGT_ENTRY(MCDECLK),
-       CLK_MGT_ENTRY(IPI2CCLK),
-       CLK_MGT_ENTRY(DSIALTCLK),
-       CLK_MGT_ENTRY(DMACLK),
-       CLK_MGT_ENTRY(B2R2CLK),
-       CLK_MGT_ENTRY(TVCLK),
-       CLK_MGT_ENTRY(SSPCLK),
-       CLK_MGT_ENTRY(RNGCLK),
-       CLK_MGT_ENTRY(UICCCLK),
+       CLK_MGT_ENTRY(SGACLK, PLL_DIV, false),
+       CLK_MGT_ENTRY(UARTCLK, PLL_FIX, true),
+       CLK_MGT_ENTRY(MSP02CLK, PLL_FIX, true),
+       CLK_MGT_ENTRY(MSP1CLK, PLL_FIX, true),
+       CLK_MGT_ENTRY(I2CCLK, PLL_FIX, true),
+       CLK_MGT_ENTRY(SDMMCCLK, PLL_DIV, true),
+       CLK_MGT_ENTRY(SLIMCLK, PLL_FIX, true),
+       CLK_MGT_ENTRY(PER1CLK, PLL_DIV, true),
+       CLK_MGT_ENTRY(PER2CLK, PLL_DIV, true),
+       CLK_MGT_ENTRY(PER3CLK, PLL_DIV, true),
+       CLK_MGT_ENTRY(PER5CLK, PLL_DIV, true),
+       CLK_MGT_ENTRY(PER6CLK, PLL_DIV, true),
+       CLK_MGT_ENTRY(PER7CLK, PLL_DIV, true),
+       CLK_MGT_ENTRY(LCDCLK, PLL_FIX, true),
+       CLK_MGT_ENTRY(BMLCLK, PLL_DIV, true),
+       CLK_MGT_ENTRY(HSITXCLK, PLL_DIV, true),
+       CLK_MGT_ENTRY(HSIRXCLK, PLL_DIV, true),
+       CLK_MGT_ENTRY(HDMICLK, PLL_FIX, false),
+       CLK_MGT_ENTRY(APEATCLK, PLL_DIV, true),
+       CLK_MGT_ENTRY(APETRACECLK, PLL_DIV, true),
+       CLK_MGT_ENTRY(MCDECLK, PLL_DIV, true),
+       CLK_MGT_ENTRY(IPI2CCLK, PLL_FIX, true),
+       CLK_MGT_ENTRY(DSIALTCLK, PLL_FIX, false),
+       CLK_MGT_ENTRY(DMACLK, PLL_DIV, true),
+       CLK_MGT_ENTRY(B2R2CLK, PLL_DIV, true),
+       CLK_MGT_ENTRY(TVCLK, PLL_FIX, true),
+       CLK_MGT_ENTRY(SSPCLK, PLL_FIX, true),
+       CLK_MGT_ENTRY(RNGCLK, PLL_FIX, true),
+       CLK_MGT_ENTRY(UICCCLK, PLL_FIX, false),
+};
+
+struct dsiclk {
+       u32 divsel_mask;
+       u32 divsel_shift;
+       u32 divsel;
+};
+
+static struct dsiclk dsiclk[2] = {
+       {
+               .divsel_mask = PRCM_DSI_PLLOUT_SEL_DSI0_PLLOUT_DIVSEL_MASK,
+               .divsel_shift = PRCM_DSI_PLLOUT_SEL_DSI0_PLLOUT_DIVSEL_SHIFT,
+               .divsel = PRCM_DSI_PLLOUT_SEL_PHI,
+       },
+       {
+               .divsel_mask = PRCM_DSI_PLLOUT_SEL_DSI1_PLLOUT_DIVSEL_MASK,
+               .divsel_shift = PRCM_DSI_PLLOUT_SEL_DSI1_PLLOUT_DIVSEL_SHIFT,
+               .divsel = PRCM_DSI_PLLOUT_SEL_PHI,
+       }
 };
 
-static struct regulator *hwacc_regulator[NUM_HW_ACC];
-static struct regulator *hwacc_ret_regulator[NUM_HW_ACC];
-
-static bool hwacc_enabled[NUM_HW_ACC];
-static bool hwacc_ret_enabled[NUM_HW_ACC];
-
-static const char *hwacc_regulator_name[NUM_HW_ACC] = {
-       [HW_ACC_SVAMMDSP]       = "hwacc-sva-mmdsp",
-       [HW_ACC_SVAPIPE]        = "hwacc-sva-pipe",
-       [HW_ACC_SIAMMDSP]       = "hwacc-sia-mmdsp",
-       [HW_ACC_SIAPIPE]        = "hwacc-sia-pipe",
-       [HW_ACC_SGA]            = "hwacc-sga",
-       [HW_ACC_B2R2]           = "hwacc-b2r2",
-       [HW_ACC_MCDE]           = "hwacc-mcde",
-       [HW_ACC_ESRAM1]         = "hwacc-esram1",
-       [HW_ACC_ESRAM2]         = "hwacc-esram2",
-       [HW_ACC_ESRAM3]         = "hwacc-esram3",
-       [HW_ACC_ESRAM4]         = "hwacc-esram4",
+struct dsiescclk {
+       u32 en;
+       u32 div_mask;
+       u32 div_shift;
 };
 
-static const char *hwacc_ret_regulator_name[NUM_HW_ACC] = {
-       [HW_ACC_SVAMMDSP]       = "hwacc-sva-mmdsp-ret",
-       [HW_ACC_SIAMMDSP]       = "hwacc-sia-mmdsp-ret",
-       [HW_ACC_ESRAM1]         = "hwacc-esram1-ret",
-       [HW_ACC_ESRAM2]         = "hwacc-esram2-ret",
-       [HW_ACC_ESRAM3]         = "hwacc-esram3-ret",
-       [HW_ACC_ESRAM4]         = "hwacc-esram4-ret",
+static struct dsiescclk dsiescclk[3] = {
+       {
+               .en = PRCM_DSITVCLK_DIV_DSI0_ESC_CLK_EN,
+               .div_mask = PRCM_DSITVCLK_DIV_DSI0_ESC_CLK_DIV_MASK,
+               .div_shift = PRCM_DSITVCLK_DIV_DSI0_ESC_CLK_DIV_SHIFT,
+       },
+       {
+               .en = PRCM_DSITVCLK_DIV_DSI1_ESC_CLK_EN,
+               .div_mask = PRCM_DSITVCLK_DIV_DSI1_ESC_CLK_DIV_MASK,
+               .div_shift = PRCM_DSITVCLK_DIV_DSI1_ESC_CLK_DIV_SHIFT,
+       },
+       {
+               .en = PRCM_DSITVCLK_DIV_DSI2_ESC_CLK_EN,
+               .div_mask = PRCM_DSITVCLK_DIV_DSI2_ESC_CLK_DIV_MASK,
+               .div_shift = PRCM_DSITVCLK_DIV_DSI2_ESC_CLK_DIV_SHIFT,
+       }
 };
 
 /*
@@ -503,9 +531,6 @@ static const char *hwacc_ret_regulator_name[NUM_HW_ACC] = {
 /* PLLDIV=12, PLLSW=4 (PLLDDR) */
 #define PRCMU_DSI_CLOCK_SETTING                0x0000008C
 
-/* PLLDIV=8, PLLSW=4 (PLLDDR) */
-#define PRCMU_DSI_CLOCK_SETTING_U8400  0x00000088
-
 /* DPI 50000000 Hz */
 #define PRCMU_DPI_CLOCK_SETTING                ((1 << PRCMU_CLK_PLL_SW_SHIFT) | \
                                          (16 << PRCMU_CLK_PLL_DIV_SHIFT))
@@ -514,9 +539,6 @@ static const char *hwacc_ret_regulator_name[NUM_HW_ACC] = {
 /* D=101, N=1, R=4, SELDIV2=0 */
 #define PRCMU_PLLDSI_FREQ_SETTING      0x00040165
 
-/* D=70, N=1, R=3, SELDIV2=0 */
-#define PRCMU_PLLDSI_FREQ_SETTING_U8400        0x00030146
-
 #define PRCMU_ENABLE_PLLDSI            0x00000001
 #define PRCMU_DISABLE_PLLDSI           0x00000000
 #define PRCMU_RELEASE_RESET_DSS                0x0000400C
@@ -528,30 +550,17 @@ static const char *hwacc_ret_regulator_name[NUM_HW_ACC] = {
 
 #define PRCMU_PLLDSI_LOCKP_LOCKED      0x3
 
-static struct {
-       u8 project_number;
-       u8 api_version;
-       u8 func_version;
-       u8 errata;
-} prcmu_version;
-
-
 int db8500_prcmu_enable_dsipll(void)
 {
        int i;
-       unsigned int plldsifreq;
 
        /* Clear DSIPLL_RESETN */
        writel(PRCMU_RESET_DSIPLL, PRCM_APE_RESETN_CLR);
        /* Unclamp DSIPLL in/out */
        writel(PRCMU_UNCLAMP_DSIPLL, PRCM_MMIP_LS_CLAMP_CLR);
 
-       if (prcmu_is_u8400())
-               plldsifreq = PRCMU_PLLDSI_FREQ_SETTING_U8400;
-       else
-               plldsifreq = PRCMU_PLLDSI_FREQ_SETTING;
        /* Set DSI PLL FREQ */
-       writel(plldsifreq, PRCM_PLLDSI_FREQ);
+       writel(PRCMU_PLLDSI_FREQ_SETTING, PRCM_PLLDSI_FREQ);
        writel(PRCMU_DSI_PLLOUT_SEL_SETTING, PRCM_DSI_PLLOUT_SEL);
        /* Enable Escape clocks */
        writel(PRCMU_ENABLE_ESCAPE_CLOCK_DIV, PRCM_DSITVCLK_DIV);
@@ -583,12 +592,6 @@ int db8500_prcmu_disable_dsipll(void)
 int db8500_prcmu_set_display_clocks(void)
 {
        unsigned long flags;
-       unsigned int dsiclk;
-
-       if (prcmu_is_u8400())
-               dsiclk = PRCMU_DSI_CLOCK_SETTING_U8400;
-       else
-               dsiclk = PRCMU_DSI_CLOCK_SETTING;
 
        spin_lock_irqsave(&clk_mgt_lock, flags);
 
@@ -596,7 +599,7 @@ int db8500_prcmu_set_display_clocks(void)
        while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0)
                cpu_relax();
 
-       writel(dsiclk, PRCM_HDMICLK_MGT);
+       writel(PRCMU_DSI_CLOCK_SETTING, PRCM_HDMICLK_MGT);
        writel(PRCMU_DSI_LP_CLOCK_SETTING, PRCM_TVCLK_MGT);
        writel(PRCMU_DPI_CLOCK_SETTING, PRCM_LCDCLK_MGT);
 
@@ -608,43 +611,41 @@ int db8500_prcmu_set_display_clocks(void)
        return 0;
 }
 
-/**
- * prcmu_enable_spi2 - Enables pin muxing for SPI2 on OtherAlternateC1.
- */
-void prcmu_enable_spi2(void)
+u32 db8500_prcmu_read(unsigned int reg)
+{
+       return readl(_PRCMU_BASE + reg);
+}
+
+void db8500_prcmu_write(unsigned int reg, u32 value)
 {
-       u32 reg;
        unsigned long flags;
 
-       spin_lock_irqsave(&gpiocr_lock, flags);
-       reg = readl(PRCM_GPIOCR);
-       writel(reg | PRCM_GPIOCR_SPI2_SELECT, PRCM_GPIOCR);
-       spin_unlock_irqrestore(&gpiocr_lock, flags);
+       spin_lock_irqsave(&prcmu_lock, flags);
+       writel(value, (_PRCMU_BASE + reg));
+       spin_unlock_irqrestore(&prcmu_lock, flags);
 }
 
-/**
- * prcmu_disable_spi2 - Disables pin muxing for SPI2 on OtherAlternateC1.
- */
-void prcmu_disable_spi2(void)
+void db8500_prcmu_write_masked(unsigned int reg, u32 mask, u32 value)
 {
-       u32 reg;
+       u32 val;
        unsigned long flags;
 
-       spin_lock_irqsave(&gpiocr_lock, flags);
-       reg = readl(PRCM_GPIOCR);
-       writel(reg & ~PRCM_GPIOCR_SPI2_SELECT, PRCM_GPIOCR);
-       spin_unlock_irqrestore(&gpiocr_lock, flags);
+       spin_lock_irqsave(&prcmu_lock, flags);
+       val = readl(_PRCMU_BASE + reg);
+       val = ((val & ~mask) | (value & mask));
+       writel(val, (_PRCMU_BASE + reg));
+       spin_unlock_irqrestore(&prcmu_lock, flags);
 }
 
-bool prcmu_has_arm_maxopp(void)
+struct prcmu_fw_version *prcmu_get_fw_version(void)
 {
-       return (readb(tcdm_base + PRCM_AVS_VARM_MAX_OPP) &
-               PRCM_AVS_ISMODEENABLE_MASK) == PRCM_AVS_ISMODEENABLE_MASK;
+       return fw_info.valid ? &fw_info.version : NULL;
 }
 
-bool prcmu_is_u8400(void)
+bool prcmu_has_arm_maxopp(void)
 {
-       return prcmu_version.project_number == PRCMU_PROJECT_ID_8400V2_0;
+       return (readb(tcdm_base + PRCM_AVS_VARM_MAX_OPP) &
+               PRCM_AVS_ISMODEENABLE_MASK) == PRCM_AVS_ISMODEENABLE_MASK;
 }
 
 /**
@@ -787,6 +788,124 @@ int db8500_prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll)
        return 0;
 }
 
+u8 db8500_prcmu_get_power_state_result(void)
+{
+       return readb(tcdm_base + PRCM_ACK_MB0_AP_PWRSTTR_STATUS);
+}
+
+/* This function decouple the gic from the prcmu */
+int db8500_prcmu_gic_decouple(void)
+{
+       u32 val = readl(PRCM_A9_MASK_REQ);
+
+       /* Set bit 0 register value to 1 */
+       writel(val | PRCM_A9_MASK_REQ_PRCM_A9_MASK_REQ,
+              PRCM_A9_MASK_REQ);
+
+       /* Make sure the register is updated */
+       readl(PRCM_A9_MASK_REQ);
+
+       /* Wait a few cycles for the gic mask completion */
+       udelay(1);
+
+       return 0;
+}
+
+/* This function recouple the gic with the prcmu */
+int db8500_prcmu_gic_recouple(void)
+{
+       u32 val = readl(PRCM_A9_MASK_REQ);
+
+       /* Set bit 0 register value to 0 */
+       writel(val & ~PRCM_A9_MASK_REQ_PRCM_A9_MASK_REQ, PRCM_A9_MASK_REQ);
+
+       return 0;
+}
+
+#define PRCMU_GIC_NUMBER_REGS 5
+
+/*
+ * This function checks if there are pending irq on the gic. It only
+ * makes sense if the gic has been decoupled before with the
+ * db8500_prcmu_gic_decouple function. Disabling an interrupt only
+ * disables the forwarding of the interrupt to any CPU interface. It
+ * does not prevent the interrupt from changing state, for example
+ * becoming pending, or active and pending if it is already
+ * active. Hence, we have to check the interrupt is pending *and* is
+ * active.
+ */
+bool db8500_prcmu_gic_pending_irq(void)
+{
+       u32 pr; /* Pending register */
+       u32 er; /* Enable register */
+       void __iomem *dist_base = __io_address(U8500_GIC_DIST_BASE);
+       int i;
+
+        /* 5 registers. STI & PPI not skipped */
+       for (i = 0; i < PRCMU_GIC_NUMBER_REGS; i++) {
+
+               pr = readl_relaxed(dist_base + GIC_DIST_PENDING_SET + i * 4);
+               er = readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4);
+
+               if (pr & er)
+                       return true; /* There is a pending interrupt */
+       }
+
+       return false;
+}
+
+/*
+ * This function checks if there are pending interrupt on the
+ * prcmu which has been delegated to monitor the irqs with the
+ * db8500_prcmu_copy_gic_settings function.
+ */
+bool db8500_prcmu_pending_irq(void)
+{
+       u32 it, im;
+       int i;
+
+       for (i = 0; i < PRCMU_GIC_NUMBER_REGS - 1; i++) {
+               it = readl(PRCM_ARMITVAL31TO0 + i * 4);
+               im = readl(PRCM_ARMITMSK31TO0 + i * 4);
+               if (it & im)
+                       return true; /* There is a pending interrupt */
+       }
+
+       return false;
+}
+
+/*
+ * This function checks if the specified cpu is in in WFI. It's usage
+ * makes sense only if the gic is decoupled with the db8500_prcmu_gic_decouple
+ * function. Of course passing smp_processor_id() to this function will
+ * always return false...
+ */
+bool db8500_prcmu_is_cpu_in_wfi(int cpu)
+{
+       return readl(PRCM_ARM_WFI_STANDBY) & cpu ? PRCM_ARM_WFI_STANDBY_WFI1 :
+                    PRCM_ARM_WFI_STANDBY_WFI0;
+}
+
+/*
+ * This function copies the gic SPI settings to the prcmu in order to
+ * monitor them and abort/finish the retention/off sequence or state.
+ */
+int db8500_prcmu_copy_gic_settings(void)
+{
+       u32 er; /* Enable register */
+       void __iomem *dist_base = __io_address(U8500_GIC_DIST_BASE);
+       int i;
+
+        /* We skip the STI and PPI */
+       for (i = 0; i < PRCMU_GIC_NUMBER_REGS - 1; i++) {
+               er = readl_relaxed(dist_base +
+                                  GIC_DIST_ENABLE_SET + (i + 1) * 4);
+               writel(er, PRCM_ARMITMSK31TO0 + i * 4);
+       }
+
+       return 0;
+}
+
 /* This function should only be called while mb0_transfer.lock is held. */
 static void config_wakeups(void)
 {
@@ -909,23 +1028,23 @@ int db8500_prcmu_get_arm_opp(void)
 }
 
 /**
- * prcmu_get_ddr_opp - get the current DDR OPP
+ * db8500_prcmu_get_ddr_opp - get the current DDR OPP
  *
  * Returns: the current DDR OPP
  */
-int prcmu_get_ddr_opp(void)
+int db8500_prcmu_get_ddr_opp(void)
 {
        return readb(PRCM_DDR_SUBSYS_APE_MINBW);
 }
 
 /**
- * set_ddr_opp - set the appropriate DDR OPP
+ * db8500_set_ddr_opp - set the appropriate DDR OPP
  * @opp: The new DDR operating point to which transition is to be made
  * Returns: 0 on success, non-zero on failure
  *
  * This function sets the operating point of the DDR.
  */
-int prcmu_set_ddr_opp(u8 opp)
+int db8500_prcmu_set_ddr_opp(u8 opp)
 {
        if (opp < DDR_100_OPP || opp > DDR_25_OPP)
                return -EINVAL;
@@ -935,25 +1054,82 @@ int prcmu_set_ddr_opp(u8 opp)
 
        return 0;
 }
+
+/* Divide the frequency of certain clocks by 2 for APE_50_PARTLY_25_OPP. */
+static void request_even_slower_clocks(bool enable)
+{
+       void __iomem *clock_reg[] = {
+               PRCM_ACLK_MGT,
+               PRCM_DMACLK_MGT
+       };
+       unsigned long flags;
+       unsigned int i;
+
+       spin_lock_irqsave(&clk_mgt_lock, flags);
+
+       /* Grab the HW semaphore. */
+       while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0)
+               cpu_relax();
+
+       for (i = 0; i < ARRAY_SIZE(clock_reg); i++) {
+               u32 val;
+               u32 div;
+
+               val = readl(clock_reg[i]);
+               div = (val & PRCM_CLK_MGT_CLKPLLDIV_MASK);
+               if (enable) {
+                       if ((div <= 1) || (div > 15)) {
+                               pr_err("prcmu: Bad clock divider %d in %s\n",
+                                       div, __func__);
+                               goto unlock_and_return;
+                       }
+                       div <<= 1;
+               } else {
+                       if (div <= 2)
+                               goto unlock_and_return;
+                       div >>= 1;
+               }
+               val = ((val & ~PRCM_CLK_MGT_CLKPLLDIV_MASK) |
+                       (div & PRCM_CLK_MGT_CLKPLLDIV_MASK));
+               writel(val, clock_reg[i]);
+       }
+
+unlock_and_return:
+       /* Release the HW semaphore. */
+       writel(0, PRCM_SEM);
+
+       spin_unlock_irqrestore(&clk_mgt_lock, flags);
+}
+
 /**
- * set_ape_opp - set the appropriate APE OPP
+ * db8500_set_ape_opp - set the appropriate APE OPP
  * @opp: The new APE operating point to which transition is to be made
  * Returns: 0 on success, non-zero on failure
  *
  * This function sets the operating point of the APE.
  */
-int prcmu_set_ape_opp(u8 opp)
+int db8500_prcmu_set_ape_opp(u8 opp)
 {
        int r = 0;
 
+       if (opp == mb1_transfer.ape_opp)
+               return 0;
+
        mutex_lock(&mb1_transfer.lock);
 
+       if (mb1_transfer.ape_opp == APE_50_PARTLY_25_OPP)
+               request_even_slower_clocks(false);
+
+       if ((opp != APE_100_OPP) && (mb1_transfer.ape_opp != APE_100_OPP))
+               goto skip_message;
+
        while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
                cpu_relax();
 
        writeb(MB1H_ARM_APE_OPP, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1));
        writeb(ARM_NO_CHANGE, (tcdm_base + PRCM_REQ_MB1_ARM_OPP));
-       writeb(opp, (tcdm_base + PRCM_REQ_MB1_APE_OPP));
+       writeb(((opp == APE_50_PARTLY_25_OPP) ? APE_50_OPP : opp),
+               (tcdm_base + PRCM_REQ_MB1_APE_OPP));
 
        writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
        wait_for_completion(&mb1_transfer.work);
@@ -962,17 +1138,24 @@ int prcmu_set_ape_opp(u8 opp)
                (mb1_transfer.ack.ape_opp != opp))
                r = -EIO;
 
+skip_message:
+       if ((!r && (opp == APE_50_PARTLY_25_OPP)) ||
+               (r && (mb1_transfer.ape_opp == APE_50_PARTLY_25_OPP)))
+               request_even_slower_clocks(true);
+       if (!r)
+               mb1_transfer.ape_opp = opp;
+
        mutex_unlock(&mb1_transfer.lock);
 
        return r;
 }
 
 /**
- * prcmu_get_ape_opp - get the current APE OPP
+ * db8500_prcmu_get_ape_opp - get the current APE OPP
  *
  * Returns: the current APE OPP
  */
-int prcmu_get_ape_opp(void)
+int db8500_prcmu_get_ape_opp(void)
 {
        return readb(tcdm_base + PRCM_ACK_MB1_CURRENT_APE_OPP);
 }
@@ -1056,7 +1239,9 @@ static int request_pll(u8 clock, bool enable)
 {
        int r = 0;
 
-       if (clock == PRCMU_PLLSOC1)
+       if (clock == PRCMU_PLLSOC0)
+               clock = (enable ? PLL_SOC0_ON : PLL_SOC0_OFF);
+       else if (clock == PRCMU_PLLSOC1)
                clock = (enable ? PLL_SOC1_ON : PLL_SOC1_OFF);
        else
                return -EINVAL;
@@ -1081,132 +1266,6 @@ static int request_pll(u8 clock, bool enable)
 }
 
 /**
- * prcmu_set_hwacc - set the power state of a h/w accelerator
- * @hwacc_dev: The hardware accelerator (enum hw_acc_dev).
- * @state: The new power state (enum hw_acc_state).
- *
- * This function sets the power state of a hardware accelerator.
- * This function should not be called from interrupt context.
- *
- * NOTE! Deprecated, to be removed when all users switched over to use the
- * regulator framework API.
- */
-int prcmu_set_hwacc(u16 hwacc_dev, u8 state)
-{
-       int r = 0;
-       bool ram_retention = false;
-       bool enable, enable_ret;
-
-       /* check argument */
-       BUG_ON(hwacc_dev >= NUM_HW_ACC);
-
-       /* get state of switches */
-       enable = hwacc_enabled[hwacc_dev];
-       enable_ret = hwacc_ret_enabled[hwacc_dev];
-
-       /* set flag if retention is possible */
-       switch (hwacc_dev) {
-       case HW_ACC_SVAMMDSP:
-       case HW_ACC_SIAMMDSP:
-       case HW_ACC_ESRAM1:
-       case HW_ACC_ESRAM2:
-       case HW_ACC_ESRAM3:
-       case HW_ACC_ESRAM4:
-               ram_retention = true;
-               break;
-       }
-
-       /* check argument */
-       BUG_ON(state > HW_ON);
-       BUG_ON(state == HW_OFF_RAMRET && !ram_retention);
-
-       /* modify enable flags */
-       switch (state) {
-       case HW_OFF:
-               enable_ret = false;
-               enable = false;
-               break;
-       case HW_ON:
-               enable = true;
-               break;
-       case HW_OFF_RAMRET:
-               enable_ret = true;
-               enable = false;
-               break;
-       }
-
-       /* get regulator (lazy) */
-       if (hwacc_regulator[hwacc_dev] == NULL) {
-               hwacc_regulator[hwacc_dev] = regulator_get(NULL,
-                       hwacc_regulator_name[hwacc_dev]);
-               if (IS_ERR(hwacc_regulator[hwacc_dev])) {
-                       pr_err("prcmu: failed to get supply %s\n",
-                               hwacc_regulator_name[hwacc_dev]);
-                       r = PTR_ERR(hwacc_regulator[hwacc_dev]);
-                       goto out;
-               }
-       }
-
-       if (ram_retention) {
-               if (hwacc_ret_regulator[hwacc_dev] == NULL) {
-                       hwacc_ret_regulator[hwacc_dev] = regulator_get(NULL,
-                               hwacc_ret_regulator_name[hwacc_dev]);
-                       if (IS_ERR(hwacc_ret_regulator[hwacc_dev])) {
-                               pr_err("prcmu: failed to get supply %s\n",
-                                       hwacc_ret_regulator_name[hwacc_dev]);
-                               r = PTR_ERR(hwacc_ret_regulator[hwacc_dev]);
-                               goto out;
-                       }
-               }
-       }
-
-       /* set regulators */
-       if (ram_retention) {
-               if (enable_ret && !hwacc_ret_enabled[hwacc_dev]) {
-                       r = regulator_enable(hwacc_ret_regulator[hwacc_dev]);
-                       if (r < 0) {
-                               pr_err("prcmu_set_hwacc: ret enable failed\n");
-                               goto out;
-                       }
-                       hwacc_ret_enabled[hwacc_dev] = true;
-               }
-       }
-
-       if (enable && !hwacc_enabled[hwacc_dev]) {
-               r = regulator_enable(hwacc_regulator[hwacc_dev]);
-               if (r < 0) {
-                       pr_err("prcmu_set_hwacc: enable failed\n");
-                       goto out;
-               }
-               hwacc_enabled[hwacc_dev] = true;
-       }
-
-       if (!enable && hwacc_enabled[hwacc_dev]) {
-               r = regulator_disable(hwacc_regulator[hwacc_dev]);
-               if (r < 0) {
-                       pr_err("prcmu_set_hwacc: disable failed\n");
-                       goto out;
-               }
-               hwacc_enabled[hwacc_dev] = false;
-       }
-
-       if (ram_retention) {
-               if (!enable_ret && hwacc_ret_enabled[hwacc_dev]) {
-                       r = regulator_disable(hwacc_ret_regulator[hwacc_dev]);
-                       if (r < 0) {
-                               pr_err("prcmu_set_hwacc: ret disable failed\n");
-                               goto out;
-                       }
-                       hwacc_ret_enabled[hwacc_dev] = false;
-               }
-       }
-
-out:
-       return r;
-}
-EXPORT_SYMBOL(prcmu_set_hwacc);
-
-/**
  * db8500_prcmu_set_epod - set the state of a EPOD (power domain)
  * @epod_id: The EPOD to set
  * @epod_state: The new EPOD state
@@ -1375,7 +1434,7 @@ static int request_timclk(bool enable)
        return 0;
 }
 
-static int request_reg_clock(u8 clock, bool enable)
+static int request_clock(u8 clock, bool enable)
 {
        u32 val;
        unsigned long flags;
@@ -1386,14 +1445,14 @@ static int request_reg_clock(u8 clock, bool enable)
        while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0)
                cpu_relax();
 
-       val = readl(_PRCMU_BASE + clk_mgt[clock].offset);
+       val = readl(clk_mgt[clock].reg);
        if (enable) {
                val |= (PRCM_CLK_MGT_CLKEN | clk_mgt[clock].pllsw);
        } else {
                clk_mgt[clock].pllsw = (val & PRCM_CLK_MGT_CLKPLLSW_MASK);
                val &= ~(PRCM_CLK_MGT_CLKEN | PRCM_CLK_MGT_CLKPLLSW_MASK);
        }
-       writel(val, (_PRCMU_BASE + clk_mgt[clock].offset));
+       writel(val, clk_mgt[clock].reg);
 
        /* Release the HW semaphore. */
        writel(0, PRCM_SEM);
@@ -1413,7 +1472,7 @@ static int request_sga_clock(u8 clock, bool enable)
                writel(val | PRCM_CGATING_BYPASS_ICN2, PRCM_CGATING_BYPASS);
        }
 
-       ret = request_reg_clock(clock, enable);
+       ret = request_clock(clock, enable);
 
        if (!ret && !enable) {
                val = readl(PRCM_CGATING_BYPASS);
@@ -1423,6 +1482,78 @@ static int request_sga_clock(u8 clock, bool enable)
        return ret;
 }
 
+static inline bool plldsi_locked(void)
+{
+       return (readl(PRCM_PLLDSI_LOCKP) &
+               (PRCM_PLLDSI_LOCKP_PRCM_PLLDSI_LOCKP10 |
+                PRCM_PLLDSI_LOCKP_PRCM_PLLDSI_LOCKP3)) ==
+               (PRCM_PLLDSI_LOCKP_PRCM_PLLDSI_LOCKP10 |
+                PRCM_PLLDSI_LOCKP_PRCM_PLLDSI_LOCKP3);
+}
+
+static int request_plldsi(bool enable)
+{
+       int r = 0;
+       u32 val;
+
+       writel((PRCM_MMIP_LS_CLAMP_DSIPLL_CLAMP |
+               PRCM_MMIP_LS_CLAMP_DSIPLL_CLAMPI), (enable ?
+               PRCM_MMIP_LS_CLAMP_CLR : PRCM_MMIP_LS_CLAMP_SET));
+
+       val = readl(PRCM_PLLDSI_ENABLE);
+       if (enable)
+               val |= PRCM_PLLDSI_ENABLE_PRCM_PLLDSI_ENABLE;
+       else
+               val &= ~PRCM_PLLDSI_ENABLE_PRCM_PLLDSI_ENABLE;
+       writel(val, PRCM_PLLDSI_ENABLE);
+
+       if (enable) {
+               unsigned int i;
+               bool locked = plldsi_locked();
+
+               for (i = 10; !locked && (i > 0); --i) {
+                       udelay(100);
+                       locked = plldsi_locked();
+               }
+               if (locked) {
+                       writel(PRCM_APE_RESETN_DSIPLL_RESETN,
+                               PRCM_APE_RESETN_SET);
+               } else {
+                       writel((PRCM_MMIP_LS_CLAMP_DSIPLL_CLAMP |
+                               PRCM_MMIP_LS_CLAMP_DSIPLL_CLAMPI),
+                               PRCM_MMIP_LS_CLAMP_SET);
+                       val &= ~PRCM_PLLDSI_ENABLE_PRCM_PLLDSI_ENABLE;
+                       writel(val, PRCM_PLLDSI_ENABLE);
+                       r = -EAGAIN;
+               }
+       } else {
+               writel(PRCM_APE_RESETN_DSIPLL_RESETN, PRCM_APE_RESETN_CLR);
+       }
+       return r;
+}
+
+static int request_dsiclk(u8 n, bool enable)
+{
+       u32 val;
+
+       val = readl(PRCM_DSI_PLLOUT_SEL);
+       val &= ~dsiclk[n].divsel_mask;
+       val |= ((enable ? dsiclk[n].divsel : PRCM_DSI_PLLOUT_SEL_OFF) <<
+               dsiclk[n].divsel_shift);
+       writel(val, PRCM_DSI_PLLOUT_SEL);
+       return 0;
+}
+
+static int request_dsiescclk(u8 n, bool enable)
+{
+       u32 val;
+
+       val = readl(PRCM_DSITVCLK_DIV);
+       enable ? (val |= dsiescclk[n].en) : (val &= ~dsiescclk[n].en);
+       writel(val, PRCM_DSITVCLK_DIV);
+       return 0;
+}
+
 /**
  * db8500_prcmu_request_clock() - Request for a clock to be enabled or disabled.
  * @clock:      The clock for which the request is made.
@@ -1433,21 +1564,435 @@ static int request_sga_clock(u8 clock, bool enable)
  */
 int db8500_prcmu_request_clock(u8 clock, bool enable)
 {
-       switch(clock) {
-       case PRCMU_SGACLK:
+       if (clock == PRCMU_SGACLK)
                return request_sga_clock(clock, enable);
-       case PRCMU_TIMCLK:
+       else if (clock < PRCMU_NUM_REG_CLOCKS)
+               return request_clock(clock, enable);
+       else if (clock == PRCMU_TIMCLK)
                return request_timclk(enable);
-       case PRCMU_SYSCLK:
+       else if ((clock == PRCMU_DSI0CLK) || (clock == PRCMU_DSI1CLK))
+               return request_dsiclk((clock - PRCMU_DSI0CLK), enable);
+       else if ((PRCMU_DSI0ESCCLK <= clock) && (clock <= PRCMU_DSI2ESCCLK))
+               return request_dsiescclk((clock - PRCMU_DSI0ESCCLK), enable);
+       else if (clock == PRCMU_PLLDSI)
+               return request_plldsi(enable);
+       else if (clock == PRCMU_SYSCLK)
                return request_sysclk(enable);
-       case PRCMU_PLLSOC1:
+       else if ((clock == PRCMU_PLLSOC0) || (clock == PRCMU_PLLSOC1))
                return request_pll(clock, enable);
+       else
+               return -EINVAL;
+}
+
+static unsigned long pll_rate(void __iomem *reg, unsigned long src_rate,
+       int branch)
+{
+       u64 rate;
+       u32 val;
+       u32 d;
+       u32 div = 1;
+
+       val = readl(reg);
+
+       rate = src_rate;
+       rate *= ((val & PRCM_PLL_FREQ_D_MASK) >> PRCM_PLL_FREQ_D_SHIFT);
+
+       d = ((val & PRCM_PLL_FREQ_N_MASK) >> PRCM_PLL_FREQ_N_SHIFT);
+       if (d > 1)
+               div *= d;
+
+       d = ((val & PRCM_PLL_FREQ_R_MASK) >> PRCM_PLL_FREQ_R_SHIFT);
+       if (d > 1)
+               div *= d;
+
+       if (val & PRCM_PLL_FREQ_SELDIV2)
+               div *= 2;
+
+       if ((branch == PLL_FIX) || ((branch == PLL_DIV) &&
+               (val & PRCM_PLL_FREQ_DIV2EN) &&
+               ((reg == PRCM_PLLSOC0_FREQ) ||
+                (reg == PRCM_PLLDDR_FREQ))))
+               div *= 2;
+
+       (void)do_div(rate, div);
+
+       return (unsigned long)rate;
+}
+
+#define ROOT_CLOCK_RATE 38400000
+
+static unsigned long clock_rate(u8 clock)
+{
+       u32 val;
+       u32 pllsw;
+       unsigned long rate = ROOT_CLOCK_RATE;
+
+       val = readl(clk_mgt[clock].reg);
+
+       if (val & PRCM_CLK_MGT_CLK38) {
+               if (clk_mgt[clock].clk38div && (val & PRCM_CLK_MGT_CLK38DIV))
+                       rate /= 2;
+               return rate;
+       }
+
+       val |= clk_mgt[clock].pllsw;
+       pllsw = (val & PRCM_CLK_MGT_CLKPLLSW_MASK);
+
+       if (pllsw == PRCM_CLK_MGT_CLKPLLSW_SOC0)
+               rate = pll_rate(PRCM_PLLSOC0_FREQ, rate, clk_mgt[clock].branch);
+       else if (pllsw == PRCM_CLK_MGT_CLKPLLSW_SOC1)
+               rate = pll_rate(PRCM_PLLSOC1_FREQ, rate, clk_mgt[clock].branch);
+       else if (pllsw == PRCM_CLK_MGT_CLKPLLSW_DDR)
+               rate = pll_rate(PRCM_PLLDDR_FREQ, rate, clk_mgt[clock].branch);
+       else
+               return 0;
+
+       if ((clock == PRCMU_SGACLK) &&
+               (val & PRCM_SGACLK_MGT_SGACLKDIV_BY_2_5_EN)) {
+               u64 r = (rate * 10);
+
+               (void)do_div(r, 25);
+               return (unsigned long)r;
+       }
+       val &= PRCM_CLK_MGT_CLKPLLDIV_MASK;
+       if (val)
+               return rate / val;
+       else
+               return 0;
+}
+
+static unsigned long dsiclk_rate(u8 n)
+{
+       u32 divsel;
+       u32 div = 1;
+
+       divsel = readl(PRCM_DSI_PLLOUT_SEL);
+       divsel = ((divsel & dsiclk[n].divsel_mask) >> dsiclk[n].divsel_shift);
+
+       if (divsel == PRCM_DSI_PLLOUT_SEL_OFF)
+               divsel = dsiclk[n].divsel;
+
+       switch (divsel) {
+       case PRCM_DSI_PLLOUT_SEL_PHI_4:
+               div *= 2;
+       case PRCM_DSI_PLLOUT_SEL_PHI_2:
+               div *= 2;
+       case PRCM_DSI_PLLOUT_SEL_PHI:
+               return pll_rate(PRCM_PLLDSI_FREQ, clock_rate(PRCMU_HDMICLK),
+                       PLL_RAW) / div;
        default:
-               break;
+               return 0;
+       }
+}
+
+static unsigned long dsiescclk_rate(u8 n)
+{
+       u32 div;
+
+       div = readl(PRCM_DSITVCLK_DIV);
+       div = ((div & dsiescclk[n].div_mask) >> (dsiescclk[n].div_shift));
+       return clock_rate(PRCMU_TVCLK) / max((u32)1, div);
+}
+
+unsigned long prcmu_clock_rate(u8 clock)
+{
+       if (clock < PRCMU_NUM_REG_CLOCKS)
+               return clock_rate(clock);
+       else if (clock == PRCMU_TIMCLK)
+               return ROOT_CLOCK_RATE / 16;
+       else if (clock == PRCMU_SYSCLK)
+               return ROOT_CLOCK_RATE;
+       else if (clock == PRCMU_PLLSOC0)
+               return pll_rate(PRCM_PLLSOC0_FREQ, ROOT_CLOCK_RATE, PLL_RAW);
+       else if (clock == PRCMU_PLLSOC1)
+               return pll_rate(PRCM_PLLSOC1_FREQ, ROOT_CLOCK_RATE, PLL_RAW);
+       else if (clock == PRCMU_PLLDDR)
+               return pll_rate(PRCM_PLLDDR_FREQ, ROOT_CLOCK_RATE, PLL_RAW);
+       else if (clock == PRCMU_PLLDSI)
+               return pll_rate(PRCM_PLLDSI_FREQ, clock_rate(PRCMU_HDMICLK),
+                       PLL_RAW);
+       else if ((clock == PRCMU_DSI0CLK) || (clock == PRCMU_DSI1CLK))
+               return dsiclk_rate(clock - PRCMU_DSI0CLK);
+       else if ((PRCMU_DSI0ESCCLK <= clock) && (clock <= PRCMU_DSI2ESCCLK))
+               return dsiescclk_rate(clock - PRCMU_DSI0ESCCLK);
+       else
+               return 0;
+}
+
+static unsigned long clock_source_rate(u32 clk_mgt_val, int branch)
+{
+       if (clk_mgt_val & PRCM_CLK_MGT_CLK38)
+               return ROOT_CLOCK_RATE;
+       clk_mgt_val &= PRCM_CLK_MGT_CLKPLLSW_MASK;
+       if (clk_mgt_val == PRCM_CLK_MGT_CLKPLLSW_SOC0)
+               return pll_rate(PRCM_PLLSOC0_FREQ, ROOT_CLOCK_RATE, branch);
+       else if (clk_mgt_val == PRCM_CLK_MGT_CLKPLLSW_SOC1)
+               return pll_rate(PRCM_PLLSOC1_FREQ, ROOT_CLOCK_RATE, branch);
+       else if (clk_mgt_val == PRCM_CLK_MGT_CLKPLLSW_DDR)
+               return pll_rate(PRCM_PLLDDR_FREQ, ROOT_CLOCK_RATE, branch);
+       else
+               return 0;
+}
+
+static u32 clock_divider(unsigned long src_rate, unsigned long rate)
+{
+       u32 div;
+
+       div = (src_rate / rate);
+       if (div == 0)
+               return 1;
+       if (rate < (src_rate / div))
+               div++;
+       return div;
+}
+
+static long round_clock_rate(u8 clock, unsigned long rate)
+{
+       u32 val;
+       u32 div;
+       unsigned long src_rate;
+       long rounded_rate;
+
+       val = readl(clk_mgt[clock].reg);
+       src_rate = clock_source_rate((val | clk_mgt[clock].pllsw),
+               clk_mgt[clock].branch);
+       div = clock_divider(src_rate, rate);
+       if (val & PRCM_CLK_MGT_CLK38) {
+               if (clk_mgt[clock].clk38div) {
+                       if (div > 2)
+                               div = 2;
+               } else {
+                       div = 1;
+               }
+       } else if ((clock == PRCMU_SGACLK) && (div == 3)) {
+               u64 r = (src_rate * 10);
+
+               (void)do_div(r, 25);
+               if (r <= rate)
+                       return (unsigned long)r;
+       }
+       rounded_rate = (src_rate / min(div, (u32)31));
+
+       return rounded_rate;
+}
+
+#define MIN_PLL_VCO_RATE 600000000ULL
+#define MAX_PLL_VCO_RATE 1680640000ULL
+
+static long round_plldsi_rate(unsigned long rate)
+{
+       long rounded_rate = 0;
+       unsigned long src_rate;
+       unsigned long rem;
+       u32 r;
+
+       src_rate = clock_rate(PRCMU_HDMICLK);
+       rem = rate;
+
+       for (r = 7; (rem > 0) && (r > 0); r--) {
+               u64 d;
+
+               d = (r * rate);
+               (void)do_div(d, src_rate);
+               if (d < 6)
+                       d = 6;
+               else if (d > 255)
+                       d = 255;
+               d *= src_rate;
+               if (((2 * d) < (r * MIN_PLL_VCO_RATE)) ||
+                       ((r * MAX_PLL_VCO_RATE) < (2 * d)))
+                       continue;
+               (void)do_div(d, r);
+               if (rate < d) {
+                       if (rounded_rate == 0)
+                               rounded_rate = (long)d;
+                       break;
+               }
+               if ((rate - d) < rem) {
+                       rem = (rate - d);
+                       rounded_rate = (long)d;
+               }
+       }
+       return rounded_rate;
+}
+
+static long round_dsiclk_rate(unsigned long rate)
+{
+       u32 div;
+       unsigned long src_rate;
+       long rounded_rate;
+
+       src_rate = pll_rate(PRCM_PLLDSI_FREQ, clock_rate(PRCMU_HDMICLK),
+               PLL_RAW);
+       div = clock_divider(src_rate, rate);
+       rounded_rate = (src_rate / ((div > 2) ? 4 : div));
+
+       return rounded_rate;
+}
+
+static long round_dsiescclk_rate(unsigned long rate)
+{
+       u32 div;
+       unsigned long src_rate;
+       long rounded_rate;
+
+       src_rate = clock_rate(PRCMU_TVCLK);
+       div = clock_divider(src_rate, rate);
+       rounded_rate = (src_rate / min(div, (u32)255));
+
+       return rounded_rate;
+}
+
+long prcmu_round_clock_rate(u8 clock, unsigned long rate)
+{
+       if (clock < PRCMU_NUM_REG_CLOCKS)
+               return round_clock_rate(clock, rate);
+       else if (clock == PRCMU_PLLDSI)
+               return round_plldsi_rate(rate);
+       else if ((clock == PRCMU_DSI0CLK) || (clock == PRCMU_DSI1CLK))
+               return round_dsiclk_rate(rate);
+       else if ((PRCMU_DSI0ESCCLK <= clock) && (clock <= PRCMU_DSI2ESCCLK))
+               return round_dsiescclk_rate(rate);
+       else
+               return (long)prcmu_clock_rate(clock);
+}
+
+static void set_clock_rate(u8 clock, unsigned long rate)
+{
+       u32 val;
+       u32 div;
+       unsigned long src_rate;
+       unsigned long flags;
+
+       spin_lock_irqsave(&clk_mgt_lock, flags);
+
+       /* Grab the HW semaphore. */
+       while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0)
+               cpu_relax();
+
+       val = readl(clk_mgt[clock].reg);
+       src_rate = clock_source_rate((val | clk_mgt[clock].pllsw),
+               clk_mgt[clock].branch);
+       div = clock_divider(src_rate, rate);
+       if (val & PRCM_CLK_MGT_CLK38) {
+               if (clk_mgt[clock].clk38div) {
+                       if (div > 1)
+                               val |= PRCM_CLK_MGT_CLK38DIV;
+                       else
+                               val &= ~PRCM_CLK_MGT_CLK38DIV;
+               }
+       } else if (clock == PRCMU_SGACLK) {
+               val &= ~(PRCM_CLK_MGT_CLKPLLDIV_MASK |
+                       PRCM_SGACLK_MGT_SGACLKDIV_BY_2_5_EN);
+               if (div == 3) {
+                       u64 r = (src_rate * 10);
+
+                       (void)do_div(r, 25);
+                       if (r <= rate) {
+                               val |= PRCM_SGACLK_MGT_SGACLKDIV_BY_2_5_EN;
+                               div = 0;
+                       }
+               }
+               val |= min(div, (u32)31);
+       } else {
+               val &= ~PRCM_CLK_MGT_CLKPLLDIV_MASK;
+               val |= min(div, (u32)31);
+       }
+       writel(val, clk_mgt[clock].reg);
+
+       /* Release the HW semaphore. */
+       writel(0, PRCM_SEM);
+
+       spin_unlock_irqrestore(&clk_mgt_lock, flags);
+}
+
+static int set_plldsi_rate(unsigned long rate)
+{
+       unsigned long src_rate;
+       unsigned long rem;
+       u32 pll_freq = 0;
+       u32 r;
+
+       src_rate = clock_rate(PRCMU_HDMICLK);
+       rem = rate;
+
+       for (r = 7; (rem > 0) && (r > 0); r--) {
+               u64 d;
+               u64 hwrate;
+
+               d = (r * rate);
+               (void)do_div(d, src_rate);
+               if (d < 6)
+                       d = 6;
+               else if (d > 255)
+                       d = 255;
+               hwrate = (d * src_rate);
+               if (((2 * hwrate) < (r * MIN_PLL_VCO_RATE)) ||
+                       ((r * MAX_PLL_VCO_RATE) < (2 * hwrate)))
+                       continue;
+               (void)do_div(hwrate, r);
+               if (rate < hwrate) {
+                       if (pll_freq == 0)
+                               pll_freq = (((u32)d << PRCM_PLL_FREQ_D_SHIFT) |
+                                       (r << PRCM_PLL_FREQ_R_SHIFT));
+                       break;
+               }
+               if ((rate - hwrate) < rem) {
+                       rem = (rate - hwrate);
+                       pll_freq = (((u32)d << PRCM_PLL_FREQ_D_SHIFT) |
+                               (r << PRCM_PLL_FREQ_R_SHIFT));
+               }
        }
+       if (pll_freq == 0)
+               return -EINVAL;
+
+       pll_freq |= (1 << PRCM_PLL_FREQ_N_SHIFT);
+       writel(pll_freq, PRCM_PLLDSI_FREQ);
+
+       return 0;
+}
+
+static void set_dsiclk_rate(u8 n, unsigned long rate)
+{
+       u32 val;
+       u32 div;
+
+       div = clock_divider(pll_rate(PRCM_PLLDSI_FREQ,
+                       clock_rate(PRCMU_HDMICLK), PLL_RAW), rate);
+
+       dsiclk[n].divsel = (div == 1) ? PRCM_DSI_PLLOUT_SEL_PHI :
+                          (div == 2) ? PRCM_DSI_PLLOUT_SEL_PHI_2 :
+                          /* else */   PRCM_DSI_PLLOUT_SEL_PHI_4;
+
+       val = readl(PRCM_DSI_PLLOUT_SEL);
+       val &= ~dsiclk[n].divsel_mask;
+       val |= (dsiclk[n].divsel << dsiclk[n].divsel_shift);
+       writel(val, PRCM_DSI_PLLOUT_SEL);
+}
+
+static void set_dsiescclk_rate(u8 n, unsigned long rate)
+{
+       u32 val;
+       u32 div;
+
+       div = clock_divider(clock_rate(PRCMU_TVCLK), rate);
+       val = readl(PRCM_DSITVCLK_DIV);
+       val &= ~dsiescclk[n].div_mask;
+       val |= (min(div, (u32)255) << dsiescclk[n].div_shift);
+       writel(val, PRCM_DSITVCLK_DIV);
+}
+
+int prcmu_set_clock_rate(u8 clock, unsigned long rate)
+{
        if (clock < PRCMU_NUM_REG_CLOCKS)
-               return request_reg_clock(clock, enable);
-       return -EINVAL;
+               set_clock_rate(clock, rate);
+       else if (clock == PRCMU_PLLDSI)
+               return set_plldsi_rate(rate);
+       else if ((clock == PRCMU_DSI0CLK) || (clock == PRCMU_DSI1CLK))
+               set_dsiclk_rate((clock - PRCMU_DSI0CLK), rate);
+       else if ((PRCMU_DSI0ESCCLK <= clock) && (clock <= PRCMU_DSI2ESCCLK))
+               set_dsiescclk_rate((clock - PRCMU_DSI0ESCCLK), rate);
+       return 0;
 }
 
 int db8500_prcmu_config_esram0_deep_sleep(u8 state)
@@ -1476,7 +2021,7 @@ int db8500_prcmu_config_esram0_deep_sleep(u8 state)
        return 0;
 }
 
-int prcmu_config_hotdog(u8 threshold)
+int db8500_prcmu_config_hotdog(u8 threshold)
 {
        mutex_lock(&mb4_transfer.lock);
 
@@ -1494,7 +2039,7 @@ int prcmu_config_hotdog(u8 threshold)
        return 0;
 }
 
-int prcmu_config_hotmon(u8 low, u8 high)
+int db8500_prcmu_config_hotmon(u8 low, u8 high)
 {
        mutex_lock(&mb4_transfer.lock);
 
@@ -1533,7 +2078,7 @@ static int config_hot_period(u16 val)
        return 0;
 }
 
-int prcmu_start_temp_sense(u16 cycles32k)
+int db8500_prcmu_start_temp_sense(u16 cycles32k)
 {
        if (cycles32k == 0xFFFF)
                return -EINVAL;
@@ -1541,7 +2086,7 @@ int prcmu_start_temp_sense(u16 cycles32k)
        return config_hot_period(cycles32k);
 }
 
-int prcmu_stop_temp_sense(void)
+int db8500_prcmu_stop_temp_sense(void)
 {
        return config_hot_period(0xFFFF);
 }
@@ -1570,7 +2115,7 @@ static int prcmu_a9wdog(u8 cmd, u8 d0, u8 d1, u8 d2, u8 d3)
 
 }
 
-int prcmu_config_a9wdog(u8 num, bool sleep_auto_off)
+int db8500_prcmu_config_a9wdog(u8 num, bool sleep_auto_off)
 {
        BUG_ON(num == 0 || num > 0xf);
        return prcmu_a9wdog(MB4H_A9WDOG_CONF, num, 0, 0,
@@ -1578,17 +2123,17 @@ int prcmu_config_a9wdog(u8 num, bool sleep_auto_off)
                            A9WDOG_AUTO_OFF_DIS);
 }
 
-int prcmu_enable_a9wdog(u8 id)
+int db8500_prcmu_enable_a9wdog(u8 id)
 {
        return prcmu_a9wdog(MB4H_A9WDOG_EN, id, 0, 0, 0);
 }
 
-int prcmu_disable_a9wdog(u8 id)
+int db8500_prcmu_disable_a9wdog(u8 id)
 {
        return prcmu_a9wdog(MB4H_A9WDOG_DIS, id, 0, 0, 0);
 }
 
-int prcmu_kick_a9wdog(u8 id)
+int db8500_prcmu_kick_a9wdog(u8 id)
 {
        return prcmu_a9wdog(MB4H_A9WDOG_KICK, id, 0, 0, 0);
 }
@@ -1596,16 +2141,8 @@ int prcmu_kick_a9wdog(u8 id)
 /*
  * timeout is 28 bit, in ms.
  */
-#define MAX_WATCHDOG_TIMEOUT 131000
-int prcmu_load_a9wdog(u8 id, u32 timeout)
+int db8500_prcmu_load_a9wdog(u8 id, u32 timeout)
 {
-       if (timeout > MAX_WATCHDOG_TIMEOUT)
-               /*
-                * Due to calculation bug in prcmu fw, timeouts
-                * can't be bigger than 131 seconds.
-                */
-               return -EINVAL;
-
        return prcmu_a9wdog(MB4H_A9WDOG_LOAD,
                            (id & A9WDOG_ID_MASK) |
                            /*
@@ -1619,41 +2156,6 @@ int prcmu_load_a9wdog(u8 id, u32 timeout)
 }
 
 /**
- * prcmu_set_clock_divider() - Configure the clock divider.
- * @clock:     The clock for which the request is made.
- * @divider:   The clock divider. (< 32)
- *
- * This function should only be used by the clock implementation.
- * Do not use it from any other place!
- */
-int prcmu_set_clock_divider(u8 clock, u8 divider)
-{
-       u32 val;
-       unsigned long flags;
-
-       if ((clock >= PRCMU_NUM_REG_CLOCKS) || (divider < 1) || (31 < divider))
-               return -EINVAL;
-
-       spin_lock_irqsave(&clk_mgt_lock, flags);
-
-       /* Grab the HW semaphore. */
-       while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0)
-               cpu_relax();
-
-       val = readl(_PRCMU_BASE + clk_mgt[clock].offset);
-       val &= ~(PRCM_CLK_MGT_CLKPLLDIV_MASK);
-       val |= (u32)divider;
-       writel(val, (_PRCMU_BASE + clk_mgt[clock].offset));
-
-       /* Release the HW semaphore. */
-       writel(0, PRCM_SEM);
-
-       spin_unlock_irqrestore(&clk_mgt_lock, flags);
-
-       return 0;
-}
-
-/**
  * prcmu_abb_read() - Read register value(s) from the ABB.
  * @slave:     The I2C slave address.
  * @reg:       The (start) register address.
@@ -1675,6 +2177,7 @@ int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
        while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5))
                cpu_relax();
 
+       writeb(0, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB5));
        writeb(PRCMU_I2C_READ(slave), (tcdm_base + PRCM_REQ_MB5_I2C_SLAVE_OP));
        writeb(PRCMU_I2C_STOP_EN, (tcdm_base + PRCM_REQ_MB5_I2C_HW_BITS));
        writeb(reg, (tcdm_base + PRCM_REQ_MB5_I2C_REG));
@@ -1700,16 +2203,19 @@ int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
 }
 
 /**
- * prcmu_abb_write() - Write register value(s) to the ABB.
+ * prcmu_abb_write_masked() - Write masked register value(s) to the ABB.
  * @slave:     The I2C slave address.
  * @reg:       The (start) register address.
  * @value:     The value(s) to write.
+ * @mask:      The mask(s) to use.
  * @size:      The number of registers to write.
  *
- * Reads register value(s) from the ABB.
+ * Writes masked register value(s) to the ABB.
+ * For each @value, only the bits set to 1 in the corresponding @mask
+ * will be written. The other bits are not changed.
  * @size has to be 1 for the current firmware version.
  */
-int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
+int prcmu_abb_write_masked(u8 slave, u8 reg, u8 *value, u8 *mask, u8 size)
 {
        int r;
 
@@ -1721,6 +2227,7 @@ int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
        while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5))
                cpu_relax();
 
+       writeb(~*mask, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB5));
        writeb(PRCMU_I2C_WRITE(slave), (tcdm_base + PRCM_REQ_MB5_I2C_SLAVE_OP));
        writeb(PRCMU_I2C_STOP_EN, (tcdm_base + PRCM_REQ_MB5_I2C_HW_BITS));
        writeb(reg, (tcdm_base + PRCM_REQ_MB5_I2C_REG));
@@ -1743,6 +2250,23 @@ int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
 }
 
 /**
+ * prcmu_abb_write() - Write register value(s) to the ABB.
+ * @slave:     The I2C slave address.
+ * @reg:       The (start) register address.
+ * @value:     The value(s) to write.
+ * @size:      The number of registers to write.
+ *
+ * Writes register value(s) to the ABB.
+ * @size has to be 1 for the current firmware version.
+ */
+int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
+{
+       u8 mask = ~0;
+
+       return prcmu_abb_write_masked(slave, reg, value, &mask, size);
+}
+
+/**
  * prcmu_ac_wake_req - should be called whenever ARM wants to wakeup Modem
  */
 void prcmu_ac_wake_req(void)
@@ -1850,9 +2374,9 @@ u16 db8500_prcmu_get_reset_code(void)
 }
 
 /**
- * prcmu_reset_modem - ask the PRCMU to reset modem
+ * db8500_prcmu_reset_modem - ask the PRCMU to reset modem
  */
-void prcmu_modem_reset(void)
+void db8500_prcmu_modem_reset(void)
 {
        mutex_lock(&mb1_transfer.lock);
 
@@ -2099,6 +2623,26 @@ static struct irq_chip prcmu_irq_chip = {
        .irq_unmask     = prcmu_irq_unmask,
 };
 
+static char *fw_project_name(u8 project)
+{
+       switch (project) {
+       case PRCMU_FW_PROJECT_U8500:
+               return "U8500";
+       case PRCMU_FW_PROJECT_U8500_C2:
+               return "U8500 C2";
+       case PRCMU_FW_PROJECT_U9500:
+               return "U9500";
+       case PRCMU_FW_PROJECT_U9500_C2:
+               return "U9500 C2";
+       case PRCMU_FW_PROJECT_U8520:
+               return "U8520";
+       case PRCMU_FW_PROJECT_U8420:
+               return "U8420";
+       default:
+               return "Unknown";
+       }
+}
+
 void __init db8500_prcmu_early_init(void)
 {
        unsigned int i;
@@ -2108,11 +2652,13 @@ void __init db8500_prcmu_early_init(void)
                if (tcpm_base != NULL) {
                        u32 version;
                        version = readl(tcpm_base + PRCMU_FW_VERSION_OFFSET);
-                       prcmu_version.project_number = version & 0xFF;
-                       prcmu_version.api_version = (version >> 8) & 0xFF;
-                       prcmu_version.func_version = (version >> 16) & 0xFF;
-                       prcmu_version.errata = (version >> 24) & 0xFF;
-                       pr_info("PRCMU firmware version %d.%d.%d\n",
+                       fw_info.version.project = version & 0xFF;
+                       fw_info.version.api_version = (version >> 8) & 0xFF;
+                       fw_info.version.func_version = (version >> 16) & 0xFF;
+                       fw_info.version.errata = (version >> 24) & 0xFF;
+                       fw_info.valid = true;
+                       pr_info("PRCMU firmware: %s, version %d.%d.%d\n",
+                               fw_project_name(fw_info.version.project),
                                (version >> 8) & 0xFF, (version >> 16) & 0xFF,
                                (version >> 24) & 0xFF);
                        iounmap(tcpm_base);
@@ -2130,6 +2676,7 @@ void __init db8500_prcmu_early_init(void)
        init_completion(&mb0_transfer.ac_wake_work);
        mutex_init(&mb1_transfer.lock);
        init_completion(&mb1_transfer.work);
+       mb1_transfer.ape_opp = APE_NO_CHANGE;
        mutex_init(&mb2_transfer.lock);
        init_completion(&mb2_transfer.work);
        spin_lock_init(&mb2_transfer.auto_pm_lock);
@@ -2154,7 +2701,7 @@ void __init db8500_prcmu_early_init(void)
        }
 }
 
-static void __init db8500_prcmu_init_clkforce(void)
+static void __init init_prcm_registers(void)
 {
        u32 val;
 
@@ -2186,19 +2733,17 @@ static struct regulator_consumer_supply db8500_vape_consumers[] = {
        REGULATOR_SUPPLY("vcore", "uart1"),
        REGULATOR_SUPPLY("vcore", "uart2"),
        REGULATOR_SUPPLY("v-ape", "nmk-ske-keypad.0"),
+       REGULATOR_SUPPLY("v-hsi", "ste_hsi.0"),
 };
 
 static struct regulator_consumer_supply db8500_vsmps2_consumers[] = {
-       /* CG2900 and CW1200 power to off-chip peripherals */
-       REGULATOR_SUPPLY("gbf_1v8", "cg2900-uart.0"),
-       REGULATOR_SUPPLY("wlan_1v8", "cw1200.0"),
        REGULATOR_SUPPLY("musb_1v8", "ab8500-usb.0"),
        /* AV8100 regulator */
        REGULATOR_SUPPLY("hdmi_1v8", "0-0070"),
 };
 
 static struct regulator_consumer_supply db8500_b2r2_mcde_consumers[] = {
-       REGULATOR_SUPPLY("vsupply", "b2r2.0"),
+       REGULATOR_SUPPLY("vsupply", "b2r2_bus"),
        REGULATOR_SUPPLY("vsupply", "mcde"),
 };
 
@@ -2235,6 +2780,7 @@ static struct regulator_consumer_supply db8500_esram12_consumers[] = {
 static struct regulator_consumer_supply db8500_esram34_consumers[] = {
        REGULATOR_SUPPLY("v-esram34", "mcde"),
        REGULATOR_SUPPLY("esram34", "cm_control"),
+       REGULATOR_SUPPLY("lcla_esram", "dma40.0"),
 };
 
 static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = {
@@ -2291,7 +2837,7 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = {
                },
        },
        [DB8500_REGULATOR_SWITCH_SVAMMDSP] = {
-               .supply_regulator = "db8500-vape",
+               /* dependency to u8500-vape is handled outside regulator framework */
                .constraints = {
                        .name = "db8500-sva-mmdsp",
                        .valid_ops_mask = REGULATOR_CHANGE_STATUS,
@@ -2307,7 +2853,7 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = {
                },
        },
        [DB8500_REGULATOR_SWITCH_SVAPIPE] = {
-               .supply_regulator = "db8500-vape",
+               /* dependency to u8500-vape is handled outside regulator framework */
                .constraints = {
                        .name = "db8500-sva-pipe",
                        .valid_ops_mask = REGULATOR_CHANGE_STATUS,
@@ -2316,7 +2862,7 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = {
                .num_consumer_supplies = ARRAY_SIZE(db8500_svapipe_consumers),
        },
        [DB8500_REGULATOR_SWITCH_SIAMMDSP] = {
-               .supply_regulator = "db8500-vape",
+               /* dependency to u8500-vape is handled outside regulator framework */
                .constraints = {
                        .name = "db8500-sia-mmdsp",
                        .valid_ops_mask = REGULATOR_CHANGE_STATUS,
@@ -2331,7 +2877,7 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = {
                },
        },
        [DB8500_REGULATOR_SWITCH_SIAPIPE] = {
-               .supply_regulator = "db8500-vape",
+               /* dependency to u8500-vape is handled outside regulator framework */
                .constraints = {
                        .name = "db8500-sia-pipe",
                        .valid_ops_mask = REGULATOR_CHANGE_STATUS,
@@ -2359,7 +2905,10 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = {
                .num_consumer_supplies = ARRAY_SIZE(db8500_b2r2_mcde_consumers),
        },
        [DB8500_REGULATOR_SWITCH_ESRAM12] = {
-               .supply_regulator = "db8500-vape",
+               /*
+                * esram12 is set in retention and supplied by Vsafe when Vape is off,
+                * no need to hold Vape
+                */
                .constraints = {
                        .name = "db8500-esram12",
                        .valid_ops_mask = REGULATOR_CHANGE_STATUS,
@@ -2374,7 +2923,10 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = {
                },
        },
        [DB8500_REGULATOR_SWITCH_ESRAM34] = {
-               .supply_regulator = "db8500-vape",
+               /*
+                * esram34 is set in retention and supplied by Vsafe when Vape is off,
+                * no need to hold Vape
+                */
                .constraints = {
                        .name = "db8500-esram34",
                        .valid_ops_mask = REGULATOR_CHANGE_STATUS,
@@ -2412,7 +2964,7 @@ static int __init db8500_prcmu_probe(struct platform_device *pdev)
        if (ux500_is_svp())
                return -ENODEV;
 
-       db8500_prcmu_init_clkforce();
+       init_prcm_registers();
 
        /* Clean up the mailbox interrupts after pre-kernel code. */
        writel(ALL_MBOX_BITS, PRCM_ARM_IT1_CLR);
index ec22e9f..3a0bf91 100644 (file)
 
 #define BITS(_start, _end) ((BIT(_end) - BIT(_start)) + BIT(_end))
 
-#define PRCM_SVACLK_MGT_OFF            0x008
-#define PRCM_SIACLK_MGT_OFF            0x00C
-#define PRCM_SGACLK_MGT_OFF            0x014
-#define PRCM_UARTCLK_MGT_OFF           0x018
-#define PRCM_MSP02CLK_MGT_OFF          0x01C
-#define PRCM_I2CCLK_MGT_OFF            0x020
-#define PRCM_SDMMCCLK_MGT_OFF          0x024
-#define PRCM_SLIMCLK_MGT_OFF           0x028
-#define PRCM_PER1CLK_MGT_OFF           0x02C
-#define PRCM_PER2CLK_MGT_OFF           0x030
-#define PRCM_PER3CLK_MGT_OFF           0x034
-#define PRCM_PER5CLK_MGT_OFF           0x038
-#define PRCM_PER6CLK_MGT_OFF           0x03C
-#define PRCM_PER7CLK_MGT_OFF           0x040
-#define PRCM_PWMCLK_MGT_OFF            0x044 /* for DB5500 */
-#define PRCM_IRDACLK_MGT_OFF           0x048 /* for DB5500 */
-#define PRCM_IRRCCLK_MGT_OFF           0x04C /* for DB5500 */
-#define PRCM_LCDCLK_MGT_OFF            0x044
-#define PRCM_BMLCLK_MGT_OFF            0x04C
-#define PRCM_HSITXCLK_MGT_OFF          0x050
-#define PRCM_HSIRXCLK_MGT_OFF          0x054
-#define PRCM_HDMICLK_MGT_OFF           0x058
-#define PRCM_APEATCLK_MGT_OFF          0x05C
-#define PRCM_APETRACECLK_MGT_OFF       0x060
-#define PRCM_MCDECLK_MGT_OFF           0x064
-#define PRCM_IPI2CCLK_MGT_OFF          0x068
-#define PRCM_DSIALTCLK_MGT_OFF         0x06C
-#define PRCM_DMACLK_MGT_OFF            0x074
-#define PRCM_B2R2CLK_MGT_OFF           0x078
-#define PRCM_TVCLK_MGT_OFF             0x07C
-#define PRCM_UNIPROCLK_MGT_OFF         0x278
-#define PRCM_SSPCLK_MGT_OFF            0x280
-#define PRCM_RNGCLK_MGT_OFF            0x284
-#define PRCM_UICCCLK_MGT_OFF           0x27C
-#define PRCM_MSP1CLK_MGT_OFF           0x288
+#define PRCM_CLK_MGT(_offset) (void __iomem *)(IO_ADDRESS(U8500_PRCMU_BASE) \
+       + _offset)
+#define PRCM_ACLK_MGT          PRCM_CLK_MGT(0x004)
+#define PRCM_SVACLK_MGT                PRCM_CLK_MGT(0x008)
+#define PRCM_SIACLK_MGT                PRCM_CLK_MGT(0x00C)
+#define PRCM_SGACLK_MGT                PRCM_CLK_MGT(0x014)
+#define PRCM_UARTCLK_MGT       PRCM_CLK_MGT(0x018)
+#define PRCM_MSP02CLK_MGT      PRCM_CLK_MGT(0x01C)
+#define PRCM_I2CCLK_MGT                PRCM_CLK_MGT(0x020)
+#define PRCM_SDMMCCLK_MGT      PRCM_CLK_MGT(0x024)
+#define PRCM_SLIMCLK_MGT       PRCM_CLK_MGT(0x028)
+#define PRCM_PER1CLK_MGT       PRCM_CLK_MGT(0x02C)
+#define PRCM_PER2CLK_MGT       PRCM_CLK_MGT(0x030)
+#define PRCM_PER3CLK_MGT       PRCM_CLK_MGT(0x034)
+#define PRCM_PER5CLK_MGT       PRCM_CLK_MGT(0x038)
+#define PRCM_PER6CLK_MGT       PRCM_CLK_MGT(0x03C)
+#define PRCM_PER7CLK_MGT       PRCM_CLK_MGT(0x040)
+#define PRCM_LCDCLK_MGT                PRCM_CLK_MGT(0x044)
+#define PRCM_BMLCLK_MGT                PRCM_CLK_MGT(0x04C)
+#define PRCM_HSITXCLK_MGT      PRCM_CLK_MGT(0x050)
+#define PRCM_HSIRXCLK_MGT      PRCM_CLK_MGT(0x054)
+#define PRCM_HDMICLK_MGT       PRCM_CLK_MGT(0x058)
+#define PRCM_APEATCLK_MGT      PRCM_CLK_MGT(0x05C)
+#define PRCM_APETRACECLK_MGT   PRCM_CLK_MGT(0x060)
+#define PRCM_MCDECLK_MGT       PRCM_CLK_MGT(0x064)
+#define PRCM_IPI2CCLK_MGT      PRCM_CLK_MGT(0x068)
+#define PRCM_DSIALTCLK_MGT     PRCM_CLK_MGT(0x06C)
+#define PRCM_DMACLK_MGT                PRCM_CLK_MGT(0x074)
+#define PRCM_B2R2CLK_MGT       PRCM_CLK_MGT(0x078)
+#define PRCM_TVCLK_MGT         PRCM_CLK_MGT(0x07C)
+#define PRCM_UNIPROCLK_MGT     PRCM_CLK_MGT(0x278)
+#define PRCM_SSPCLK_MGT                PRCM_CLK_MGT(0x280)
+#define PRCM_RNGCLK_MGT                PRCM_CLK_MGT(0x284)
+#define PRCM_UICCCLK_MGT       PRCM_CLK_MGT(0x27C)
+#define PRCM_MSP1CLK_MGT       PRCM_CLK_MGT(0x288)
 
 #define PRCM_ARM_PLLDIVPS      (_PRCMU_BASE + 0x118)
 #define PRCM_ARM_PLLDIVPS_ARM_BRM_RATE         0x3f
@@ -79,6 +79,8 @@
 
 /* ARM WFI Standby signal register */
 #define PRCM_ARM_WFI_STANDBY    (_PRCMU_BASE + 0x130)
+#define PRCM_ARM_WFI_STANDBY_WFI0               0x08
+#define PRCM_ARM_WFI_STANDBY_WFI1               0x10
 #define PRCM_IOCR              (_PRCMU_BASE + 0x310)
 #define PRCM_IOCR_IOFORCE                      0x1
 
 #define PRCM_MMIP_LS_CLAMP_SET     (_PRCMU_BASE + 0x420)
 #define PRCM_MMIP_LS_CLAMP_CLR     (_PRCMU_BASE + 0x424)
 
+#define PRCM_MMIP_LS_CLAMP_DSIPLL_CLAMP                BIT(11)
+#define PRCM_MMIP_LS_CLAMP_DSIPLL_CLAMPI       BIT(22)
+
 /* PRCMU clock/PLL/reset registers */
+#define PRCM_PLLSOC0_FREQ         (_PRCMU_BASE + 0x080)
+#define PRCM_PLLSOC1_FREQ         (_PRCMU_BASE + 0x084)
+#define PRCM_PLLDDR_FREQ          (_PRCMU_BASE + 0x08C)
+#define PRCM_PLL_FREQ_D_SHIFT  0
+#define PRCM_PLL_FREQ_D_MASK   BITS(0, 7)
+#define PRCM_PLL_FREQ_N_SHIFT  8
+#define PRCM_PLL_FREQ_N_MASK   BITS(8, 13)
+#define PRCM_PLL_FREQ_R_SHIFT  16
+#define PRCM_PLL_FREQ_R_MASK   BITS(16, 18)
+#define PRCM_PLL_FREQ_SELDIV2  BIT(24)
+#define PRCM_PLL_FREQ_DIV2EN   BIT(25)
+
 #define PRCM_PLLDSI_FREQ           (_PRCMU_BASE + 0x500)
 #define PRCM_PLLDSI_ENABLE         (_PRCMU_BASE + 0x504)
 #define PRCM_PLLDSI_LOCKP          (_PRCMU_BASE + 0x508)
-#define PRCM_LCDCLK_MGT            (_PRCMU_BASE + PRCM_LCDCLK_MGT_OFF)
-#define PRCM_MCDECLK_MGT           (_PRCMU_BASE + PRCM_MCDECLK_MGT_OFF)
-#define PRCM_HDMICLK_MGT           (_PRCMU_BASE + PRCM_HDMICLK_MGT_OFF)
-#define PRCM_TVCLK_MGT             (_PRCMU_BASE + PRCM_TVCLK_MGT_OFF)
 #define PRCM_DSI_PLLOUT_SEL        (_PRCMU_BASE + 0x530)
 #define PRCM_DSITVCLK_DIV          (_PRCMU_BASE + 0x52C)
 #define PRCM_PLLDSI_LOCKP          (_PRCMU_BASE + 0x508)
 #define PRCM_APE_RESETN_SET        (_PRCMU_BASE + 0x1E4)
 #define PRCM_APE_RESETN_CLR        (_PRCMU_BASE + 0x1E8)
 
+#define PRCM_PLLDSI_ENABLE_PRCM_PLLDSI_ENABLE BIT(0)
+
+#define PRCM_PLLDSI_LOCKP_PRCM_PLLDSI_LOCKP10  BIT(0)
+#define PRCM_PLLDSI_LOCKP_PRCM_PLLDSI_LOCKP3   BIT(1)
+
+#define PRCM_DSI_PLLOUT_SEL_DSI0_PLLOUT_DIVSEL_SHIFT   0
+#define PRCM_DSI_PLLOUT_SEL_DSI0_PLLOUT_DIVSEL_MASK    BITS(0, 2)
+#define PRCM_DSI_PLLOUT_SEL_DSI1_PLLOUT_DIVSEL_SHIFT   8
+#define PRCM_DSI_PLLOUT_SEL_DSI1_PLLOUT_DIVSEL_MASK    BITS(8, 10)
+
+#define PRCM_DSI_PLLOUT_SEL_OFF                0
+#define PRCM_DSI_PLLOUT_SEL_PHI                1
+#define PRCM_DSI_PLLOUT_SEL_PHI_2      2
+#define PRCM_DSI_PLLOUT_SEL_PHI_4      3
+
+#define PRCM_DSITVCLK_DIV_DSI0_ESC_CLK_DIV_SHIFT       0
+#define PRCM_DSITVCLK_DIV_DSI0_ESC_CLK_DIV_MASK                BITS(0, 7)
+#define PRCM_DSITVCLK_DIV_DSI1_ESC_CLK_DIV_SHIFT       8
+#define PRCM_DSITVCLK_DIV_DSI1_ESC_CLK_DIV_MASK                BITS(8, 15)
+#define PRCM_DSITVCLK_DIV_DSI2_ESC_CLK_DIV_SHIFT       16
+#define PRCM_DSITVCLK_DIV_DSI2_ESC_CLK_DIV_MASK                BITS(16, 23)
+#define PRCM_DSITVCLK_DIV_DSI0_ESC_CLK_EN              BIT(24)
+#define PRCM_DSITVCLK_DIV_DSI1_ESC_CLK_EN              BIT(25)
+#define PRCM_DSITVCLK_DIV_DSI2_ESC_CLK_EN              BIT(26)
+
+#define PRCM_APE_RESETN_DSIPLL_RESETN BIT(14)
+
 #define PRCM_CLKOCR               (_PRCMU_BASE + 0x1CC)
 #define PRCM_CLKOCR_CLKOUT0_REF_CLK    (1 << 0)
 #define PRCM_CLKOCR_CLKOUT0_MASK       BITS(0, 13)
 #define PRCM_CLKOCR_CLKOSEL1_MASK      BITS(22, 24)
 #define PRCM_CLKOCR_CLK1TYPE           BIT(28)
 
-#define PRCM_CLK_MGT_CLKPLLDIV_MASK    BITS(0, 4)
-#define PRCM_CLK_MGT_CLKPLLSW_MASK     BITS(5, 7)
-#define PRCM_CLK_MGT_CLKEN             BIT(8)
+#define PRCM_CLK_MGT_CLKPLLDIV_MASK            BITS(0, 4)
+#define PRCM_CLK_MGT_CLKPLLSW_SOC0             BIT(5)
+#define PRCM_CLK_MGT_CLKPLLSW_SOC1             BIT(6)
+#define PRCM_CLK_MGT_CLKPLLSW_DDR              BIT(7)
+#define PRCM_CLK_MGT_CLKPLLSW_MASK             BITS(5, 7)
+#define PRCM_CLK_MGT_CLKEN                     BIT(8)
+#define PRCM_CLK_MGT_CLK38                     BIT(9)
+#define PRCM_CLK_MGT_CLK38DIV                  BIT(11)
+#define PRCM_SGACLK_MGT_SGACLKDIV_BY_2_5_EN    BIT(12)
 
 /* GPIOCR register */
 #define PRCM_GPIOCR_SPI2_SELECT BIT(23)
index 7122386..9fd4f63 100644 (file)
@@ -560,6 +560,8 @@ EXPORT_SYMBOL(mc13xxx_get_flags);
 
 #define MC13XXX_ADC1_CHAN0_SHIFT       5
 #define MC13XXX_ADC1_CHAN1_SHIFT       8
+#define MC13783_ADC1_ATO_SHIFT         11
+#define MC13783_ADC1_ATOX              (1 << 19)
 
 struct mc13xxx_adcdone_data {
        struct mc13xxx *mc13xxx;
@@ -580,7 +582,8 @@ static irqreturn_t mc13xxx_handler_adcdone(int irq, void *data)
 #define MC13XXX_ADC_WORKING (1 << 0)
 
 int mc13xxx_adc_do_conversion(struct mc13xxx *mc13xxx, unsigned int mode,
-               unsigned int channel, unsigned int *sample)
+               unsigned int channel, u8 ato, bool atox,
+               unsigned int *sample)
 {
        u32 adc0, adc1, old_adc0;
        int i, ret;
@@ -631,6 +634,9 @@ int mc13xxx_adc_do_conversion(struct mc13xxx *mc13xxx, unsigned int mode,
                return -EINVAL;
        }
 
+       adc1 |= ato << MC13783_ADC1_ATO_SHIFT;
+       if (atox)
+               adc1 |= MC13783_ADC1_ATOX;
        dev_dbg(&mc13xxx->spidev->dev, "%s: request irq\n", __func__);
        mc13xxx_irq_request(mc13xxx, MC13XXX_IRQ_ADCDONE,
                        mc13xxx_handler_adcdone, __func__, &adcdone_data);
@@ -813,7 +819,8 @@ err_revision:
                mc13xxx_add_subdevice(mc13xxx, "%s-rtc");
 
        if (mc13xxx->flags & MC13XXX_USE_TOUCHSCREEN)
-               mc13xxx_add_subdevice(mc13xxx, "%s-ts");
+               mc13xxx_add_subdevice_pdata(mc13xxx, "%s-ts",
+                               &pdata->touch, sizeof(pdata->touch));
 
        if (pdata) {
                mc13xxx_add_subdevice_pdata(mc13xxx, "%s-regulator",
index 6acf2e0..62e5e36 100644 (file)
@@ -19,8 +19,6 @@
 #include <linux/string.h>
 #include <linux/mfd/mcp.h>
 
-#include <asm/system.h>
-
 
 #define to_mcp(d)              container_of(d, struct mcp, attached_device)
 #define to_mcp_driver(d)       container_of(d, struct mcp_driver, drv)
index 1c0ceac..c54e244 100644 (file)
@@ -24,7 +24,6 @@
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
-#include <asm/system.h>
 #include <mach/mcp.h>
 
 #define DRIVER_NAME "sa11x0-mcp"
index 411f523..ffc3d48 100644 (file)
@@ -162,7 +162,7 @@ int mfd_add_devices(struct device *parent, int id,
        atomic_t *cnts;
 
        /* initialize reference counting for all cells */
-       cnts = kcalloc(sizeof(*cnts), n_devs, GFP_KERNEL);
+       cnts = kcalloc(n_devs, sizeof(*cnts), GFP_KERNEL);
        if (!cnts)
                return -ENOMEM;
 
index 68ac2c5..95a2e54 100644 (file)
@@ -170,7 +170,7 @@ struct usbhs_hcd_omap {
 /*-------------------------------------------------------------------------*/
 
 const char usbhs_driver_name[] = USBHS_DRIVER_NAME;
-static u64 usbhs_dmamask = ~(u32)0;
+static u64 usbhs_dmamask = DMA_BIT_MASK(32);
 
 /*-------------------------------------------------------------------------*/
 
@@ -223,7 +223,7 @@ static struct platform_device *omap_usbhs_alloc_child(const char *name,
        }
 
        child->dev.dma_mask             = &usbhs_dmamask;
-       child->dev.coherent_dma_mask    = 0xffffffff;
+       dma_set_coherent_mask(&child->dev, DMA_BIT_MASK(32));
        child->dev.parent               = dev;
 
        ret = platform_device_add(child);
@@ -799,14 +799,13 @@ static int __devinit usbhs_omap_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, omap);
 
+       omap_usbhs_init(dev);
        ret = omap_usbhs_alloc_children(pdev);
        if (ret) {
                dev_err(dev, "omap_usbhs_alloc_children failed\n");
                goto err_alloc;
        }
 
-       omap_usbhs_init(dev);
-
        goto end_probe;
 
 err_alloc:
index ff1a7e7..189c2f0 100644 (file)
@@ -46,13 +46,7 @@ EXPORT_SYMBOL_GPL(pcf50633_read_block);
 int pcf50633_write_block(struct pcf50633 *pcf , u8 reg,
                                        int nr_regs, u8 *data)
 {
-       int ret;
-
-       ret = regmap_raw_write(pcf->regmap, reg, data, nr_regs);
-       if (ret != 0)
-               return ret;
-
-       return nr_regs;
+       return regmap_raw_write(pcf->regmap, reg, data, nr_regs);
 }
 EXPORT_SYMBOL_GPL(pcf50633_write_block);
 
index 9ab19a8..d02ddf2 100644 (file)
 
 #include <linux/mfd/pcf50633/core.h>
 #include <linux/mfd/pcf50633/gpio.h>
-
-enum pcf50633_regulator_id {
-       PCF50633_REGULATOR_AUTO,
-       PCF50633_REGULATOR_DOWN1,
-       PCF50633_REGULATOR_DOWN2,
-       PCF50633_REGULATOR_LDO1,
-       PCF50633_REGULATOR_LDO2,
-       PCF50633_REGULATOR_LDO3,
-       PCF50633_REGULATOR_LDO4,
-       PCF50633_REGULATOR_LDO5,
-       PCF50633_REGULATOR_LDO6,
-       PCF50633_REGULATOR_HCLDO,
-       PCF50633_REGULATOR_MEMLDO,
-};
-
-#define PCF50633_REG_AUTOOUT   0x1a
-#define PCF50633_REG_DOWN1OUT  0x1e
-#define PCF50633_REG_DOWN2OUT  0x22
-#define PCF50633_REG_MEMLDOOUT 0x26
-#define PCF50633_REG_LDO1OUT   0x2d
-#define PCF50633_REG_LDO2OUT   0x2f
-#define PCF50633_REG_LDO3OUT   0x31
-#define PCF50633_REG_LDO4OUT   0x33
-#define PCF50633_REG_LDO5OUT   0x35
-#define PCF50633_REG_LDO6OUT   0x37
-#define PCF50633_REG_HCLDOOUT  0x39
+#include <linux/mfd/pcf50633/pmic.h>
 
 static const u8 pcf50633_regulator_registers[PCF50633_NUM_REGULATORS] = {
        [PCF50633_REGULATOR_AUTO]       = PCF50633_REG_AUTOOUT,
index 048a3b9..498286c 100644 (file)
 #include <linux/slab.h>
 
 #include <linux/mfd/pcf50633/core.h>
-
-/* Two MBCS registers used during cold start */
-#define PCF50633_REG_MBCS1             0x4b
-#define PCF50633_REG_MBCS2             0x4c
-#define PCF50633_MBCS1_USBPRES                 0x01
-#define PCF50633_MBCS1_ADAPTPRES       0x01
+#include <linux/mfd/pcf50633/mbc.h>
 
 int pcf50633_register_irq(struct pcf50633 *pcf, int irq,
                        void (*handler) (int, void *), void *data)
diff --git a/drivers/mfd/rc5t583-irq.c b/drivers/mfd/rc5t583-irq.c
new file mode 100644 (file)
index 0000000..fa6f80f
--- /dev/null
@@ -0,0 +1,408 @@
+/*
+ * Interrupt driver for RICOH583 power management chip.
+ *
+ * Copyright (c) 2011-2012, NVIDIA CORPORATION.  All rights reserved.
+ * Author: Laxman dewangan <ldewangan@nvidia.com>
+ *
+ * based on code
+ *      Copyright (C) 2011 RICOH COMPANY,LTD
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/mfd/rc5t583.h>
+
+enum int_type {
+       SYS_INT  = 0x1,
+       DCDC_INT = 0x2,
+       RTC_INT  = 0x4,
+       ADC_INT  = 0x8,
+       GPIO_INT = 0x10,
+};
+
+static int gpedge_add[] = {
+       RC5T583_GPIO_GPEDGE2,
+       RC5T583_GPIO_GPEDGE2
+};
+
+static int irq_en_add[] = {
+       RC5T583_INT_EN_SYS1,
+       RC5T583_INT_EN_SYS2,
+       RC5T583_INT_EN_DCDC,
+       RC5T583_INT_EN_RTC,
+       RC5T583_INT_EN_ADC1,
+       RC5T583_INT_EN_ADC2,
+       RC5T583_INT_EN_ADC3,
+       RC5T583_GPIO_EN_INT
+};
+
+static int irq_mon_add[] = {
+       RC5T583_INT_MON_SYS1,
+       RC5T583_INT_MON_SYS2,
+       RC5T583_INT_MON_DCDC,
+       RC5T583_INT_MON_RTC,
+       RC5T583_INT_IR_ADCL,
+       RC5T583_INT_IR_ADCH,
+       RC5T583_INT_IR_ADCEND,
+       RC5T583_INT_IR_GPIOF,
+       RC5T583_INT_IR_GPIOR
+};
+
+static int irq_clr_add[] = {
+       RC5T583_INT_IR_SYS1,
+       RC5T583_INT_IR_SYS2,
+       RC5T583_INT_IR_DCDC,
+       RC5T583_INT_IR_RTC,
+       RC5T583_INT_IR_ADCL,
+       RC5T583_INT_IR_ADCH,
+       RC5T583_INT_IR_ADCEND,
+       RC5T583_INT_IR_GPIOF,
+       RC5T583_INT_IR_GPIOR
+};
+
+static int main_int_type[] = {
+       SYS_INT,
+       SYS_INT,
+       DCDC_INT,
+       RTC_INT,
+       ADC_INT,
+       ADC_INT,
+       ADC_INT,
+       GPIO_INT,
+       GPIO_INT,
+};
+
+struct rc5t583_irq_data {
+       u8      int_type;
+       u8      master_bit;
+       u8      int_en_bit;
+       u8      mask_reg_index;
+       int     grp_index;
+};
+
+#define RC5T583_IRQ(_int_type, _master_bit, _grp_index, \
+                       _int_bit, _mask_ind)            \
+       {                                               \
+               .int_type       = _int_type,            \
+               .master_bit     = _master_bit,          \
+               .grp_index      = _grp_index,           \
+               .int_en_bit     = _int_bit,             \
+               .mask_reg_index = _mask_ind,            \
+       }
+
+static const struct rc5t583_irq_data rc5t583_irqs[RC5T583_MAX_IRQS] = {
+       [RC5T583_IRQ_ONKEY]             = RC5T583_IRQ(SYS_INT,  0, 0, 0, 0),
+       [RC5T583_IRQ_ACOK]              = RC5T583_IRQ(SYS_INT,  0, 1, 1, 0),
+       [RC5T583_IRQ_LIDOPEN]           = RC5T583_IRQ(SYS_INT,  0, 2, 2, 0),
+       [RC5T583_IRQ_PREOT]             = RC5T583_IRQ(SYS_INT,  0, 3, 3, 0),
+       [RC5T583_IRQ_CLKSTP]            = RC5T583_IRQ(SYS_INT,  0, 4, 4, 0),
+       [RC5T583_IRQ_ONKEY_OFF]         = RC5T583_IRQ(SYS_INT,  0, 5, 5, 0),
+       [RC5T583_IRQ_WD]                = RC5T583_IRQ(SYS_INT,  0, 7, 7, 0),
+       [RC5T583_IRQ_EN_PWRREQ1]        = RC5T583_IRQ(SYS_INT,  0, 8, 0, 1),
+       [RC5T583_IRQ_EN_PWRREQ2]        = RC5T583_IRQ(SYS_INT,  0, 9, 1, 1),
+       [RC5T583_IRQ_PRE_VINDET]        = RC5T583_IRQ(SYS_INT,  0, 10, 2, 1),
+
+       [RC5T583_IRQ_DC0LIM]            = RC5T583_IRQ(DCDC_INT, 1, 0, 0, 2),
+       [RC5T583_IRQ_DC1LIM]            = RC5T583_IRQ(DCDC_INT, 1, 1, 1, 2),
+       [RC5T583_IRQ_DC2LIM]            = RC5T583_IRQ(DCDC_INT, 1, 2, 2, 2),
+       [RC5T583_IRQ_DC3LIM]            = RC5T583_IRQ(DCDC_INT, 1, 3, 3, 2),
+
+       [RC5T583_IRQ_CTC]               = RC5T583_IRQ(RTC_INT,  2, 0, 0, 3),
+       [RC5T583_IRQ_YALE]              = RC5T583_IRQ(RTC_INT,  2, 5, 5, 3),
+       [RC5T583_IRQ_DALE]              = RC5T583_IRQ(RTC_INT,  2, 6, 6, 3),
+       [RC5T583_IRQ_WALE]              = RC5T583_IRQ(RTC_INT,  2, 7, 7, 3),
+
+       [RC5T583_IRQ_AIN1L]             = RC5T583_IRQ(ADC_INT,  3, 0, 0, 4),
+       [RC5T583_IRQ_AIN2L]             = RC5T583_IRQ(ADC_INT,  3, 1, 1, 4),
+       [RC5T583_IRQ_AIN3L]             = RC5T583_IRQ(ADC_INT,  3, 2, 2, 4),
+       [RC5T583_IRQ_VBATL]             = RC5T583_IRQ(ADC_INT,  3, 3, 3, 4),
+       [RC5T583_IRQ_VIN3L]             = RC5T583_IRQ(ADC_INT,  3, 4, 4, 4),
+       [RC5T583_IRQ_VIN8L]             = RC5T583_IRQ(ADC_INT,  3, 5, 5, 4),
+       [RC5T583_IRQ_AIN1H]             = RC5T583_IRQ(ADC_INT,  3, 6, 0, 5),
+       [RC5T583_IRQ_AIN2H]             = RC5T583_IRQ(ADC_INT,  3, 7, 1, 5),
+       [RC5T583_IRQ_AIN3H]             = RC5T583_IRQ(ADC_INT,  3, 8, 2, 5),
+       [RC5T583_IRQ_VBATH]             = RC5T583_IRQ(ADC_INT,  3, 9, 3, 5),
+       [RC5T583_IRQ_VIN3H]             = RC5T583_IRQ(ADC_INT,  3, 10, 4, 5),
+       [RC5T583_IRQ_VIN8H]             = RC5T583_IRQ(ADC_INT,  3, 11, 5, 5),
+       [RC5T583_IRQ_ADCEND]            = RC5T583_IRQ(ADC_INT,  3, 12, 0, 6),
+
+       [RC5T583_IRQ_GPIO0]             = RC5T583_IRQ(GPIO_INT, 4, 0, 0, 7),
+       [RC5T583_IRQ_GPIO1]             = RC5T583_IRQ(GPIO_INT, 4, 1, 1, 7),
+       [RC5T583_IRQ_GPIO2]             = RC5T583_IRQ(GPIO_INT, 4, 2, 2, 7),
+       [RC5T583_IRQ_GPIO3]             = RC5T583_IRQ(GPIO_INT, 4, 3, 3, 7),
+       [RC5T583_IRQ_GPIO4]             = RC5T583_IRQ(GPIO_INT, 4, 4, 4, 7),
+       [RC5T583_IRQ_GPIO5]             = RC5T583_IRQ(GPIO_INT, 4, 5, 5, 7),
+       [RC5T583_IRQ_GPIO6]             = RC5T583_IRQ(GPIO_INT, 4, 6, 6, 7),
+       [RC5T583_IRQ_GPIO7]             = RC5T583_IRQ(GPIO_INT, 4, 7, 7, 7),
+};
+
+static void rc5t583_irq_lock(struct irq_data *irq_data)
+{
+       struct rc5t583 *rc5t583 = irq_data_get_irq_chip_data(irq_data);
+       mutex_lock(&rc5t583->irq_lock);
+}
+
+static void rc5t583_irq_unmask(struct irq_data *irq_data)
+{
+       struct rc5t583 *rc5t583 = irq_data_get_irq_chip_data(irq_data);
+       unsigned int __irq = irq_data->irq - rc5t583->irq_base;
+       const struct rc5t583_irq_data *data = &rc5t583_irqs[__irq];
+
+       rc5t583->group_irq_en[data->grp_index] |= 1 << data->grp_index;
+       rc5t583->intc_inten_reg |= 1 << data->master_bit;
+       rc5t583->irq_en_reg[data->mask_reg_index] |= 1 << data->int_en_bit;
+}
+
+static void rc5t583_irq_mask(struct irq_data *irq_data)
+{
+       struct rc5t583 *rc5t583 = irq_data_get_irq_chip_data(irq_data);
+       unsigned int __irq = irq_data->irq - rc5t583->irq_base;
+       const struct rc5t583_irq_data *data = &rc5t583_irqs[__irq];
+
+       rc5t583->group_irq_en[data->grp_index] &= ~(1 << data->grp_index);
+       if (!rc5t583->group_irq_en[data->grp_index])
+               rc5t583->intc_inten_reg &= ~(1 << data->master_bit);
+
+       rc5t583->irq_en_reg[data->mask_reg_index] &= ~(1 << data->int_en_bit);
+}
+
+static int rc5t583_irq_set_type(struct irq_data *irq_data, unsigned int type)
+{
+       struct rc5t583 *rc5t583 = irq_data_get_irq_chip_data(irq_data);
+       unsigned int __irq = irq_data->irq - rc5t583->irq_base;
+       const struct rc5t583_irq_data *data = &rc5t583_irqs[__irq];
+       int val = 0;
+       int gpedge_index;
+       int gpedge_bit_pos;
+
+       /* Supporting only trigger level inetrrupt */
+       if ((data->int_type & GPIO_INT) && (type & IRQ_TYPE_EDGE_BOTH)) {
+               gpedge_index = data->int_en_bit / 4;
+               gpedge_bit_pos = data->int_en_bit % 4;
+
+               if (type & IRQ_TYPE_EDGE_FALLING)
+                       val |= 0x2;
+
+               if (type & IRQ_TYPE_EDGE_RISING)
+                       val |= 0x1;
+
+               rc5t583->gpedge_reg[gpedge_index] &= ~(3 << gpedge_bit_pos);
+               rc5t583->gpedge_reg[gpedge_index] |= (val << gpedge_bit_pos);
+               rc5t583_irq_unmask(irq_data);
+               return 0;
+       }
+       return -EINVAL;
+}
+
+static void rc5t583_irq_sync_unlock(struct irq_data *irq_data)
+{
+       struct rc5t583 *rc5t583 = irq_data_get_irq_chip_data(irq_data);
+       int i;
+       int ret;
+
+       for (i = 0; i < ARRAY_SIZE(rc5t583->gpedge_reg); i++) {
+               ret = rc5t583_write(rc5t583->dev, gpedge_add[i],
+                               rc5t583->gpedge_reg[i]);
+               if (ret < 0)
+                       dev_warn(rc5t583->dev,
+                               "Error in writing reg 0x%02x error: %d\n",
+                               gpedge_add[i], ret);
+       }
+
+       for (i = 0; i < ARRAY_SIZE(rc5t583->irq_en_reg); i++) {
+               ret = rc5t583_write(rc5t583->dev, irq_en_add[i],
+                                       rc5t583->irq_en_reg[i]);
+               if (ret < 0)
+                       dev_warn(rc5t583->dev,
+                               "Error in writing reg 0x%02x error: %d\n",
+                               irq_en_add[i], ret);
+       }
+
+       ret = rc5t583_write(rc5t583->dev, RC5T583_INTC_INTEN,
+                               rc5t583->intc_inten_reg);
+       if (ret < 0)
+               dev_warn(rc5t583->dev,
+                       "Error in writing reg 0x%02x error: %d\n",
+                       RC5T583_INTC_INTEN, ret);
+
+       mutex_unlock(&rc5t583->irq_lock);
+}
+#ifdef CONFIG_PM_SLEEP
+static int rc5t583_irq_set_wake(struct irq_data *irq_data, unsigned int on)
+{
+       struct rc5t583 *rc5t583 = irq_data_get_irq_chip_data(irq_data);
+       return irq_set_irq_wake(rc5t583->chip_irq, on);
+}
+#else
+#define rc5t583_irq_set_wake NULL
+#endif
+
+static irqreturn_t rc5t583_irq(int irq, void *data)
+{
+       struct rc5t583 *rc5t583 = data;
+       uint8_t int_sts[RC5T583_MAX_INTERRUPT_MASK_REGS];
+       uint8_t master_int;
+       int i;
+       int ret;
+       unsigned int rtc_int_sts = 0;
+
+       /* Clear the status */
+       for (i = 0; i < RC5T583_MAX_INTERRUPT_MASK_REGS; i++)
+               int_sts[i] = 0;
+
+       ret  = rc5t583_read(rc5t583->dev, RC5T583_INTC_INTMON, &master_int);
+       if (ret < 0) {
+               dev_err(rc5t583->dev,
+                       "Error in reading reg 0x%02x error: %d\n",
+                       RC5T583_INTC_INTMON, ret);
+               return IRQ_HANDLED;
+       }
+
+       for (i = 0; i < RC5T583_MAX_INTERRUPT_MASK_REGS; ++i) {
+               if (!(master_int & main_int_type[i]))
+                       continue;
+
+               ret = rc5t583_read(rc5t583->dev, irq_mon_add[i], &int_sts[i]);
+               if (ret < 0) {
+                       dev_warn(rc5t583->dev,
+                               "Error in reading reg 0x%02x error: %d\n",
+                               irq_mon_add[i], ret);
+                       int_sts[i] = 0;
+                       continue;
+               }
+
+               if (main_int_type[i] & RTC_INT) {
+                       rtc_int_sts = 0;
+                       if (int_sts[i] & 0x1)
+                               rtc_int_sts |= BIT(6);
+                       if (int_sts[i] & 0x2)
+                               rtc_int_sts |= BIT(7);
+                       if (int_sts[i] & 0x4)
+                               rtc_int_sts |= BIT(0);
+                       if (int_sts[i] & 0x8)
+                               rtc_int_sts |= BIT(5);
+               }
+
+               ret = rc5t583_write(rc5t583->dev, irq_clr_add[i],
+                               ~int_sts[i]);
+               if (ret < 0)
+                       dev_warn(rc5t583->dev,
+                               "Error in reading reg 0x%02x error: %d\n",
+                               irq_clr_add[i], ret);
+
+               if (main_int_type[i] & RTC_INT)
+                       int_sts[i] = rtc_int_sts;
+       }
+
+       /* Merge gpio interrupts for rising and falling case*/
+       int_sts[7] |= int_sts[8];
+
+       /* Call interrupt handler if enabled */
+       for (i = 0; i < RC5T583_MAX_IRQS; ++i) {
+               const struct rc5t583_irq_data *data = &rc5t583_irqs[i];
+               if ((int_sts[data->mask_reg_index] & (1 << data->int_en_bit)) &&
+                       (rc5t583->group_irq_en[data->master_bit] &
+                                       (1 << data->grp_index)))
+                       handle_nested_irq(rc5t583->irq_base + i);
+       }
+
+       return IRQ_HANDLED;
+}
+
+static struct irq_chip rc5t583_irq_chip = {
+       .name = "rc5t583-irq",
+       .irq_mask = rc5t583_irq_mask,
+       .irq_unmask = rc5t583_irq_unmask,
+       .irq_bus_lock = rc5t583_irq_lock,
+       .irq_bus_sync_unlock = rc5t583_irq_sync_unlock,
+       .irq_set_type = rc5t583_irq_set_type,
+       .irq_set_wake = rc5t583_irq_set_wake,
+};
+
+int rc5t583_irq_init(struct rc5t583 *rc5t583, int irq, int irq_base)
+{
+       int i, ret;
+
+       if (!irq_base) {
+               dev_warn(rc5t583->dev, "No interrupt support on IRQ base\n");
+               return -EINVAL;
+       }
+
+       mutex_init(&rc5t583->irq_lock);
+
+       /* Initailize all int register to 0 */
+       for (i = 0; i < RC5T583_MAX_INTERRUPT_MASK_REGS; i++)  {
+               ret = rc5t583_write(rc5t583->dev, irq_en_add[i],
+                               rc5t583->irq_en_reg[i]);
+               if (ret < 0)
+                       dev_warn(rc5t583->dev,
+                               "Error in writing reg 0x%02x error: %d\n",
+                               irq_en_add[i], ret);
+       }
+
+       for (i = 0; i < RC5T583_MAX_GPEDGE_REG; i++)  {
+               ret = rc5t583_write(rc5t583->dev, gpedge_add[i],
+                               rc5t583->gpedge_reg[i]);
+               if (ret < 0)
+                       dev_warn(rc5t583->dev,
+                               "Error in writing reg 0x%02x error: %d\n",
+                               gpedge_add[i], ret);
+       }
+
+       ret = rc5t583_write(rc5t583->dev, RC5T583_INTC_INTEN, 0x0);
+       if (ret < 0)
+               dev_warn(rc5t583->dev,
+                       "Error in writing reg 0x%02x error: %d\n",
+                       RC5T583_INTC_INTEN, ret);
+
+       /* Clear all interrupts in case they woke up active. */
+       for (i = 0; i < RC5T583_MAX_INTERRUPT_MASK_REGS; i++)  {
+               ret = rc5t583_write(rc5t583->dev, irq_clr_add[i], 0);
+               if (ret < 0)
+                       dev_warn(rc5t583->dev,
+                               "Error in writing reg 0x%02x error: %d\n",
+                               irq_clr_add[i], ret);
+       }
+
+       rc5t583->irq_base = irq_base;
+       rc5t583->chip_irq = irq;
+
+       for (i = 0; i < RC5T583_MAX_IRQS; i++) {
+               int __irq = i + rc5t583->irq_base;
+               irq_set_chip_data(__irq, rc5t583);
+               irq_set_chip_and_handler(__irq, &rc5t583_irq_chip,
+                                        handle_simple_irq);
+               irq_set_nested_thread(__irq, 1);
+#ifdef CONFIG_ARM
+               set_irq_flags(__irq, IRQF_VALID);
+#endif
+       }
+
+       ret = request_threaded_irq(irq, NULL, rc5t583_irq, IRQF_ONESHOT,
+                               "rc5t583", rc5t583);
+       if (ret < 0)
+               dev_err(rc5t583->dev,
+                       "Error in registering interrupt error: %d\n", ret);
+       return ret;
+}
+
+int rc5t583_irq_exit(struct rc5t583 *rc5t583)
+{
+       if (rc5t583->chip_irq)
+               free_irq(rc5t583->chip_irq, rc5t583);
+       return 0;
+}
diff --git a/drivers/mfd/rc5t583.c b/drivers/mfd/rc5t583.c
new file mode 100644 (file)
index 0000000..99ef944
--- /dev/null
@@ -0,0 +1,386 @@
+/*
+ * Core driver access RC5T583 power management chip.
+ *
+ * Copyright (c) 2011-2012, NVIDIA CORPORATION.  All rights reserved.
+ * Author: Laxman dewangan <ldewangan@nvidia.com>
+ *
+ * Based on code
+ *     Copyright (C) 2011 RICOH COMPANY,LTD
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/rc5t583.h>
+#include <linux/regmap.h>
+
+#define RICOH_ONOFFSEL_REG     0x10
+#define RICOH_SWCTL_REG                0x5E
+
+struct deepsleep_control_data {
+       u8 reg_add;
+       u8 ds_pos_bit;
+};
+
+#define DEEPSLEEP_INIT(_id, _reg, _pos)                \
+       {                                       \
+               .reg_add = RC5T583_##_reg,      \
+               .ds_pos_bit = _pos,             \
+       }
+
+static struct deepsleep_control_data deepsleep_data[] = {
+       DEEPSLEEP_INIT(DC0, SLPSEQ1, 0),
+       DEEPSLEEP_INIT(DC1, SLPSEQ1, 4),
+       DEEPSLEEP_INIT(DC2, SLPSEQ2, 0),
+       DEEPSLEEP_INIT(DC3, SLPSEQ2, 4),
+       DEEPSLEEP_INIT(LDO0, SLPSEQ3, 0),
+       DEEPSLEEP_INIT(LDO1, SLPSEQ3, 4),
+       DEEPSLEEP_INIT(LDO2, SLPSEQ4, 0),
+       DEEPSLEEP_INIT(LDO3, SLPSEQ4, 4),
+       DEEPSLEEP_INIT(LDO4, SLPSEQ5, 0),
+       DEEPSLEEP_INIT(LDO5, SLPSEQ5, 4),
+       DEEPSLEEP_INIT(LDO6, SLPSEQ6, 0),
+       DEEPSLEEP_INIT(LDO7, SLPSEQ6, 4),
+       DEEPSLEEP_INIT(LDO8, SLPSEQ7, 0),
+       DEEPSLEEP_INIT(LDO9, SLPSEQ7, 4),
+       DEEPSLEEP_INIT(PSO0, SLPSEQ8, 0),
+       DEEPSLEEP_INIT(PSO1, SLPSEQ8, 4),
+       DEEPSLEEP_INIT(PSO2, SLPSEQ9, 0),
+       DEEPSLEEP_INIT(PSO3, SLPSEQ9, 4),
+       DEEPSLEEP_INIT(PSO4, SLPSEQ10, 0),
+       DEEPSLEEP_INIT(PSO5, SLPSEQ10, 4),
+       DEEPSLEEP_INIT(PSO6, SLPSEQ11, 0),
+       DEEPSLEEP_INIT(PSO7, SLPSEQ11, 4),
+};
+
+#define EXT_PWR_REQ            \
+       (RC5T583_EXT_PWRREQ1_CONTROL | RC5T583_EXT_PWRREQ2_CONTROL)
+
+static struct mfd_cell rc5t583_subdevs[] = {
+       {.name = "rc5t583-regulator",},
+       {.name = "rc5t583-rtc",      },
+       {.name = "rc5t583-key",      }
+};
+
+int rc5t583_write(struct device *dev, uint8_t reg, uint8_t val)
+{
+       struct rc5t583 *rc5t583 = dev_get_drvdata(dev);
+       return regmap_write(rc5t583->regmap, reg, val);
+}
+
+int rc5t583_read(struct device *dev, uint8_t reg, uint8_t *val)
+{
+       struct rc5t583 *rc5t583 = dev_get_drvdata(dev);
+       unsigned int ival;
+       int ret;
+       ret = regmap_read(rc5t583->regmap, reg, &ival);
+       if (!ret)
+               *val = (uint8_t)ival;
+       return ret;
+}
+
+int rc5t583_set_bits(struct device *dev, unsigned int reg,
+                       unsigned int bit_mask)
+{
+       struct rc5t583 *rc5t583 = dev_get_drvdata(dev);
+       return regmap_update_bits(rc5t583->regmap, reg, bit_mask, bit_mask);
+}
+
+int rc5t583_clear_bits(struct device *dev, unsigned int reg,
+                       unsigned int bit_mask)
+{
+       struct rc5t583 *rc5t583 = dev_get_drvdata(dev);
+       return regmap_update_bits(rc5t583->regmap, reg, bit_mask, 0);
+}
+
+int rc5t583_update(struct device *dev, unsigned int reg,
+               unsigned int val, unsigned int mask)
+{
+       struct rc5t583 *rc5t583 = dev_get_drvdata(dev);
+       return regmap_update_bits(rc5t583->regmap, reg, mask, val);
+}
+
+static int __rc5t583_set_ext_pwrreq1_control(struct device *dev,
+       int id, int ext_pwr, int slots)
+{
+       int ret;
+       uint8_t sleepseq_val;
+       unsigned int en_bit;
+       unsigned int slot_bit;
+
+       if (id == RC5T583_DS_DC0) {
+               dev_err(dev, "PWRREQ1 is invalid control for rail %d\n", id);
+               return -EINVAL;
+       }
+
+       en_bit = deepsleep_data[id].ds_pos_bit;
+       slot_bit = en_bit + 1;
+       ret = rc5t583_read(dev, deepsleep_data[id].reg_add, &sleepseq_val);
+       if (ret < 0) {
+               dev_err(dev, "Error in reading reg 0x%x\n",
+                               deepsleep_data[id].reg_add);
+               return ret;
+       }
+
+       sleepseq_val &= ~(0xF << en_bit);
+       sleepseq_val |= BIT(en_bit);
+       sleepseq_val |= ((slots & 0x7) << slot_bit);
+       ret = rc5t583_set_bits(dev, RICOH_ONOFFSEL_REG, BIT(1));
+       if (ret < 0) {
+               dev_err(dev, "Error in updating the 0x%02x register\n",
+                               RICOH_ONOFFSEL_REG);
+               return ret;
+       }
+
+       ret = rc5t583_write(dev, deepsleep_data[id].reg_add, sleepseq_val);
+       if (ret < 0) {
+               dev_err(dev, "Error in writing reg 0x%x\n",
+                               deepsleep_data[id].reg_add);
+               return ret;
+       }
+
+       if (id == RC5T583_DS_LDO4) {
+               ret = rc5t583_write(dev, RICOH_SWCTL_REG, 0x1);
+               if (ret < 0)
+                       dev_err(dev, "Error in writing reg 0x%x\n",
+                               RICOH_SWCTL_REG);
+       }
+       return ret;
+}
+
+static int __rc5t583_set_ext_pwrreq2_control(struct device *dev,
+       int id, int ext_pwr)
+{
+       int ret;
+
+       if (id != RC5T583_DS_DC0) {
+               dev_err(dev, "PWRREQ2 is invalid control for rail %d\n", id);
+               return -EINVAL;
+       }
+
+       ret = rc5t583_set_bits(dev, RICOH_ONOFFSEL_REG, BIT(2));
+       if (ret < 0)
+               dev_err(dev, "Error in updating the ONOFFSEL 0x10 register\n");
+       return ret;
+}
+
+int rc5t583_ext_power_req_config(struct device *dev, int ds_id,
+       int ext_pwr_req, int deepsleep_slot_nr)
+{
+       if ((ext_pwr_req & EXT_PWR_REQ) == EXT_PWR_REQ)
+               return -EINVAL;
+
+       if (ext_pwr_req & RC5T583_EXT_PWRREQ1_CONTROL)
+               return __rc5t583_set_ext_pwrreq1_control(dev, ds_id,
+                               ext_pwr_req, deepsleep_slot_nr);
+
+       if (ext_pwr_req & RC5T583_EXT_PWRREQ2_CONTROL)
+               return __rc5t583_set_ext_pwrreq2_control(dev,
+                       ds_id, ext_pwr_req);
+       return 0;
+}
+
+static int rc5t583_clear_ext_power_req(struct rc5t583 *rc5t583,
+       struct rc5t583_platform_data *pdata)
+{
+       int ret;
+       int i;
+       uint8_t on_off_val = 0;
+
+       /*  Clear ONOFFSEL register */
+       if (pdata->enable_shutdown)
+               on_off_val = 0x1;
+
+       ret = rc5t583_write(rc5t583->dev, RICOH_ONOFFSEL_REG, on_off_val);
+       if (ret < 0)
+               dev_warn(rc5t583->dev, "Error in writing reg %d error: %d\n",
+                                       RICOH_ONOFFSEL_REG, ret);
+
+       ret = rc5t583_write(rc5t583->dev, RICOH_SWCTL_REG, 0x0);
+       if (ret < 0)
+               dev_warn(rc5t583->dev, "Error in writing reg %d error: %d\n",
+                                       RICOH_SWCTL_REG, ret);
+
+       /* Clear sleep sequence register */
+       for (i = RC5T583_SLPSEQ1; i <= RC5T583_SLPSEQ11; ++i) {
+               ret = rc5t583_write(rc5t583->dev, i, 0x0);
+               if (ret < 0)
+                       dev_warn(rc5t583->dev,
+                               "Error in writing reg 0x%02x error: %d\n",
+                               i, ret);
+       }
+       return 0;
+}
+
+static bool volatile_reg(struct device *dev, unsigned int reg)
+{
+       /* Enable caching in interrupt registers */
+       switch (reg) {
+       case RC5T583_INT_EN_SYS1:
+       case RC5T583_INT_EN_SYS2:
+       case RC5T583_INT_EN_DCDC:
+       case RC5T583_INT_EN_RTC:
+       case RC5T583_INT_EN_ADC1:
+       case RC5T583_INT_EN_ADC2:
+       case RC5T583_INT_EN_ADC3:
+       case RC5T583_GPIO_GPEDGE1:
+       case RC5T583_GPIO_GPEDGE2:
+       case RC5T583_GPIO_EN_INT:
+               return false;
+
+       case RC5T583_GPIO_MON_IOIN:
+               /* This is gpio input register */
+               return true;
+
+       default:
+               /* Enable caching in gpio registers */
+               if ((reg >= RC5T583_GPIO_IOSEL) &&
+                               (reg <= RC5T583_GPIO_GPOFUNC))
+                       return false;
+
+               /* Enable caching in sleep seq registers */
+               if ((reg >= RC5T583_SLPSEQ1) && (reg <= RC5T583_SLPSEQ11))
+                       return false;
+
+               /* Enable caching of regulator registers */
+               if ((reg >= RC5T583_REG_DC0CTL) && (reg <= RC5T583_REG_SR3CTL))
+                       return false;
+               if ((reg >= RC5T583_REG_LDOEN1) &&
+                                       (reg <= RC5T583_REG_LDO9DAC_DS))
+                       return false;
+
+               break;
+       }
+
+       return true;
+}
+
+static const struct regmap_config rc5t583_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+       .volatile_reg = volatile_reg,
+       .max_register = RC5T583_MAX_REGS,
+       .num_reg_defaults_raw = RC5T583_MAX_REGS,
+       .cache_type = REGCACHE_RBTREE,
+};
+
+static int __devinit rc5t583_i2c_probe(struct i2c_client *i2c,
+                             const struct i2c_device_id *id)
+{
+       struct rc5t583 *rc5t583;
+       struct rc5t583_platform_data *pdata = i2c->dev.platform_data;
+       int ret;
+       bool irq_init_success = false;
+
+       if (!pdata) {
+               dev_err(&i2c->dev, "Err: Platform data not found\n");
+               return -EINVAL;
+       }
+
+       rc5t583 = devm_kzalloc(&i2c->dev, sizeof(struct rc5t583), GFP_KERNEL);
+       if (!rc5t583) {
+               dev_err(&i2c->dev, "Memory allocation failed\n");
+               return -ENOMEM;
+       }
+
+       rc5t583->dev = &i2c->dev;
+       i2c_set_clientdata(i2c, rc5t583);
+
+       rc5t583->regmap = regmap_init_i2c(i2c, &rc5t583_regmap_config);
+       if (IS_ERR(rc5t583->regmap)) {
+               ret = PTR_ERR(rc5t583->regmap);
+               dev_err(&i2c->dev, "regmap initialization failed: %d\n", ret);
+               return ret;
+       }
+
+       ret = rc5t583_clear_ext_power_req(rc5t583, pdata);
+       if (ret < 0)
+               goto err_irq_init;
+
+       if (i2c->irq) {
+               ret = rc5t583_irq_init(rc5t583, i2c->irq, pdata->irq_base);
+               /* Still continue with waring if irq init fails */
+               if (ret)
+                       dev_warn(&i2c->dev, "IRQ init failed: %d\n", ret);
+               else
+                       irq_init_success = true;
+       }
+
+       ret = mfd_add_devices(rc5t583->dev, -1, rc5t583_subdevs,
+                       ARRAY_SIZE(rc5t583_subdevs), NULL, 0);
+       if (ret) {
+               dev_err(&i2c->dev, "add mfd devices failed: %d\n", ret);
+               goto err_add_devs;
+       }
+
+       return 0;
+
+err_add_devs:
+       if (irq_init_success)
+               rc5t583_irq_exit(rc5t583);
+err_irq_init:
+       regmap_exit(rc5t583->regmap);
+       return ret;
+}
+
+static int  __devexit rc5t583_i2c_remove(struct i2c_client *i2c)
+{
+       struct rc5t583 *rc5t583 = i2c_get_clientdata(i2c);
+
+       mfd_remove_devices(rc5t583->dev);
+       rc5t583_irq_exit(rc5t583);
+       regmap_exit(rc5t583->regmap);
+       return 0;
+}
+
+static const struct i2c_device_id rc5t583_i2c_id[] = {
+       {.name = "rc5t583", .driver_data = 0},
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, rc5t583_i2c_id);
+
+static struct i2c_driver rc5t583_i2c_driver = {
+       .driver = {
+                  .name = "rc5t583",
+                  .owner = THIS_MODULE,
+                  },
+       .probe = rc5t583_i2c_probe,
+       .remove = __devexit_p(rc5t583_i2c_remove),
+       .id_table = rc5t583_i2c_id,
+};
+
+static int __init rc5t583_i2c_init(void)
+{
+       return i2c_add_driver(&rc5t583_i2c_driver);
+}
+subsys_initcall(rc5t583_i2c_init);
+
+static void __exit rc5t583_i2c_exit(void)
+{
+       i2c_del_driver(&rc5t583_i2c_driver);
+}
+
+module_exit(rc5t583_i2c_exit);
+
+MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
+MODULE_DESCRIPTION("RICOH RC5T583 power management system device driver");
+MODULE_LICENSE("GPL v2");
index caadabe..48949d9 100644 (file)
 #include <linux/mfd/s5m87xx/s5m-rtc.h>
 #include <linux/regmap.h>
 
-static struct mfd_cell s5m87xx_devs[] = {
+static struct mfd_cell s5m8751_devs[] = {
+       {
+               .name = "s5m8751-pmic",
+       }, {
+               .name = "s5m-charger",
+       }, {
+               .name = "s5m8751-codec",
+       },
+};
+
+static struct mfd_cell s5m8763_devs[] = {
+       {
+               .name = "s5m8763-pmic",
+       }, {
+               .name = "s5m-rtc",
+       }, {
+               .name = "s5m-charger",
+       },
+};
+
+static struct mfd_cell s5m8767_devs[] = {
        {
                .name = "s5m8767-pmic",
        }, {
@@ -42,7 +62,7 @@ EXPORT_SYMBOL_GPL(s5m_reg_read);
 
 int s5m_bulk_read(struct s5m87xx_dev *s5m87xx, u8 reg, int count, u8 *buf)
 {
-       return regmap_bulk_read(s5m87xx->regmap, reg, buf, count);;
+       return regmap_bulk_read(s5m87xx->regmap, reg, buf, count);
 }
 EXPORT_SYMBOL_GPL(s5m_bulk_read);
 
@@ -54,7 +74,7 @@ EXPORT_SYMBOL_GPL(s5m_reg_write);
 
 int s5m_bulk_write(struct s5m87xx_dev *s5m87xx, u8 reg, int count, u8 *buf)
 {
-       return regmap_raw_write(s5m87xx->regmap, reg, buf, count * sizeof(u16));
+       return regmap_raw_write(s5m87xx->regmap, reg, buf, count);
 }
 EXPORT_SYMBOL_GPL(s5m_bulk_write);
 
@@ -74,10 +94,10 @@ static int s5m87xx_i2c_probe(struct i2c_client *i2c,
 {
        struct s5m_platform_data *pdata = i2c->dev.platform_data;
        struct s5m87xx_dev *s5m87xx;
-       int ret = 0;
-       int error;
+       int ret;
 
-       s5m87xx = kzalloc(sizeof(struct s5m87xx_dev), GFP_KERNEL);
+       s5m87xx = devm_kzalloc(&i2c->dev, sizeof(struct s5m87xx_dev),
+                               GFP_KERNEL);
        if (s5m87xx == NULL)
                return -ENOMEM;
 
@@ -96,9 +116,9 @@ static int s5m87xx_i2c_probe(struct i2c_client *i2c,
 
        s5m87xx->regmap = regmap_init_i2c(i2c, &s5m_regmap_config);
        if (IS_ERR(s5m87xx->regmap)) {
-               error = PTR_ERR(s5m87xx->regmap);
+               ret = PTR_ERR(s5m87xx->regmap);
                dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
-                       error);
+                       ret);
                goto err;
        }
 
@@ -112,9 +132,23 @@ static int s5m87xx_i2c_probe(struct i2c_client *i2c,
 
        pm_runtime_set_active(s5m87xx->dev);
 
-       ret = mfd_add_devices(s5m87xx->dev, -1,
-                               s5m87xx_devs, ARRAY_SIZE(s5m87xx_devs),
-                               NULL, 0);
+       switch (s5m87xx->device_type) {
+       case S5M8751X:
+               ret = mfd_add_devices(s5m87xx->dev, -1, s5m8751_devs,
+                                       ARRAY_SIZE(s5m8751_devs), NULL, 0);
+               break;
+       case S5M8763X:
+               ret = mfd_add_devices(s5m87xx->dev, -1, s5m8763_devs,
+                                       ARRAY_SIZE(s5m8763_devs), NULL, 0);
+               break;
+       case S5M8767X:
+               ret = mfd_add_devices(s5m87xx->dev, -1, s5m8767_devs,
+                                       ARRAY_SIZE(s5m8767_devs), NULL, 0);
+               break;
+       default:
+               /* If this happens the probe function is problem */
+               BUG();
+       }
 
        if (ret < 0)
                goto err;
@@ -126,7 +160,6 @@ err:
        s5m_irq_exit(s5m87xx);
        i2c_unregister_device(s5m87xx->rtc);
        regmap_exit(s5m87xx->regmap);
-       kfree(s5m87xx);
        return ret;
 }
 
@@ -138,7 +171,6 @@ static int s5m87xx_i2c_remove(struct i2c_client *i2c)
        s5m_irq_exit(s5m87xx);
        i2c_unregister_device(s5m87xx->rtc);
        regmap_exit(s5m87xx->regmap);
-       kfree(s5m87xx);
        return 0;
 }
 
index de76dfb..0236676 100644 (file)
@@ -342,7 +342,10 @@ int s5m_irq_resume(struct s5m87xx_dev *s5m87xx)
                        s5m8767_irq_thread(s5m87xx->irq_base, s5m87xx);
                        break;
                default:
-                       break;
+                       dev_err(s5m87xx->dev,
+                               "Unknown device type %d\n",
+                               s5m87xx->device_type);
+                       return -EINVAL;
 
                }
        }
@@ -444,7 +447,9 @@ int s5m_irq_init(struct s5m87xx_dev *s5m87xx)
                }
                break;
        default:
-               break;
+               dev_err(s5m87xx->dev,
+                       "Unknown device type %d\n", s5m87xx->device_type);
+               return -EINVAL;
        }
 
        if (!s5m87xx->ono)
@@ -467,12 +472,15 @@ int s5m_irq_init(struct s5m87xx_dev *s5m87xx)
                                        IRQF_ONESHOT, "s5m87xx-ono", s5m87xx);
                break;
        default:
+               ret = -EINVAL;
                break;
        }
 
-       if (ret)
+       if (ret) {
                dev_err(s5m87xx->dev, "Failed to request IRQ %d: %d\n",
                        s5m87xx->ono, ret);
+               return ret;
+       }
 
        return 0;
 }
index f4d8611..d927dd4 100644 (file)
@@ -387,14 +387,6 @@ int sm501_unit_power(struct device *dev, unsigned int unit, unsigned int to)
 
 EXPORT_SYMBOL_GPL(sm501_unit_power);
 
-
-/* Perform a rounded division. */
-static long sm501fb_round_div(long num, long denom)
-{
-        /* n / d + 1 / 2 = (2n + d) / 2d */
-        return (2 * num + denom) / (2 * denom);
-}
-
 /* clock value structure. */
 struct sm501_clock {
        unsigned long mclk;
@@ -428,7 +420,7 @@ static int sm501_calc_clock(unsigned long freq,
                /* try all 8 shift values.*/
                for (shift = 0; shift < 8; shift++) {
                        /* Calculate difference to requested clock */
-                       diff = sm501fb_round_div(mclk, divider << shift) - freq;
+                       diff = DIV_ROUND_CLOSEST(mclk, divider << shift) - freq;
                        if (diff < 0)
                                diff = -diff;
 
index e07947e..2dd8d49 100644 (file)
@@ -298,6 +298,11 @@ static struct mfd_cell stmpe_gpio_cell = {
        .num_resources  = ARRAY_SIZE(stmpe_gpio_resources),
 };
 
+static struct mfd_cell stmpe_gpio_cell_noirq = {
+       .name           = "stmpe-gpio",
+       /* gpio cell resources consist of an irq only so no resources here */
+};
+
 /*
  * Keypad (1601, 2401, 2403)
  */
@@ -346,6 +351,13 @@ static struct stmpe_variant_block stmpe801_blocks[] = {
        },
 };
 
+static struct stmpe_variant_block stmpe801_blocks_noirq[] = {
+       {
+               .cell   = &stmpe_gpio_cell_noirq,
+               .block  = STMPE_BLOCK_GPIO,
+       },
+};
+
 static int stmpe801_enable(struct stmpe *stmpe, unsigned int blocks,
                           bool enable)
 {
@@ -367,6 +379,17 @@ static struct stmpe_variant_info stmpe801 = {
        .enable         = stmpe801_enable,
 };
 
+static struct stmpe_variant_info stmpe801_noirq = {
+       .name           = "stmpe801",
+       .id_val         = STMPE801_ID,
+       .id_mask        = 0xffff,
+       .num_gpios      = 8,
+       .regs           = stmpe801_regs,
+       .blocks         = stmpe801_blocks_noirq,
+       .num_blocks     = ARRAY_SIZE(stmpe801_blocks_noirq),
+       .enable         = stmpe801_enable,
+};
+
 /*
  * Touchscreen (STMPE811 or STMPE610)
  */
@@ -712,7 +735,7 @@ static struct stmpe_variant_info stmpe2403 = {
        .enable_autosleep       = stmpe1601_autosleep, /* same as stmpe1601 */
 };
 
-static struct stmpe_variant_info *stmpe_variant_info[] = {
+static struct stmpe_variant_info *stmpe_variant_info[STMPE_NBR_PARTS] = {
        [STMPE610]      = &stmpe610,
        [STMPE801]      = &stmpe801,
        [STMPE811]      = &stmpe811,
@@ -721,6 +744,16 @@ static struct stmpe_variant_info *stmpe_variant_info[] = {
        [STMPE2403]     = &stmpe2403,
 };
 
+/*
+ * These devices can be connected in a 'no-irq' configuration - the irq pin
+ * is not used and the device cannot interrupt the CPU. Here we only list
+ * devices which support this configuration - the driver will fail probing
+ * for any devices not listed here which are configured in this way.
+ */
+static struct stmpe_variant_info *stmpe_noirq_variant_info[STMPE_NBR_PARTS] = {
+       [STMPE801]      = &stmpe801_noirq,
+};
+
 static irqreturn_t stmpe_irq(int irq, void *data)
 {
        struct stmpe *stmpe = data;
@@ -864,7 +897,7 @@ static int __devinit stmpe_chip_init(struct stmpe *stmpe)
        unsigned int irq_trigger = stmpe->pdata->irq_trigger;
        int autosleep_timeout = stmpe->pdata->autosleep_timeout;
        struct stmpe_variant_info *variant = stmpe->variant;
-       u8 icr;
+       u8 icr = 0;
        unsigned int id;
        u8 data[2];
        int ret;
@@ -887,31 +920,33 @@ static int __devinit stmpe_chip_init(struct stmpe *stmpe)
        if (ret)
                return ret;
 
-       if (id == STMPE801_ID)
-               icr = STMPE801_REG_SYS_CTRL_INT_EN;
-       else
-               icr = STMPE_ICR_LSB_GIM;
-
-       /* STMPE801 doesn't support Edge interrupts */
-       if (id != STMPE801_ID) {
-               if (irq_trigger == IRQF_TRIGGER_FALLING ||
-                               irq_trigger == IRQF_TRIGGER_RISING)
-                       icr |= STMPE_ICR_LSB_EDGE;
-       }
-
-       if (irq_trigger == IRQF_TRIGGER_RISING ||
-                       irq_trigger == IRQF_TRIGGER_HIGH) {
+       if (stmpe->irq >= 0) {
                if (id == STMPE801_ID)
-                       icr |= STMPE801_REG_SYS_CTRL_INT_HI;
+                       icr = STMPE801_REG_SYS_CTRL_INT_EN;
                else
-                       icr |= STMPE_ICR_LSB_HIGH;
-       }
+                       icr = STMPE_ICR_LSB_GIM;
 
-       if (stmpe->pdata->irq_invert_polarity) {
-               if (id == STMPE801_ID)
-                       icr ^= STMPE801_REG_SYS_CTRL_INT_HI;
-               else
-                       icr ^= STMPE_ICR_LSB_HIGH;
+               /* STMPE801 doesn't support Edge interrupts */
+               if (id != STMPE801_ID) {
+                       if (irq_trigger == IRQF_TRIGGER_FALLING ||
+                                       irq_trigger == IRQF_TRIGGER_RISING)
+                               icr |= STMPE_ICR_LSB_EDGE;
+               }
+
+               if (irq_trigger == IRQF_TRIGGER_RISING ||
+                               irq_trigger == IRQF_TRIGGER_HIGH) {
+                       if (id == STMPE801_ID)
+                               icr |= STMPE801_REG_SYS_CTRL_INT_HI;
+                       else
+                               icr |= STMPE_ICR_LSB_HIGH;
+               }
+
+               if (stmpe->pdata->irq_invert_polarity) {
+                       if (id == STMPE801_ID)
+                               icr ^= STMPE801_REG_SYS_CTRL_INT_HI;
+                       else
+                               icr ^= STMPE_ICR_LSB_HIGH;
+               }
        }
 
        if (stmpe->pdata->autosleep) {
@@ -1001,19 +1036,38 @@ int __devinit stmpe_probe(struct stmpe_client_info *ci, int partnum)
                stmpe->irq = ci->irq;
        }
 
+       if (stmpe->irq < 0) {
+               /* use alternate variant info for no-irq mode, if supported */
+               dev_info(stmpe->dev,
+                       "%s configured in no-irq mode by platform data\n",
+                       stmpe->variant->name);
+               if (!stmpe_noirq_variant_info[stmpe->partnum]) {
+                       dev_err(stmpe->dev,
+                               "%s does not support no-irq mode!\n",
+                               stmpe->variant->name);
+                       ret = -ENODEV;
+                       goto free_gpio;
+               }
+               stmpe->variant = stmpe_noirq_variant_info[stmpe->partnum];
+       }
+
        ret = stmpe_chip_init(stmpe);
        if (ret)
                goto free_gpio;
 
-       ret = stmpe_irq_init(stmpe);
-       if (ret)
-               goto free_gpio;
+       if (stmpe->irq >= 0) {
+               ret = stmpe_irq_init(stmpe);
+               if (ret)
+                       goto free_gpio;
 
-       ret = request_threaded_irq(stmpe->irq, NULL, stmpe_irq,
-                       pdata->irq_trigger | IRQF_ONESHOT, "stmpe", stmpe);
-       if (ret) {
-               dev_err(stmpe->dev, "failed to request IRQ: %d\n", ret);
-               goto out_removeirq;
+               ret = request_threaded_irq(stmpe->irq, NULL, stmpe_irq,
+                               pdata->irq_trigger | IRQF_ONESHOT,
+                               "stmpe", stmpe);
+               if (ret) {
+                       dev_err(stmpe->dev, "failed to request IRQ: %d\n",
+                                       ret);
+                       goto out_removeirq;
+               }
        }
 
        ret = stmpe_devices_init(stmpe);
@@ -1026,9 +1080,11 @@ int __devinit stmpe_probe(struct stmpe_client_info *ci, int partnum)
 
 out_removedevs:
        mfd_remove_devices(stmpe->dev);
-       free_irq(stmpe->irq, stmpe);
+       if (stmpe->irq >= 0)
+               free_irq(stmpe->irq, stmpe);
 out_removeirq:
-       stmpe_irq_remove(stmpe);
+       if (stmpe->irq >= 0)
+               stmpe_irq_remove(stmpe);
 free_gpio:
        if (pdata->irq_over_gpio)
                gpio_free(pdata->irq_gpio);
@@ -1041,8 +1097,10 @@ int stmpe_remove(struct stmpe *stmpe)
 {
        mfd_remove_devices(stmpe->dev);
 
-       free_irq(stmpe->irq, stmpe);
-       stmpe_irq_remove(stmpe);
+       if (stmpe->irq >= 0) {
+               free_irq(stmpe->irq, stmpe);
+               stmpe_irq_remove(stmpe);
+       }
 
        if (stmpe->pdata->irq_over_gpio)
                gpio_free(stmpe->pdata->irq_gpio);
@@ -1057,7 +1115,7 @@ static int stmpe_suspend(struct device *dev)
 {
        struct stmpe *stmpe = dev_get_drvdata(dev);
 
-       if (device_may_wakeup(dev))
+       if (stmpe->irq >= 0 && device_may_wakeup(dev))
                enable_irq_wake(stmpe->irq);
 
        return 0;
@@ -1067,7 +1125,7 @@ static int stmpe_resume(struct device *dev)
 {
        struct stmpe *stmpe = dev_get_drvdata(dev);
 
-       if (device_may_wakeup(dev))
+       if (stmpe->irq >= 0 && device_may_wakeup(dev))
                disable_irq_wake(stmpe->irq);
 
        return 0;
diff --git a/drivers/mfd/tps65090.c b/drivers/mfd/tps65090.c
new file mode 100644 (file)
index 0000000..a66d4df
--- /dev/null
@@ -0,0 +1,387 @@
+/*
+ * Core driver for TI TPS65090 PMIC family
+ *
+ * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
+
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/tps65090.h>
+#include <linux/regmap.h>
+#include <linux/err.h>
+
+#define NUM_INT_REG 2
+#define TOTAL_NUM_REG 0x18
+
+/* interrupt status registers */
+#define TPS65090_INT_STS       0x0
+#define TPS65090_INT_STS2      0x1
+
+/* interrupt mask registers */
+#define TPS65090_INT_MSK       0x2
+#define TPS65090_INT_MSK2      0x3
+
+struct tps65090_irq_data {
+       u8              mask_reg;
+       u8              mask_pos;
+};
+
+#define TPS65090_IRQ(_reg, _mask_pos)          \
+       {                                       \
+               .mask_reg       = (_reg),       \
+               .mask_pos       = (_mask_pos),  \
+       }
+
+static const struct tps65090_irq_data tps65090_irqs[] = {
+       [0]             = TPS65090_IRQ(0, 0),
+       [1]             = TPS65090_IRQ(0, 1),
+       [2]             = TPS65090_IRQ(0, 2),
+       [3]             = TPS65090_IRQ(0, 3),
+       [4]             = TPS65090_IRQ(0, 4),
+       [5]             = TPS65090_IRQ(0, 5),
+       [6]             = TPS65090_IRQ(0, 6),
+       [7]             = TPS65090_IRQ(0, 7),
+       [8]             = TPS65090_IRQ(1, 0),
+       [9]             = TPS65090_IRQ(1, 1),
+       [10]            = TPS65090_IRQ(1, 2),
+       [11]            = TPS65090_IRQ(1, 3),
+       [12]            = TPS65090_IRQ(1, 4),
+       [13]            = TPS65090_IRQ(1, 5),
+       [14]            = TPS65090_IRQ(1, 6),
+       [15]            = TPS65090_IRQ(1, 7),
+};
+
+static struct mfd_cell tps65090s[] = {
+       {
+               .name = "tps65910-pmic",
+       },
+       {
+               .name = "tps65910-regulator",
+       },
+};
+
+struct tps65090 {
+       struct mutex            lock;
+       struct device           *dev;
+       struct i2c_client       *client;
+       struct regmap           *rmap;
+       struct irq_chip         irq_chip;
+       struct mutex            irq_lock;
+       int                     irq_base;
+       unsigned int            id;
+};
+
+int tps65090_write(struct device *dev, int reg, uint8_t val)
+{
+       struct tps65090 *tps = dev_get_drvdata(dev);
+       return regmap_write(tps->rmap, reg, val);
+}
+EXPORT_SYMBOL_GPL(tps65090_write);
+
+int tps65090_read(struct device *dev, int reg, uint8_t *val)
+{
+       struct tps65090 *tps = dev_get_drvdata(dev);
+       unsigned int temp_val;
+       int ret;
+       ret = regmap_read(tps->rmap, reg, &temp_val);
+       if (!ret)
+               *val = temp_val;
+       return ret;
+}
+EXPORT_SYMBOL_GPL(tps65090_read);
+
+int tps65090_set_bits(struct device *dev, int reg, uint8_t bit_num)
+{
+       struct tps65090 *tps = dev_get_drvdata(dev);
+       return regmap_update_bits(tps->rmap, reg, BIT(bit_num), ~0u);
+}
+EXPORT_SYMBOL_GPL(tps65090_set_bits);
+
+int tps65090_clr_bits(struct device *dev, int reg, uint8_t bit_num)
+{
+       struct tps65090 *tps = dev_get_drvdata(dev);
+       return regmap_update_bits(tps->rmap, reg, BIT(bit_num), 0u);
+}
+EXPORT_SYMBOL_GPL(tps65090_clr_bits);
+
+static void tps65090_irq_lock(struct irq_data *data)
+{
+       struct tps65090 *tps65090 = irq_data_get_irq_chip_data(data);
+
+       mutex_lock(&tps65090->irq_lock);
+}
+
+static void tps65090_irq_mask(struct irq_data *irq_data)
+{
+       struct tps65090 *tps65090 = irq_data_get_irq_chip_data(irq_data);
+       unsigned int __irq = irq_data->hwirq;
+       const struct tps65090_irq_data *data = &tps65090_irqs[__irq];
+
+       tps65090_set_bits(tps65090->dev, (TPS65090_INT_MSK + data->mask_reg),
+               data->mask_pos);
+}
+
+static void tps65090_irq_unmask(struct irq_data *irq_data)
+{
+       struct tps65090 *tps65090 = irq_data_get_irq_chip_data(irq_data);
+       unsigned int __irq = irq_data->irq - tps65090->irq_base;
+       const struct tps65090_irq_data *data = &tps65090_irqs[__irq];
+
+       tps65090_clr_bits(tps65090->dev, (TPS65090_INT_MSK + data->mask_reg),
+               data->mask_pos);
+}
+
+static void tps65090_irq_sync_unlock(struct irq_data *data)
+{
+       struct tps65090 *tps65090 = irq_data_get_irq_chip_data(data);
+
+       mutex_unlock(&tps65090->irq_lock);
+}
+
+static irqreturn_t tps65090_irq(int irq, void *data)
+{
+       struct tps65090 *tps65090 = data;
+       int ret = 0;
+       u8 status, mask;
+       unsigned long int acks = 0;
+       int i;
+
+       for (i = 0; i < NUM_INT_REG; i++) {
+               ret = tps65090_read(tps65090->dev, TPS65090_INT_MSK + i, &mask);
+               if (ret < 0) {
+                       dev_err(tps65090->dev,
+                               "failed to read mask reg [addr:%d]\n",
+                               TPS65090_INT_MSK + i);
+                       return IRQ_NONE;
+               }
+               ret = tps65090_read(tps65090->dev, TPS65090_INT_STS + i,
+                       &status);
+               if (ret < 0) {
+                       dev_err(tps65090->dev,
+                               "failed to read status reg [addr:%d]\n",
+                                TPS65090_INT_STS + i);
+                       return IRQ_NONE;
+               }
+               if (status) {
+                       /* Ack only those interrupts which are not masked */
+                       status &= (~mask);
+                       ret = tps65090_write(tps65090->dev,
+                                       TPS65090_INT_STS + i, status);
+                       if (ret < 0) {
+                               dev_err(tps65090->dev,
+                                       "failed to write interrupt status\n");
+                               return IRQ_NONE;
+                       }
+                       acks |= (status << (i * 8));
+               }
+       }
+
+       for_each_set_bit(i, &acks, ARRAY_SIZE(tps65090_irqs))
+               handle_nested_irq(tps65090->irq_base + i);
+       return acks ? IRQ_HANDLED : IRQ_NONE;
+}
+
+static int __devinit tps65090_irq_init(struct tps65090 *tps65090, int irq,
+       int irq_base)
+{
+       int i, ret;
+
+       if (!irq_base) {
+               dev_err(tps65090->dev, "IRQ base not set\n");
+               return -EINVAL;
+       }
+
+       mutex_init(&tps65090->irq_lock);
+
+       for (i = 0; i < NUM_INT_REG; i++)
+               tps65090_write(tps65090->dev, TPS65090_INT_MSK + i, 0xFF);
+
+       for (i = 0; i < NUM_INT_REG; i++)
+               tps65090_write(tps65090->dev, TPS65090_INT_STS + i, 0xff);
+
+       tps65090->irq_base = irq_base;
+       tps65090->irq_chip.name = "tps65090";
+       tps65090->irq_chip.irq_mask = tps65090_irq_mask;
+       tps65090->irq_chip.irq_unmask = tps65090_irq_unmask;
+       tps65090->irq_chip.irq_bus_lock = tps65090_irq_lock;
+       tps65090->irq_chip.irq_bus_sync_unlock = tps65090_irq_sync_unlock;
+
+       for (i = 0; i < ARRAY_SIZE(tps65090_irqs); i++) {
+               int __irq = i + tps65090->irq_base;
+               irq_set_chip_data(__irq, tps65090);
+               irq_set_chip_and_handler(__irq, &tps65090->irq_chip,
+                                        handle_simple_irq);
+               irq_set_nested_thread(__irq, 1);
+#ifdef CONFIG_ARM
+               set_irq_flags(__irq, IRQF_VALID);
+#endif
+       }
+
+       ret = request_threaded_irq(irq, NULL, tps65090_irq, IRQF_ONESHOT,
+                               "tps65090", tps65090);
+       if (!ret) {
+               device_init_wakeup(tps65090->dev, 1);
+               enable_irq_wake(irq);
+       }
+
+       return ret;
+}
+
+static bool is_volatile_reg(struct device *dev, unsigned int reg)
+{
+       if ((reg == TPS65090_INT_STS) || (reg == TPS65090_INT_STS))
+               return true;
+       else
+               return false;
+}
+
+static const struct regmap_config tps65090_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+       .max_register = TOTAL_NUM_REG,
+       .num_reg_defaults_raw = TOTAL_NUM_REG,
+       .cache_type = REGCACHE_RBTREE,
+       .volatile_reg = is_volatile_reg,
+};
+
+static int __devinit tps65090_i2c_probe(struct i2c_client *client,
+                                       const struct i2c_device_id *id)
+{
+       struct tps65090_platform_data *pdata = client->dev.platform_data;
+       struct tps65090 *tps65090;
+       int ret;
+
+       if (!pdata) {
+               dev_err(&client->dev, "tps65090 requires platform data\n");
+               return -EINVAL;
+       }
+
+       tps65090 = devm_kzalloc(&client->dev, sizeof(struct tps65090),
+               GFP_KERNEL);
+       if (tps65090 == NULL)
+               return -ENOMEM;
+
+       tps65090->client = client;
+       tps65090->dev = &client->dev;
+       i2c_set_clientdata(client, tps65090);
+
+       mutex_init(&tps65090->lock);
+
+       if (client->irq) {
+               ret = tps65090_irq_init(tps65090, client->irq, pdata->irq_base);
+               if (ret) {
+                       dev_err(&client->dev, "IRQ init failed with err: %d\n",
+                               ret);
+                       goto err_exit;
+               }
+       }
+
+       tps65090->rmap = regmap_init_i2c(tps65090->client,
+               &tps65090_regmap_config);
+       if (IS_ERR(tps65090->rmap)) {
+               dev_err(&client->dev, "regmap_init failed with err: %ld\n",
+                       PTR_ERR(tps65090->rmap));
+               goto err_irq_exit;
+       };
+
+       ret = mfd_add_devices(tps65090->dev, -1, tps65090s,
+               ARRAY_SIZE(tps65090s), NULL, 0);
+       if (ret) {
+               dev_err(&client->dev, "add mfd devices failed with err: %d\n",
+                       ret);
+               goto err_regmap_exit;
+       }
+
+       return 0;
+
+err_regmap_exit:
+       regmap_exit(tps65090->rmap);
+
+err_irq_exit:
+       if (client->irq)
+               free_irq(client->irq, tps65090);
+err_exit:
+       return ret;
+}
+
+static int __devexit tps65090_i2c_remove(struct i2c_client *client)
+{
+       struct tps65090 *tps65090 = i2c_get_clientdata(client);
+
+       mfd_remove_devices(tps65090->dev);
+       regmap_exit(tps65090->rmap);
+       if (client->irq)
+               free_irq(client->irq, tps65090);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int tps65090_i2c_suspend(struct i2c_client *client, pm_message_t state)
+{
+       if (client->irq)
+               disable_irq(client->irq);
+       return 0;
+}
+
+static int tps65090_i2c_resume(struct i2c_client *client)
+{
+       if (client->irq)
+               enable_irq(client->irq);
+       return 0;
+}
+#endif
+
+static const struct i2c_device_id tps65090_id_table[] = {
+       { "tps65090", 0 },
+       { },
+};
+MODULE_DEVICE_TABLE(i2c, tps65090_id_table);
+
+static struct i2c_driver tps65090_driver = {
+       .driver = {
+               .name   = "tps65090",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = tps65090_i2c_probe,
+       .remove         = __devexit_p(tps65090_i2c_remove),
+#ifdef CONFIG_PM
+       .suspend        = tps65090_i2c_suspend,
+       .resume         = tps65090_i2c_resume,
+#endif
+       .id_table       = tps65090_id_table,
+};
+
+static int __init tps65090_init(void)
+{
+       return i2c_add_driver(&tps65090_driver);
+}
+subsys_initcall(tps65090_init);
+
+static void __exit tps65090_exit(void)
+{
+       i2c_del_driver(&tps65090_driver);
+}
+module_exit(tps65090_exit);
+
+MODULE_DESCRIPTION("TPS65090 core driver");
+MODULE_AUTHOR("Venu Byravarasu <vbyravarasu@nvidia.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mfd/tps65217.c b/drivers/mfd/tps65217.c
new file mode 100644 (file)
index 0000000..f7d854e
--- /dev/null
@@ -0,0 +1,242 @@
+/*
+ * tps65217.c
+ *
+ * TPS65217 chip family multi-function driver
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/regmap.h>
+#include <linux/err.h>
+
+#include <linux/mfd/core.h>
+#include <linux/mfd/tps65217.h>
+
+/**
+ * tps65217_reg_read: Read a single tps65217 register.
+ *
+ * @tps: Device to read from.
+ * @reg: Register to read.
+ * @val: Contians the value
+ */
+int tps65217_reg_read(struct tps65217 *tps, unsigned int reg,
+                       unsigned int *val)
+{
+       return regmap_read(tps->regmap, reg, val);
+}
+EXPORT_SYMBOL_GPL(tps65217_reg_read);
+
+/**
+ * tps65217_reg_write: Write a single tps65217 register.
+ *
+ * @tps65217: Device to write to.
+ * @reg: Register to write to.
+ * @val: Value to write.
+ * @level: Password protected level
+ */
+int tps65217_reg_write(struct tps65217 *tps, unsigned int reg,
+                       unsigned int val, unsigned int level)
+{
+       int ret;
+       unsigned int xor_reg_val;
+
+       switch (level) {
+       case TPS65217_PROTECT_NONE:
+               return regmap_write(tps->regmap, reg, val);
+       case TPS65217_PROTECT_L1:
+               xor_reg_val = reg ^ TPS65217_PASSWORD_REGS_UNLOCK;
+               ret = regmap_write(tps->regmap, TPS65217_REG_PASSWORD,
+                                                       xor_reg_val);
+               if (ret < 0)
+                       return ret;
+
+               return regmap_write(tps->regmap, reg, val);
+       case TPS65217_PROTECT_L2:
+               xor_reg_val = reg ^ TPS65217_PASSWORD_REGS_UNLOCK;
+               ret = regmap_write(tps->regmap, TPS65217_REG_PASSWORD,
+                                                       xor_reg_val);
+               if (ret < 0)
+                       return ret;
+               ret = regmap_write(tps->regmap, reg, val);
+               if (ret < 0)
+                       return ret;
+               ret = regmap_write(tps->regmap, TPS65217_REG_PASSWORD,
+                                                       xor_reg_val);
+               if (ret < 0)
+                       return ret;
+               return regmap_write(tps->regmap, reg, val);
+       default:
+               return -EINVAL;
+       }
+}
+EXPORT_SYMBOL_GPL(tps65217_reg_write);
+
+/**
+ * tps65217_update_bits: Modify bits w.r.t mask, val and level.
+ *
+ * @tps65217: Device to write to.
+ * @reg: Register to read-write to.
+ * @mask: Mask.
+ * @val: Value to write.
+ * @level: Password protected level
+ */
+int tps65217_update_bits(struct tps65217 *tps, unsigned int reg,
+               unsigned int mask, unsigned int val, unsigned int level)
+{
+       int ret;
+       unsigned int data;
+
+       ret = tps65217_reg_read(tps, reg, &data);
+       if (ret) {
+               dev_err(tps->dev, "Read from reg 0x%x failed\n", reg);
+               return ret;
+       }
+
+       data &= ~mask;
+       data |= val & mask;
+
+       ret = tps65217_reg_write(tps, reg, data, level);
+       if (ret)
+               dev_err(tps->dev, "Write for reg 0x%x failed\n", reg);
+
+       return ret;
+}
+
+int tps65217_set_bits(struct tps65217 *tps, unsigned int reg,
+               unsigned int mask, unsigned int val, unsigned int level)
+{
+       return tps65217_update_bits(tps, reg, mask, val, level);
+}
+EXPORT_SYMBOL_GPL(tps65217_set_bits);
+
+int tps65217_clear_bits(struct tps65217 *tps, unsigned int reg,
+               unsigned int mask, unsigned int level)
+{
+       return tps65217_update_bits(tps, reg, mask, 0, level);
+}
+EXPORT_SYMBOL_GPL(tps65217_clear_bits);
+
+static struct regmap_config tps65217_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+};
+
+static int __devinit tps65217_probe(struct i2c_client *client,
+                               const struct i2c_device_id *ids)
+{
+       struct tps65217 *tps;
+       struct tps65217_board *pdata = client->dev.platform_data;
+       int i, ret;
+       unsigned int version;
+
+       tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
+       if (!tps)
+               return -ENOMEM;
+
+       tps->pdata = pdata;
+       tps->regmap = regmap_init_i2c(client, &tps65217_regmap_config);
+       if (IS_ERR(tps->regmap)) {
+               ret = PTR_ERR(tps->regmap);
+               dev_err(tps->dev, "Failed to allocate register map: %d\n",
+                       ret);
+               return ret;
+       }
+
+       i2c_set_clientdata(client, tps);
+       tps->dev = &client->dev;
+
+       ret = tps65217_reg_read(tps, TPS65217_REG_CHIPID, &version);
+       if (ret < 0) {
+               dev_err(tps->dev, "Failed to read revision"
+                                       " register: %d\n", ret);
+               goto err_regmap;
+       }
+
+       dev_info(tps->dev, "TPS65217 ID %#x version 1.%d\n",
+                       (version & TPS65217_CHIPID_CHIP_MASK) >> 4,
+                       version & TPS65217_CHIPID_REV_MASK);
+
+       for (i = 0; i < TPS65217_NUM_REGULATOR; i++) {
+               struct platform_device *pdev;
+
+               pdev = platform_device_alloc("tps65217-pmic", i);
+               if (!pdev) {
+                       dev_err(tps->dev, "Cannot create regulator %d\n", i);
+                       continue;
+               }
+
+               pdev->dev.parent = tps->dev;
+               platform_device_add_data(pdev, &pdata->tps65217_init_data[i],
+                                       sizeof(pdata->tps65217_init_data[i]));
+               tps->regulator_pdev[i] = pdev;
+
+               platform_device_add(pdev);
+       }
+
+       return 0;
+
+err_regmap:
+       regmap_exit(tps->regmap);
+
+       return ret;
+}
+
+static int __devexit tps65217_remove(struct i2c_client *client)
+{
+       struct tps65217 *tps = i2c_get_clientdata(client);
+       int i;
+
+       for (i = 0; i < TPS65217_NUM_REGULATOR; i++)
+               platform_device_unregister(tps->regulator_pdev[i]);
+
+       regmap_exit(tps->regmap);
+
+       return 0;
+}
+
+static const struct i2c_device_id tps65217_id_table[] = {
+       {"tps65217", 0xF0},
+       {/* end of list */}
+};
+MODULE_DEVICE_TABLE(i2c, tps65217_id_table);
+
+static struct i2c_driver tps65217_driver = {
+       .driver         = {
+               .name   = "tps65217",
+       },
+       .id_table       = tps65217_id_table,
+       .probe          = tps65217_probe,
+       .remove         = __devexit_p(tps65217_remove),
+};
+
+static int __init tps65217_init(void)
+{
+       return i2c_add_driver(&tps65217_driver);
+}
+subsys_initcall(tps65217_init);
+
+static void __exit tps65217_exit(void)
+{
+       i2c_del_driver(&tps65217_driver);
+}
+module_exit(tps65217_exit);
+
+MODULE_AUTHOR("AnilKumar Ch <anilkumar@ti.com>");
+MODULE_DESCRIPTION("TPS65217 chip family multi-function driver");
+MODULE_LICENSE("GPL v2");
index 95c0d79..c9ed5c0 100644 (file)
@@ -145,12 +145,23 @@ static void tps65910_irq_disable(struct irq_data *data)
        tps65910->irq_mask |= ( 1 << irq_to_tps65910_irq(tps65910, data->irq));
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int tps65910_irq_set_wake(struct irq_data *data, unsigned int enable)
+{
+       struct tps65910 *tps65910 = irq_data_get_irq_chip_data(data);
+       return irq_set_irq_wake(tps65910->chip_irq, enable);
+}
+#else
+#define tps65910_irq_set_wake NULL
+#endif
+
 static struct irq_chip tps65910_irq_chip = {
        .name = "tps65910",
        .irq_bus_lock = tps65910_irq_lock,
        .irq_bus_sync_unlock = tps65910_irq_sync_unlock,
        .irq_disable = tps65910_irq_disable,
        .irq_enable = tps65910_irq_enable,
+       .irq_set_wake = tps65910_irq_set_wake,
 };
 
 int tps65910_irq_init(struct tps65910 *tps65910, int irq,
index 4392f6b..bf2b25e 100644 (file)
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
+#include <linux/err.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
 #include <linux/gpio.h>
 #include <linux/mfd/core.h>
+#include <linux/regmap.h>
 #include <linux/mfd/tps65910.h>
 
 static struct mfd_cell tps65910s[] = {
@@ -38,99 +40,56 @@ static struct mfd_cell tps65910s[] = {
 static int tps65910_i2c_read(struct tps65910 *tps65910, u8 reg,
                                  int bytes, void *dest)
 {
-       struct i2c_client *i2c = tps65910->i2c_client;
-       struct i2c_msg xfer[2];
-       int ret;
-
-       /* Write register */
-       xfer[0].addr = i2c->addr;
-       xfer[0].flags = 0;
-       xfer[0].len = 1;
-       xfer[0].buf = &reg;
-
-       /* Read data */
-       xfer[1].addr = i2c->addr;
-       xfer[1].flags = I2C_M_RD;
-       xfer[1].len = bytes;
-       xfer[1].buf = dest;
-
-       ret = i2c_transfer(i2c->adapter, xfer, 2);
-       if (ret == 2)
-               ret = 0;
-       else if (ret >= 0)
-               ret = -EIO;
-
-       return ret;
+       return regmap_bulk_read(tps65910->regmap, reg, dest, bytes);
 }
 
 static int tps65910_i2c_write(struct tps65910 *tps65910, u8 reg,
-                                  int bytes, void *src)
+                                 int bytes, void *src)
 {
-       struct i2c_client *i2c = tps65910->i2c_client;
-       /* we add 1 byte for device register */
-       u8 msg[TPS65910_MAX_REGISTER + 1];
-       int ret;
-
-       if (bytes > TPS65910_MAX_REGISTER)
-               return -EINVAL;
-
-       msg[0] = reg;
-       memcpy(&msg[1], src, bytes);
-
-       ret = i2c_master_send(i2c, msg, bytes + 1);
-       if (ret < 0)
-               return ret;
-       if (ret != bytes + 1)
-               return -EIO;
-       return 0;
+       return regmap_bulk_write(tps65910->regmap, reg, src, bytes);
 }
 
 int tps65910_set_bits(struct tps65910 *tps65910, u8 reg, u8 mask)
 {
-       u8 data;
-       int err;
-
-       mutex_lock(&tps65910->io_mutex);
-       err = tps65910_i2c_read(tps65910, reg, 1, &data);
-       if (err) {
-               dev_err(tps65910->dev, "read from reg %x failed\n", reg);
-               goto out;
-       }
-
-       data |= mask;
-       err = tps65910_i2c_write(tps65910, reg, 1, &data);
-       if (err)
-               dev_err(tps65910->dev, "write to reg %x failed\n", reg);
-
-out:
-       mutex_unlock(&tps65910->io_mutex);
-       return err;
+       return regmap_update_bits(tps65910->regmap, reg, mask, mask);
 }
 EXPORT_SYMBOL_GPL(tps65910_set_bits);
 
 int tps65910_clear_bits(struct tps65910 *tps65910, u8 reg, u8 mask)
 {
-       u8 data;
-       int err;
-
-       mutex_lock(&tps65910->io_mutex);
-       err = tps65910_i2c_read(tps65910, reg, 1, &data);
-       if (err) {
-               dev_err(tps65910->dev, "read from reg %x failed\n", reg);
-               goto out;
-       }
-
-       data &= ~mask;
-       err = tps65910_i2c_write(tps65910, reg, 1, &data);
-       if (err)
-               dev_err(tps65910->dev, "write to reg %x failed\n", reg);
-
-out:
-       mutex_unlock(&tps65910->io_mutex);
-       return err;
+       return regmap_update_bits(tps65910->regmap, reg, mask, 0);
 }
 EXPORT_SYMBOL_GPL(tps65910_clear_bits);
 
+static bool is_volatile_reg(struct device *dev, unsigned int reg)
+{
+       struct tps65910 *tps65910 = dev_get_drvdata(dev);
+
+       /*
+        * Caching all regulator registers.
+        * All regualator register address range is same for
+        * TPS65910 and TPS65911
+        */
+       if ((reg >= TPS65910_VIO) && (reg <= TPS65910_VDAC)) {
+               /* Check for non-existing register */
+               if (tps65910_chip_id(tps65910) == TPS65910)
+                       if ((reg == TPS65911_VDDCTRL_OP) ||
+                               (reg == TPS65911_VDDCTRL_SR))
+                               return true;
+               return false;
+       }
+       return true;
+}
+
+static const struct regmap_config tps65910_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+       .volatile_reg = is_volatile_reg,
+       .max_register = TPS65910_MAX_REGISTER,
+       .num_reg_defaults_raw = TPS65910_MAX_REGISTER,
+       .cache_type = REGCACHE_RBTREE,
+};
+
 static int tps65910_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
@@ -161,6 +120,13 @@ static int tps65910_i2c_probe(struct i2c_client *i2c,
        tps65910->write = tps65910_i2c_write;
        mutex_init(&tps65910->io_mutex);
 
+       tps65910->regmap = regmap_init_i2c(i2c, &tps65910_regmap_config);
+       if (IS_ERR(tps65910->regmap)) {
+               ret = PTR_ERR(tps65910->regmap);
+               dev_err(&i2c->dev, "regmap initialization failed: %d\n", ret);
+               goto regmap_err;
+       }
+
        ret = mfd_add_devices(tps65910->dev, -1,
                              tps65910s, ARRAY_SIZE(tps65910s),
                              NULL, 0);
@@ -178,6 +144,8 @@ static int tps65910_i2c_probe(struct i2c_client *i2c,
        return ret;
 
 err:
+       regmap_exit(tps65910->regmap);
+regmap_err:
        kfree(tps65910);
        kfree(init_data);
        return ret;
@@ -189,6 +157,7 @@ static int tps65910_i2c_remove(struct i2c_client *i2c)
 
        tps65910_irq_exit(tps65910);
        mfd_remove_devices(tps65910->dev);
+       regmap_exit(tps65910->regmap);
        kfree(tps65910);
 
        return 0;
index 806680d..7c2267e 100644 (file)
@@ -46,9 +46,7 @@
 #include <linux/i2c.h>
 #include <linux/i2c/twl.h>
 
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
-#include <plat/cpu.h>
-#endif
+#include "twl-core.h"
 
 /*
  * The TWL4030 "Triton 2" is one of a family of a multi-function "Power
 #define twl_has_watchdog()        false
 #endif
 
-#if defined(CONFIG_MFD_TWL4030_AUDIO) || defined(CONFIG_MFD_TWL4030_AUDIO_MODULE) ||\
-       defined(CONFIG_TWL6040_CORE) || defined(CONFIG_TWL6040_CORE_MODULE)
+#if defined(CONFIG_MFD_TWL4030_AUDIO) || \
+       defined(CONFIG_MFD_TWL4030_AUDIO_MODULE)
 #define twl_has_codec()        true
 #else
 #define twl_has_codec()        false
 #define SUB_CHIP_ID1 1
 #define SUB_CHIP_ID2 2
 #define SUB_CHIP_ID3 3
+#define SUB_CHIP_ID_INVAL 0xff
 
 #define TWL_MODULE_LAST TWL4030_MODULE_LAST
 
-#define TWL4030_NR_IRQS    34 /* core:8, power:8, gpio: 18 */
-#define TWL6030_NR_IRQS    20
-
 /* Base Address defns for twl4030_map[] */
 
 /* subchip/slave 0 - USB ID */
@@ -314,7 +310,7 @@ static struct twl_mapping twl6030_map[] = {
         * so they continue to match the order in this table.
         */
        { SUB_CHIP_ID1, TWL6030_BASEADD_USB },
-       { SUB_CHIP_ID3, TWL6030_BASEADD_AUDIO },
+       { SUB_CHIP_ID_INVAL, TWL6030_BASEADD_AUDIO },
        { SUB_CHIP_ID2, TWL6030_BASEADD_DIEID },
        { SUB_CHIP_ID2, TWL6030_BASEADD_RSV },
        { SUB_CHIP_ID1, TWL6030_BASEADD_PIH },
@@ -376,6 +372,11 @@ int twl_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
                return -EPERM;
        }
        sid = twl_map[mod_no].sid;
+       if (unlikely(sid == SUB_CHIP_ID_INVAL)) {
+               pr_err("%s: module %d is not part of the pmic\n",
+                      DRIVER_NAME, mod_no);
+               return -EINVAL;
+       }
        twl = &twl_modules[sid];
 
        mutex_lock(&twl->xfer_lock);
@@ -433,6 +434,11 @@ int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
                return -EPERM;
        }
        sid = twl_map[mod_no].sid;
+       if (unlikely(sid == SUB_CHIP_ID_INVAL)) {
+               pr_err("%s: module %d is not part of the pmic\n",
+                      DRIVER_NAME, mod_no);
+               return -EINVAL;
+       }
        twl = &twl_modules[sid];
 
        mutex_lock(&twl->xfer_lock);
@@ -663,7 +669,8 @@ add_regulator(int num, struct regulator_init_data *pdata,
  */
 
 static int
-add_children(struct twl4030_platform_data *pdata, unsigned long features)
+add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
+               unsigned long features)
 {
        struct device   *child;
        unsigned sub_chip_id;
@@ -671,7 +678,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
        if (twl_has_gpio() && pdata->gpio) {
                child = add_child(SUB_CHIP_ID1, "twl4030_gpio",
                                pdata->gpio, sizeof(*pdata->gpio),
-                               false, pdata->irq_base + GPIO_INTR_OFFSET, 0);
+                               false, irq_base + GPIO_INTR_OFFSET, 0);
                if (IS_ERR(child))
                        return PTR_ERR(child);
        }
@@ -679,7 +686,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
        if (twl_has_keypad() && pdata->keypad) {
                child = add_child(SUB_CHIP_ID2, "twl4030_keypad",
                                pdata->keypad, sizeof(*pdata->keypad),
-                               true, pdata->irq_base + KEYPAD_INTR_OFFSET, 0);
+                               true, irq_base + KEYPAD_INTR_OFFSET, 0);
                if (IS_ERR(child))
                        return PTR_ERR(child);
        }
@@ -687,7 +694,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
        if (twl_has_madc() && pdata->madc) {
                child = add_child(2, "twl4030_madc",
                                pdata->madc, sizeof(*pdata->madc),
-                               true, pdata->irq_base + MADC_INTR_OFFSET, 0);
+                               true, irq_base + MADC_INTR_OFFSET, 0);
                if (IS_ERR(child))
                        return PTR_ERR(child);
        }
@@ -703,7 +710,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
                sub_chip_id = twl_map[TWL_MODULE_RTC].sid;
                child = add_child(sub_chip_id, "twl_rtc",
                                NULL, 0,
-                               true, pdata->irq_base + RTC_INTR_OFFSET, 0);
+                               true, irq_base + RTC_INTR_OFFSET, 0);
                if (IS_ERR(child))
                        return PTR_ERR(child);
        }
@@ -756,8 +763,8 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
                                pdata->usb, sizeof(*pdata->usb),
                                true,
                                /* irq0 = USB_PRES, irq1 = USB */
-                               pdata->irq_base + USB_PRES_INTR_OFFSET,
-                               pdata->irq_base + USB_INTR_OFFSET);
+                               irq_base + USB_PRES_INTR_OFFSET,
+                               irq_base + USB_INTR_OFFSET);
 
                if (IS_ERR(child))
                        return PTR_ERR(child);
@@ -805,8 +812,8 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
                        pdata->usb, sizeof(*pdata->usb),
                        true,
                        /* irq1 = VBUS_PRES, irq0 = USB ID */
-                       pdata->irq_base + USBOTG_INTR_OFFSET,
-                       pdata->irq_base + USB_PRES_INTR_OFFSET);
+                       irq_base + USBOTG_INTR_OFFSET,
+                       irq_base + USB_PRES_INTR_OFFSET);
 
                if (IS_ERR(child))
                        return PTR_ERR(child);
@@ -833,7 +840,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
 
        if (twl_has_pwrbutton() && twl_class_is_4030()) {
                child = add_child(1, "twl4030_pwrbutton",
-                               NULL, 0, true, pdata->irq_base + 8 + 0, 0);
+                               NULL, 0, true, irq_base + 8 + 0, 0);
                if (IS_ERR(child))
                        return PTR_ERR(child);
        }
@@ -847,15 +854,6 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
                        return PTR_ERR(child);
        }
 
-       if (twl_has_codec() && pdata->audio && twl_class_is_6030()) {
-               sub_chip_id = twl_map[TWL_MODULE_AUDIO_VOICE].sid;
-               child = add_child(sub_chip_id, "twl6040",
-                               pdata->audio, sizeof(*pdata->audio),
-                               false, 0, 0);
-               if (IS_ERR(child))
-                       return PTR_ERR(child);
-       }
-
        /* twl4030 regulators */
        if (twl_has_regulator() && twl_class_is_4030()) {
                child = add_regulator(TWL4030_REG_VPLL1, pdata->vpll1,
@@ -1092,8 +1090,8 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
                child = add_child(3, "twl4030_bci",
                                pdata->bci, sizeof(*pdata->bci), false,
                                /* irq0 = CHG_PRES, irq1 = BCI */
-                               pdata->irq_base + BCI_PRES_INTR_OFFSET,
-                               pdata->irq_base + BCI_INTR_OFFSET);
+                               irq_base + BCI_PRES_INTR_OFFSET,
+                               irq_base + BCI_INTR_OFFSET);
                if (IS_ERR(child))
                        return PTR_ERR(child);
        }
@@ -1193,26 +1191,24 @@ static void clocks_init(struct device *dev,
 
 /*----------------------------------------------------------------------*/
 
-int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end);
-int twl4030_exit_irq(void);
-int twl4030_init_chip_irq(const char *chip);
-int twl6030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end);
-int twl6030_exit_irq(void);
 
 static int twl_remove(struct i2c_client *client)
 {
-       unsigned i;
+       unsigned i, num_slaves;
        int status;
 
-       if (twl_class_is_4030())
+       if (twl_class_is_4030()) {
                status = twl4030_exit_irq();
-       else
+               num_slaves = TWL_NUM_SLAVES;
+       } else {
                status = twl6030_exit_irq();
+               num_slaves = TWL_NUM_SLAVES - 1;
+       }
 
        if (status < 0)
                return status;
 
-       for (i = 0; i < TWL_NUM_SLAVES; i++) {
+       for (i = 0; i < num_slaves; i++) {
                struct twl_client       *twl = &twl_modules[i];
 
                if (twl->client && twl->client != client)
@@ -1223,20 +1219,15 @@ static int twl_remove(struct i2c_client *client)
        return 0;
 }
 
-/* NOTE:  this driver only handles a single twl4030/tps659x0 chip */
+/* NOTE: This driver only handles a single twl4030/tps659x0 chip */
 static int __devinit
 twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
-       int                             status;
-       unsigned                        i;
        struct twl4030_platform_data    *pdata = client->dev.platform_data;
        struct device_node              *node = client->dev.of_node;
-       u8 temp;
-       int ret = 0;
-       int nr_irqs = TWL4030_NR_IRQS;
-
-       if ((id->driver_data) & TWL6030_CLASS)
-               nr_irqs = TWL6030_NR_IRQS;
+       int                             irq_base = 0;
+       int                             status;
+       unsigned                        i, num_slaves;
 
        if (node && !pdata) {
                /*
@@ -1255,17 +1246,6 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
                return -EINVAL;
        }
 
-       status = irq_alloc_descs(-1, pdata->irq_base, nr_irqs, 0);
-       if (IS_ERR_VALUE(status)) {
-               dev_err(&client->dev, "Fail to allocate IRQ descs\n");
-               return status;
-       }
-
-       pdata->irq_base = status;
-       pdata->irq_end = pdata->irq_base + nr_irqs;
-       irq_domain_add_legacy(node, nr_irqs, pdata->irq_base, 0,
-                             &irq_domain_simple_ops, NULL);
-
        if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C) == 0) {
                dev_dbg(&client->dev, "can't talk I2C?\n");
                return -EIO;
@@ -1276,13 +1256,23 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
                return -EBUSY;
        }
 
-       for (i = 0; i < TWL_NUM_SLAVES; i++) {
-               struct twl_client       *twl = &twl_modules[i];
+       if ((id->driver_data) & TWL6030_CLASS) {
+               twl_id = TWL6030_CLASS_ID;
+               twl_map = &twl6030_map[0];
+               num_slaves = TWL_NUM_SLAVES - 1;
+       } else {
+               twl_id = TWL4030_CLASS_ID;
+               twl_map = &twl4030_map[0];
+               num_slaves = TWL_NUM_SLAVES;
+       }
+
+       for (i = 0; i < num_slaves; i++) {
+               struct twl_client *twl = &twl_modules[i];
 
                twl->address = client->addr + i;
-               if (i == 0)
+               if (i == 0) {
                        twl->client = client;
-               else {
+               } else {
                        twl->client = i2c_new_dummy(client->adapter,
                                        twl->address);
                        if (!twl->client) {
@@ -1294,22 +1284,16 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
                }
                mutex_init(&twl->xfer_lock);
        }
+
        inuse = true;
-       if ((id->driver_data) & TWL6030_CLASS) {
-               twl_id = TWL6030_CLASS_ID;
-               twl_map = &twl6030_map[0];
-       } else {
-               twl_id = TWL4030_CLASS_ID;
-               twl_map = &twl4030_map[0];
-       }
 
        /* setup clock framework */
        clocks_init(&client->dev, pdata->clock);
 
        /* read TWL IDCODE Register */
        if (twl_id == TWL4030_CLASS_ID) {
-               ret = twl_read_idcode_register();
-               WARN(ret < 0, "Error: reading twl_idcode register value\n");
+               status = twl_read_idcode_register();
+               WARN(status < 0, "Error: reading twl_idcode register value\n");
        }
 
        /* load power event scripts */
@@ -1317,31 +1301,31 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
                twl4030_power_init(pdata->power);
 
        /* Maybe init the T2 Interrupt subsystem */
-       if (client->irq
-                       && pdata->irq_base
-                       && pdata->irq_end > pdata->irq_base) {
+       if (client->irq) {
                if (twl_class_is_4030()) {
                        twl4030_init_chip_irq(id->name);
-                       status = twl4030_init_irq(client->irq, pdata->irq_base,
-                       pdata->irq_end);
+                       irq_base = twl4030_init_irq(&client->dev, client->irq);
                } else {
-                       status = twl6030_init_irq(client->irq, pdata->irq_base,
-                       pdata->irq_end);
+                       irq_base = twl6030_init_irq(&client->dev, client->irq);
                }
 
-               if (status < 0)
+               if (irq_base < 0) {
+                       status = irq_base;
                        goto fail;
+               }
        }
 
-       /* Disable TWL4030/TWL5030 I2C Pull-up on I2C1 and I2C4(SR) interface.
+       /*
+        * Disable TWL4030/TWL5030 I2C Pull-up on I2C1 and I2C4(SR) interface.
         * Program I2C_SCL_CTRL_PU(bit 0)=0, I2C_SDA_CTRL_PU (bit 2)=0,
         * SR_I2C_SCL_CTRL_PU(bit 4)=0 and SR_I2C_SDA_CTRL_PU(bit 6)=0.
         */
-
        if (twl_class_is_4030()) {
+               u8 temp;
+
                twl_i2c_read_u8(TWL4030_MODULE_INTBR, &temp, REG_GPPUPDCTR1);
                temp &= ~(SR_I2C_SDA_CTRL_PU | SR_I2C_SCL_CTRL_PU | \
-               I2C_SDA_CTRL_PU | I2C_SCL_CTRL_PU);
+                       I2C_SDA_CTRL_PU | I2C_SCL_CTRL_PU);
                twl_i2c_write_u8(TWL4030_MODULE_INTBR, temp, REG_GPPUPDCTR1);
        }
 
@@ -1349,11 +1333,12 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
        if (node)
                status = of_platform_populate(node, NULL, NULL, &client->dev);
        if (status)
-               status = add_children(pdata, id->driver_data);
+               status = add_children(pdata, irq_base, id->driver_data);
 
 fail:
        if (status < 0)
                twl_remove(client);
+
        return status;
 }
 
index 8c50a55..6ff99dc 100644 (file)
@@ -1,9 +1,9 @@
 #ifndef __TWL_CORE_H__
 #define __TWL_CORE_H__
 
-extern int twl6030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end);
+extern int twl6030_init_irq(struct device *dev, int irq_num);
 extern int twl6030_exit_irq(void);
-extern int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end);
+extern int twl4030_init_irq(struct device *dev, int irq_num);
 extern int twl4030_exit_irq(void);
 extern int twl4030_init_chip_irq(const char *chip);
 
index b69bb51..5d656e8 100644 (file)
  */
 
 #include <linux/init.h>
+#include <linux/export.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/slab.h>
-
+#include <linux/of.h>
+#include <linux/irqdomain.h>
 #include <linux/i2c/twl.h>
 
 #include "twl-core.h"
  *     base + 8  .. base + 15  SIH for PWR_INT
  *     base + 16 .. base + 33  SIH for GPIO
  */
+#define TWL4030_CORE_NR_IRQS   8
+#define TWL4030_PWR_NR_IRQS    8
 
 /* PIH register offsets */
 #define REG_PIH_ISR_P1                 0x01
 #define REG_PIH_ISR_P2                 0x02
 #define REG_PIH_SIR                    0x03    /* for testing */
 
-
 /* Linux could (eventually) use either IRQ line */
 static int irq_line;
 
@@ -111,7 +114,8 @@ static int nr_sih_modules;
 #define TWL4030_MODULE_INT_PWR         TWL4030_MODULE_INT
 
 
-/* Order in this table matches order in PIH_ISR.  That is,
+/*
+ * Order in this table matches order in PIH_ISR.  That is,
  * BIT(n) in PIH_ISR is sih_modules[n].
  */
 /* sih_modules_twl4030 is used both in twl4030 and twl5030 */
@@ -288,7 +292,6 @@ static unsigned twl4030_irq_base;
  */
 static irqreturn_t handle_twl4030_pih(int irq, void *devid)
 {
-       int             module_irq;
        irqreturn_t     ret;
        u8              pih_isr;
 
@@ -299,16 +302,18 @@ static irqreturn_t handle_twl4030_pih(int irq, void *devid)
                return IRQ_NONE;
        }
 
-       /* these handlers deal with the relevant SIH irq status */
-       for (module_irq = twl4030_irq_base;
-                       pih_isr;
-                       pih_isr >>= 1, module_irq++) {
-               if (pih_isr & 0x1)
-                       handle_nested_irq(module_irq);
+       while (pih_isr) {
+               unsigned long   pending = __ffs(pih_isr);
+               unsigned int    irq;
+
+               pih_isr &= ~BIT(pending);
+               irq = pending + twl4030_irq_base;
+               handle_nested_irq(irq);
        }
 
        return IRQ_HANDLED;
 }
+
 /*----------------------------------------------------------------------*/
 
 /*
@@ -337,7 +342,6 @@ static int twl4030_init_sih_modules(unsigned line)
        memset(buf, 0xff, sizeof buf);
        sih = sih_modules;
        for (i = 0; i < nr_sih_modules; i++, sih++) {
-
                /* skip USB -- it's funky */
                if (!sih->bytes_ixr)
                        continue;
@@ -352,7 +356,8 @@ static int twl4030_init_sih_modules(unsigned line)
                        pr_err("twl4030: err %d initializing %s %s\n",
                                        status, sih->name, "IMR");
 
-               /* Maybe disable "exclusive" mode; buffer second pending irq;
+               /*
+                * Maybe disable "exclusive" mode; buffer second pending irq;
                 * set Clear-On-Read (COR) bit.
                 *
                 * NOTE that sometimes COR polarity is documented as being
@@ -382,7 +387,8 @@ static int twl4030_init_sih_modules(unsigned line)
                if (sih->irq_lines <= line)
                        continue;
 
-               /* Clear pending interrupt status.  Either the read was
+               /*
+                * Clear pending interrupt status.  Either the read was
                 * enough, or we need to write those bits.  Repeat, in
                 * case an IRQ is pending (PENDDIS=0) ... that's not
                 * uncommon with PWR_INT.PWRON.
@@ -398,7 +404,8 @@ static int twl4030_init_sih_modules(unsigned line)
                                status = twl_i2c_write(sih->module, buf,
                                        sih->mask[line].isr_offset,
                                        sih->bytes_ixr);
-                       /* else COR=1 means read sufficed.
+                       /*
+                        * else COR=1 means read sufficed.
                         * (for most SIH modules...)
                         */
                }
@@ -410,7 +417,8 @@ static int twl4030_init_sih_modules(unsigned line)
 static inline void activate_irq(int irq)
 {
 #ifdef CONFIG_ARM
-       /* ARM requires an extra step to clear IRQ_NOREQUEST, which it
+       /*
+        * ARM requires an extra step to clear IRQ_NOREQUEST, which it
         * sets on behalf of every irq_chip.  Also sets IRQ_NOPROBE.
         */
        set_irq_flags(irq, IRQF_VALID);
@@ -620,33 +628,24 @@ static irqreturn_t handle_twl4030_sih(int irq, void *data)
        return IRQ_HANDLED;
 }
 
-static unsigned twl4030_irq_next;
-
-/* returns the first IRQ used by this SIH bank,
- * or negative errno
- */
-int twl4030_sih_setup(int module)
+/* returns the first IRQ used by this SIH bank, or negative errno */
+int twl4030_sih_setup(struct device *dev, int module, int irq_base)
 {
        int                     sih_mod;
        const struct sih        *sih = NULL;
        struct sih_agent        *agent;
        int                     i, irq;
        int                     status = -EINVAL;
-       unsigned                irq_base = twl4030_irq_next;
 
        /* only support modules with standard clear-on-read for now */
-       for (sih_mod = 0, sih = sih_modules;
-                       sih_mod < nr_sih_modules;
+       for (sih_mod = 0, sih = sih_modules; sih_mod < nr_sih_modules;
                        sih_mod++, sih++) {
                if (sih->module == module && sih->set_cor) {
-                       if (!WARN((irq_base + sih->bits) > NR_IRQS,
-                                       "irq %d for %s too big\n",
-                                       irq_base + sih->bits,
-                                       sih->name))
-                               status = 0;
+                       status = 0;
                        break;
                }
        }
+
        if (status < 0)
                return status;
 
@@ -654,8 +653,6 @@ int twl4030_sih_setup(int module)
        if (!agent)
                return -ENOMEM;
 
-       status = 0;
-
        agent->irq_base = irq_base;
        agent->sih = sih;
        agent->imr = ~0;
@@ -671,8 +668,6 @@ int twl4030_sih_setup(int module)
                activate_irq(irq);
        }
 
-       twl4030_irq_next += i;
-
        /* replace generic PIH handler (handle_simple_irq) */
        irq = sih_mod + twl4030_irq_base;
        irq_set_handler_data(irq, agent);
@@ -680,26 +675,43 @@ int twl4030_sih_setup(int module)
        status = request_threaded_irq(irq, NULL, handle_twl4030_sih, 0,
                                      agent->irq_name ?: sih->name, NULL);
 
-       pr_info("twl4030: %s (irq %d) chaining IRQs %d..%d\n", sih->name,
-                       irq, irq_base, twl4030_irq_next - 1);
+       dev_info(dev, "%s (irq %d) chaining IRQs %d..%d\n", sih->name,
+                       irq, irq_base, irq_base + i - 1);
 
        return status < 0 ? status : irq_base;
 }
 
 /* FIXME need a call to reverse twl4030_sih_setup() ... */
 
-
 /*----------------------------------------------------------------------*/
 
 /* FIXME pass in which interrupt line we'll use ... */
 #define twl_irq_line   0
 
-int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end)
+int twl4030_init_irq(struct device *dev, int irq_num)
 {
        static struct irq_chip  twl4030_irq_chip;
+       int                     status, i;
+       int                     irq_base, irq_end, nr_irqs;
+       struct                  device_node *node = dev->of_node;
 
-       int                     status;
-       int                     i;
+       /*
+        * TWL core and pwr interrupts must be contiguous because
+        * the hwirqs numbers are defined contiguously from 1 to 15.
+        * Create only one domain for both.
+        */
+       nr_irqs = TWL4030_PWR_NR_IRQS + TWL4030_CORE_NR_IRQS;
+
+       irq_base = irq_alloc_descs(-1, 0, nr_irqs, 0);
+       if (IS_ERR_VALUE(irq_base)) {
+               dev_err(dev, "Fail to allocate IRQ descs\n");
+               return irq_base;
+       }
+
+       irq_domain_add_legacy(node, nr_irqs, irq_base, 0,
+                             &irq_domain_simple_ops, NULL);
+
+       irq_end = irq_base + TWL4030_CORE_NR_IRQS;
 
        /*
         * Mask and clear all TWL4030 interrupts since initially we do
@@ -711,7 +723,8 @@ int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end)
 
        twl4030_irq_base = irq_base;
 
-       /* install an irq handler for each of the SIH modules;
+       /*
+        * Install an irq handler for each of the SIH modules;
         * clone dummy irq_chip since PIH can't *do* anything
         */
        twl4030_irq_chip = dummy_irq_chip;
@@ -725,14 +738,14 @@ int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end)
                irq_set_nested_thread(i, 1);
                activate_irq(i);
        }
-       twl4030_irq_next = i;
-       pr_info("twl4030: %s (irq %d) chaining IRQs %d..%d\n", "PIH",
-                       irq_num, irq_base, twl4030_irq_next - 1);
+
+       dev_info(dev, "%s (irq %d) chaining IRQs %d..%d\n", "PIH",
+                       irq_num, irq_base, irq_end);
 
        /* ... and the PWR_INT module ... */
-       status = twl4030_sih_setup(TWL4030_MODULE_INT);
+       status = twl4030_sih_setup(dev, TWL4030_MODULE_INT, irq_end);
        if (status < 0) {
-               pr_err("twl4030: sih_setup PWR INT --> %d\n", status);
+               dev_err(dev, "sih_setup PWR INT --> %d\n", status);
                goto fail;
        }
 
@@ -741,11 +754,11 @@ int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end)
                                      IRQF_ONESHOT,
                                      "TWL4030-PIH", NULL);
        if (status < 0) {
-               pr_err("twl4030: could not claim irq%d: %d\n", irq_num, status);
+               dev_err(dev, "could not claim irq%d: %d\n", irq_num, status);
                goto fail_rqirq;
        }
 
-       return status;
+       return irq_base;
 fail_rqirq:
        /* clean up twl4030_sih_setup */
 fail:
index c6b456a..b76902f 100644 (file)
@@ -39,6 +39,8 @@
 #include <linux/i2c/twl.h>
 #include <linux/platform_device.h>
 #include <linux/suspend.h>
+#include <linux/of.h>
+#include <linux/irqdomain.h>
 
 #include "twl-core.h"
 
@@ -51,8 +53,8 @@
  *
  * We set up IRQs starting at a platform-specified base. An interrupt map table,
  * specifies mapping between interrupt number and the associated module.
- *
  */
+#define TWL6030_NR_IRQS    20
 
 static int twl6030_interrupt_mapping[24] = {
        PWR_INTR_OFFSET,        /* Bit 0        PWRON                   */
@@ -185,8 +187,17 @@ static int twl6030_irq_thread(void *data)
                        }
                local_irq_enable();
                }
-               ret = twl_i2c_write(TWL_MODULE_PIH, sts.bytes,
-                               REG_INT_STS_A, 3); /* clear INT_STS_A */
+
+               /*
+                * NOTE:
+                * Simulation confirms that documentation is wrong w.r.t the
+                * interrupt status clear operation. A single *byte* write to
+                * any one of STS_A to STS_C register results in all three
+                * STS registers being reset. Since it does not matter which
+                * value is written, all three registers are cleared on a
+                * single byte write, so we just use 0x0 to clear.
+                */
+               ret = twl_i2c_write_u8(TWL_MODULE_PIH, 0x00, REG_INT_STS_A);
                if (ret)
                        pr_warning("twl6030: I2C error in clearing PIH ISR\n");
 
@@ -227,7 +238,7 @@ static inline void activate_irq(int irq)
 #endif
 }
 
-int twl6030_irq_set_wake(struct irq_data *d, unsigned int on)
+static int twl6030_irq_set_wake(struct irq_data *d, unsigned int on)
 {
        if (on)
                atomic_inc(&twl6030_wakeirqs);
@@ -237,11 +248,6 @@ int twl6030_irq_set_wake(struct irq_data *d, unsigned int on)
        return 0;
 }
 
-/*----------------------------------------------------------------------*/
-
-static unsigned twl6030_irq_next;
-
-/*----------------------------------------------------------------------*/
 int twl6030_interrupt_unmask(u8 bit_mask, u8 offset)
 {
        int ret;
@@ -311,7 +317,8 @@ int twl6030_mmc_card_detect_config(void)
                                                                        ret);
                return ret;
        }
-       return 0;
+
+       return twl6030_irq_base + MMCDETECT_INTR_OFFSET;
 }
 EXPORT_SYMBOL(twl6030_mmc_card_detect_config);
 
@@ -340,29 +347,44 @@ int twl6030_mmc_card_detect(struct device *dev, int slot)
 }
 EXPORT_SYMBOL(twl6030_mmc_card_detect);
 
-int twl6030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end)
+int twl6030_init_irq(struct device *dev, int irq_num)
 {
-
-       int     status = 0;
-       int     i;
+       struct                  device_node *node = dev->of_node;
+       int                     nr_irqs, irq_base, irq_end;
        struct task_struct      *task;
-       int ret;
-       u8 mask[4];
+       static struct irq_chip  twl6030_irq_chip;
+       int                     status = 0;
+       int                     i;
+       u8                      mask[4];
+
+       nr_irqs = TWL6030_NR_IRQS;
+
+       irq_base = irq_alloc_descs(-1, 0, nr_irqs, 0);
+       if (IS_ERR_VALUE(irq_base)) {
+               dev_err(dev, "Fail to allocate IRQ descs\n");
+               return irq_base;
+       }
+
+       irq_domain_add_legacy(node, nr_irqs, irq_base, 0,
+                             &irq_domain_simple_ops, NULL);
+
+       irq_end = irq_base + nr_irqs;
 
-       static struct irq_chip  twl6030_irq_chip;
        mask[1] = 0xFF;
        mask[2] = 0xFF;
        mask[3] = 0xFF;
-       ret = twl_i2c_write(TWL_MODULE_PIH, &mask[0],
-                       REG_INT_MSK_LINE_A, 3); /* MASK ALL INT LINES */
-       ret = twl_i2c_write(TWL_MODULE_PIH, &mask[0],
-                       REG_INT_MSK_STS_A, 3); /* MASK ALL INT STS */
-       ret = twl_i2c_write(TWL_MODULE_PIH, &mask[0],
-                       REG_INT_STS_A, 3); /* clear INT_STS_A,B,C */
+
+       /* mask all int lines */
+       twl_i2c_write(TWL_MODULE_PIH, &mask[0], REG_INT_MSK_LINE_A, 3);
+       /* mask all int sts */
+       twl_i2c_write(TWL_MODULE_PIH, &mask[0], REG_INT_MSK_STS_A, 3);
+       /* clear INT_STS_A,B,C */
+       twl_i2c_write(TWL_MODULE_PIH, &mask[0], REG_INT_STS_A, 3);
 
        twl6030_irq_base = irq_base;
 
-       /* install an irq handler for each of the modules;
+       /*
+        * install an irq handler for each of the modules;
         * clone dummy irq_chip since PIH can't *do* anything
         */
        twl6030_irq_chip = dummy_irq_chip;
@@ -377,30 +399,29 @@ int twl6030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end)
                activate_irq(i);
        }
 
-       twl6030_irq_next = i;
-       pr_info("twl6030: %s (irq %d) chaining IRQs %d..%d\n", "PIH",
-                       irq_num, irq_base, twl6030_irq_next - 1);
+       dev_info(dev, "PIH (irq %d) chaining IRQs %d..%d\n",
+                       irq_num, irq_base, irq_end);
 
        /* install an irq handler to demultiplex the TWL6030 interrupt */
        init_completion(&irq_event);
 
-       status = request_irq(irq_num, handle_twl6030_pih, 0,
-                               "TWL6030-PIH", &irq_event);
+       status = request_irq(irq_num, handle_twl6030_pih, 0, "TWL6030-PIH",
+                            &irq_event);
        if (status < 0) {
-               pr_err("twl6030: could not claim irq%d: %d\n", irq_num, status);
+               dev_err(dev, "could not claim irq %d: %d\n", irq_num, status);
                goto fail_irq;
        }
 
        task = kthread_run(twl6030_irq_thread, (void *)irq_num, "twl6030-irq");
        if (IS_ERR(task)) {
-               pr_err("twl6030: could not create irq %d thread!\n", irq_num);
+               dev_err(dev, "could not create irq %d thread!\n", irq_num);
                status = PTR_ERR(task);
                goto fail_kthread;
        }
 
        twl_irq = irq_num;
        register_pm_notifier(&twl6030_irq_pm_notifier_block);
-       return status;
+       return irq_base;
 
 fail_kthread:
        free_irq(irq_num, &irq_event);
@@ -408,6 +429,7 @@ fail_kthread:
 fail_irq:
        for (i = irq_base; i < irq_end; i++)
                irq_set_chip_and_handler(i, NULL, NULL);
+
        return status;
 }
 
index 745c879..4bceee9 100644 (file)
@@ -89,7 +89,7 @@ static const struct spi_device_id wm831x_spi_ids[] = {
        { "wm8326", WM8326 },
        { },
 };
-MODULE_DEVICE_TABLE(spi, wm831x_spi_id);
+MODULE_DEVICE_TABLE(spi, wm831x_spi_ids);
 
 static struct spi_driver wm831x_spi_driver = {
        .driver = {
index 237764a..1189a17 100644 (file)
@@ -271,8 +271,7 @@ static int wm8400_init(struct wm8400 *wm8400,
                return -EIO;
        }
        if (i != reg_data[WM8400_RESET_ID].default_val) {
-               dev_err(wm8400->dev, "Device is not a WM8400, ID is %x\n",
-                       reg);
+               dev_err(wm8400->dev, "Device is not a WM8400, ID is %x\n", i);
                return -ENODEV;
        }
 
index 98733d4..9d7ca1e 100644 (file)
@@ -639,7 +639,7 @@ static __devinit int wm8994_device_init(struct wm8994 *wm8994, int irq)
        }
 
        pm_runtime_enable(wm8994->dev);
-       pm_runtime_resume(wm8994->dev);
+       pm_runtime_idle(wm8994->dev);
 
        return 0;
 
index 7605b60..bfd25af 100644 (file)
@@ -20,7 +20,6 @@
 #include "wm8994.h"
 
 static struct reg_default wm1811_defaults[] = {
-       { 0x0000, 0x1811 },    /* R0    - Software Reset */
        { 0x0001, 0x0000 },    /* R1    - Power Management (1) */
        { 0x0002, 0x6000 },    /* R2    - Power Management (2) */
        { 0x0003, 0x0000 },    /* R3    - Power Management (3) */
@@ -61,7 +60,7 @@ static struct reg_default wm1811_defaults[] = {
        { 0x0036, 0x0000 },    /* R54   - Speaker Mixer */
        { 0x0037, 0x0000 },    /* R55   - Additional Control */
        { 0x0038, 0x0000 },    /* R56   - AntiPOP (1) */
-       { 0x0039, 0x0180 },    /* R57   - AntiPOP (2) */
+       { 0x0039, 0x0000 },    /* R57   - AntiPOP (2) */
        { 0x003B, 0x000D },    /* R59   - LDO 1 */
        { 0x003C, 0x0003 },    /* R60   - LDO 2 */
        { 0x003D, 0x0039 },    /* R61   - MICBIAS1 */
@@ -69,16 +68,12 @@ static struct reg_default wm1811_defaults[] = {
        { 0x004C, 0x1F25 },    /* R76   - Charge Pump (1) */
        { 0x004D, 0xAB19 },    /* R77   - Charge Pump (2) */
        { 0x0051, 0x0004 },    /* R81   - Class W (1) */
-       { 0x0054, 0x0000 },    /* R84   - DC Servo (1) */
        { 0x0055, 0x054A },    /* R85   - DC Servo (2) */
-       { 0x0058, 0x0000 },    /* R88   - DC Servo Readback */
        { 0x0059, 0x0000 },    /* R89   - DC Servo (4) */
        { 0x0060, 0x0000 },    /* R96   - Analogue HP (1) */
        { 0x00C5, 0x0000 },    /* R197  - Class D Test (5) */
        { 0x00D0, 0x7600 },    /* R208  - Mic Detect 1 */
        { 0x00D1, 0x007F },    /* R209  - Mic Detect 2 */
-       { 0x00D2, 0x0000 },    /* R210  - Mic Detect 3 */
-       { 0x0100, 0x0100 },    /* R256  - Chip Revision */
        { 0x0101, 0x8004 },    /* R257  - Control Interface */
        { 0x0200, 0x0000 },    /* R512  - AIF1 Clocking (1) */
        { 0x0201, 0x0000 },    /* R513  - AIF1 Clocking (2) */
@@ -88,7 +83,6 @@ static struct reg_default wm1811_defaults[] = {
        { 0x0209, 0x0000 },    /* R521  - Clocking (2) */
        { 0x0210, 0x0083 },    /* R528  - AIF1 Rate */
        { 0x0211, 0x0083 },    /* R529  - AIF2 Rate */
-       { 0x0212, 0x0000 },    /* R530  - Rate Status */
        { 0x0220, 0x0000 },    /* R544  - FLL1 Control (1) */
        { 0x0221, 0x0000 },    /* R545  - FLL1 Control (2) */
        { 0x0222, 0x0000 },    /* R546  - FLL1 Control (3) */
@@ -218,8 +212,6 @@ static struct reg_default wm1811_defaults[] = {
        { 0x070A, 0xA101 },    /* R1802 - GPIO 11 */
        { 0x0720, 0x0000 },    /* R1824 - Pull Control (1) */
        { 0x0721, 0x0156 },    /* R1825 - Pull Control (2) */
-       { 0x0730, 0x0000 },    /* R1840 - Interrupt Status 1 */
-       { 0x0731, 0x0000 },    /* R1841 - Interrupt Status 2 */
        { 0x0732, 0x0000 },    /* R1842 - Interrupt Raw Status 2 */
        { 0x0738, 0x07FF },    /* R1848 - Interrupt Status 1 Mask */
        { 0x0739, 0xDFEF },    /* R1849 - Interrupt Status 2 Mask */
@@ -228,7 +220,6 @@ static struct reg_default wm1811_defaults[] = {
 };
 
 static struct reg_default wm8994_defaults[] = {
-       { 0x0000, 0x8994 },    /* R0     - Software Reset */ 
        { 0x0001, 0x0000 },    /* R1     - Power Management (1) */ 
        { 0x0002, 0x6000 },    /* R2     - Power Management (2) */ 
        { 0x0003, 0x0000 },    /* R3     - Power Management (3) */ 
@@ -275,12 +266,9 @@ static struct reg_default wm8994_defaults[] = {
        { 0x003C, 0x0003 },    /* R60    - LDO 2 */ 
        { 0x004C, 0x1F25 },    /* R76    - Charge Pump (1) */ 
        { 0x0051, 0x0004 },    /* R81    - Class W (1) */ 
-       { 0x0054, 0x0000 },    /* R84    - DC Servo (1) */ 
        { 0x0055, 0x054A },    /* R85    - DC Servo (2) */ 
        { 0x0057, 0x0000 },    /* R87    - DC Servo (4) */ 
-       { 0x0058, 0x0000 },    /* R88    - DC Servo Readback */ 
        { 0x0060, 0x0000 },    /* R96    - Analogue HP (1) */ 
-       { 0x0100, 0x0003 },    /* R256   - Chip Revision */ 
        { 0x0101, 0x8004 },    /* R257   - Control Interface */ 
        { 0x0110, 0x0000 },    /* R272   - Write Sequencer Ctrl (1) */ 
        { 0x0111, 0x0000 },    /* R273   - Write Sequencer Ctrl (2) */ 
@@ -292,7 +280,6 @@ static struct reg_default wm8994_defaults[] = {
        { 0x0209, 0x0000 },    /* R521   - Clocking (2) */ 
        { 0x0210, 0x0083 },    /* R528   - AIF1 Rate */ 
        { 0x0211, 0x0083 },    /* R529   - AIF2 Rate */ 
-       { 0x0212, 0x0000 },    /* R530   - Rate Status */ 
        { 0x0220, 0x0000 },    /* R544   - FLL1 Control (1) */ 
        { 0x0221, 0x0000 },    /* R545   - FLL1 Control (2) */ 
        { 0x0222, 0x0000 },    /* R546   - FLL1 Control (3) */ 
@@ -445,9 +432,6 @@ static struct reg_default wm8994_defaults[] = {
        { 0x070A, 0xA101 },    /* R1802  - GPIO 11 */ 
        { 0x0720, 0x0000 },    /* R1824  - Pull Control (1) */ 
        { 0x0721, 0x0156 },    /* R1825  - Pull Control (2) */ 
-       { 0x0730, 0x0000 },    /* R1840  - Interrupt Status 1 */ 
-       { 0x0731, 0x0000 },    /* R1841  - Interrupt Status 2 */ 
-       { 0x0732, 0x0000 },    /* R1842  - Interrupt Raw Status 2 */ 
        { 0x0738, 0x07FF },    /* R1848  - Interrupt Status 1 Mask */ 
        { 0x0739, 0xFFFF },    /* R1849  - Interrupt Status 2 Mask */ 
        { 0x0740, 0x0000 },    /* R1856  - Interrupt Control */ 
@@ -455,7 +439,6 @@ static struct reg_default wm8994_defaults[] = {
 };
 
 static struct reg_default wm8958_defaults[] = {
-       { 0x0000, 0x8958 },    /* R0     - Software Reset */ 
        { 0x0001, 0x0000 },    /* R1     - Power Management (1) */
        { 0x0002, 0x6000 },    /* R2     - Power Management (2) */
        { 0x0003, 0x0000 },    /* R3     - Power Management (3) */
@@ -970,6 +953,7 @@ static bool wm8994_readable_register(struct device *dev, unsigned int reg)
 {
        switch (reg) {
        case WM8994_DC_SERVO_READBACK:
+       case WM8994_MICBIAS:
        case WM8994_WRITE_SEQUENCER_CTRL_1:
        case WM8994_WRITE_SEQUENCER_CTRL_2:
        case WM8994_AIF1_ADC2_LEFT_VOLUME:
index d95587c..04d5170 100644 (file)
@@ -40,6 +40,7 @@ extern void gru_wait_abort_proc(void *cb);
                        *((volatile unsigned long *)(p)) = v; /* force st.rel */        \
                } while (0)
 #elif defined(CONFIG_X86_64)
+#include <asm/cacheflush.h>
 #define __flush_cache(p)               clflush(p)
 #define gru_ordered_store_ulong(p, v)                                  \
                do {                                                    \
index 851b2f2..c862cd4 100644 (file)
@@ -25,7 +25,6 @@
 #endif
 
 #if defined CONFIG_IA64
-#include <asm/system.h>
 #include <asm/sn/arch.h>       /* defines is_shub1() and is_shub2() */
 #define is_shub()      ia64_platform_is("sn2")
 #endif
index e5a3c7b..4c3b284 100644 (file)
@@ -41,7 +41,6 @@
 #include <linux/mmc/mmc.h>
 #include <linux/mmc/sd.h>
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 
 #include "queue.h"
index ecff765..5d53c57 100644 (file)
@@ -93,7 +93,6 @@
 #include <linux/fs.h>
 #include <linux/ioctl.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <linux/pci.h>
 
 #include <linux/mtd/mtd.h>
index e585263..2885941 100644 (file)
@@ -42,7 +42,6 @@
 #include <linux/ioctl.h>
 #include <linux/init.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include <linux/mtd/mtd.h>
 
index e8e9fec..0259cf5 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/timer.h>
 #include <linux/init.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
index 35b4fb5..ae7e37d 100644 (file)
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/of_mtd.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/dmaengine.h>
 #include <linux/gpio.h>
 #include <linux/io.h>
+#include <linux/platform_data/atmel.h>
 
-#include <mach/board.h>
 #include <mach/cpu.h>
 
-#ifdef CONFIG_MTD_NAND_ATMEL_ECC_HW
-#define hard_ecc       1
-#else
-#define hard_ecc       0
-#endif
-
-#ifdef CONFIG_MTD_NAND_ATMEL_ECC_NONE
-#define no_ecc         1
-#else
-#define no_ecc         0
-#endif
-
 static int use_dma = 1;
 module_param(use_dma, int, 0);
 
@@ -95,7 +87,7 @@ struct atmel_nand_host {
        struct mtd_info         mtd;
        void __iomem            *io_base;
        dma_addr_t              io_phys;
-       struct atmel_nand_data  *board;
+       struct atmel_nand_data  board;
        struct device           *dev;
        void __iomem            *ecc;
 
@@ -113,8 +105,8 @@ static int cpu_has_dma(void)
  */
 static void atmel_nand_enable(struct atmel_nand_host *host)
 {
-       if (gpio_is_valid(host->board->enable_pin))
-               gpio_set_value(host->board->enable_pin, 0);
+       if (gpio_is_valid(host->board.enable_pin))
+               gpio_set_value(host->board.enable_pin, 0);
 }
 
 /*
@@ -122,8 +114,8 @@ static void atmel_nand_enable(struct atmel_nand_host *host)
  */
 static void atmel_nand_disable(struct atmel_nand_host *host)
 {
-       if (gpio_is_valid(host->board->enable_pin))
-               gpio_set_value(host->board->enable_pin, 1);
+       if (gpio_is_valid(host->board.enable_pin))
+               gpio_set_value(host->board.enable_pin, 1);
 }
 
 /*
@@ -144,9 +136,9 @@ static void atmel_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl
                return;
 
        if (ctrl & NAND_CLE)
-               writeb(cmd, host->io_base + (1 << host->board->cle));
+               writeb(cmd, host->io_base + (1 << host->board.cle));
        else
-               writeb(cmd, host->io_base + (1 << host->board->ale));
+               writeb(cmd, host->io_base + (1 << host->board.ale));
 }
 
 /*
@@ -157,8 +149,8 @@ static int atmel_nand_device_ready(struct mtd_info *mtd)
        struct nand_chip *nand_chip = mtd->priv;
        struct atmel_nand_host *host = nand_chip->priv;
 
-       return gpio_get_value(host->board->rdy_pin) ^
-                !!host->board->rdy_pin_active_low;
+       return gpio_get_value(host->board.rdy_pin) ^
+                !!host->board.rdy_pin_active_low;
 }
 
 /*
@@ -273,7 +265,7 @@ static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len)
                if (atmel_nand_dma_op(mtd, buf, len, 1) == 0)
                        return;
 
-       if (host->board->bus_width_16)
+       if (host->board.bus_width_16)
                atmel_read_buf16(mtd, buf, len);
        else
                atmel_read_buf8(mtd, buf, len);
@@ -289,7 +281,7 @@ static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
                if (atmel_nand_dma_op(mtd, (void *)buf, len, 0) == 0)
                        return;
 
-       if (host->board->bus_width_16)
+       if (host->board.bus_width_16)
                atmel_write_buf16(mtd, buf, len);
        else
                atmel_write_buf8(mtd, buf, len);
@@ -481,6 +473,56 @@ static void atmel_nand_hwctl(struct mtd_info *mtd, int mode)
        }
 }
 
+#if defined(CONFIG_OF)
+static int __devinit atmel_of_init_port(struct atmel_nand_host *host,
+                                        struct device_node *np)
+{
+       u32 val;
+       int ecc_mode;
+       struct atmel_nand_data *board = &host->board;
+       enum of_gpio_flags flags;
+
+       if (of_property_read_u32(np, "atmel,nand-addr-offset", &val) == 0) {
+               if (val >= 32) {
+                       dev_err(host->dev, "invalid addr-offset %u\n", val);
+                       return -EINVAL;
+               }
+               board->ale = val;
+       }
+
+       if (of_property_read_u32(np, "atmel,nand-cmd-offset", &val) == 0) {
+               if (val >= 32) {
+                       dev_err(host->dev, "invalid cmd-offset %u\n", val);
+                       return -EINVAL;
+               }
+               board->cle = val;
+       }
+
+       ecc_mode = of_get_nand_ecc_mode(np);
+
+       board->ecc_mode = ecc_mode < 0 ? NAND_ECC_SOFT : ecc_mode;
+
+       board->on_flash_bbt = of_get_nand_on_flash_bbt(np);
+
+       if (of_get_nand_bus_width(np) == 16)
+               board->bus_width_16 = 1;
+
+       board->rdy_pin = of_get_gpio_flags(np, 0, &flags);
+       board->rdy_pin_active_low = (flags == OF_GPIO_ACTIVE_LOW);
+
+       board->enable_pin = of_get_gpio(np, 1);
+       board->det_pin = of_get_gpio(np, 2);
+
+       return 0;
+}
+#else
+static int __devinit atmel_of_init_port(struct atmel_nand_host *host,
+                                        struct device_node *np)
+{
+       return -EINVAL;
+}
+#endif
+
 /*
  * Probe for the NAND device.
  */
@@ -491,6 +533,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
        struct nand_chip *nand_chip;
        struct resource *regs;
        struct resource *mem;
+       struct mtd_part_parser_data ppdata = {};
        int res;
 
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -517,8 +560,15 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
 
        mtd = &host->mtd;
        nand_chip = &host->nand_chip;
-       host->board = pdev->dev.platform_data;
        host->dev = &pdev->dev;
+       if (pdev->dev.of_node) {
+               res = atmel_of_init_port(host, pdev->dev.of_node);
+               if (res)
+                       goto err_nand_ioremap;
+       } else {
+               memcpy(&host->board, pdev->dev.platform_data,
+                      sizeof(struct atmel_nand_data));
+       }
 
        nand_chip->priv = host;         /* link the private data structures */
        mtd->priv = nand_chip;
@@ -529,26 +579,25 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
        nand_chip->IO_ADDR_W = host->io_base;
        nand_chip->cmd_ctrl = atmel_nand_cmd_ctrl;
 
-       if (gpio_is_valid(host->board->rdy_pin))
+       if (gpio_is_valid(host->board.rdy_pin))
                nand_chip->dev_ready = atmel_nand_device_ready;
 
+       nand_chip->ecc.mode = host->board.ecc_mode;
+
        regs = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-       if (!regs && hard_ecc) {
+       if (!regs && nand_chip->ecc.mode == NAND_ECC_HW) {
                printk(KERN_ERR "atmel_nand: can't get I/O resource "
                                "regs\nFalling back on software ECC\n");
+               nand_chip->ecc.mode = NAND_ECC_SOFT;
        }
 
-       nand_chip->ecc.mode = NAND_ECC_SOFT;    /* enable ECC */
-       if (no_ecc)
-               nand_chip->ecc.mode = NAND_ECC_NONE;
-       if (hard_ecc && regs) {
+       if (nand_chip->ecc.mode == NAND_ECC_HW) {
                host->ecc = ioremap(regs->start, resource_size(regs));
                if (host->ecc == NULL) {
                        printk(KERN_ERR "atmel_nand: ioremap failed\n");
                        res = -EIO;
                        goto err_ecc_ioremap;
                }
-               nand_chip->ecc.mode = NAND_ECC_HW;
                nand_chip->ecc.calculate = atmel_nand_calculate;
                nand_chip->ecc.correct = atmel_nand_correct;
                nand_chip->ecc.hwctl = atmel_nand_hwctl;
@@ -558,7 +607,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
 
        nand_chip->chip_delay = 20;             /* 20us command delay time */
 
-       if (host->board->bus_width_16)  /* 16-bit bus width */
+       if (host->board.bus_width_16)   /* 16-bit bus width */
                nand_chip->options |= NAND_BUSWIDTH_16;
 
        nand_chip->read_buf = atmel_read_buf;
@@ -567,15 +616,15 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, host);
        atmel_nand_enable(host);
 
-       if (gpio_is_valid(host->board->det_pin)) {
-               if (gpio_get_value(host->board->det_pin)) {
+       if (gpio_is_valid(host->board.det_pin)) {
+               if (gpio_get_value(host->board.det_pin)) {
                        printk(KERN_INFO "No SmartMedia card inserted.\n");
                        res = -ENXIO;
                        goto err_no_card;
                }
        }
 
-       if (on_flash_bbt) {
+       if (host->board.on_flash_bbt || on_flash_bbt) {
                printk(KERN_INFO "atmel_nand: Use On Flash BBT\n");
                nand_chip->bbt_options |= NAND_BBT_USE_FLASH;
        }
@@ -650,8 +699,9 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
        }
 
        mtd->name = "atmel_nand";
-       res = mtd_device_parse_register(mtd, NULL, 0,
-                       host->board->parts, host->board->num_parts);
+       ppdata.of_node = pdev->dev.of_node;
+       res = mtd_device_parse_register(mtd, NULL, &ppdata,
+                       host->board.parts, host->board.num_parts);
        if (!res)
                return res;
 
@@ -695,11 +745,21 @@ static int __exit atmel_nand_remove(struct platform_device *pdev)
        return 0;
 }
 
+#if defined(CONFIG_OF)
+static const struct of_device_id atmel_nand_dt_ids[] = {
+       { .compatible = "atmel,at91rm9200-nand" },
+       { /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, atmel_nand_dt_ids);
+#endif
+
 static struct platform_driver atmel_nand_driver = {
        .remove         = __exit_p(atmel_nand_remove),
        .driver         = {
                .name   = "atmel_nand",
                .owner  = THIS_MODULE,
+               .of_match_table = of_match_ptr(atmel_nand_dt_ids),
        },
 };
 
index 50387fd..64c9cba 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/mtd/partitions.h>
 
 #include <asm/mach-types.h>
-#include <asm/system.h>
 
 #include <mach/reg_nand.h>
 #include <mach/reg_umi.h>
index 9abd4eb..dd5e048 100644 (file)
@@ -70,7 +70,6 @@ static const char *version =
 #include <linux/bitops.h>
 #include <linux/jiffies.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 
index 6057b30..0910dce 100644 (file)
@@ -229,7 +229,6 @@ static int dma;
 #include <linux/bitops.h>
 #include <linux/gfp.h>
 
-#include <asm/system.h>
 #include <asm/dma.h>
 #include <asm/io.h>
 
index 980e65c..5bed4c4 100644 (file)
@@ -47,7 +47,6 @@
 #include <pcmcia/ds.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 
 #define VERSION "arcnet: COM20020 PCMCIA support loaded.\n"
 
index b920d82..0c76186 100644 (file)
@@ -54,7 +54,6 @@
 #include <linux/inet.h>
 #include <linux/bitops.h>
 #include <linux/io.h>
-#include <asm/system.h>
 #include <asm/dma.h>
 #include <linux/uaccess.h>
 #include <linux/errno.h>
index 98a5a7d..034c16b 100644 (file)
@@ -40,7 +40,6 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 
-#include <asm/system.h>
 #include <linux/uaccess.h>
 #include <linux/bitops.h>
 #include <linux/string.h>
index 7cb2785..ec03b40 100644 (file)
@@ -35,7 +35,6 @@
 #include <asm/io.h>         /* CRIS_LED_* I/O functions */
 #include <asm/irq.h>
 #include <asm/dma.h>
-#include <asm/system.h>
 #include <asm/ethernet.h>
 #include <asm/cache.h>
 #include <arch/io_interface_mux.h>
index e61b2f8..66df936 100644 (file)
@@ -95,7 +95,6 @@ earlier 3Com products.
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 /*====================================================================*/
 
index b23253b..a556c01 100644 (file)
@@ -50,7 +50,6 @@
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 /* To minimize the size of the driver source I only define operating
    constants if they are used several times.  You'll need the manual
index fbab136..49d76bd 100644 (file)
@@ -54,7 +54,6 @@ static const char version[] =
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/byteorder.h>
 
 #include "8390.h"
index 5337dd0..ccf0794 100644 (file)
@@ -34,7 +34,6 @@ static const char version[] =
 #include <linux/init.h>
 #include <linux/interrupt.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 
index 3ad5d2f..9239592 100644 (file)
@@ -39,7 +39,6 @@
 #include <linux/interrupt.h>
 #include <linux/jiffies.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/setup.h>
 #include <asm/amigaints.h>
index c30adcc..11476ca 100644 (file)
@@ -31,7 +31,6 @@
 
 #include <net/ax88796.h>
 
-#include <asm/system.h>
 
 /* Rename the lib8390.c functions to show that they are in this driver */
 #define __ei_open ax_ei_open
index c5bd8eb..e1b3941 100644 (file)
@@ -46,7 +46,6 @@
 #include <pcmcia/cisreg.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/byteorder.h>
 #include <asm/uaccess.h>
 
index d16dc53..ed55ce8 100644 (file)
@@ -48,7 +48,6 @@ static const char version[] =
 #include <linux/delay.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include "8390.h"
 
index 6428f9e..ba1b5c9 100644 (file)
@@ -59,7 +59,6 @@ static const char version[] =
 #include <linux/etherdevice.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include "8390.h"
 
index 48c4948..dbefd56 100644 (file)
@@ -45,9 +45,9 @@
 #include <linux/bitops.h>
 #include <linux/jiffies.h>
 
-#include <asm/system.h>
 #include <asm/ecard.h>
 #include <asm/io.h>
+#include <asm/system_info.h>
 
 #define EI_SHIFT(x)    (ei_local->reg_offset[x])
 
index d42938b..52f70f9 100644 (file)
@@ -33,7 +33,6 @@ static const char version[] =
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 
 #include "8390.h"
index 113f1e0..37fa89a 100644 (file)
@@ -33,7 +33,6 @@ static const char version[] =
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 
 #include "8390.h"
index e77f624..b329f5c 100644 (file)
@@ -57,7 +57,6 @@
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/bitops.h>
-#include <asm/system.h>
 #include <linux/uaccess.h>
 #include <linux/io.h>
 #include <asm/irq.h>
index 69490ae..479409b 100644 (file)
@@ -46,7 +46,6 @@ static const char *version =
 #include <linux/etherdevice.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include "8390.h"
 
index af5d982..88ccc8b 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/bitops.h>
 #include <linux/io.h>
 
-#include <asm/system.h>
 #include <asm/dma.h>
 #include <asm/hwtest.h>
 #include <asm/macints.h>
index 9b9c77d..7fc28f2 100644 (file)
@@ -29,7 +29,6 @@ static const char version1[] =
 #include <linux/etherdevice.h>
 #include <linux/jiffies.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 
index f92ea2a..d04911d 100644 (file)
@@ -53,7 +53,6 @@ static const char version2[] =
 #include <linux/jiffies.h>
 #include <linux/platform_device.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 
 #include "8390.h"
index 922b320..ef85839 100644 (file)
@@ -76,7 +76,6 @@ static const char *version = "ne2.c:v0.91 Nov 16 1998 Wim Dumon <wimpie@kotnet.o
 #include <linux/bitops.h>
 #include <linux/jiffies.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 
index 3fab04a..5e8845f 100644 (file)
@@ -54,7 +54,6 @@ static int options[MAX_UNITS];
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/uaccess.h>
index 2a3e805..a2f8b2b 100644 (file)
@@ -39,7 +39,6 @@
 #include <linux/mm.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include "8390.h"
 
index f2a4e5d..de1af0b 100644 (file)
@@ -49,7 +49,6 @@
 #include <pcmcia/cisreg.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/byteorder.h>
 #include <asm/uaccess.h>
 
index 77efec4..7a68590 100644 (file)
@@ -47,7 +47,6 @@
 #include <linux/etherdevice.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include "8390.h"
 
index 1cc306a..b0fbce3 100644 (file)
@@ -69,7 +69,6 @@ static const char version[] =
 
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 
 #include "8390.h"
 
index bb87053..923e42a 100644 (file)
@@ -57,7 +57,6 @@ static const char *version = "smc-ultra32.c: 06/97 v1.00\n";
 #include <linux/etherdevice.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include "8390.h"
 
index 3b90375..8df4c41 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <mach-se/mach/se.h>
 #include <asm/machvec.h>
index c175fad..03eb3ee 100644 (file)
@@ -39,7 +39,6 @@ static const char version[] =
 #include <linux/etherdevice.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include "8390.h"
 
index bcd2732..7818e63 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/zorro.h>
 #include <linux/jiffies.h>
 
-#include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/amigaints.h>
 #include <asm/amigahw.h>
index 6c3b1c0..7219123 100644 (file)
@@ -78,7 +78,6 @@
 #include <net/sock.h>
 #include <net/ip.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/byteorder.h>
index 1b046f5..6e722dc 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/socket.h>
 #include <linux/bitops.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/pgtable.h>
index cc7b9e4..e10ffad 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/io.h>
 
 #include <mach/hardware.h>
-#include <asm/system.h>
 
 #define TX_BUFFERS 15
 #define RX_BUFFERS 25
index 9f62504..64d0d9c 100644 (file)
@@ -88,7 +88,6 @@ Revision History:
 #include <linux/crc32.h>
 #include <linux/dma-mapping.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/byteorder.h>
 #include <asm/uaccess.h>
index 7dc508e..75299f5 100644 (file)
@@ -64,7 +64,6 @@
 #include <linux/types.h>
 
 #include <asm/addrspace.h>
-#include <asm/system.h>
 
 #include <asm/dec/interrupts.h>
 #include <asm/dec/ioasic.h>
index 4e2d68a..8baff4e 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
 
index 56bc47a..9af3c30 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/mvme147hw.h>
index ebdb9e2..9f59bf6 100644 (file)
@@ -154,7 +154,6 @@ Include Files
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 /* ----------------------------------------------------------------------------
 Defines
index e3fe350..d7a3533 100644 (file)
@@ -95,7 +95,6 @@ static char lancestr[] = "LANCE";
 #include <linux/of_device.h>
 #include <linux/gfp.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/pgtable.h>
index 7b71387..4e4bb38 100644 (file)
@@ -48,7 +48,6 @@
 #include <net/checksum.h>
 #include <net/ip.h>
 
-#include <asm/system.h>
 #include <linux/io.h>
 #include <asm/byteorder.h>
 #include <linux/uaccess.h>
index 30fee42..b9406cb 100644 (file)
 #include <linux/delay.h>
 #include <linux/gfp.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <linux/atomic.h>
index 932fdcc..e285f38 100644 (file)
@@ -99,7 +99,6 @@ static char *version =
 #include <linux/bitops.h>
 #include <linux/gfp.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/hwtest.h>
 #include <asm/macints.h>
index 682750c..414f0ee 100644 (file)
@@ -46,7 +46,6 @@ static const char version[] = "de600.c: $Revision: 1.41-2.5 $,  Bjorn Ekwall (bj
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/in.h>
-#include <asm/system.h>
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/delay.h>
index afc5aaa..2e2bc60 100644 (file)
@@ -122,7 +122,6 @@ static const char version[] =
 #include <linux/skbuff.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 
 /* Constant definitions for the DE-620 registers, commands and bits */
 #include "de620.h"
index 586b46f..3d94797 100644 (file)
@@ -52,7 +52,6 @@
 #include <linux/crc32.h>
 #include <linux/bitops.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 
index c3f0178..a992d1f 100644 (file)
@@ -163,7 +163,6 @@ static char *version =
 #include <linux/jiffies.h>
 #include <linux/io.h>
 
-#include <asm/system.h>
 #include <asm/dma.h>
 
 
index 0230319..2418faf 100644 (file)
@@ -57,7 +57,6 @@
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 /*====================================================================*/
 
index ed6925f..e8984b0 100644 (file)
@@ -63,7 +63,6 @@ static const char version[] =
 
 #include <asm/dma.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 
 /* use 0 for production, 1 for verification, 2..7 for debug */
index ef43f3e..278e791 100644 (file)
@@ -106,7 +106,6 @@ DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " Richard Procter <rnp@paradise.net.
 #include <linux/semaphore.h>
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 
index 7a4ad4a..7f49fd5 100644 (file)
@@ -148,7 +148,6 @@ static const char version[] =
 #include <linux/bitops.h>
 #include <linux/ethtool.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 
index 3fc649e..cc2e66a 100644 (file)
 #include <linux/bitops.h>
 #include <linux/jiffies.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 
index 406a12b..067db3f 100644 (file)
@@ -48,7 +48,6 @@
 #include <linux/skbuff.h>
 #include <linux/bitops.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/ecard.h>
index a436497..bd1f1ef 100644 (file)
 #include <linux/if_arp.h>
 #include <linux/bitops.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 
index e877371..9010cea 100644 (file)
@@ -1616,11 +1616,8 @@ static struct vio_driver ibmveth_driver = {
        .probe          = ibmveth_probe,
        .remove         = ibmveth_remove,
        .get_desired_dma = ibmveth_get_desired_dma,
-       .driver         = {
-               .name   = ibmveth_driver_name,
-               .owner  = THIS_MODULE,
-               .pm = &ibmveth_pm_ops,
-       }
+       .name           = ibmveth_driver_name,
+       .pm             = &ibmveth_pm_ops,
 };
 
 static int __init ibmveth_module_init(void)
index f30db1c..bc58f1d 100644 (file)
@@ -55,7 +55,6 @@
 #include <linux/crc32.h>
 
 #include <asm/bootinfo.h>
-#include <asm/system.h>
 #include <asm/bitops.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
index 75af1af..5e1ca0f 100644 (file)
@@ -57,7 +57,6 @@
 #include <linux/types.h>
 #include <linux/inet_lro.h>
 #include <linux/slab.h>
-#include <asm/system.h>
 
 static char mv643xx_eth_driver_name[] = "mv643xx_eth";
 static char mv643xx_eth_driver_version[] = "1.4";
index 45a6333..efec6b6 100644 (file)
@@ -43,7 +43,6 @@
 #include <linux/interrupt.h>
 #include <linux/types.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <asm/cacheflush.h>
 #include <linux/pxa168_eth.h>
 
index 5b89fd3..95dd39f 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/slab.h>
 
 #include <asm/bootinfo.h>
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
 #include <asm/dma.h>
index e640e23..b9680ba 100644 (file)
@@ -53,7 +53,6 @@
 #include <linux/slab.h>
 
 #include <asm/bootinfo.h>
-#include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
 #include <asm/hwtest.h>
index c24b46c..d52728b 100644 (file)
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 
 #define DRV_NAME "ns83820"
 
index 22a8de0..6338ef8 100644 (file)
@@ -81,7 +81,6 @@
 #include <linux/prefetch.h>
 #include <net/tcp.h>
 
-#include <asm/system.h>
 #include <asm/div64.h>
 #include <asm/irq.h>
 
index 8561dd2..aca1304 100644 (file)
@@ -69,7 +69,6 @@
 #include <linux/io.h>
 
 #include <asm/irq.h>
-#include <asm/system.h>
 
 #define TX_WORK_PER_LOOP  64
 #define RX_WORK_PER_LOOP  64
index 46c1932..e02f04d 100644 (file)
@@ -140,7 +140,6 @@ static int xcvr[NUM_UNITS];                         /* The data transfer mode. */
 #include <linux/delay.h>
 #include <linux/bitops.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 
index 27c358c..7b23554 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/pci-aspm.h>
 #include <linux/prefetch.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 
index 7b819bd..df808ac 100644 (file)
@@ -64,7 +64,6 @@
 #include <linux/delay.h>
 #include <linux/bitops.h>
 
-#include <asm/system.h>
 #include <asm/ecard.h>
 #include <asm/io.h>
 
index 7989907..698edbb 100644 (file)
@@ -47,7 +47,6 @@ static const char version[] =
 #include <linux/bitops.h>
 #include <linux/jiffies.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 
index d12e48a..04393b5 100644 (file)
@@ -53,7 +53,6 @@
 #include <pcmcia/ss.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 
 /*====================================================================*/
index 3c22955..ce4df61 100644 (file)
@@ -99,7 +99,6 @@
 #include <net/checksum.h>
 
 #include <linux/atomic.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/byteorder.h>
 #include <asm/uaccess.h>
index f359863..2a83fc5 100644 (file)
@@ -35,7 +35,6 @@
 #include <asm/openprom.h>
 #include <asm/oplib.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 
 #include "sunbmac.h"
 
index ba04159..558409f 100644 (file)
@@ -41,7 +41,6 @@
 #include <linux/mm.h>
 #include <linux/gfp.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/byteorder.h>
 #include <asm/uaccess.h>
index 8b627e2..b95e7e6 100644 (file)
@@ -36,7 +36,6 @@
 #include <linux/bitops.h>
 #include <linux/dma-mapping.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/byteorder.h>
index 139d6b4..7d4a040 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/of.h>
 #include <linux/of_device.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/byteorder.h>
index 92a037a..38e3ae9 100644 (file)
@@ -1259,10 +1259,7 @@ static struct vio_driver vnet_port_driver = {
        .id_table       = vnet_port_match,
        .probe          = vnet_port_probe,
        .remove         = vnet_port_remove,
-       .driver         = {
-               .name   = "vnet_port",
-               .owner  = THIS_MODULE,
-       }
+       .name           = "vnet_port",
 };
 
 static int __init vnet_init(void)
index 840e0e9..277c93e 100644 (file)
@@ -50,7 +50,6 @@
 #include <linux/platform_device.h>
 #include <linux/gfp.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/tsi108.h>
 
index 5c69c6f..94a1f94 100644 (file)
@@ -89,7 +89,6 @@
 #include <pcmcia/ciscode.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 
 #ifndef MANFID_COMPAQ
index 2a5a34d..64783a0 100644 (file)
@@ -13,7 +13,6 @@
  */
 
 #include <linux/module.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <linux/bitops.h>
 #include <linux/string.h>
index f1aea0c..acb6369 100644 (file)
@@ -86,7 +86,6 @@
 #include <linux/bitops.h>
 #include <linux/jiffies.h>
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 
 /* --------------------------------------------------------------------- */
index 18d8aff..76d5477 100644 (file)
@@ -69,7 +69,6 @@
 #include <linux/if_arp.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index bc02968..aed1a61 100644 (file)
@@ -17,7 +17,6 @@
  * Copyright (C) 2004, 05 Thomas Osterried DL9SAU <thomas@x-berg.in-berlin.de>
  */
 #include <linux/module.h>
-#include <asm/system.h>
 #include <linux/bitops.h>
 #include <asm/uaccess.h>
 #include <linux/crc16.h>
index 3365581..efc6c97 100644 (file)
 #include <net/ax25.h>
 
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
index 6963277..5a6412e 100644 (file)
@@ -52,7 +52,6 @@
 #include <linux/bitops.h>
 #include <linux/random.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/firmware.h>
index 2a51363..168c8f4 100644 (file)
@@ -43,7 +43,6 @@
 #include <linux/slab.h>
 #include <net/sock.h>
 
-#include <asm/system.h>
 #include <asm/cache.h>
 #include <asm/byteorder.h>
 #include <asm/io.h>
index 617a446..4351296 100644 (file)
 #include <linux/pci.h>
 #include <linux/rtnetlink.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 
 #include <net/irda/wrapper.h>
index b71998d..32eb94e 100644 (file)
@@ -41,7 +41,6 @@
 #include <linux/in.h>
 #include <linux/init.h>
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
index 1a5a316..bed62d9 100644 (file)
@@ -113,7 +113,6 @@ static const char version[] = "NET3 PLIP version 2.4-parport gniibe@mri.co.jp\n"
 
 #include <net/neighbour.h>
 
-#include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/byteorder.h>
 
index 0a0a664..1252d9c 100644 (file)
@@ -75,7 +75,6 @@
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <linux/timer.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <net/checksum.h>
 #include <asm/unaligned.h>
index 69345df..d4c9db3 100644 (file)
@@ -64,7 +64,6 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <linux/bitops.h>
 #include <linux/sched.h>
index d7c292a..b15ac81 100644 (file)
@@ -68,7 +68,6 @@
 #include <net/checksum.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include "3c359.h"
 
index 515f122..b715e6b 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/netdevice.h>
 #include <linux/trdevice.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 
index 91b6846..356e28e 100644 (file)
@@ -63,7 +63,6 @@
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 #define PCMCIA
 #include "ibmtr.c"
index 8d71e0d..3e4b4f0 100644 (file)
 #include <net/checksum.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include "lanstreamer.h"
 
index 1cdc034..28adcdf 100644 (file)
@@ -28,7 +28,6 @@ static const char version[] = "madgemc.c: v0.91 23/01/2000 by Adam Fritzler\n";
 #include <linux/netdevice.h>
 #include <linux/trdevice.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 
index fd8dce9..0e23474 100644 (file)
 #include <net/net_namespace.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include "olympic.h"
 
index 8d362e6..62d90e4 100644 (file)
@@ -31,7 +31,6 @@ static const char version[] = "proteon.c: v1.00 02/01/2003 by Jochen Friedrich\n
 #include <linux/trdevice.h>
 #include <linux/platform_device.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/pci.h>
index 46db5c5..ee11e93 100644 (file)
@@ -38,7 +38,6 @@ static const char version[] = "skisa.c: v1.03 09/12/2002 by Jochen Friedrich\n";
 #include <linux/trdevice.h>
 #include <linux/platform_device.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/pci.h>
index 029846a..cb35fb7 100644 (file)
@@ -49,7 +49,6 @@
 #include <linux/bitops.h>
 #include <linux/firmware.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/irq.h>
index 102f896..be4813e 100644 (file)
@@ -98,7 +98,6 @@ static const char version[] = "tms380tr.c: v1.10 30/12/2002 by Christoph Goos, A
 #include <linux/firmware.h>
 #include <linux/bitops.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/irq.h>
index d3e788a..fb9918d 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/netdevice.h>
 #include <linux/trdevice.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 
index 74d7f76..bb8c72c 100644 (file)
@@ -69,7 +69,6 @@
 #include <net/rtnetlink.h>
 #include <net/sock.h>
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 
 /* Uncomment to enable debugging */
index 48ab38a..147614e 100644 (file)
@@ -50,7 +50,6 @@
 
 #include <net/sock.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/uaccess.h>
index fe8d060..c676de7 100644 (file)
@@ -93,7 +93,6 @@
 #include <linux/mm.h>
 #include <linux/slab.h>
 
-#include <asm/system.h>
 #include <asm/cache.h>
 #include <asm/byteorder.h>
 #include <asm/uaccess.h>
index 33b67d8..cf49033 100644 (file)
@@ -40,7 +40,6 @@
 #include <linux/string.h>
 #include <linux/types.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include "hd64570.h"
 
index efc0db1..e2779fa 100644 (file)
@@ -40,7 +40,6 @@
 #include <linux/string.h>
 #include <linux/types.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include "hd64572.h"
 
index 7beeb9b..a73b49e 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/if_arp.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index c853161..de3bbf4 100644 (file)
@@ -54,7 +54,6 @@
 #include <linux/sdla.h>
 #include <linux/bitops.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/uaccess.h>
index e862369..d7a65e1 100644 (file)
@@ -18,7 +18,6 @@
 
 #include <linux/module.h>
 
-#include <asm/system.h>
 #include <linux/uaccess.h>
 #include <linux/bitops.h>
 #include <linux/string.h>
index ddc061d..520a4b2 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/scatterlist.h>
 #include <linux/crypto.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/unaligned.h>
 
 #include <linux/netdevice.h>
index c983c10..630577d 100644 (file)
@@ -37,7 +37,6 @@
 #include <pcmcia/ds.h>
 
 #include <linux/io.h>
-#include <asm/system.h>
 
 #include "airo.h"
 
index 3010cee..6c87a82 100644 (file)
@@ -50,7 +50,6 @@
 #include <linux/timer.h>
 #include <asm/byteorder.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
index ec295c4..ded03d2 100644 (file)
@@ -48,7 +48,6 @@
 #include <pcmcia/ciscode.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 #include <linux/wireless.h>
 
 #include "atmel.h"
index 851fa10..c5404cb 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/slab.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 #include <linux/if_arp.h>
 
 #include "prismcompat.h"
index 04fec1f..86a738b 100644 (file)
@@ -53,7 +53,6 @@
 #include <net/iw_handler.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/byteorder.h>
 #include <asm/uaccess.h>
 
index 98fbf54..00f6e69 100644 (file)
@@ -53,7 +53,6 @@
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 
 #include "wl3501.h"
 
index b764ac2..44d01af 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <asm/setup.h>
-#include <asm/system.h>
 #include <asm/page.h>
 #include <asm/hwtest.h>
 #include <linux/proc_fs.h>
index 6ea51dc..8e84ce9 100644 (file)
@@ -91,4 +91,8 @@ config OF_PCI_IRQ
        help
          OpenFirmware PCI IRQ routing helpers
 
+config OF_MTD
+       depends on MTD
+       def_bool y
+
 endmenu # OF
index a73f5a5..aa90e60 100644 (file)
@@ -12,3 +12,4 @@ obj-$(CONFIG_OF_SELFTEST) += selftest.o
 obj-$(CONFIG_OF_MDIO)  += of_mdio.o
 obj-$(CONFIG_OF_PCI)   += of_pci.o
 obj-$(CONFIG_OF_PCI_IRQ)  += of_pci_irq.o
+obj-$(CONFIG_OF_MTD)   += of_mtd.o
index 7e62d15..bba8121 100644 (file)
@@ -78,8 +78,9 @@ err0:
 EXPORT_SYMBOL(of_get_named_gpio_flags);
 
 /**
- * of_gpio_count - Count GPIOs for a device
+ * of_gpio_named_count - Count GPIOs for a device
  * @np:                device node to count GPIOs for
+ * @propname:  property name containing gpio specifier(s)
  *
  * The function returns the count of GPIOs specified for a node.
  *
@@ -93,14 +94,14 @@ EXPORT_SYMBOL(of_get_named_gpio_flags);
  * defines four GPIOs (so this function will return 4), two of which
  * are not specified.
  */
-unsigned int of_gpio_count(struct device_node *np)
+unsigned int of_gpio_named_count(struct device_node *np, const char* propname)
 {
        unsigned int cnt = 0;
 
        do {
                int ret;
 
-               ret = of_parse_phandle_with_args(np, "gpios", "#gpio-cells",
+               ret = of_parse_phandle_with_args(np, propname, "#gpio-cells",
                                                 cnt, NULL);
                /* A hole in the gpios = <> counts anyway. */
                if (ret < 0 && ret != -EEXIST)
@@ -109,7 +110,7 @@ unsigned int of_gpio_count(struct device_node *np)
 
        return cnt;
 }
-EXPORT_SYMBOL(of_gpio_count);
+EXPORT_SYMBOL(of_gpio_named_count);
 
 /**
  * of_gpio_simple_xlate - translate gpio_spec to the GPIO number and flags
@@ -228,7 +229,7 @@ void of_gpiochip_remove(struct gpio_chip *chip)
 }
 
 /* Private function for resolving node pointer to gpio_chip */
-static int of_gpiochip_is_match(struct gpio_chip *chip, void *data)
+static int of_gpiochip_is_match(struct gpio_chip *chip, const void *data)
 {
        return chip->of_node == data;
 }
diff --git a/drivers/of/of_mtd.c b/drivers/of/of_mtd.c
new file mode 100644 (file)
index 0000000..e7cad62
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * OF helpers for mtd.
+ *
+ * This file is released under the GPLv2
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/of_mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/export.h>
+
+/**
+ * It maps 'enum nand_ecc_modes_t' found in include/linux/mtd/nand.h
+ * into the device tree binding of 'nand-ecc', so that MTD
+ * device driver can get nand ecc from device tree.
+ */
+static const char *nand_ecc_modes[] = {
+       [NAND_ECC_NONE]         = "none",
+       [NAND_ECC_SOFT]         = "soft",
+       [NAND_ECC_HW]           = "hw",
+       [NAND_ECC_HW_SYNDROME]  = "hw_syndrome",
+       [NAND_ECC_HW_OOB_FIRST] = "hw_oob_first",
+       [NAND_ECC_SOFT_BCH]     = "soft_bch",
+};
+
+/**
+ * of_get_nand_ecc_mode - Get nand ecc mode for given device_node
+ * @np:        Pointer to the given device_node
+ *
+ * The function gets ecc mode string from property 'nand-ecc-mode',
+ * and return its index in nand_ecc_modes table, or errno in error case.
+ */
+const int of_get_nand_ecc_mode(struct device_node *np)
+{
+       const char *pm;
+       int err, i;
+
+       err = of_property_read_string(np, "nand-ecc-mode", &pm);
+       if (err < 0)
+               return err;
+
+       for (i = 0; i < ARRAY_SIZE(nand_ecc_modes); i++)
+               if (!strcasecmp(pm, nand_ecc_modes[i]))
+                       return i;
+
+       return -ENODEV;
+}
+EXPORT_SYMBOL_GPL(of_get_nand_ecc_mode);
+
+/**
+ * of_get_nand_bus_width - Get nand bus witdh for given device_node
+ * @np:        Pointer to the given device_node
+ *
+ * return bus width option, or errno in error case.
+ */
+int of_get_nand_bus_width(struct device_node *np)
+{
+       u32 val;
+
+       if (of_property_read_u32(np, "nand-bus-width", &val))
+               return 8;
+
+       switch(val) {
+       case 8:
+       case 16:
+               return val;
+       default:
+               return -EIO;
+       }
+}
+EXPORT_SYMBOL_GPL(of_get_nand_bus_width);
+
+/**
+ * of_get_nand_on_flash_bbt - Get nand on flash bbt for given device_node
+ * @np:        Pointer to the given device_node
+ *
+ * return true if present false other wise
+ */
+bool of_get_nand_on_flash_bbt(struct device_node *np)
+{
+       return of_property_read_bool(np, "nand-on-flash-bbt");
+}
+EXPORT_SYMBOL_GPL(of_get_nand_on_flash_bbt);
index 0610e91..432d4bb 100644 (file)
@@ -55,7 +55,6 @@
 
 #include <asm/pdc.h>
 #include <asm/page.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/hardware.h>
 
index 95930d0..1f9e9fe 100644 (file)
 #include <asm/pdc.h>
 #include <asm/pdcpat.h>
 #include <asm/page.h>
-#include <asm/system.h>
 #include <asm/io.h>            /* read/write functions */
 #ifdef CONFIG_SUPERIO
 #include <asm/superio.h>
index e885764..052fa23 100644 (file)
@@ -43,7 +43,6 @@
 #include <asm/pdc.h>
 #include <asm/pdcpat.h>
 #include <asm/page.h>
-#include <asm/system.h>
 
 #include <asm/ropes.h>
 #include <asm/hardware.h>      /* for register_parisc_driver() stuff */
index d9ea192..673c14e 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/device.h>
 #include <linux/kthread.h>
 #include <linux/freezer.h>
-#include <asm/system.h>
 #include <asm/irq.h>
 
 #include <pcmcia/ss.h>
index 3e447d0..0b66bfc 100644 (file)
@@ -17,7 +17,6 @@
 
 #include <pcmcia/ss.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 
 #include "i82092aa.h"
index 72a033a..e6f3d17 100644 (file)
@@ -48,7 +48,6 @@
 #include <linux/bitops.h>
 #include <asm/irq.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include <pcmcia/ss.h>
 
index 2adb010..a26f38c 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/bitops.h>
 #include <asm/irq.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include <pcmcia/ss.h>
 
index 1511ff7..2965141 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/bitops.h>
 #include <asm/irq.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/addrspace.h>
 
 #include <pcmcia/ss.h>
index 271a590..a317def 100644 (file)
@@ -52,7 +52,6 @@
 #include <linux/of_platform.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/mpc8xx.h>
 #include <asm/8xx_immap.h>
index 96c72e9..0f8b70b 100644 (file)
@@ -19,7 +19,6 @@
 
 #include <pcmcia/ss.h>
 
-#include <asm/system.h>
 
 #include "pd6729.h"
 #include "i82365.h"
index 66a5422..490bb82 100644 (file)
@@ -29,7 +29,6 @@
 #include <mach/smemc.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <mach/pxa2xx-regs.h>
 #include <asm/mach-types.h>
 
index a3ee89a..6eecd7c 100644 (file)
@@ -41,7 +41,6 @@
 
 #include <mach/hardware.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 
 #include "soc_common.h"
 #include "sa11xx_base.h"
index e0433f5..a2bc6ee 100644 (file)
@@ -46,7 +46,6 @@
 #include <linux/timer.h>
 
 #include <mach/hardware.h>
-#include <asm/system.h>
 
 #include "soc_common.h"
 
index 71aeed9..d688151 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/pm.h>
 #include <linux/device.h>
 #include <linux/mutex.h>
-#include <asm/system.h>
 #include <asm/irq.h>
 
 #include <pcmcia/ss.h>
index 310160b..cbe15fc 100644 (file)
@@ -47,7 +47,6 @@
 #include <linux/bitops.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include <pcmcia/ss.h>
 #include "tcic.h"
index 379f421..8f66980 100644 (file)
@@ -21,7 +21,6 @@
 #include <pcmcia/cistpl.h>
 
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/mach-au1x00/au1000.h>
 
 #define MEM_MAP_SIZE   0x400000
index 2dc02c9..2a262f5 100644 (file)
@@ -26,6 +26,10 @@ config ACER_WMI
        depends on RFKILL || RFKILL = n
        depends on ACPI_WMI
        select INPUT_SPARSEKMAP
+       # Acer WMI depends on ACPI_VIDEO when ACPI is enabled
+       # but for select to work, need to select ACPI_VIDEO's dependencies, ick
+        select VIDEO_OUTPUT_CONTROL if ACPI
+        select ACPI_VIDEO if ACPI
        ---help---
          This is a driver for newer Acer (and Wistron) laptops. It adds
          wireless radio and bluetooth control, and on some laptops,
@@ -54,7 +58,6 @@ config ACERHDF
 config ASUS_LAPTOP
        tristate "Asus Laptop Extras"
        depends on ACPI
-       depends on !ACPI_ASUS
        select LEDS_CLASS
        select NEW_LEDS
        select BACKLIGHT_CLASS_DEVICE
@@ -460,10 +463,9 @@ config INTEL_MENLOW
          If unsure, say N.
 
 config EEEPC_LAPTOP
-       tristate "Eee PC Hotkey Driver (EXPERIMENTAL)"
+       tristate "Eee PC Hotkey Driver"
        depends on ACPI
        depends on INPUT
-       depends on EXPERIMENTAL
        depends on RFKILL || RFKILL = n
        depends on HOTPLUG_PCI
        select BACKLIGHT_CLASS_DEVICE
@@ -482,11 +484,10 @@ config EEEPC_LAPTOP
          doesn't work on your Eee PC, try eeepc-wmi instead.
 
 config ASUS_WMI
-       tristate "ASUS WMI Driver (EXPERIMENTAL)"
+       tristate "ASUS WMI Driver"
        depends on ACPI_WMI
        depends on INPUT
        depends on HWMON
-       depends on EXPERIMENTAL
        depends on BACKLIGHT_CLASS_DEVICE
        depends on RFKILL || RFKILL = n
        depends on HOTPLUG_PCI
@@ -501,7 +502,7 @@ config ASUS_WMI
          be called asus-wmi.
 
 config ASUS_NB_WMI
-       tristate "Asus Notebook WMI Driver (EXPERIMENTAL)"
+       tristate "Asus Notebook WMI Driver"
        depends on ASUS_WMI
        ---help---
          This is a driver for newer Asus notebooks. It adds extra features
@@ -514,7 +515,7 @@ config ASUS_NB_WMI
          here.
 
 config EEEPC_WMI
-       tristate "Eee PC WMI Driver (EXPERIMENTAL)"
+       tristate "Eee PC WMI Driver"
        depends on ASUS_WMI
        ---help---
          This is a driver for newer Eee PC laptops. It adds extra features
@@ -559,38 +560,6 @@ config MSI_WMI
         To compile this driver as a module, choose M here: the module will
         be called msi-wmi.
 
-config ACPI_ASUS
-       tristate "ASUS/Medion Laptop Extras (DEPRECATED)"
-       depends on ACPI
-       select BACKLIGHT_CLASS_DEVICE
-       ---help---
-         This driver provides support for extra features of ACPI-compatible
-         ASUS laptops. As some of Medion laptops are made by ASUS, it may also
-         support some Medion laptops (such as 9675 for example).  It makes all
-         the extra buttons generate standard ACPI events that go through
-         /proc/acpi/events, and (on some models) adds support for changing the
-         display brightness and output, switching the LCD backlight on and off,
-         and most importantly, allows you to blink those fancy LEDs intended
-         for reporting mail and wireless status.
-
-         Note: display switching code is currently considered EXPERIMENTAL,
-         toying with these values may even lock your machine.
-
-         All settings are changed via /proc/acpi/asus directory entries. Owner
-         and group for these entries can be set with asus_uid and asus_gid
-         parameters.
-
-         More information and a userspace daemon for handling the extra buttons
-         at <http://acpi4asus.sf.net>.
-
-         If you have an ACPI-compatible ASUS laptop, say Y or M here. This
-         driver is still under development, so if your laptop is unsupported or
-         something works not quite as expected, please use the mailing list
-         available on the above page (acpi4asus-user@lists.sourceforge.net).
-
-         NOTE: This driver is deprecated and will probably be removed soon,
-         use asus-laptop instead.
-
 config TOPSTAR_LAPTOP
        tristate "Topstar Laptop Extras"
        depends on ACPI
@@ -604,6 +573,7 @@ config TOPSTAR_LAPTOP
 config ACPI_TOSHIBA
        tristate "Toshiba Laptop Extras"
        depends on ACPI
+       depends on ACPI_WMI
        select LEDS_CLASS
        select NEW_LEDS
        depends on BACKLIGHT_CLASS_DEVICE
@@ -746,13 +716,18 @@ config XO15_EBOOK
 
 config SAMSUNG_LAPTOP
        tristate "Samsung Laptop driver"
-       depends on RFKILL && BACKLIGHT_CLASS_DEVICE && X86
+       depends on X86
+       depends on RFKILL || RFKILL = n
+       depends on BACKLIGHT_CLASS_DEVICE
+       select LEDS_CLASS
+       select NEW_LEDS
        ---help---
          This module implements a driver for a wide range of different
          Samsung laptops.  It offers control over the different
-         function keys, wireless LED, LCD backlight level, and
-         sometimes provides a "performance_control" sysfs file to allow
-         the performance level of the laptop to be changed.
+         function keys, wireless LED, LCD backlight level.
+
+         It may also provide some sysfs files described in
+         <file:Documentation/ABI/testing/sysfs-platform-samsung-laptop>
 
          To compile this driver as a module, choose M here: the module
          will be called samsung-laptop.
@@ -781,4 +756,14 @@ config SAMSUNG_Q10
          This driver provides support for backlight control on Samsung Q10
          and related laptops, including Dell Latitude X200.
 
+config APPLE_GMUX
+       tristate "Apple Gmux Driver"
+       depends on PNP
+       select BACKLIGHT_CLASS_DEVICE
+       ---help---
+         This driver provides support for the gmux device found on many
+         Apple laptops, which controls the display mux for the hybrid
+         graphics as well as the backlight. Currently only backlight
+         control is supported by the driver.
+
 endif # X86_PLATFORM_DEVICES
index bb94765..bf7e4f9 100644 (file)
@@ -29,9 +29,12 @@ obj-$(CONFIG_PANASONIC_LAPTOP)       += panasonic-laptop.o
 obj-$(CONFIG_INTEL_MENLOW)     += intel_menlow.o
 obj-$(CONFIG_ACPI_WMI)         += wmi.o
 obj-$(CONFIG_MSI_WMI)          += msi-wmi.o
-obj-$(CONFIG_ACPI_ASUS)                += asus_acpi.o
 obj-$(CONFIG_TOPSTAR_LAPTOP)   += topstar-laptop.o
+
+# toshiba_acpi must link after wmi to ensure that wmi devices are found
+# before toshiba_acpi initializes
 obj-$(CONFIG_ACPI_TOSHIBA)     += toshiba_acpi.o
+
 obj-$(CONFIG_TOSHIBA_BT_RFKILL)        += toshiba_bluetooth.o
 obj-$(CONFIG_INTEL_SCU_IPC)    += intel_scu_ipc.o
 obj-$(CONFIG_INTEL_SCU_IPC_UTIL) += intel_scu_ipcutil.o
@@ -46,3 +49,4 @@ obj-$(CONFIG_MXM_WMI)         += mxm-wmi.o
 obj-$(CONFIG_INTEL_MID_POWER_BUTTON)   += intel_mid_powerbtn.o
 obj-$(CONFIG_INTEL_OAKTRAIL)   += intel_oaktrail.o
 obj-$(CONFIG_SAMSUNG_Q10)      += samsung-q10.o
+obj-$(CONFIG_APPLE_GMUX)       += apple-gmux.o
index 1e5290b..c1a3fd8 100644 (file)
@@ -43,6 +43,7 @@
 #include <linux/input/sparse-keymap.h>
 
 #include <acpi/acpi_drivers.h>
+#include <acpi/video.h>
 
 MODULE_AUTHOR("Carlos Corbacho");
 MODULE_DESCRIPTION("Acer Laptop WMI Extras Driver");
@@ -105,13 +106,19 @@ static const struct key_entry acer_wmi_keymap[] = {
        {KE_KEY, 0x22, {KEY_PROG2} },    /* Arcade */
        {KE_KEY, 0x23, {KEY_PROG3} },    /* P_Key */
        {KE_KEY, 0x24, {KEY_PROG4} },    /* Social networking_Key */
+       {KE_KEY, 0x29, {KEY_PROG3} },    /* P_Key for TM8372 */
        {KE_IGNORE, 0x41, {KEY_MUTE} },
        {KE_IGNORE, 0x42, {KEY_PREVIOUSSONG} },
+       {KE_IGNORE, 0x4d, {KEY_PREVIOUSSONG} },
        {KE_IGNORE, 0x43, {KEY_NEXTSONG} },
+       {KE_IGNORE, 0x4e, {KEY_NEXTSONG} },
        {KE_IGNORE, 0x44, {KEY_PLAYPAUSE} },
+       {KE_IGNORE, 0x4f, {KEY_PLAYPAUSE} },
        {KE_IGNORE, 0x45, {KEY_STOP} },
+       {KE_IGNORE, 0x50, {KEY_STOP} },
        {KE_IGNORE, 0x48, {KEY_VOLUMEUP} },
        {KE_IGNORE, 0x49, {KEY_VOLUMEDOWN} },
+       {KE_IGNORE, 0x4a, {KEY_VOLUMEDOWN} },
        {KE_IGNORE, 0x61, {KEY_SWITCHVIDEOMODE} },
        {KE_IGNORE, 0x62, {KEY_BRIGHTNESSUP} },
        {KE_IGNORE, 0x63, {KEY_BRIGHTNESSDOWN} },
@@ -153,7 +160,14 @@ struct lm_return_value {
        u16 reserved;
 } __attribute__((packed));
 
-struct wmid3_gds_input_param { /* Get Device Status input parameter */
+struct wmid3_gds_set_input_param {     /* Set Device Status input parameter */
+       u8 function_num;        /* Function Number */
+       u8 hotkey_number;       /* Hotkey Number */
+       u16 devices;            /* Set Device */
+       u8 volume_value;        /* Volume Value */
+} __attribute__((packed));
+
+struct wmid3_gds_get_input_param {     /* Get Device Status input parameter */
        u8 function_num;        /* Function Number */
        u8 hotkey_number;       /* Hotkey Number */
        u16 devices;            /* Get Device */
@@ -171,6 +185,11 @@ struct hotkey_function_type_aa {
        u8 length;
        u16 handle;
        u16 commun_func_bitmap;
+       u16 application_func_bitmap;
+       u16 media_func_bitmap;
+       u16 display_func_bitmap;
+       u16 others_func_bitmap;
+       u8 commun_fn_key_number;
 } __attribute__((packed));
 
 /*
@@ -207,6 +226,7 @@ static int force_series;
 static bool ec_raw_mode;
 static bool has_type_aa;
 static u16 commun_func_bitmap;
+static u8 commun_fn_key_number;
 
 module_param(mailled, int, 0444);
 module_param(brightness, int, 0444);
@@ -468,6 +488,15 @@ static struct dmi_system_id acer_quirks[] = {
        },
        {
                .callback = dmi_matched,
+               .ident = "Lenovo Ideapad S205 (Brazos)",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Brazos"),
+               },
+               .driver_data = &quirk_lenovo_ideapad_s205,
+       },
+       {
+               .callback = dmi_matched,
                .ident = "Lenovo 3000 N200",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
@@ -478,6 +507,25 @@ static struct dmi_system_id acer_quirks[] = {
        {}
 };
 
+static int video_set_backlight_video_vendor(const struct dmi_system_id *d)
+{
+       interface->capability &= ~ACER_CAP_BRIGHTNESS;
+       pr_info("Brightness must be controlled by generic video driver\n");
+       return 0;
+}
+
+static const struct dmi_system_id video_vendor_dmi_table[] = {
+       {
+               .callback = video_set_backlight_video_vendor,
+               .ident = "Acer TravelMate 4750",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "Acer"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 4750"),
+               },
+       },
+       {}
+};
+
 /* Find which quirks are needed for a particular vendor/ model pair */
 static void find_quirks(void)
 {
@@ -536,8 +584,7 @@ struct acpi_buffer *result)
        return status;
 }
 
-static acpi_status AMW0_get_u32(u32 *value, u32 cap,
-struct wmi_interface *iface)
+static acpi_status AMW0_get_u32(u32 *value, u32 cap)
 {
        int err;
        u8 result;
@@ -607,7 +654,7 @@ struct wmi_interface *iface)
        return AE_OK;
 }
 
-static acpi_status AMW0_set_u32(u32 value, u32 cap, struct wmi_interface *iface)
+static acpi_status AMW0_set_u32(u32 value, u32 cap)
 {
        struct wmab_args args;
 
@@ -692,6 +739,7 @@ static const struct acpi_device_id norfkill_ids[] = {
        { "VPC2004", 0},
        { "IBM0068", 0},
        { "LEN0068", 0},
+       { "SNY5001", 0},        /* sony-laptop in charge */
        { "", 0},
 };
 
@@ -827,8 +875,7 @@ WMI_execute_u32(u32 method_id, u32 in, u32 *out)
        return status;
 }
 
-static acpi_status WMID_get_u32(u32 *value, u32 cap,
-struct wmi_interface *iface)
+static acpi_status WMID_get_u32(u32 *value, u32 cap)
 {
        acpi_status status;
        u8 tmp;
@@ -864,7 +911,7 @@ struct wmi_interface *iface)
        return status;
 }
 
-static acpi_status WMID_set_u32(u32 value, u32 cap, struct wmi_interface *iface)
+static acpi_status WMID_set_u32(u32 value, u32 cap)
 {
        u32 method_id = 0;
        char param;
@@ -912,13 +959,13 @@ static acpi_status wmid3_get_device_status(u32 *value, u16 device)
        struct wmid3_gds_return_value return_value;
        acpi_status status;
        union acpi_object *obj;
-       struct wmid3_gds_input_param params = {
+       struct wmid3_gds_get_input_param params = {
                .function_num = 0x1,
-               .hotkey_number = 0x01,
+               .hotkey_number = commun_fn_key_number,
                .devices = device,
        };
        struct acpi_buffer input = {
-               sizeof(struct wmid3_gds_input_param),
+               sizeof(struct wmid3_gds_get_input_param),
                &params
        };
        struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
@@ -981,19 +1028,28 @@ static acpi_status wmid3_set_device_status(u32 value, u16 device)
        acpi_status status;
        union acpi_object *obj;
        u16 devices;
-       struct wmid3_gds_input_param params = {
+       struct wmid3_gds_get_input_param get_params = {
                .function_num = 0x1,
-               .hotkey_number = 0x01,
+               .hotkey_number = commun_fn_key_number,
                .devices = commun_func_bitmap,
        };
-       struct acpi_buffer input = {
-               sizeof(struct wmid3_gds_input_param),
-               &params
+       struct acpi_buffer get_input = {
+               sizeof(struct wmid3_gds_get_input_param),
+               &get_params
+       };
+       struct wmid3_gds_set_input_param set_params = {
+               .function_num = 0x2,
+               .hotkey_number = commun_fn_key_number,
+               .devices = commun_func_bitmap,
+       };
+       struct acpi_buffer set_input = {
+               sizeof(struct wmid3_gds_set_input_param),
+               &set_params
        };
        struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
        struct acpi_buffer output2 = { ACPI_ALLOCATE_BUFFER, NULL };
 
-       status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output);
+       status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &get_input, &output);
        if (ACPI_FAILURE(status))
                return status;
 
@@ -1006,7 +1062,7 @@ static acpi_status wmid3_set_device_status(u32 value, u16 device)
                return AE_ERROR;
        }
        if (obj->buffer.length != 8) {
-               pr_warning("Unknown buffer length %d\n", obj->buffer.length);
+               pr_warn("Unknown buffer length %d\n", obj->buffer.length);
                kfree(obj);
                return AE_ERROR;
        }
@@ -1015,18 +1071,16 @@ static acpi_status wmid3_set_device_status(u32 value, u16 device)
        kfree(obj);
 
        if (return_value.error_code || return_value.ec_return_value) {
-               pr_warning("Get Current Device Status failed: "
-                       "0x%x - 0x%x\n", return_value.error_code,
+               pr_warn("Get Current Device Status failed: 0x%x - 0x%x\n",
+                       return_value.error_code,
                        return_value.ec_return_value);
                return status;
        }
 
        devices = return_value.devices;
-       params.function_num = 0x2;
-       params.hotkey_number = 0x01;
-       params.devices = (value) ? (devices | device) : (devices & ~device);
+       set_params.devices = (value) ? (devices | device) : (devices & ~device);
 
-       status = wmi_evaluate_method(WMID_GUID3, 0, 0x1, &input, &output2);
+       status = wmi_evaluate_method(WMID_GUID3, 0, 0x1, &set_input, &output2);
        if (ACPI_FAILURE(status))
                return status;
 
@@ -1039,7 +1093,7 @@ static acpi_status wmid3_set_device_status(u32 value, u16 device)
                return AE_ERROR;
        }
        if (obj->buffer.length != 4) {
-               pr_warning("Unknown buffer length %d\n", obj->buffer.length);
+               pr_warn("Unknown buffer length %d\n", obj->buffer.length);
                kfree(obj);
                return AE_ERROR;
        }
@@ -1048,8 +1102,8 @@ static acpi_status wmid3_set_device_status(u32 value, u16 device)
        kfree(obj);
 
        if (return_value.error_code || return_value.ec_return_value)
-               pr_warning("Set Device Status failed: "
-                       "0x%x - 0x%x\n", return_value.error_code,
+               pr_warn("Set Device Status failed: 0x%x - 0x%x\n",
+                       return_value.error_code,
                        return_value.ec_return_value);
 
        return status;
@@ -1096,6 +1150,8 @@ static void type_aa_dmi_decode(const struct dmi_header *header, void *dummy)
                interface->capability |= ACER_CAP_THREEG;
        if (type_aa->commun_func_bitmap & ACER_WMID3_GDS_BLUETOOTH)
                interface->capability |= ACER_CAP_BLUETOOTH;
+
+       commun_fn_key_number = type_aa->commun_fn_key_number;
 }
 
 static acpi_status WMID_set_capabilities(void)
@@ -1154,15 +1210,15 @@ static acpi_status get_u32(u32 *value, u32 cap)
 
        switch (interface->type) {
        case ACER_AMW0:
-               status = AMW0_get_u32(value, cap, interface);
+               status = AMW0_get_u32(value, cap);
                break;
        case ACER_AMW0_V2:
                if (cap == ACER_CAP_MAILLED) {
-                       status = AMW0_get_u32(value, cap, interface);
+                       status = AMW0_get_u32(value, cap);
                        break;
                }
        case ACER_WMID:
-               status = WMID_get_u32(value, cap, interface);
+               status = WMID_get_u32(value, cap);
                break;
        case ACER_WMID_v2:
                if (cap & (ACER_CAP_WIRELESS |
@@ -1170,7 +1226,7 @@ static acpi_status get_u32(u32 *value, u32 cap)
                           ACER_CAP_THREEG))
                        status = wmid_v2_get_u32(value, cap);
                else if (wmi_has_guid(WMID_GUID2))
-                       status = WMID_get_u32(value, cap, interface);
+                       status = WMID_get_u32(value, cap);
                break;
        }
 
@@ -1184,10 +1240,10 @@ static acpi_status set_u32(u32 value, u32 cap)
        if (interface->capability & cap) {
                switch (interface->type) {
                case ACER_AMW0:
-                       return AMW0_set_u32(value, cap, interface);
+                       return AMW0_set_u32(value, cap);
                case ACER_AMW0_V2:
                        if (cap == ACER_CAP_MAILLED)
-                               return AMW0_set_u32(value, cap, interface);
+                               return AMW0_set_u32(value, cap);
 
                        /*
                         * On some models, some WMID methods don't toggle
@@ -1197,21 +1253,21 @@ static acpi_status set_u32(u32 value, u32 cap)
                         */
                        if (cap == ACER_CAP_WIRELESS ||
                                cap == ACER_CAP_BLUETOOTH) {
-                               status = WMID_set_u32(value, cap, interface);
+                               status = WMID_set_u32(value, cap);
                                if (ACPI_FAILURE(status))
                                        return status;
 
-                               return AMW0_set_u32(value, cap, interface);
+                               return AMW0_set_u32(value, cap);
                        }
                case ACER_WMID:
-                       return WMID_set_u32(value, cap, interface);
+                       return WMID_set_u32(value, cap);
                case ACER_WMID_v2:
                        if (cap & (ACER_CAP_WIRELESS |
                                   ACER_CAP_BLUETOOTH |
                                   ACER_CAP_THREEG))
                                return wmid_v2_set_u32(value, cap);
                        else if (wmi_has_guid(WMID_GUID2))
-                               return WMID_set_u32(value, cap, interface);
+                               return WMID_set_u32(value, cap);
                default:
                        return AE_BAD_PARAMETER;
                }
@@ -1488,8 +1544,8 @@ static ssize_t show_bool_threeg(struct device *dev,
        u32 result; \
        acpi_status status;
 
-       pr_info("This threeg sysfs will be removed in 2012"
-               " - used by: %s\n", current->comm);
+       pr_info("This threeg sysfs will be removed in 2012 - used by: %s\n",
+               current->comm);
        status = get_u32(&result, ACER_CAP_THREEG);
        if (ACPI_SUCCESS(status))
                return sprintf(buf, "%u\n", result);
@@ -1501,8 +1557,8 @@ static ssize_t set_bool_threeg(struct device *dev,
 {
        u32 tmp = simple_strtoul(buf, NULL, 10);
        acpi_status status = set_u32(tmp, ACER_CAP_THREEG);
-       pr_info("This threeg sysfs will be removed in 2012"
-               " - used by: %s\n", current->comm);
+       pr_info("This threeg sysfs will be removed in 2012 - used by: %s\n",
+               current->comm);
        if (ACPI_FAILURE(status))
                return -EINVAL;
        return count;
@@ -1513,8 +1569,8 @@ static DEVICE_ATTR(threeg, S_IRUGO | S_IWUSR, show_bool_threeg,
 static ssize_t show_interface(struct device *dev, struct device_attribute *attr,
        char *buf)
 {
-       pr_info("This interface sysfs will be removed in 2012"
-               " - used by: %s\n", current->comm);
+       pr_info("This interface sysfs will be removed in 2012 - used by: %s\n",
+               current->comm);
        switch (interface->type) {
        case ACER_AMW0:
                return sprintf(buf, "AMW0\n");
@@ -1981,9 +2037,13 @@ static int __init acer_wmi_init(void)
        set_quirks();
 
        if (acpi_video_backlight_support()) {
-               interface->capability &= ~ACER_CAP_BRIGHTNESS;
-               pr_info("Brightness must be controlled by "
-                      "generic video driver\n");
+               if (dmi_check_system(video_vendor_dmi_table)) {
+                       acpi_video_unregister();
+               } else {
+                       interface->capability &= ~ACER_CAP_BRIGHTNESS;
+                       pr_info("Brightness must be controlled by "
+                               "acpi video driver\n");
+               }
        }
 
        if (wmi_has_guid(WMID_GUID3)) {
@@ -2008,7 +2068,7 @@ static int __init acer_wmi_init(void)
 
        err = platform_driver_register(&acer_platform_driver);
        if (err) {
-               pr_err("Unable to register platform driver.\n");
+               pr_err("Unable to register platform driver\n");
                goto error_platform_register;
        }
 
index 760c6d7..bc8384c 100644 (file)
@@ -244,12 +244,11 @@ static void acerhdf_change_fanstate(int state)
        unsigned char cmd;
 
        if (verbose)
-               pr_notice("fan %s\n", (state == ACERHDF_FAN_OFF) ?
-                               "OFF" : "ON");
+               pr_notice("fan %s\n", state == ACERHDF_FAN_OFF ? "OFF" : "ON");
 
        if ((state != ACERHDF_FAN_OFF) && (state != ACERHDF_FAN_AUTO)) {
                pr_err("invalid fan state %d requested, setting to auto!\n",
-                       state);
+                      state);
                state = ACERHDF_FAN_AUTO;
        }
 
@@ -264,19 +263,18 @@ static void acerhdf_check_param(struct thermal_zone_device *thermal)
 {
        if (fanon > ACERHDF_MAX_FANON) {
                pr_err("fanon temperature too high, set to %d\n",
-                               ACERHDF_MAX_FANON);
+                      ACERHDF_MAX_FANON);
                fanon = ACERHDF_MAX_FANON;
        }
 
        if (kernelmode && prev_interval != interval) {
                if (interval > ACERHDF_MAX_INTERVAL) {
                        pr_err("interval too high, set to %d\n",
-                               ACERHDF_MAX_INTERVAL);
+                              ACERHDF_MAX_INTERVAL);
                        interval = ACERHDF_MAX_INTERVAL;
                }
                if (verbose)
-                       pr_notice("interval changed to: %d\n",
-                                       interval);
+                       pr_notice("interval changed to: %d\n", interval);
                thermal->polling_delay = interval*1000;
                prev_interval = interval;
        }
@@ -587,8 +585,8 @@ static int acerhdf_check_hardware(void)
        }
 
        if (!bios_cfg) {
-               pr_err("unknown (unsupported) BIOS version %s/%s/%s, "
-                       "please report, aborting!\n", vendor, product, version);
+               pr_err("unknown (unsupported) BIOS version %s/%s/%s, please report, aborting!\n",
+                      vendor, product, version);
                return -EINVAL;
        }
 
@@ -598,8 +596,7 @@ static int acerhdf_check_hardware(void)
         */
        if (!kernelmode) {
                pr_notice("Fan control off, to enable do:\n");
-               pr_notice("echo -n \"enabled\" > "
-                       "/sys/class/thermal/thermal_zone0/mode\n");
+               pr_notice("echo -n \"enabled\" > /sys/class/thermal/thermal_zone0/mode\n");
        }
 
        return 0;
index 19170bb..a514bf6 100644 (file)
@@ -97,9 +97,12 @@ static struct rfkill *amilo_rfkill_dev;
 
 static int __devinit amilo_rfkill_probe(struct platform_device *device)
 {
+       int rc;
        const struct dmi_system_id *system_id =
                dmi_first_match(amilo_rfkill_id_table);
-       int rc;
+
+       if (!system_id)
+               return -ENXIO;
 
        amilo_rfkill_dev = rfkill_alloc(KBUILD_MODNAME, &device->dev,
                                        RFKILL_TYPE_WLAN,
diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c
new file mode 100644 (file)
index 0000000..8a582bd
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+ *  Gmux driver for Apple laptops
+ *
+ *  Copyright (C) Canonical Ltd. <seth.forshee@canonical.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.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/backlight.h>
+#include <linux/acpi.h>
+#include <linux/pnp.h>
+#include <linux/apple_bl.h>
+#include <linux/slab.h>
+#include <acpi/video.h>
+#include <asm/io.h>
+
+struct apple_gmux_data {
+       unsigned long iostart;
+       unsigned long iolen;
+
+       struct backlight_device *bdev;
+};
+
+/*
+ * gmux port offsets. Many of these are not yet used, but may be in the
+ * future, and it's useful to have them documented here anyhow.
+ */
+#define GMUX_PORT_VERSION_MAJOR                0x04
+#define GMUX_PORT_VERSION_MINOR                0x05
+#define GMUX_PORT_VERSION_RELEASE      0x06
+#define GMUX_PORT_SWITCH_DISPLAY       0x10
+#define GMUX_PORT_SWITCH_GET_DISPLAY   0x11
+#define GMUX_PORT_INTERRUPT_ENABLE     0x14
+#define GMUX_PORT_INTERRUPT_STATUS     0x16
+#define GMUX_PORT_SWITCH_DDC           0x28
+#define GMUX_PORT_SWITCH_EXTERNAL      0x40
+#define GMUX_PORT_SWITCH_GET_EXTERNAL  0x41
+#define GMUX_PORT_DISCRETE_POWER       0x50
+#define GMUX_PORT_MAX_BRIGHTNESS       0x70
+#define GMUX_PORT_BRIGHTNESS           0x74
+
+#define GMUX_MIN_IO_LEN                        (GMUX_PORT_BRIGHTNESS + 4)
+
+#define GMUX_INTERRUPT_ENABLE          0xff
+#define GMUX_INTERRUPT_DISABLE         0x00
+
+#define GMUX_INTERRUPT_STATUS_ACTIVE   0
+#define GMUX_INTERRUPT_STATUS_DISPLAY  (1 << 0)
+#define GMUX_INTERRUPT_STATUS_POWER    (1 << 2)
+#define GMUX_INTERRUPT_STATUS_HOTPLUG  (1 << 3)
+
+#define GMUX_BRIGHTNESS_MASK           0x00ffffff
+#define GMUX_MAX_BRIGHTNESS            GMUX_BRIGHTNESS_MASK
+
+static inline u8 gmux_read8(struct apple_gmux_data *gmux_data, int port)
+{
+       return inb(gmux_data->iostart + port);
+}
+
+static inline void gmux_write8(struct apple_gmux_data *gmux_data, int port,
+                              u8 val)
+{
+       outb(val, gmux_data->iostart + port);
+}
+
+static inline u32 gmux_read32(struct apple_gmux_data *gmux_data, int port)
+{
+       return inl(gmux_data->iostart + port);
+}
+
+static int gmux_get_brightness(struct backlight_device *bd)
+{
+       struct apple_gmux_data *gmux_data = bl_get_data(bd);
+       return gmux_read32(gmux_data, GMUX_PORT_BRIGHTNESS) &
+              GMUX_BRIGHTNESS_MASK;
+}
+
+static int gmux_update_status(struct backlight_device *bd)
+{
+       struct apple_gmux_data *gmux_data = bl_get_data(bd);
+       u32 brightness = bd->props.brightness;
+
+       /*
+        * Older gmux versions require writing out lower bytes first then
+        * setting the upper byte to 0 to flush the values. Newer versions
+        * accept a single u32 write, but the old method also works, so we
+        * just use the old method for all gmux versions.
+        */
+       gmux_write8(gmux_data, GMUX_PORT_BRIGHTNESS, brightness);
+       gmux_write8(gmux_data, GMUX_PORT_BRIGHTNESS + 1, brightness >> 8);
+       gmux_write8(gmux_data, GMUX_PORT_BRIGHTNESS + 2, brightness >> 16);
+       gmux_write8(gmux_data, GMUX_PORT_BRIGHTNESS + 3, 0);
+
+       return 0;
+}
+
+static const struct backlight_ops gmux_bl_ops = {
+       .get_brightness = gmux_get_brightness,
+       .update_status = gmux_update_status,
+};
+
+static int __devinit gmux_probe(struct pnp_dev *pnp,
+                               const struct pnp_device_id *id)
+{
+       struct apple_gmux_data *gmux_data;
+       struct resource *res;
+       struct backlight_properties props;
+       struct backlight_device *bdev;
+       u8 ver_major, ver_minor, ver_release;
+       int ret = -ENXIO;
+
+       gmux_data = kzalloc(sizeof(*gmux_data), GFP_KERNEL);
+       if (!gmux_data)
+               return -ENOMEM;
+       pnp_set_drvdata(pnp, gmux_data);
+
+       res = pnp_get_resource(pnp, IORESOURCE_IO, 0);
+       if (!res) {
+               pr_err("Failed to find gmux I/O resource\n");
+               goto err_free;
+       }
+
+       gmux_data->iostart = res->start;
+       gmux_data->iolen = res->end - res->start;
+
+       if (gmux_data->iolen < GMUX_MIN_IO_LEN) {
+               pr_err("gmux I/O region too small (%lu < %u)\n",
+                      gmux_data->iolen, GMUX_MIN_IO_LEN);
+               goto err_free;
+       }
+
+       if (!request_region(gmux_data->iostart, gmux_data->iolen,
+                           "Apple gmux")) {
+               pr_err("gmux I/O already in use\n");
+               goto err_free;
+       }
+
+       /*
+        * On some machines the gmux is in ACPI even thought the machine
+        * doesn't really have a gmux. Check for invalid version information
+        * to detect this.
+        */
+       ver_major = gmux_read8(gmux_data, GMUX_PORT_VERSION_MAJOR);
+       ver_minor = gmux_read8(gmux_data, GMUX_PORT_VERSION_MINOR);
+       ver_release = gmux_read8(gmux_data, GMUX_PORT_VERSION_RELEASE);
+       if (ver_major == 0xff && ver_minor == 0xff && ver_release == 0xff) {
+               pr_info("gmux device not present\n");
+               ret = -ENODEV;
+               goto err_release;
+       }
+
+       pr_info("Found gmux version %d.%d.%d\n", ver_major, ver_minor,
+               ver_release);
+
+       memset(&props, 0, sizeof(props));
+       props.type = BACKLIGHT_PLATFORM;
+       props.max_brightness = gmux_read32(gmux_data, GMUX_PORT_MAX_BRIGHTNESS);
+
+       /*
+        * Currently it's assumed that the maximum brightness is less than
+        * 2^24 for compatibility with old gmux versions. Cap the max
+        * brightness at this value, but print a warning if the hardware
+        * reports something higher so that it can be fixed.
+        */
+       if (WARN_ON(props.max_brightness > GMUX_MAX_BRIGHTNESS))
+               props.max_brightness = GMUX_MAX_BRIGHTNESS;
+
+       bdev = backlight_device_register("gmux_backlight", &pnp->dev,
+                                        gmux_data, &gmux_bl_ops, &props);
+       if (IS_ERR(bdev)) {
+               ret = PTR_ERR(bdev);
+               goto err_release;
+       }
+
+       gmux_data->bdev = bdev;
+       bdev->props.brightness = gmux_get_brightness(bdev);
+       backlight_update_status(bdev);
+
+       /*
+        * The backlight situation on Macs is complicated. If the gmux is
+        * present it's the best choice, because it always works for
+        * backlight control and supports more levels than other options.
+        * Disable the other backlight choices.
+        */
+       acpi_video_unregister();
+       apple_bl_unregister();
+
+       return 0;
+
+err_release:
+       release_region(gmux_data->iostart, gmux_data->iolen);
+err_free:
+       kfree(gmux_data);
+       return ret;
+}
+
+static void __devexit gmux_remove(struct pnp_dev *pnp)
+{
+       struct apple_gmux_data *gmux_data = pnp_get_drvdata(pnp);
+
+       backlight_device_unregister(gmux_data->bdev);
+       release_region(gmux_data->iostart, gmux_data->iolen);
+       kfree(gmux_data);
+
+       acpi_video_register();
+       apple_bl_register();
+}
+
+static const struct pnp_device_id gmux_device_ids[] = {
+       {"APP000B", 0},
+       {"", 0}
+};
+
+static struct pnp_driver gmux_pnp_driver = {
+       .name           = "apple-gmux",
+       .probe          = gmux_probe,
+       .remove         = __devexit_p(gmux_remove),
+       .id_table       = gmux_device_ids,
+};
+
+static int __init apple_gmux_init(void)
+{
+       return pnp_register_driver(&gmux_pnp_driver);
+}
+
+static void __exit apple_gmux_exit(void)
+{
+       pnp_unregister_driver(&gmux_pnp_driver);
+}
+
+module_init(apple_gmux_init);
+module_exit(apple_gmux_exit);
+
+MODULE_AUTHOR("Seth Forshee <seth.forshee@canonical.com>");
+MODULE_DESCRIPTION("Apple Gmux Driver");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pnp, gmux_device_ids);
index b7944f9..e38f91b 100644 (file)
@@ -81,6 +81,19 @@ static uint wapf = 1;
 module_param(wapf, uint, 0444);
 MODULE_PARM_DESC(wapf, "WAPF value");
 
+static char *wled_type = "unknown";
+static char *bled_type = "unknown";
+
+module_param(wled_type, charp, 0444);
+MODULE_PARM_DESC(wlan_status, "Set the wled type on boot "
+                "(unknown, led or rfkill). "
+                "default is unknown");
+
+module_param(bled_type, charp, 0444);
+MODULE_PARM_DESC(bled_type, "Set the bled type on boot "
+                "(unknown, led or rfkill). "
+                "default is unknown");
+
 static int wlan_status = 1;
 static int bluetooth_status = 1;
 static int wimax_status = -1;
@@ -137,6 +150,11 @@ MODULE_PARM_DESC(als_status, "Set the ALS status on boot "
 #define WM_RSTS                0x08    /* internal wimax */
 #define WW_RSTS                0x20    /* internal wwan */
 
+/* WLED and BLED type */
+#define TYPE_UNKNOWN   0
+#define TYPE_LED       1
+#define TYPE_RFKILL    2
+
 /* LED */
 #define METHOD_MLED            "MLED"
 #define METHOD_TLED            "TLED"
@@ -218,8 +236,9 @@ struct asus_led {
 /*
  * Same thing for rfkill
  */
-struct asus_pega_rfkill {
-       int control_id;         /* type of control. Maps to PEGA_* values */
+struct asus_rfkill {
+       /* type of control. Maps to PEGA_* values or *_RSTS  */
+       int control_id;
        struct rfkill *rfkill;
        struct asus_laptop *asus;
 };
@@ -240,6 +259,8 @@ struct asus_laptop {
        struct key_entry *keymap;
        struct input_polled_dev *pega_accel_poll;
 
+       struct asus_led wled;
+       struct asus_led bled;
        struct asus_led mled;
        struct asus_led tled;
        struct asus_led rled;
@@ -248,6 +269,8 @@ struct asus_laptop {
        struct asus_led kled;
        struct workqueue_struct *led_workqueue;
 
+       int wled_type;
+       int bled_type;
        int wireless_status;
        bool have_rsts;
        bool is_pega_lucid;
@@ -256,11 +279,11 @@ struct asus_laptop {
        int pega_acc_y;
        int pega_acc_z;
 
-       struct rfkill *gps_rfkill;
-
-       struct asus_pega_rfkill wlanrfk;
-       struct asus_pega_rfkill btrfk;
-       struct asus_pega_rfkill wwanrfk;
+       struct asus_rfkill wlan;
+       struct asus_rfkill bluetooth;
+       struct asus_rfkill wwan;
+       struct asus_rfkill wimax;
+       struct asus_rfkill gps;
 
        acpi_handle handle;     /* the handle of the hotk device */
        u32 ledd_status;        /* status of the LED display */
@@ -274,6 +297,7 @@ static const struct key_entry asus_keymap[] = {
        {KE_KEY, 0x02, { KEY_SCREENLOCK } },
        {KE_KEY, 0x05, { KEY_WLAN } },
        {KE_KEY, 0x08, { KEY_F13 } },
+       {KE_KEY, 0x09, { KEY_PROG2 } }, /* Dock */
        {KE_KEY, 0x17, { KEY_ZOOM } },
        {KE_KEY, 0x1f, { KEY_BATTERY } },
        /* End of Lenovo SL Specific keycodes */
@@ -299,6 +323,8 @@ static const struct key_entry asus_keymap[] = {
        {KE_KEY, 0x62, { KEY_SWITCHVIDEOMODE } },
        {KE_KEY, 0x63, { KEY_SWITCHVIDEOMODE } },
        {KE_KEY, 0x6B, { KEY_F13 } }, /* Lock Touchpad */
+       {KE_KEY, 0x6C, { KEY_SLEEP } }, /* Suspend */
+       {KE_KEY, 0x6D, { KEY_SLEEP } }, /* Hibernate */
        {KE_KEY, 0x7E, { KEY_BLUETOOTH } },
        {KE_KEY, 0x7D, { KEY_BLUETOOTH } },
        {KE_KEY, 0x82, { KEY_CAMERA } },
@@ -601,6 +627,10 @@ static enum led_brightness asus_kled_cdev_get(struct led_classdev *led_cdev)
 
 static void asus_led_exit(struct asus_laptop *asus)
 {
+       if (!IS_ERR_OR_NULL(asus->wled.led.dev))
+               led_classdev_unregister(&asus->wled.led);
+       if (!IS_ERR_OR_NULL(asus->bled.led.dev))
+               led_classdev_unregister(&asus->bled.led);
        if (!IS_ERR_OR_NULL(asus->mled.led.dev))
                led_classdev_unregister(&asus->mled.led);
        if (!IS_ERR_OR_NULL(asus->tled.led.dev))
@@ -642,7 +672,7 @@ static int asus_led_register(struct asus_laptop *asus,
 
 static int asus_led_init(struct asus_laptop *asus)
 {
-       int r;
+       int r = 0;
 
        /*
         * The Pegatron Lucid has no physical leds, but all methods are
@@ -661,6 +691,16 @@ static int asus_led_init(struct asus_laptop *asus)
        if (!asus->led_workqueue)
                return -ENOMEM;
 
+       if (asus->wled_type == TYPE_LED)
+               r = asus_led_register(asus, &asus->wled, "asus::wlan",
+                                     METHOD_WLAN);
+       if (r)
+               goto error;
+       if (asus->bled_type == TYPE_LED)
+               r = asus_led_register(asus, &asus->bled, "asus::bluetooth",
+                                     METHOD_BLUETOOTH);
+       if (r)
+               goto error;
        r = asus_led_register(asus, &asus->mled, "asus::mail", METHOD_MLED);
        if (r)
                goto error;
@@ -963,7 +1003,7 @@ static ssize_t store_wlan(struct device *dev, struct device_attribute *attr,
        return sysfs_acpi_set(asus, buf, count, METHOD_WLAN);
 }
 
-/*
+/*e
  * Bluetooth
  */
 static int asus_bluetooth_set(struct asus_laptop *asus, int status)
@@ -1228,7 +1268,7 @@ static ssize_t store_gps(struct device *dev, struct device_attribute *attr,
        ret = asus_gps_switch(asus, !!value);
        if (ret)
                return ret;
-       rfkill_set_sw_state(asus->gps_rfkill, !value);
+       rfkill_set_sw_state(asus->gps.rfkill, !value);
        return rv;
 }
 
@@ -1246,90 +1286,139 @@ static const struct rfkill_ops asus_gps_rfkill_ops = {
        .set_block = asus_gps_rfkill_set,
 };
 
+static int asus_rfkill_set(void *data, bool blocked)
+{
+       struct asus_rfkill *rfk = data;
+       struct asus_laptop *asus = rfk->asus;
+
+       if (rfk->control_id == WL_RSTS)
+               return asus_wlan_set(asus, !blocked);
+       else if (rfk->control_id == BT_RSTS)
+               return asus_bluetooth_set(asus, !blocked);
+       else if (rfk->control_id == WM_RSTS)
+               return asus_wimax_set(asus, !blocked);
+       else if (rfk->control_id == WW_RSTS)
+               return asus_wwan_set(asus, !blocked);
+
+       return -EINVAL;
+}
+
+static const struct rfkill_ops asus_rfkill_ops = {
+       .set_block = asus_rfkill_set,
+};
+
+static void asus_rfkill_terminate(struct asus_rfkill *rfk)
+{
+       if (!rfk->rfkill)
+               return ;
+
+       rfkill_unregister(rfk->rfkill);
+       rfkill_destroy(rfk->rfkill);
+       rfk->rfkill = NULL;
+}
+
 static void asus_rfkill_exit(struct asus_laptop *asus)
 {
-       if (asus->gps_rfkill) {
-               rfkill_unregister(asus->gps_rfkill);
-               rfkill_destroy(asus->gps_rfkill);
-               asus->gps_rfkill = NULL;
-       }
+       asus_rfkill_terminate(&asus->wwan);
+       asus_rfkill_terminate(&asus->bluetooth);
+       asus_rfkill_terminate(&asus->wlan);
+       asus_rfkill_terminate(&asus->gps);
 }
 
-static int asus_rfkill_init(struct asus_laptop *asus)
+static int asus_rfkill_setup(struct asus_laptop *asus, struct asus_rfkill *rfk,
+                            const char *name, int control_id, int type,
+                            const struct rfkill_ops *ops)
 {
        int result;
 
-       if (acpi_check_handle(asus->handle, METHOD_GPS_ON, NULL) ||
-           acpi_check_handle(asus->handle, METHOD_GPS_OFF, NULL) ||
-           acpi_check_handle(asus->handle, METHOD_GPS_STATUS, NULL))
-               return 0;
-
-       asus->gps_rfkill = rfkill_alloc("asus-gps", &asus->platform_device->dev,
-                                       RFKILL_TYPE_GPS,
-                                       &asus_gps_rfkill_ops, asus);
-       if (!asus->gps_rfkill)
+       rfk->control_id = control_id;
+       rfk->asus = asus;
+       rfk->rfkill = rfkill_alloc(name, &asus->platform_device->dev,
+                                  type, ops, rfk);
+       if (!rfk->rfkill)
                return -EINVAL;
 
-       result = rfkill_register(asus->gps_rfkill);
+       result = rfkill_register(rfk->rfkill);
        if (result) {
-               rfkill_destroy(asus->gps_rfkill);
-               asus->gps_rfkill = NULL;
+               rfkill_destroy(rfk->rfkill);
+               rfk->rfkill = NULL;
        }
 
        return result;
 }
 
-static int pega_rfkill_set(void *data, bool blocked)
+static int asus_rfkill_init(struct asus_laptop *asus)
 {
-       struct asus_pega_rfkill *pega_rfk = data;
+       int result = 0;
 
-       int ret = asus_pega_lucid_set(pega_rfk->asus, pega_rfk->control_id, !blocked);
-       pr_warn("Setting rfkill %d, to %d; returned %d\n", pega_rfk->control_id, !blocked, ret);
+       if (asus->is_pega_lucid)
+               return -ENODEV;
 
-       return ret;
-}
+       if (!acpi_check_handle(asus->handle, METHOD_GPS_ON, NULL) &&
+           !acpi_check_handle(asus->handle, METHOD_GPS_OFF, NULL) &&
+           !acpi_check_handle(asus->handle, METHOD_GPS_STATUS, NULL))
+               result = asus_rfkill_setup(asus, &asus->gps, "asus-gps",
+                                          -1, RFKILL_TYPE_GPS,
+                                          &asus_gps_rfkill_ops);
+       if (result)
+               goto exit;
 
-static const struct rfkill_ops pega_rfkill_ops = {
-       .set_block = pega_rfkill_set,
-};
 
-static void pega_rfkill_terminate(struct asus_pega_rfkill *pega_rfk)
-{
-       pr_warn("Terminating %d\n", pega_rfk->control_id);
-       if (pega_rfk->rfkill) {
-               rfkill_unregister(pega_rfk->rfkill);
-               rfkill_destroy(pega_rfk->rfkill);
-               pega_rfk->rfkill = NULL;
-       }
-}
+       if (!acpi_check_handle(asus->handle, METHOD_WLAN, NULL) &&
+           asus->wled_type == TYPE_RFKILL)
+               result = asus_rfkill_setup(asus, &asus->wlan, "asus-wlan",
+                                          WL_RSTS, RFKILL_TYPE_WLAN,
+                                          &asus_rfkill_ops);
+       if (result)
+               goto exit;
 
-static void pega_rfkill_exit(struct asus_laptop *asus)
-{
-       pega_rfkill_terminate(&asus->wwanrfk);
-       pega_rfkill_terminate(&asus->btrfk);
-       pega_rfkill_terminate(&asus->wlanrfk);
+       if (!acpi_check_handle(asus->handle, METHOD_BLUETOOTH, NULL) &&
+           asus->bled_type == TYPE_RFKILL)
+               result = asus_rfkill_setup(asus, &asus->bluetooth,
+                                          "asus-bluetooth", BT_RSTS,
+                                          RFKILL_TYPE_BLUETOOTH,
+                                          &asus_rfkill_ops);
+       if (result)
+               goto exit;
+
+       if (!acpi_check_handle(asus->handle, METHOD_WWAN, NULL))
+               result = asus_rfkill_setup(asus, &asus->wwan, "asus-wwan",
+                                          WW_RSTS, RFKILL_TYPE_WWAN,
+                                          &asus_rfkill_ops);
+       if (result)
+               goto exit;
+
+       if (!acpi_check_handle(asus->handle, METHOD_WIMAX, NULL))
+               result = asus_rfkill_setup(asus, &asus->wimax, "asus-wimax",
+                                          WM_RSTS, RFKILL_TYPE_WIMAX,
+                                          &asus_rfkill_ops);
+       if (result)
+               goto exit;
+
+exit:
+       if (result)
+               asus_rfkill_exit(asus);
+
+       return result;
 }
 
-static int pega_rfkill_setup(struct asus_laptop *asus, struct asus_pega_rfkill *pega_rfk,
-               const char *name, int controlid, int rfkill_type)
+static int pega_rfkill_set(void *data, bool blocked)
 {
-       int result;
+       struct asus_rfkill *rfk = data;
 
-       pr_warn("Setting up rfk %s, control %d, type %d\n", name, controlid, rfkill_type);
-       pega_rfk->control_id = controlid;
-       pega_rfk->asus = asus;
-       pega_rfk->rfkill = rfkill_alloc(name, &asus->platform_device->dev,
-                                       rfkill_type, &pega_rfkill_ops, pega_rfk);
-       if (!pega_rfk->rfkill)
-               return -EINVAL;
+       int ret = asus_pega_lucid_set(rfk->asus, rfk->control_id, !blocked);
+       return ret;
+}
 
-       result = rfkill_register(pega_rfk->rfkill);
-       if (result) {
-               rfkill_destroy(pega_rfk->rfkill);
-               pega_rfk->rfkill = NULL;
-       }
+static const struct rfkill_ops pega_rfkill_ops = {
+       .set_block = pega_rfkill_set,
+};
 
-       return result;
+static int pega_rfkill_setup(struct asus_laptop *asus, struct asus_rfkill *rfk,
+                            const char *name, int controlid, int rfkill_type)
+{
+       return asus_rfkill_setup(asus, rfk, name, controlid, rfkill_type,
+                                &pega_rfkill_ops);
 }
 
 static int pega_rfkill_init(struct asus_laptop *asus)
@@ -1339,22 +1428,22 @@ static int pega_rfkill_init(struct asus_laptop *asus)
        if(!asus->is_pega_lucid)
                return -ENODEV;
 
-       ret = pega_rfkill_setup(asus, &asus->wlanrfk, "pega-wlan", PEGA_WLAN, RFKILL_TYPE_WLAN);
-       if(ret)
-               return ret;
-       ret = pega_rfkill_setup(asus, &asus->btrfk, "pega-bt", PEGA_BLUETOOTH, RFKILL_TYPE_BLUETOOTH);
+       ret = pega_rfkill_setup(asus, &asus->wlan, "pega-wlan",
+                               PEGA_WLAN, RFKILL_TYPE_WLAN);
        if(ret)
-               goto err_btrfk;
-       ret = pega_rfkill_setup(asus, &asus->wwanrfk, "pega-wwan", PEGA_WWAN, RFKILL_TYPE_WWAN);
+               goto exit;
+
+       ret = pega_rfkill_setup(asus, &asus->bluetooth, "pega-bt",
+                               PEGA_BLUETOOTH, RFKILL_TYPE_BLUETOOTH);
        if(ret)
-               goto err_wwanrfk;
+               goto exit;
 
-       pr_warn("Pega rfkill init succeeded\n");
-       return 0;
-err_wwanrfk:
-       pega_rfkill_terminate(&asus->btrfk);
-err_btrfk:
-       pega_rfkill_terminate(&asus->wlanrfk);
+       ret = pega_rfkill_setup(asus, &asus->wwan, "pega-wwan",
+                               PEGA_WWAN, RFKILL_TYPE_WWAN);
+
+exit:
+       if (ret)
+               asus_rfkill_exit(asus);
 
        return ret;
 }
@@ -1364,8 +1453,10 @@ err_btrfk:
  */
 static void asus_input_notify(struct asus_laptop *asus, int event)
 {
-       if (asus->inputdev)
-               sparse_keymap_report_event(asus->inputdev, event, 1, true);
+       if (!asus->inputdev)
+               return ;
+       if (!sparse_keymap_report_event(asus->inputdev, event, 1, true))
+               pr_info("Unknown key %x pressed\n", event);
 }
 
 static int asus_input_init(struct asus_laptop *asus)
@@ -1375,7 +1466,7 @@ static int asus_input_init(struct asus_laptop *asus)
 
        input = input_allocate_device();
        if (!input) {
-               pr_info("Unable to allocate input device\n");
+               pr_warn("Unable to allocate input device\n");
                return -ENOMEM;
        }
        input->name = "Asus Laptop extra buttons";
@@ -1390,7 +1481,7 @@ static int asus_input_init(struct asus_laptop *asus)
        }
        error = input_register_device(input);
        if (error) {
-               pr_info("Unable to register input device\n");
+               pr_warn("Unable to register input device\n");
                goto err_free_keymap;
        }
 
@@ -1688,7 +1779,16 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus)
        if (result)
                return result;
 
-       /* WLED and BLED are on by default */
+       if (!strcmp(bled_type, "led"))
+               asus->bled_type = TYPE_LED;
+       else if (!strcmp(bled_type, "rfkill"))
+               asus->bled_type = TYPE_RFKILL;
+
+       if (!strcmp(wled_type, "led"))
+               asus->wled_type = TYPE_LED;
+       else if (!strcmp(wled_type, "rfkill"))
+               asus->wled_type = TYPE_RFKILL;
+
        if (bluetooth_status >= 0)
                asus_bluetooth_set(asus, !!bluetooth_status);
 
@@ -1786,7 +1886,7 @@ static int __devinit asus_acpi_add(struct acpi_device *device)
                goto fail_led;
 
        result = asus_rfkill_init(asus);
-       if (result)
+       if (result && result != -ENODEV)
                goto fail_rfkill;
 
        result = pega_accel_init(asus);
@@ -1828,7 +1928,6 @@ static int asus_acpi_remove(struct acpi_device *device, int type)
        asus_led_exit(asus);
        asus_input_exit(asus);
        pega_accel_exit(asus);
-       pega_rfkill_exit(asus);
        asus_platform_exit(asus);
 
        kfree(asus->name);
index b0859d4..99a30b5 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/init.h>
 #include <linux/input.h>
 #include <linux/input/sparse-keymap.h>
+#include <linux/fb.h>
 
 #include "asus-wmi.h"
 
@@ -51,9 +52,14 @@ static uint wapf;
 module_param(wapf, uint, 0444);
 MODULE_PARM_DESC(wapf, "WAPF value");
 
+static struct quirk_entry quirk_asus_unknown = {
+};
+
 static void asus_nb_wmi_quirks(struct asus_wmi_driver *driver)
 {
-       driver->wapf = wapf;
+       driver->quirks = &quirk_asus_unknown;
+       driver->quirks->wapf = wapf;
+       driver->panel_power = FB_BLANK_UNBLANK;
 }
 
 static const struct key_entry asus_nb_wmi_keymap[] = {
@@ -70,6 +76,8 @@ static const struct key_entry asus_nb_wmi_keymap[] = {
        { KE_KEY, 0x50, { KEY_EMAIL } },
        { KE_KEY, 0x51, { KEY_WWW } },
        { KE_KEY, 0x55, { KEY_CALC } },
+       { KE_IGNORE, 0x57, },  /* Battery mode */
+       { KE_IGNORE, 0x58, },  /* AC mode */
        { KE_KEY, 0x5C, { KEY_F15 } },  /* Power Gear key */
        { KE_KEY, 0x5D, { KEY_WLAN } }, /* Wireless console Toggle */
        { KE_KEY, 0x5E, { KEY_WLAN } }, /* Wireless console Enable */
@@ -99,7 +107,7 @@ static struct asus_wmi_driver asus_nb_wmi_driver = {
        .keymap = asus_nb_wmi_keymap,
        .input_name = "Asus WMI hotkeys",
        .input_phys = ASUS_NB_WMI_FILE "/input0",
-       .quirks = asus_nb_wmi_quirks,
+       .detect_quirks = asus_nb_wmi_quirks,
 };
 
 
index 9929246..77aadde 100644 (file)
@@ -411,7 +411,7 @@ static int kbd_led_read(struct asus_wmi *asus, int *level, int *env)
 
        if (retval >= 0) {
                if (level)
-                       *level = retval & 0x80 ? retval & 0x7F : 0;
+                       *level = retval & 0x7F;
                if (env)
                        *env = (retval >> 8) & 0x7F;
                retval = 0;
@@ -784,7 +784,8 @@ static int asus_new_rfkill(struct asus_wmi *asus,
        arfkill->dev_id = dev_id;
        arfkill->asus = asus;
 
-       if (dev_id == ASUS_WMI_DEVID_WLAN && asus->driver->hotplug_wireless)
+       if (dev_id == ASUS_WMI_DEVID_WLAN &&
+           asus->driver->quirks->hotplug_wireless)
                *rfkill = rfkill_alloc(name, &asus->platform_device->dev, type,
                                       &asus_rfkill_wlan_ops, arfkill);
        else
@@ -895,7 +896,7 @@ static int asus_wmi_rfkill_init(struct asus_wmi *asus)
        if (result && result != -ENODEV)
                goto exit;
 
-       if (!asus->driver->hotplug_wireless)
+       if (!asus->driver->quirks->hotplug_wireless)
                goto exit;
 
        result = asus_setup_pci_hotplug(asus);
@@ -1075,7 +1076,12 @@ static int asus_wmi_hwmon_init(struct asus_wmi *asus)
  */
 static int read_backlight_power(struct asus_wmi *asus)
 {
-       int ret = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_BACKLIGHT);
+       int ret;
+       if (asus->driver->quirks->store_backlight_power)
+               ret = !asus->driver->panel_power;
+       else
+               ret = asus_wmi_get_devstate_simple(asus,
+                                                  ASUS_WMI_DEVID_BACKLIGHT);
 
        if (ret < 0)
                return ret;
@@ -1116,26 +1122,51 @@ static int read_brightness(struct backlight_device *bd)
        return retval & ASUS_WMI_DSTS_BRIGHTNESS_MASK;
 }
 
-static int update_bl_status(struct backlight_device *bd)
+static u32 get_scalar_command(struct backlight_device *bd)
 {
        struct asus_wmi *asus = bl_get_data(bd);
-       u32 ctrl_param;
-       int power, err;
+       u32 ctrl_param = 0;
 
-       ctrl_param = bd->props.brightness;
+       if ((asus->driver->brightness < bd->props.brightness) ||
+           bd->props.brightness == bd->props.max_brightness)
+               ctrl_param = 0x00008001;
+       else if ((asus->driver->brightness > bd->props.brightness) ||
+                bd->props.brightness == 0)
+               ctrl_param = 0x00008000;
 
-       err = asus_wmi_set_devstate(ASUS_WMI_DEVID_BRIGHTNESS,
-                                   ctrl_param, NULL);
+       asus->driver->brightness = bd->props.brightness;
 
-       if (err < 0)
-               return err;
+       return ctrl_param;
+}
+
+static int update_bl_status(struct backlight_device *bd)
+{
+       struct asus_wmi *asus = bl_get_data(bd);
+       u32 ctrl_param;
+       int power, err = 0;
 
        power = read_backlight_power(asus);
        if (power != -ENODEV && bd->props.power != power) {
                ctrl_param = !!(bd->props.power == FB_BLANK_UNBLANK);
                err = asus_wmi_set_devstate(ASUS_WMI_DEVID_BACKLIGHT,
                                            ctrl_param, NULL);
+               if (asus->driver->quirks->store_backlight_power)
+                       asus->driver->panel_power = bd->props.power;
+
+               /* When using scalar brightness, updating the brightness
+                * will mess with the backlight power */
+               if (asus->driver->quirks->scalar_panel_brightness)
+                       return err;
        }
+
+       if (asus->driver->quirks->scalar_panel_brightness)
+               ctrl_param = get_scalar_command(bd);
+       else
+               ctrl_param = bd->props.brightness;
+
+       err = asus_wmi_set_devstate(ASUS_WMI_DEVID_BRIGHTNESS,
+                                   ctrl_param, NULL);
+
        return err;
 }
 
@@ -1196,10 +1227,15 @@ static int asus_wmi_backlight_init(struct asus_wmi *asus)
 
        asus->backlight_device = bd;
 
+       if (asus->driver->quirks->store_backlight_power)
+               asus->driver->panel_power = power;
+
        bd->props.brightness = read_brightness(bd);
        bd->props.power = power;
        backlight_update_status(bd);
 
+       asus->driver->brightness = bd->props.brightness;
+
        return 0;
 }
 
@@ -1441,9 +1477,9 @@ static int asus_wmi_platform_init(struct asus_wmi *asus)
 
        /* CWAP allow to define the behavior of the Fn+F2 key,
         * this method doesn't seems to be present on Eee PCs */
-       if (asus->driver->wapf >= 0)
+       if (asus->driver->quirks->wapf >= 0)
                asus_wmi_set_devstate(ASUS_WMI_DEVID_CWAP,
-                                     asus->driver->wapf, NULL);
+                                     asus->driver->quirks->wapf, NULL);
 
        return asus_wmi_sysfs_init(asus->platform_device);
 }
@@ -1622,8 +1658,8 @@ static int asus_wmi_add(struct platform_device *pdev)
        wdrv->platform_device = pdev;
        platform_set_drvdata(asus->platform_device, asus);
 
-       if (wdrv->quirks)
-               wdrv->quirks(asus->driver);
+       if (wdrv->detect_quirks)
+               wdrv->detect_quirks(asus->driver);
 
        err = asus_wmi_platform_init(asus);
        if (err)
index 8147c10..d43b667 100644 (file)
@@ -35,9 +35,16 @@ struct module;
 struct key_entry;
 struct asus_wmi;
 
+struct quirk_entry {
+       bool hotplug_wireless;
+       bool scalar_panel_brightness;
+       bool store_backlight_power;
+       int wapf;
+};
+
 struct asus_wmi_driver {
-       bool                    hotplug_wireless;
-       int                     wapf;
+       int                     brightness;
+       int                     panel_power;
 
        const char              *name;
        struct module           *owner;
@@ -47,13 +54,14 @@ struct asus_wmi_driver {
        const struct key_entry  *keymap;
        const char              *input_name;
        const char              *input_phys;
+       struct quirk_entry      *quirks;
        /* Returns new code, value, and autorelease values in arguments.
         * Return ASUS_WMI_KEY_IGNORE in code if event should be ignored. */
        void (*key_filter) (struct asus_wmi_driver *driver, int *code,
                            unsigned int *value, bool *autorelease);
 
        int (*probe) (struct platform_device *device);
-       void (*quirks) (struct asus_wmi_driver *driver);
+       void (*detect_quirks) (struct asus_wmi_driver *driver);
 
        struct platform_driver  platform_driver;
        struct platform_device *platform_device;
diff --git a/drivers/platform/x86/asus_acpi.c b/drivers/platform/x86/asus_acpi.c
deleted file mode 100644 (file)
index 6f966d6..0000000
+++ /dev/null
@@ -1,1513 +0,0 @@
-/*
- *  asus_acpi.c - Asus Laptop ACPI Extras
- *
- *
- *  Copyright (C) 2002-2005 Julien Lerouge, 2003-2006 Karol Kozimor
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the 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
- *
- *
- *  The development page for this driver is located at
- *  http://sourceforge.net/projects/acpi4asus/
- *
- *  Credits:
- *  Pontus Fuchs   - Helper functions, cleanup
- *  Johann Wiesner - Small compile fixes
- *  John Belmonte  - ACPI code for Toshiba laptop was a good starting point.
- *  ï¿½ic Burghard  - LED display support for W1N
- *
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/backlight.h>
-#include <acpi/acpi_drivers.h>
-#include <acpi/acpi_bus.h>
-#include <asm/uaccess.h>
-
-#define ASUS_ACPI_VERSION "0.30"
-
-#define PROC_ASUS       "asus" /* The directory */
-#define PROC_MLED       "mled"
-#define PROC_WLED       "wled"
-#define PROC_TLED       "tled"
-#define PROC_BT         "bluetooth"
-#define PROC_LEDD       "ledd"
-#define PROC_INFO       "info"
-#define PROC_LCD        "lcd"
-#define PROC_BRN        "brn"
-#define PROC_DISP       "disp"
-
-#define ACPI_HOTK_NAME          "Asus Laptop ACPI Extras Driver"
-#define ACPI_HOTK_CLASS         "hotkey"
-#define ACPI_HOTK_DEVICE_NAME   "Hotkey"
-
-/*
- * Some events we use, same for all Asus
- */
-#define BR_UP       0x10
-#define BR_DOWN     0x20
-
-/*
- * Flags for hotk status
- */
-#define MLED_ON     0x01       /* Mail LED */
-#define WLED_ON     0x02       /* Wireless LED */
-#define TLED_ON     0x04       /* Touchpad LED */
-#define BT_ON       0x08       /* Internal Bluetooth */
-
-MODULE_AUTHOR("Julien Lerouge, Karol Kozimor");
-MODULE_DESCRIPTION(ACPI_HOTK_NAME);
-MODULE_LICENSE("GPL");
-
-static uid_t asus_uid;
-static gid_t asus_gid;
-module_param(asus_uid, uint, 0);
-MODULE_PARM_DESC(asus_uid, "UID for entries in /proc/acpi/asus");
-module_param(asus_gid, uint, 0);
-MODULE_PARM_DESC(asus_gid, "GID for entries in /proc/acpi/asus");
-
-/* For each model, all features implemented,
- * those marked with R are relative to HOTK, A for absolute */
-struct model_data {
-       char *name;             /* name of the laptop________________A */
-       char *mt_mled;          /* method to handle mled_____________R */
-       char *mled_status;      /* node to handle mled reading_______A */
-       char *mt_wled;          /* method to handle wled_____________R */
-       char *wled_status;      /* node to handle wled reading_______A */
-       char *mt_tled;          /* method to handle tled_____________R */
-       char *tled_status;      /* node to handle tled reading_______A */
-       char *mt_ledd;          /* method to handle LED display______R */
-       char *mt_bt_switch;     /* method to switch Bluetooth on/off_R */
-       char *bt_status;        /* no model currently supports this__? */
-       char *mt_lcd_switch;    /* method to turn LCD on/off_________A */
-       char *lcd_status;       /* node to read LCD panel state______A */
-       char *brightness_up;    /* method to set brightness up_______A */
-       char *brightness_down;  /* method to set brightness down ____A */
-       char *brightness_set;   /* method to set absolute brightness_R */
-       char *brightness_get;   /* method to get absolute brightness_R */
-       char *brightness_status;/* node to get brightness____________A */
-       char *display_set;      /* method to set video output________R */
-       char *display_get;      /* method to get video output________R */
-};
-
-/*
- * This is the main structure, we can use it to store anything interesting
- * about the hotk device
- */
-struct asus_hotk {
-       struct acpi_device *device;     /* the device we are in */
-       acpi_handle handle;             /* the handle of the hotk device */
-       char status;                    /* status of the hotk, for LEDs */
-       u32 ledd_status;                /* status of the LED display */
-       struct model_data *methods;     /* methods available on the laptop */
-       u8 brightness;                  /* brightness level */
-       enum {
-               A1x = 0,        /* A1340D, A1300F */
-               A2x,            /* A2500H */
-               A4G,            /* A4700G */
-               D1x,            /* D1 */
-               L2D,            /* L2000D */
-               L3C,            /* L3800C */
-               L3D,            /* L3400D */
-               L3H,            /* L3H, L2000E, L5D */
-               L4R,            /* L4500R */
-               L5x,            /* L5800C */
-               L8L,            /* L8400L */
-               M1A,            /* M1300A */
-               M2E,            /* M2400E, L4400L */
-               M6N,            /* M6800N, W3400N */
-               M6R,            /* M6700R, A3000G */
-               P30,            /* Samsung P30 */
-               S1x,            /* S1300A, but also L1400B and M2400A (L84F) */
-               S2x,            /* S200 (J1 reported), Victor MP-XP7210 */
-               W1N,            /* W1000N */
-               W5A,            /* W5A */
-               W3V,            /* W3030V */
-               xxN,            /* M2400N, M3700N, M5200N, M6800N,
-                                                        S1300N, S5200N*/
-               A4S,            /* Z81sp */
-               F3Sa,           /* (Centrino) */
-               R1F,
-               END_MODEL
-       } model;                /* Models currently supported */
-       u16 event_count[128];   /* Count for each event TODO make this better */
-};
-
-/* Here we go */
-#define A1x_PREFIX "\\_SB.PCI0.ISA.EC0."
-#define L3C_PREFIX "\\_SB.PCI0.PX40.ECD0."
-#define M1A_PREFIX "\\_SB.PCI0.PX40.EC0."
-#define P30_PREFIX "\\_SB.PCI0.LPCB.EC0."
-#define S1x_PREFIX "\\_SB.PCI0.PX40."
-#define S2x_PREFIX A1x_PREFIX
-#define xxN_PREFIX "\\_SB.PCI0.SBRG.EC0."
-
-static struct model_data model_conf[END_MODEL] = {
-       /*
-        * TODO I have seen a SWBX and AIBX method on some models, like L1400B,
-        * it seems to be a kind of switch, but what for ?
-        */
-
-       {
-        .name = "A1x",
-        .mt_mled = "MLED",
-        .mled_status = "\\MAIL",
-        .mt_lcd_switch = A1x_PREFIX "_Q10",
-        .lcd_status = "\\BKLI",
-        .brightness_up = A1x_PREFIX "_Q0E",
-        .brightness_down = A1x_PREFIX "_Q0F"},
-
-       {
-        .name = "A2x",
-        .mt_mled = "MLED",
-        .mt_wled = "WLED",
-        .wled_status = "\\SG66",
-        .mt_lcd_switch = "\\Q10",
-        .lcd_status = "\\BAOF",
-        .brightness_set = "SPLV",
-        .brightness_get = "GPLV",
-        .display_set = "SDSP",
-        .display_get = "\\INFB"},
-
-       {
-        .name = "A4G",
-        .mt_mled = "MLED",
-/* WLED present, but not controlled by ACPI */
-        .mt_lcd_switch = xxN_PREFIX "_Q10",
-        .brightness_set = "SPLV",
-        .brightness_get = "GPLV",
-        .display_set = "SDSP",
-        .display_get = "\\ADVG"},
-
-       {
-        .name = "D1x",
-        .mt_mled = "MLED",
-        .mt_lcd_switch = "\\Q0D",
-        .lcd_status = "\\GP11",
-        .brightness_up = "\\Q0C",
-        .brightness_down = "\\Q0B",
-        .brightness_status = "\\BLVL",
-        .display_set = "SDSP",
-        .display_get = "\\INFB"},
-
-       {
-        .name = "L2D",
-        .mt_mled = "MLED",
-        .mled_status = "\\SGP6",
-        .mt_wled = "WLED",
-        .wled_status = "\\RCP3",
-        .mt_lcd_switch = "\\Q10",
-        .lcd_status = "\\SGP0",
-        .brightness_up = "\\Q0E",
-        .brightness_down = "\\Q0F",
-        .display_set = "SDSP",
-        .display_get = "\\INFB"},
-
-       {
-        .name = "L3C",
-        .mt_mled = "MLED",
-        .mt_wled = "WLED",
-        .mt_lcd_switch = L3C_PREFIX "_Q10",
-        .lcd_status = "\\GL32",
-        .brightness_set = "SPLV",
-        .brightness_get = "GPLV",
-        .display_set = "SDSP",
-        .display_get = "\\_SB.PCI0.PCI1.VGAC.NMAP"},
-
-       {
-        .name = "L3D",
-        .mt_mled = "MLED",
-        .mled_status = "\\MALD",
-        .mt_wled = "WLED",
-        .mt_lcd_switch = "\\Q10",
-        .lcd_status = "\\BKLG",
-        .brightness_set = "SPLV",
-        .brightness_get = "GPLV",
-        .display_set = "SDSP",
-        .display_get = "\\INFB"},
-
-       {
-        .name = "L3H",
-        .mt_mled = "MLED",
-        .mt_wled = "WLED",
-        .mt_lcd_switch = "EHK",
-        .lcd_status = "\\_SB.PCI0.PM.PBC",
-        .brightness_set = "SPLV",
-        .brightness_get = "GPLV",
-        .display_set = "SDSP",
-        .display_get = "\\INFB"},
-
-       {
-        .name = "L4R",
-        .mt_mled = "MLED",
-        .mt_wled = "WLED",
-        .wled_status = "\\_SB.PCI0.SBRG.SG13",
-        .mt_lcd_switch = xxN_PREFIX "_Q10",
-        .lcd_status = "\\_SB.PCI0.SBSM.SEO4",
-        .brightness_set = "SPLV",
-        .brightness_get = "GPLV",
-        .display_set = "SDSP",
-        .display_get = "\\_SB.PCI0.P0P1.VGA.GETD"},
-
-       {
-        .name = "L5x",
-        .mt_mled = "MLED",
-/* WLED present, but not controlled by ACPI */
-        .mt_tled = "TLED",
-        .mt_lcd_switch = "\\Q0D",
-        .lcd_status = "\\BAOF",
-        .brightness_set = "SPLV",
-        .brightness_get = "GPLV",
-        .display_set = "SDSP",
-        .display_get = "\\INFB"},
-
-       {
-        .name = "L8L"
-/* No features, but at least support the hotkeys */
-        },
-
-       {
-        .name = "M1A",
-        .mt_mled = "MLED",
-        .mt_lcd_switch = M1A_PREFIX "Q10",
-        .lcd_status = "\\PNOF",
-        .brightness_up = M1A_PREFIX "Q0E",
-        .brightness_down = M1A_PREFIX "Q0F",
-        .brightness_status = "\\BRIT",
-        .display_set = "SDSP",
-        .display_get = "\\INFB"},
-
-       {
-        .name = "M2E",
-        .mt_mled = "MLED",
-        .mt_wled = "WLED",
-        .mt_lcd_switch = "\\Q10",
-        .lcd_status = "\\GP06",
-        .brightness_set = "SPLV",
-        .brightness_get = "GPLV",
-        .display_set = "SDSP",
-        .display_get = "\\INFB"},
-
-       {
-        .name = "M6N",
-        .mt_mled = "MLED",
-        .mt_wled = "WLED",
-        .wled_status = "\\_SB.PCI0.SBRG.SG13",
-        .mt_lcd_switch = xxN_PREFIX "_Q10",
-        .lcd_status = "\\_SB.BKLT",
-        .brightness_set = "SPLV",
-        .brightness_get = "GPLV",
-        .display_set = "SDSP",
-        .display_get = "\\SSTE"},
-
-       {
-        .name = "M6R",
-        .mt_mled = "MLED",
-        .mt_wled = "WLED",
-        .mt_lcd_switch = xxN_PREFIX "_Q10",
-        .lcd_status = "\\_SB.PCI0.SBSM.SEO4",
-        .brightness_set = "SPLV",
-        .brightness_get = "GPLV",
-        .display_set = "SDSP",
-        .display_get = "\\_SB.PCI0.P0P1.VGA.GETD"},
-
-       {
-        .name = "P30",
-        .mt_wled = "WLED",
-        .mt_lcd_switch = P30_PREFIX "_Q0E",
-        .lcd_status = "\\BKLT",
-        .brightness_up = P30_PREFIX "_Q68",
-        .brightness_down = P30_PREFIX "_Q69",
-        .brightness_get = "GPLV",
-        .display_set = "SDSP",
-        .display_get = "\\DNXT"},
-
-       {
-        .name = "S1x",
-        .mt_mled = "MLED",
-        .mled_status = "\\EMLE",
-        .mt_wled = "WLED",
-        .mt_lcd_switch = S1x_PREFIX "Q10",
-        .lcd_status = "\\PNOF",
-        .brightness_set = "SPLV",
-        .brightness_get = "GPLV"},
-
-       {
-        .name = "S2x",
-        .mt_mled = "MLED",
-        .mled_status = "\\MAIL",
-        .mt_lcd_switch = S2x_PREFIX "_Q10",
-        .lcd_status = "\\BKLI",
-        .brightness_up = S2x_PREFIX "_Q0B",
-        .brightness_down = S2x_PREFIX "_Q0A"},
-
-       {
-        .name = "W1N",
-        .mt_mled = "MLED",
-        .mt_wled = "WLED",
-        .mt_ledd = "SLCM",
-        .mt_lcd_switch = xxN_PREFIX "_Q10",
-        .lcd_status = "\\BKLT",
-        .brightness_set = "SPLV",
-        .brightness_get = "GPLV",
-        .display_set = "SDSP",
-        .display_get = "\\ADVG"},
-
-       {
-        .name = "W5A",
-        .mt_bt_switch = "BLED",
-        .mt_wled = "WLED",
-        .mt_lcd_switch = xxN_PREFIX "_Q10",
-        .brightness_set = "SPLV",
-        .brightness_get = "GPLV",
-        .display_set = "SDSP",
-        .display_get = "\\ADVG"},
-
-       {
-        .name = "W3V",
-        .mt_mled = "MLED",
-        .mt_wled = "WLED",
-        .mt_lcd_switch = xxN_PREFIX "_Q10",
-        .lcd_status = "\\BKLT",
-        .brightness_set = "SPLV",
-        .brightness_get = "GPLV",
-        .display_set = "SDSP",
-        .display_get = "\\INFB"},
-
-       {
-        .name = "xxN",
-        .mt_mled = "MLED",
-/* WLED present, but not controlled by ACPI */
-        .mt_lcd_switch = xxN_PREFIX "_Q10",
-        .lcd_status = "\\BKLT",
-        .brightness_set = "SPLV",
-        .brightness_get = "GPLV",
-        .display_set = "SDSP",
-       .display_get = "\\ADVG"},
-
-       {
-               .name              = "A4S",
-               .brightness_set    = "SPLV",
-               .brightness_get    = "GPLV",
-               .mt_bt_switch      = "BLED",
-               .mt_wled           = "WLED"
-       },
-
-       {
-               .name           = "F3Sa",
-               .mt_bt_switch   = "BLED",
-               .mt_wled        = "WLED",
-               .mt_mled        = "MLED",
-               .brightness_get = "GPLV",
-               .brightness_set = "SPLV",
-               .mt_lcd_switch  = "\\_SB.PCI0.SBRG.EC0._Q10",
-               .lcd_status     = "\\_SB.PCI0.SBRG.EC0.RPIN",
-               .display_get    = "\\ADVG",
-               .display_set    = "SDSP",
-       },
-       {
-               .name = "R1F",
-               .mt_bt_switch = "BLED",
-               .mt_mled = "MLED",
-               .mt_wled = "WLED",
-               .mt_lcd_switch = "\\Q10",
-               .lcd_status = "\\GP06",
-               .brightness_set = "SPLV",
-               .brightness_get = "GPLV",
-               .display_set = "SDSP",
-               .display_get = "\\INFB"
-       }
-};
-
-/* procdir we use */
-static struct proc_dir_entry *asus_proc_dir;
-
-static struct backlight_device *asus_backlight_device;
-
-/*
- * This header is made available to allow proper configuration given model,
- * revision number , ... this info cannot go in struct asus_hotk because it is
- * available before the hotk
- */
-static struct acpi_table_header *asus_info;
-
-/* The actual device the driver binds to */
-static struct asus_hotk *hotk;
-
-/*
- * The hotkey driver and autoloading declaration
- */
-static int asus_hotk_add(struct acpi_device *device);
-static int asus_hotk_remove(struct acpi_device *device, int type);
-static void asus_hotk_notify(struct acpi_device *device, u32 event);
-
-static const struct acpi_device_id asus_device_ids[] = {
-       {"ATK0100", 0},
-       {"", 0},
-};
-MODULE_DEVICE_TABLE(acpi, asus_device_ids);
-
-static struct acpi_driver asus_hotk_driver = {
-       .name = "asus_acpi",
-       .class = ACPI_HOTK_CLASS,
-       .owner = THIS_MODULE,
-       .ids = asus_device_ids,
-       .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
-       .ops = {
-               .add = asus_hotk_add,
-               .remove = asus_hotk_remove,
-               .notify = asus_hotk_notify,
-               },
-};
-
-/*
- * This function evaluates an ACPI method, given an int as parameter, the
- * method is searched within the scope of the handle, can be NULL. The output
- * of the method is written is output, which can also be NULL
- *
- * returns 1 if write is successful, 0 else.
- */
-static int write_acpi_int(acpi_handle handle, const char *method, int val,
-                         struct acpi_buffer *output)
-{
-       struct acpi_object_list params; /* list of input parameters (int) */
-       union acpi_object in_obj;       /* the only param we use */
-       acpi_status status;
-
-       params.count = 1;
-       params.pointer = &in_obj;
-       in_obj.type = ACPI_TYPE_INTEGER;
-       in_obj.integer.value = val;
-
-       status = acpi_evaluate_object(handle, (char *)method, &params, output);
-       return (status == AE_OK);
-}
-
-static int read_acpi_int(acpi_handle handle, const char *method, int *val)
-{
-       struct acpi_buffer output;
-       union acpi_object out_obj;
-       acpi_status status;
-
-       output.length = sizeof(out_obj);
-       output.pointer = &out_obj;
-
-       status = acpi_evaluate_object(handle, (char *)method, NULL, &output);
-       *val = out_obj.integer.value;
-       return (status == AE_OK) && (out_obj.type == ACPI_TYPE_INTEGER);
-}
-
-static int asus_info_proc_show(struct seq_file *m, void *v)
-{
-       int temp;
-
-       seq_printf(m, ACPI_HOTK_NAME " " ASUS_ACPI_VERSION "\n");
-       seq_printf(m, "Model reference    : %s\n", hotk->methods->name);
-       /*
-        * The SFUN method probably allows the original driver to get the list
-        * of features supported by a given model. For now, 0x0100 or 0x0800
-        * bit signifies that the laptop is equipped with a Wi-Fi MiniPCI card.
-        * The significance of others is yet to be found.
-        */
-       if (read_acpi_int(hotk->handle, "SFUN", &temp))
-               seq_printf(m, "SFUN value         : 0x%04x\n", temp);
-       /*
-        * Another value for userspace: the ASYM method returns 0x02 for
-        * battery low and 0x04 for battery critical, its readings tend to be
-        * more accurate than those provided by _BST.
-        * Note: since not all the laptops provide this method, errors are
-        * silently ignored.
-        */
-       if (read_acpi_int(hotk->handle, "ASYM", &temp))
-               seq_printf(m, "ASYM value         : 0x%04x\n", temp);
-       if (asus_info) {
-               seq_printf(m, "DSDT length        : %d\n", asus_info->length);
-               seq_printf(m, "DSDT checksum      : %d\n", asus_info->checksum);
-               seq_printf(m, "DSDT revision      : %d\n", asus_info->revision);
-               seq_printf(m, "OEM id             : %.*s\n", ACPI_OEM_ID_SIZE, asus_info->oem_id);
-               seq_printf(m, "OEM table id       : %.*s\n", ACPI_OEM_TABLE_ID_SIZE, asus_info->oem_table_id);
-               seq_printf(m, "OEM revision       : 0x%x\n", asus_info->oem_revision);
-               seq_printf(m, "ASL comp vendor id : %.*s\n", ACPI_NAME_SIZE, asus_info->asl_compiler_id);
-               seq_printf(m, "ASL comp revision  : 0x%x\n", asus_info->asl_compiler_revision);
-       }
-
-       return 0;
-}
-
-static int asus_info_proc_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, asus_info_proc_show, NULL);
-}
-
-static const struct file_operations asus_info_proc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = asus_info_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-};
-
-/*
- * /proc handlers
- * We write our info in page, we begin at offset off and cannot write more
- * than count bytes. We set eof to 1 if we handle those 2 values. We return the
- * number of bytes written in page
- */
-
-/* Generic LED functions */
-static int read_led(const char *ledname, int ledmask)
-{
-       if (ledname) {
-               int led_status;
-
-               if (read_acpi_int(NULL, ledname, &led_status))
-                       return led_status;
-               else
-                       pr_warn("Error reading LED status\n");
-       }
-       return (hotk->status & ledmask) ? 1 : 0;
-}
-
-static int parse_arg(const char __user *buf, unsigned long count, int *val)
-{
-       char s[32];
-       if (!count)
-               return 0;
-       if (count > 31)
-               return -EINVAL;
-       if (copy_from_user(s, buf, count))
-               return -EFAULT;
-       s[count] = 0;
-       if (sscanf(s, "%i", val) != 1)
-               return -EINVAL;
-       return count;
-}
-
-/* FIXME: kill extraneous args so it can be called independently */
-static int
-write_led(const char __user *buffer, unsigned long count,
-         char *ledname, int ledmask, int invert)
-{
-       int rv, value;
-       int led_out = 0;
-
-       rv = parse_arg(buffer, count, &value);
-       if (rv > 0)
-               led_out = value ? 1 : 0;
-
-       hotk->status =
-           (led_out) ? (hotk->status | ledmask) : (hotk->status & ~ledmask);
-
-       if (invert)             /* invert target value */
-               led_out = !led_out;
-
-       if (!write_acpi_int(hotk->handle, ledname, led_out, NULL))
-               pr_warn("LED (%s) write failed\n", ledname);
-
-       return rv;
-}
-
-/*
- * Proc handlers for MLED
- */
-static int mled_proc_show(struct seq_file *m, void *v)
-{
-       seq_printf(m, "%d\n", read_led(hotk->methods->mled_status, MLED_ON));
-       return 0;
-}
-
-static int mled_proc_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, mled_proc_show, NULL);
-}
-
-static ssize_t mled_proc_write(struct file *file, const char __user *buffer,
-               size_t count, loff_t *pos)
-{
-       return write_led(buffer, count, hotk->methods->mt_mled, MLED_ON, 1);
-}
-
-static const struct file_operations mled_proc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = mled_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = mled_proc_write,
-};
-
-/*
- * Proc handlers for LED display
- */
-static int ledd_proc_show(struct seq_file *m, void *v)
-{
-       seq_printf(m, "0x%08x\n", hotk->ledd_status);
-       return 0;
-}
-
-static int ledd_proc_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, ledd_proc_show, NULL);
-}
-
-static ssize_t ledd_proc_write(struct file *file, const char __user *buffer,
-               size_t count, loff_t *pos)
-{
-       int rv, value;
-
-       rv = parse_arg(buffer, count, &value);
-       if (rv > 0) {
-               if (!write_acpi_int
-                   (hotk->handle, hotk->methods->mt_ledd, value, NULL))
-                       pr_warn("LED display write failed\n");
-               else
-                       hotk->ledd_status = (u32) value;
-       }
-       return rv;
-}
-
-static const struct file_operations ledd_proc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = ledd_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = ledd_proc_write,
-};
-
-/*
- * Proc handlers for WLED
- */
-static int wled_proc_show(struct seq_file *m, void *v)
-{
-       seq_printf(m, "%d\n", read_led(hotk->methods->wled_status, WLED_ON));
-       return 0;
-}
-
-static int wled_proc_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, wled_proc_show, NULL);
-}
-
-static ssize_t wled_proc_write(struct file *file, const char __user *buffer,
-               size_t count, loff_t *pos)
-{
-       return write_led(buffer, count, hotk->methods->mt_wled, WLED_ON, 0);
-}
-
-static const struct file_operations wled_proc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = wled_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = wled_proc_write,
-};
-
-/*
- * Proc handlers for Bluetooth
- */
-static int bluetooth_proc_show(struct seq_file *m, void *v)
-{
-       seq_printf(m, "%d\n", read_led(hotk->methods->bt_status, BT_ON));
-       return 0;
-}
-
-static int bluetooth_proc_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, bluetooth_proc_show, NULL);
-}
-
-static ssize_t bluetooth_proc_write(struct file *file,
-               const char __user *buffer, size_t count, loff_t *pos)
-{
-       /* Note: mt_bt_switch controls both internal Bluetooth adapter's
-          presence and its LED */
-       return write_led(buffer, count, hotk->methods->mt_bt_switch, BT_ON, 0);
-}
-
-static const struct file_operations bluetooth_proc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = bluetooth_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = bluetooth_proc_write,
-};
-
-/*
- * Proc handlers for TLED
- */
-static int tled_proc_show(struct seq_file *m, void *v)
-{
-       seq_printf(m, "%d\n", read_led(hotk->methods->tled_status, TLED_ON));
-       return 0;
-}
-
-static int tled_proc_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, tled_proc_show, NULL);
-}
-
-static ssize_t tled_proc_write(struct file *file, const char __user *buffer,
-               size_t count, loff_t *pos)
-{
-       return write_led(buffer, count, hotk->methods->mt_tled, TLED_ON, 0);
-}
-
-static const struct file_operations tled_proc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = tled_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = tled_proc_write,
-};
-
-static int get_lcd_state(void)
-{
-       int lcd = 0;
-
-       if (hotk->model == L3H) {
-               /* L3H and the like have to be handled differently */
-               acpi_status status = 0;
-               struct acpi_object_list input;
-               union acpi_object mt_params[2];
-               struct acpi_buffer output;
-               union acpi_object out_obj;
-
-               input.count = 2;
-               input.pointer = mt_params;
-               /* Note: the following values are partly guessed up, but
-                  otherwise they seem to work */
-               mt_params[0].type = ACPI_TYPE_INTEGER;
-               mt_params[0].integer.value = 0x02;
-               mt_params[1].type = ACPI_TYPE_INTEGER;
-               mt_params[1].integer.value = 0x02;
-
-               output.length = sizeof(out_obj);
-               output.pointer = &out_obj;
-
-               status =
-                   acpi_evaluate_object(NULL, hotk->methods->lcd_status,
-                                        &input, &output);
-               if (status != AE_OK)
-                       return -1;
-               if (out_obj.type == ACPI_TYPE_INTEGER)
-                       /* That's what the AML code does */
-                       lcd = out_obj.integer.value >> 8;
-       } else if (hotk->model == F3Sa) {
-               unsigned long long tmp;
-               union acpi_object param;
-               struct acpi_object_list input;
-               acpi_status status;
-
-               /* Read pin 11 */
-               param.type = ACPI_TYPE_INTEGER;
-               param.integer.value = 0x11;
-               input.count = 1;
-               input.pointer = &param;
-
-               status = acpi_evaluate_integer(NULL, hotk->methods->lcd_status,
-                                               &input, &tmp);
-               if (status != AE_OK)
-                       return -1;
-
-               lcd = tmp;
-       } else {
-               /* We don't have to check anything if we are here */
-               if (!read_acpi_int(NULL, hotk->methods->lcd_status, &lcd))
-                       pr_warn("Error reading LCD status\n");
-
-               if (hotk->model == L2D)
-                       lcd = ~lcd;
-       }
-
-       return (lcd & 1);
-}
-
-static int set_lcd_state(int value)
-{
-       int lcd = 0;
-       acpi_status status = 0;
-
-       lcd = value ? 1 : 0;
-       if (lcd != get_lcd_state()) {
-               /* switch */
-               if (hotk->model != L3H) {
-                       status =
-                           acpi_evaluate_object(NULL,
-                                                hotk->methods->mt_lcd_switch,
-                                                NULL, NULL);
-               } else {
-                       /* L3H and the like must be handled differently */
-                       if (!write_acpi_int
-                           (hotk->handle, hotk->methods->mt_lcd_switch, 0x07,
-                            NULL))
-                               status = AE_ERROR;
-                       /* L3H's AML executes EHK (0x07) upon Fn+F7 keypress,
-                          the exact behaviour is simulated here */
-               }
-               if (ACPI_FAILURE(status))
-                       pr_warn("Error switching LCD\n");
-       }
-       return 0;
-
-}
-
-static int lcd_proc_show(struct seq_file *m, void *v)
-{
-       seq_printf(m, "%d\n", get_lcd_state());
-       return 0;
-}
-
-static int lcd_proc_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, lcd_proc_show, NULL);
-}
-
-static ssize_t lcd_proc_write(struct file *file, const char __user *buffer,
-              size_t count, loff_t *pos)
-{
-       int rv, value;
-
-       rv = parse_arg(buffer, count, &value);
-       if (rv > 0)
-               set_lcd_state(value);
-       return rv;
-}
-
-static const struct file_operations lcd_proc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = lcd_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = lcd_proc_write,
-};
-
-static int read_brightness(struct backlight_device *bd)
-{
-       int value;
-
-       if (hotk->methods->brightness_get) {    /* SPLV/GPLV laptop */
-               if (!read_acpi_int(hotk->handle, hotk->methods->brightness_get,
-                                  &value))
-                       pr_warn("Error reading brightness\n");
-       } else if (hotk->methods->brightness_status) {  /* For D1 for example */
-               if (!read_acpi_int(NULL, hotk->methods->brightness_status,
-                                  &value))
-                       pr_warn("Error reading brightness\n");
-       } else                  /* No GPLV method */
-               value = hotk->brightness;
-       return value;
-}
-
-/*
- * Change the brightness level
- */
-static int set_brightness(int value)
-{
-       acpi_status status = 0;
-       int ret = 0;
-
-       /* SPLV laptop */
-       if (hotk->methods->brightness_set) {
-               if (!write_acpi_int(hotk->handle, hotk->methods->brightness_set,
-                                   value, NULL)) {
-                       pr_warn("Error changing brightness\n");
-                       ret = -EIO;
-               }
-               goto out;
-       }
-
-       /* No SPLV method if we are here, act as appropriate */
-       value -= read_brightness(NULL);
-       while (value != 0) {
-               status = acpi_evaluate_object(NULL, (value > 0) ?
-                                             hotk->methods->brightness_up :
-                                             hotk->methods->brightness_down,
-                                             NULL, NULL);
-               (value > 0) ? value-- : value++;
-               if (ACPI_FAILURE(status)) {
-                       pr_warn("Error changing brightness\n");
-                       ret = -EIO;
-               }
-       }
-out:
-       return ret;
-}
-
-static int set_brightness_status(struct backlight_device *bd)
-{
-       return set_brightness(bd->props.brightness);
-}
-
-static int brn_proc_show(struct seq_file *m, void *v)
-{
-       seq_printf(m, "%d\n", read_brightness(NULL));
-       return 0;
-}
-
-static int brn_proc_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, brn_proc_show, NULL);
-}
-
-static ssize_t brn_proc_write(struct file *file, const char __user *buffer,
-              size_t count, loff_t *pos)
-{
-       int rv, value;
-
-       rv = parse_arg(buffer, count, &value);
-       if (rv > 0) {
-               value = (0 < value) ? ((15 < value) ? 15 : value) : 0;
-               /* 0 <= value <= 15 */
-               set_brightness(value);
-       }
-       return rv;
-}
-
-static const struct file_operations brn_proc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = brn_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = brn_proc_write,
-};
-
-static void set_display(int value)
-{
-       /* no sanity check needed for now */
-       if (!write_acpi_int(hotk->handle, hotk->methods->display_set,
-                           value, NULL))
-               pr_warn("Error setting display\n");
-       return;
-}
-
-/*
- * Now, *this* one could be more user-friendly, but so far, no-one has
- * complained. The significance of bits is the same as in proc_write_disp()
- */
-static int disp_proc_show(struct seq_file *m, void *v)
-{
-       int value = 0;
-
-       if (!read_acpi_int(hotk->handle, hotk->methods->display_get, &value))
-               pr_warn("Error reading display status\n");
-       value &= 0x07;  /* needed for some models, shouldn't hurt others */
-       seq_printf(m, "%d\n", value);
-       return 0;
-}
-
-static int disp_proc_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, disp_proc_show, NULL);
-}
-
-/*
- * Experimental support for display switching. As of now: 1 should activate
- * the LCD output, 2 should do for CRT, and 4 for TV-Out. Any combination
- * (bitwise) of these will suffice. I never actually tested 3 displays hooked
- * up simultaneously, so be warned. See the acpi4asus README for more info.
- */
-static ssize_t disp_proc_write(struct file *file, const char __user *buffer,
-               size_t count, loff_t *pos)
-{
-       int rv, value;
-
-       rv = parse_arg(buffer, count, &value);
-       if (rv > 0)
-               set_display(value);
-       return rv;
-}
-
-static const struct file_operations disp_proc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = disp_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = disp_proc_write,
-};
-
-static int
-asus_proc_add(char *name, const struct file_operations *proc_fops, umode_t mode,
-                    struct acpi_device *device)
-{
-       struct proc_dir_entry *proc;
-
-       proc = proc_create_data(name, mode, acpi_device_dir(device),
-                               proc_fops, acpi_driver_data(device));
-       if (!proc) {
-               pr_warn("  Unable to create %s fs entry\n", name);
-               return -1;
-       }
-       proc->uid = asus_uid;
-       proc->gid = asus_gid;
-       return 0;
-}
-
-static int asus_hotk_add_fs(struct acpi_device *device)
-{
-       struct proc_dir_entry *proc;
-       umode_t mode;
-
-       if ((asus_uid == 0) && (asus_gid == 0)) {
-               mode = S_IFREG | S_IRUGO | S_IWUSR | S_IWGRP;
-       } else {
-               mode = S_IFREG | S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP;
-               pr_warn("  asus_uid and asus_gid parameters are "
-                       "deprecated, use chown and chmod instead!\n");
-       }
-
-       acpi_device_dir(device) = asus_proc_dir;
-       if (!acpi_device_dir(device))
-               return -ENODEV;
-
-       proc = proc_create(PROC_INFO, mode, acpi_device_dir(device),
-                          &asus_info_proc_fops);
-       if (proc) {
-               proc->uid = asus_uid;
-               proc->gid = asus_gid;
-       } else {
-               pr_warn("  Unable to create " PROC_INFO " fs entry\n");
-       }
-
-       if (hotk->methods->mt_wled) {
-               asus_proc_add(PROC_WLED, &wled_proc_fops, mode, device);
-       }
-
-       if (hotk->methods->mt_ledd) {
-               asus_proc_add(PROC_LEDD, &ledd_proc_fops, mode, device);
-       }
-
-       if (hotk->methods->mt_mled) {
-               asus_proc_add(PROC_MLED, &mled_proc_fops, mode, device);
-       }
-
-       if (hotk->methods->mt_tled) {
-               asus_proc_add(PROC_TLED, &tled_proc_fops, mode, device);
-       }
-
-       if (hotk->methods->mt_bt_switch) {
-               asus_proc_add(PROC_BT, &bluetooth_proc_fops, mode, device);
-       }
-
-       /*
-        * We need both read node and write method as LCD switch is also
-        * accessible from the keyboard
-        */
-       if (hotk->methods->mt_lcd_switch && hotk->methods->lcd_status) {
-               asus_proc_add(PROC_LCD, &lcd_proc_fops, mode, device);
-       }
-
-       if ((hotk->methods->brightness_up && hotk->methods->brightness_down) ||
-           (hotk->methods->brightness_get && hotk->methods->brightness_set)) {
-               asus_proc_add(PROC_BRN, &brn_proc_fops, mode, device);
-       }
-
-       if (hotk->methods->display_set) {
-               asus_proc_add(PROC_DISP, &disp_proc_fops, mode, device);
-       }
-
-       return 0;
-}
-
-static int asus_hotk_remove_fs(struct acpi_device *device)
-{
-       if (acpi_device_dir(device)) {
-               remove_proc_entry(PROC_INFO, acpi_device_dir(device));
-               if (hotk->methods->mt_wled)
-                       remove_proc_entry(PROC_WLED, acpi_device_dir(device));
-               if (hotk->methods->mt_mled)
-                       remove_proc_entry(PROC_MLED, acpi_device_dir(device));
-               if (hotk->methods->mt_tled)
-                       remove_proc_entry(PROC_TLED, acpi_device_dir(device));
-               if (hotk->methods->mt_ledd)
-                       remove_proc_entry(PROC_LEDD, acpi_device_dir(device));
-               if (hotk->methods->mt_bt_switch)
-                       remove_proc_entry(PROC_BT, acpi_device_dir(device));
-               if (hotk->methods->mt_lcd_switch && hotk->methods->lcd_status)
-                       remove_proc_entry(PROC_LCD, acpi_device_dir(device));
-               if ((hotk->methods->brightness_up
-                    && hotk->methods->brightness_down)
-                   || (hotk->methods->brightness_get
-                       && hotk->methods->brightness_set))
-                       remove_proc_entry(PROC_BRN, acpi_device_dir(device));
-               if (hotk->methods->display_set)
-                       remove_proc_entry(PROC_DISP, acpi_device_dir(device));
-       }
-       return 0;
-}
-
-static void asus_hotk_notify(struct acpi_device *device, u32 event)
-{
-       /* TODO Find a better way to handle events count. */
-       if (!hotk)
-               return;
-
-       /*
-        * The BIOS *should* be sending us device events, but apparently
-        * Asus uses system events instead, so just ignore any device
-        * events we get.
-        */
-       if (event > ACPI_MAX_SYS_NOTIFY)
-               return;
-
-       if ((event & ~((u32) BR_UP)) < 16)
-               hotk->brightness = (event & ~((u32) BR_UP));
-       else if ((event & ~((u32) BR_DOWN)) < 16)
-               hotk->brightness = (event & ~((u32) BR_DOWN));
-
-       acpi_bus_generate_proc_event(hotk->device, event,
-                               hotk->event_count[event % 128]++);
-
-       return;
-}
-
-/*
- * Match the model string to the list of supported models. Return END_MODEL if
- * no match or model is NULL.
- */
-static int asus_model_match(char *model)
-{
-       if (model == NULL)
-               return END_MODEL;
-
-       if (strncmp(model, "L3D", 3) == 0)
-               return L3D;
-       else if (strncmp(model, "L2E", 3) == 0 ||
-                strncmp(model, "L3H", 3) == 0 || strncmp(model, "L5D", 3) == 0)
-               return L3H;
-       else if (strncmp(model, "L3", 2) == 0 || strncmp(model, "L2B", 3) == 0)
-               return L3C;
-       else if (strncmp(model, "L8L", 3) == 0)
-               return L8L;
-       else if (strncmp(model, "L4R", 3) == 0)
-               return L4R;
-       else if (strncmp(model, "M6N", 3) == 0 || strncmp(model, "W3N", 3) == 0)
-               return M6N;
-       else if (strncmp(model, "M6R", 3) == 0 || strncmp(model, "A3G", 3) == 0)
-               return M6R;
-       else if (strncmp(model, "M2N", 3) == 0 ||
-                strncmp(model, "M3N", 3) == 0 ||
-                strncmp(model, "M5N", 3) == 0 ||
-                strncmp(model, "S1N", 3) == 0 ||
-                strncmp(model, "S5N", 3) == 0)
-               return xxN;
-       else if (strncmp(model, "M1", 2) == 0)
-               return M1A;
-       else if (strncmp(model, "M2", 2) == 0 || strncmp(model, "L4E", 3) == 0)
-               return M2E;
-       else if (strncmp(model, "L2", 2) == 0)
-               return L2D;
-       else if (strncmp(model, "L8", 2) == 0)
-               return S1x;
-       else if (strncmp(model, "D1", 2) == 0)
-               return D1x;
-       else if (strncmp(model, "A1", 2) == 0)
-               return A1x;
-       else if (strncmp(model, "A2", 2) == 0)
-               return A2x;
-       else if (strncmp(model, "J1", 2) == 0)
-               return S2x;
-       else if (strncmp(model, "L5", 2) == 0)
-               return L5x;
-       else if (strncmp(model, "A4G", 3) == 0)
-               return A4G;
-       else if (strncmp(model, "W1N", 3) == 0)
-               return W1N;
-       else if (strncmp(model, "W3V", 3) == 0)
-               return W3V;
-       else if (strncmp(model, "W5A", 3) == 0)
-               return W5A;
-       else if (strncmp(model, "R1F", 3) == 0)
-               return R1F;
-       else if (strncmp(model, "A4S", 3) == 0)
-               return A4S;
-       else if (strncmp(model, "F3Sa", 4) == 0)
-               return F3Sa;
-       else
-               return END_MODEL;
-}
-
-/*
- * This function is used to initialize the hotk with right values. In this
- * method, we can make all the detection we want, and modify the hotk struct
- */
-static int asus_hotk_get_info(void)
-{
-       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
-       union acpi_object *model = NULL;
-       int bsts_result;
-       char *string = NULL;
-       acpi_status status;
-
-       /*
-        * Get DSDT headers early enough to allow for differentiating between
-        * models, but late enough to allow acpi_bus_register_driver() to fail
-        * before doing anything ACPI-specific. Should we encounter a machine,
-        * which needs special handling (i.e. its hotkey device has a different
-        * HID), this bit will be moved. A global variable asus_info contains
-        * the DSDT header.
-        */
-       status = acpi_get_table(ACPI_SIG_DSDT, 1, &asus_info);
-       if (ACPI_FAILURE(status))
-               pr_warn("  Couldn't get the DSDT table header\n");
-
-       /* We have to write 0 on init this far for all ASUS models */
-       if (!write_acpi_int(hotk->handle, "INIT", 0, &buffer)) {
-               pr_err("  Hotkey initialization failed\n");
-               return -ENODEV;
-       }
-
-       /* This needs to be called for some laptops to init properly */
-       if (!read_acpi_int(hotk->handle, "BSTS", &bsts_result))
-               pr_warn("  Error calling BSTS\n");
-       else if (bsts_result)
-               pr_notice("  BSTS called, 0x%02x returned\n", bsts_result);
-
-       /*
-        * Try to match the object returned by INIT to the specific model.
-        * Handle every possible object (or the lack of thereof) the DSDT
-        * writers might throw at us. When in trouble, we pass NULL to
-        * asus_model_match() and try something completely different.
-        */
-       if (buffer.pointer) {
-               model = buffer.pointer;
-               switch (model->type) {
-               case ACPI_TYPE_STRING:
-                       string = model->string.pointer;
-                       break;
-               case ACPI_TYPE_BUFFER:
-                       string = model->buffer.pointer;
-                       break;
-               default:
-                       kfree(model);
-                       model = NULL;
-                       break;
-               }
-       }
-       hotk->model = asus_model_match(string);
-       if (hotk->model == END_MODEL) { /* match failed */
-               if (asus_info &&
-                   strncmp(asus_info->oem_table_id, "ODEM", 4) == 0) {
-                       hotk->model = P30;
-                       pr_notice("  Samsung P30 detected, supported\n");
-                       hotk->methods = &model_conf[hotk->model];
-                       kfree(model);
-                       return 0;
-               } else {
-                       hotk->model = M2E;
-                       pr_notice("  unsupported model %s, trying default values\n",
-                                 string);
-                       pr_notice("  send /proc/acpi/dsdt to the developers\n");
-                       kfree(model);
-                       return -ENODEV;
-               }
-       }
-       hotk->methods = &model_conf[hotk->model];
-       pr_notice("  %s model detected, supported\n", string);
-
-       /* Sort of per-model blacklist */
-       if (strncmp(string, "L2B", 3) == 0)
-               hotk->methods->lcd_status = NULL;
-       /* L2B is similar enough to L3C to use its settings, with this only
-          exception */
-       else if (strncmp(string, "A3G", 3) == 0)
-               hotk->methods->lcd_status = "\\BLFG";
-       /* A3G is like M6R */
-       else if (strncmp(string, "S5N", 3) == 0 ||
-                strncmp(string, "M5N", 3) == 0 ||
-                strncmp(string, "W3N", 3) == 0)
-               hotk->methods->mt_mled = NULL;
-       /* S5N, M5N and W3N have no MLED */
-       else if (strncmp(string, "L5D", 3) == 0)
-               hotk->methods->mt_wled = NULL;
-       /* L5D's WLED is not controlled by ACPI */
-       else if (strncmp(string, "M2N", 3) == 0 ||
-                strncmp(string, "W3V", 3) == 0 ||
-                strncmp(string, "S1N", 3) == 0)
-               hotk->methods->mt_wled = "WLED";
-       /* M2N, S1N and W3V have a usable WLED */
-       else if (asus_info) {
-               if (strncmp(asus_info->oem_table_id, "L1", 2) == 0)
-                       hotk->methods->mled_status = NULL;
-               /* S1300A reports L84F, but L1400B too, account for that */
-       }
-
-       kfree(model);
-
-       return 0;
-}
-
-static int asus_hotk_check(void)
-{
-       int result = 0;
-
-       result = acpi_bus_get_status(hotk->device);
-       if (result)
-               return result;
-
-       if (hotk->device->status.present) {
-               result = asus_hotk_get_info();
-       } else {
-               pr_err("  Hotkey device not present, aborting\n");
-               return -EINVAL;
-       }
-
-       return result;
-}
-
-static int asus_hotk_found;
-
-static int asus_hotk_add(struct acpi_device *device)
-{
-       acpi_status status = AE_OK;
-       int result;
-
-       pr_notice("Asus Laptop ACPI Extras version %s\n", ASUS_ACPI_VERSION);
-
-       hotk = kzalloc(sizeof(struct asus_hotk), GFP_KERNEL);
-       if (!hotk)
-               return -ENOMEM;
-
-       hotk->handle = device->handle;
-       strcpy(acpi_device_name(device), ACPI_HOTK_DEVICE_NAME);
-       strcpy(acpi_device_class(device), ACPI_HOTK_CLASS);
-       device->driver_data = hotk;
-       hotk->device = device;
-
-       result = asus_hotk_check();
-       if (result)
-               goto end;
-
-       result = asus_hotk_add_fs(device);
-       if (result)
-               goto end;
-
-       /* For laptops without GPLV: init the hotk->brightness value */
-       if ((!hotk->methods->brightness_get)
-           && (!hotk->methods->brightness_status)
-           && (hotk->methods->brightness_up && hotk->methods->brightness_down)) {
-               status =
-                   acpi_evaluate_object(NULL, hotk->methods->brightness_down,
-                                        NULL, NULL);
-               if (ACPI_FAILURE(status))
-                       pr_warn("  Error changing brightness\n");
-               else {
-                       status =
-                           acpi_evaluate_object(NULL,
-                                                hotk->methods->brightness_up,
-                                                NULL, NULL);
-                       if (ACPI_FAILURE(status))
-                               pr_warn("  Strange, error changing brightness\n");
-               }
-       }
-
-       asus_hotk_found = 1;
-
-       /* LED display is off by default */
-       hotk->ledd_status = 0xFFF;
-
-end:
-       if (result)
-               kfree(hotk);
-
-       return result;
-}
-
-static int asus_hotk_remove(struct acpi_device *device, int type)
-{
-       asus_hotk_remove_fs(device);
-
-       kfree(hotk);
-
-       return 0;
-}
-
-static const struct backlight_ops asus_backlight_data = {
-       .get_brightness = read_brightness,
-       .update_status  = set_brightness_status,
-};
-
-static void asus_acpi_exit(void)
-{
-       if (asus_backlight_device)
-               backlight_device_unregister(asus_backlight_device);
-
-       acpi_bus_unregister_driver(&asus_hotk_driver);
-       remove_proc_entry(PROC_ASUS, acpi_root_dir);
-
-       return;
-}
-
-static int __init asus_acpi_init(void)
-{
-       struct backlight_properties props;
-       int result;
-
-       result = acpi_bus_register_driver(&asus_hotk_driver);
-       if (result < 0)
-               return result;
-
-       asus_proc_dir = proc_mkdir(PROC_ASUS, acpi_root_dir);
-       if (!asus_proc_dir) {
-               pr_err("Unable to create /proc entry\n");
-               acpi_bus_unregister_driver(&asus_hotk_driver);
-               return -ENODEV;
-       }
-
-       /*
-        * This is a bit of a kludge.  We only want this module loaded
-        * for ASUS systems, but there's currently no way to probe the
-        * ACPI namespace for ASUS HIDs.  So we just return failure if
-        * we didn't find one, which will cause the module to be
-        * unloaded.
-        */
-       if (!asus_hotk_found) {
-               acpi_bus_unregister_driver(&asus_hotk_driver);
-               remove_proc_entry(PROC_ASUS, acpi_root_dir);
-               return -ENODEV;
-       }
-
-       memset(&props, 0, sizeof(struct backlight_properties));
-       props.type = BACKLIGHT_PLATFORM;
-       props.max_brightness = 15;
-       asus_backlight_device = backlight_device_register("asus", NULL, NULL,
-                                                         &asus_backlight_data,
-                                                         &props);
-       if (IS_ERR(asus_backlight_device)) {
-               pr_err("Could not register asus backlight device\n");
-               asus_backlight_device = NULL;
-               asus_acpi_exit();
-               return -ENODEV;
-       }
-
-       return 0;
-}
-
-module_init(asus_acpi_init);
-module_exit(asus_acpi_exit);
index d967344..1887e2f 100644 (file)
@@ -882,6 +882,7 @@ static struct dmi_system_id __initdata compal_dmi_table[] = {
        },
        { }
 };
+MODULE_DEVICE_TABLE(dmi, compal_dmi_table);
 
 static void initialize_power_supply_data(struct compal_data *data)
 {
@@ -1097,16 +1098,3 @@ MODULE_AUTHOR("Roald Frederickx (roald.frederickx@gmail.com)");
 MODULE_DESCRIPTION("Compal Laptop Support");
 MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL");
-
-MODULE_ALIAS("dmi:*:rnIFL90:rvrIFT00:*");
-MODULE_ALIAS("dmi:*:rnIFL90:rvrREFERENCE:*");
-MODULE_ALIAS("dmi:*:rnIFL91:rvrIFT00:*");
-MODULE_ALIAS("dmi:*:rnJFL92:rvrIFT00:*");
-MODULE_ALIAS("dmi:*:rnIFT00:rvrIFT00:*");
-MODULE_ALIAS("dmi:*:rnJHL90:rvrREFERENCE:*");
-MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron910:*");
-MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron1010:*");
-MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron1011:*");
-MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron1012:*");
-MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron1110:*");
-MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron1210:*");
index d93e962..a05fc9c 100644 (file)
@@ -117,6 +117,7 @@ static const struct dmi_system_id __initdata dell_device_table[] = {
        },
        { }
 };
+MODULE_DEVICE_TABLE(dmi, dell_device_table);
 
 static struct dmi_system_id __devinitdata dell_blacklist[] = {
        /* Supported by compal-laptop */
@@ -184,6 +185,33 @@ static struct dmi_system_id __devinitdata dell_quirks[] = {
                },
                .driver_data = &quirk_dell_vostro_v130,
        },
+       {
+               .callback = dmi_matched,
+               .ident = "Dell Vostro 3555",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3555"),
+               },
+               .driver_data = &quirk_dell_vostro_v130,
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Dell Inspiron N311z",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron N311z"),
+               },
+               .driver_data = &quirk_dell_vostro_v130,
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Dell Inspiron M5110",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron M5110"),
+               },
+               .driver_data = &quirk_dell_vostro_v130,
+       },
 };
 
 static struct calling_interface_buffer *buffer;
@@ -236,9 +264,7 @@ static void __init find_tokens(const struct dmi_header *dm, void *dummy)
 {
        switch (dm->type) {
        case 0xd4: /* Indexed IO */
-               break;
        case 0xd5: /* Protected Area Type 1 */
-               break;
        case 0xd6: /* Protected Area Type 2 */
                break;
        case 0xda: /* Calling interface */
@@ -615,6 +641,7 @@ static void touchpad_led_set(struct led_classdev *led_cdev,
 static struct led_classdev touchpad_led = {
        .name = "dell-laptop::touchpad",
        .brightness_set = touchpad_led_set,
+       .flags = LED_CORE_SUSPENDRESUME,
 };
 
 static int __devinit touchpad_led_init(struct device *dev)
@@ -794,6 +821,3 @@ module_exit(dell_exit);
 MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>");
 MODULE_DESCRIPTION("Dell laptop driver");
 MODULE_LICENSE("GPL");
-MODULE_ALIAS("dmi:*svnDellInc.:*:ct8:*");
-MODULE_ALIAS("dmi:*svnDellInc.:*:ct9:*");
-MODULE_ALIAS("dmi:*svnDellComputerCorporation.:*:ct8:*");
index d9a9e2b..dab91b4 100644 (file)
@@ -1251,6 +1251,14 @@ static void eeepc_input_exit(struct eeepc_laptop *eeepc)
 /*
  * ACPI driver
  */
+static void eeepc_input_notify(struct eeepc_laptop *eeepc, int event)
+{
+       if (!eeepc->inputdev)
+               return ;
+       if (!sparse_keymap_report_event(eeepc->inputdev, event, 1, true))
+               pr_info("Unknown key %x pressed\n", event);
+}
+
 static void eeepc_acpi_notify(struct acpi_device *device, u32 event)
 {
        struct eeepc_laptop *eeepc = acpi_driver_data(device);
@@ -1287,12 +1295,11 @@ static void eeepc_acpi_notify(struct acpi_device *device, u32 event)
                                * event will be desired value (or else ignored)
                                */
                        }
-                       sparse_keymap_report_event(eeepc->inputdev, event,
-                                                  1, true);
+                       eeepc_input_notify(eeepc, event);
                }
        } else {
                /* Everything else is a bona-fide keypress event */
-               sparse_keymap_report_event(eeepc->inputdev, event, 1, true);
+               eeepc_input_notify(eeepc, event);
        }
 }
 
index 9f6e643..6567613 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/input.h>
 #include <linux/input/sparse-keymap.h>
 #include <linux/dmi.h>
+#include <linux/fb.h>
 #include <acpi/acpi_bus.h>
 
 #include "asus-wmi.h"
@@ -84,9 +85,81 @@ static const struct key_entry eeepc_wmi_keymap[] = {
        { KE_KEY, 0xed, { KEY_CAMERA_DOWN } },
        { KE_KEY, 0xee, { KEY_CAMERA_LEFT } },
        { KE_KEY, 0xef, { KEY_CAMERA_RIGHT } },
+       { KE_KEY, 0xf3, { KEY_MENU } },
+       { KE_KEY, 0xf5, { KEY_HOMEPAGE } },
+       { KE_KEY, 0xf6, { KEY_ESC } },
        { KE_END, 0},
 };
 
+static struct quirk_entry quirk_asus_unknown = {
+};
+
+static struct quirk_entry quirk_asus_1000h = {
+       .hotplug_wireless = true,
+};
+
+static struct quirk_entry quirk_asus_et2012_type1 = {
+       .store_backlight_power = true,
+};
+
+static struct quirk_entry quirk_asus_et2012_type3 = {
+       .scalar_panel_brightness = true,
+       .store_backlight_power = true,
+};
+
+static struct quirk_entry *quirks;
+
+static void et2012_quirks(void)
+{
+       const struct dmi_device *dev = NULL;
+       char oemstring[30];
+
+       while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, NULL, dev))) {
+               if (sscanf(dev->name, "AEMS%24c", oemstring) == 1) {
+                       if (oemstring[18] == '1')
+                               quirks = &quirk_asus_et2012_type1;
+                       else if (oemstring[18] == '3')
+                               quirks = &quirk_asus_et2012_type3;
+                       break;
+               }
+       }
+}
+
+static int dmi_matched(const struct dmi_system_id *dmi)
+{
+       char *model;
+
+       quirks = dmi->driver_data;
+
+       model = (char *)dmi->matches[1].substr;
+       if (unlikely(strncmp(model, "ET2012", 6) == 0))
+               et2012_quirks();
+
+       return 1;
+}
+
+static struct dmi_system_id asus_quirks[] = {
+       {
+               .callback = dmi_matched,
+               .ident = "ASUSTeK Computer INC. 1000H",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer INC."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "1000H"),
+               },
+               .driver_data = &quirk_asus_1000h,
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "ASUSTeK Computer INC. ET2012E/I",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer INC."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ET2012"),
+               },
+               .driver_data = &quirk_asus_unknown,
+       },
+       {},
+};
+
 static void eeepc_wmi_key_filter(struct asus_wmi_driver *asus_wmi, int *code,
                                 unsigned int *value, bool *autorelease)
 {
@@ -141,33 +214,16 @@ static int eeepc_wmi_probe(struct platform_device *pdev)
        return 0;
 }
 
-static void eeepc_dmi_check(struct asus_wmi_driver *driver)
-{
-       const char *model;
-
-       model = dmi_get_system_info(DMI_PRODUCT_NAME);
-       if (!model)
-               return;
-
-       /*
-        * Whitelist for wlan hotplug
-        *
-        * Asus 1000H needs the current hotplug code to handle
-        * Fn+F2 correctly. We may add other Asus here later, but
-        * it seems that most of the laptops supported by asus-wmi
-        * don't need to be on this list
-        */
-       if (strcmp(model, "1000H") == 0) {
-               driver->hotplug_wireless = true;
-               pr_info("wlan hotplug enabled\n");
-       }
-}
-
 static void eeepc_wmi_quirks(struct asus_wmi_driver *driver)
 {
-       driver->hotplug_wireless = hotplug_wireless;
-       driver->wapf = -1;
-       eeepc_dmi_check(driver);
+       quirks = &quirk_asus_unknown;
+       quirks->hotplug_wireless = hotplug_wireless;
+
+       dmi_check_system(asus_quirks);
+
+       driver->quirks = quirks;
+       driver->quirks->wapf = -1;
+       driver->panel_power = FB_BLANK_UNBLANK;
 }
 
 static struct asus_wmi_driver asus_wmi_driver = {
@@ -179,7 +235,7 @@ static struct asus_wmi_driver asus_wmi_driver = {
        .input_phys = EEEPC_WMI_FILE "/input0",
        .key_filter = eeepc_wmi_key_filter,
        .probe = eeepc_wmi_probe,
-       .quirks = eeepc_wmi_quirks,
+       .detect_quirks = eeepc_wmi_quirks,
 };
 
 
index ba68d4e..7387f97 100644 (file)
@@ -375,7 +375,7 @@ static ssize_t hdaps_variance_show(struct device *dev,
 static ssize_t hdaps_temp1_show(struct device *dev,
                                struct device_attribute *attr, char *buf)
 {
-       u8 temp;
+       u8 uninitialized_var(temp);
        int ret;
 
        ret = hdaps_readb_one(HDAPS_PORT_TEMP1, &temp);
@@ -388,7 +388,7 @@ static ssize_t hdaps_temp1_show(struct device *dev,
 static ssize_t hdaps_temp2_show(struct device *dev,
                                struct device_attribute *attr, char *buf)
 {
-       u8 temp;
+       u8 uninitialized_var(temp);
        int ret;
 
        ret = hdaps_readb_one(HDAPS_PORT_TEMP2, &temp);
index 0903a88..0a3594c 100644 (file)
@@ -142,17 +142,7 @@ static struct platform_driver mfld_pb_driver = {
        .remove = __devexit_p(mfld_pb_remove),
 };
 
-static int __init mfld_pb_init(void)
-{
-       return platform_driver_register(&mfld_pb_driver);
-}
-module_init(mfld_pb_init);
-
-static void __exit mfld_pb_exit(void)
-{
-       platform_driver_unregister(&mfld_pb_driver);
-}
-module_exit(mfld_pb_exit);
+module_platform_driver(mfld_pb_driver);
 
 MODULE_AUTHOR("Hong Liu <hong.liu@intel.com>");
 MODULE_DESCRIPTION("Intel Medfield Power Button Driver");
index 2ee9766..5ae9cd9 100644 (file)
@@ -549,6 +549,7 @@ static int mid_thermal_remove(struct platform_device *pdev)
 
 static const struct platform_device_id therm_id_table[] = {
        { DRIVER_NAME, 1 },
+       { "msic_thermal", 1 },
        { }
 };
 
@@ -564,18 +565,7 @@ static struct platform_driver mid_thermal_driver = {
        .id_table = therm_id_table,
 };
 
-static int __init mid_thermal_module_init(void)
-{
-       return platform_driver_register(&mid_thermal_driver);
-}
-
-static void __exit mid_thermal_module_exit(void)
-{
-       platform_driver_unregister(&mid_thermal_driver);
-}
-
-module_init(mid_thermal_module_init);
-module_exit(mid_thermal_module_exit);
+module_platform_driver(mid_thermal_driver);
 
 MODULE_AUTHOR("Durgadoss R <durgadoss.r@intel.com>");
 MODULE_DESCRIPTION("Intel Medfield Platform Thermal Driver");
index 6ee0b5c..79a0c2f 100644 (file)
@@ -313,6 +313,7 @@ static struct dmi_system_id __initdata oaktrail_dmi_table[] = {
        },
        { }
 };
+MODULE_DEVICE_TABLE(dmi, oaktrail_dmi_table);
 
 static int __init oaktrail_init(void)
 {
@@ -394,4 +395,3 @@ MODULE_AUTHOR("Yin Kangkai (kangkai.yin@intel.com)");
 MODULE_DESCRIPTION("Intel Oaktrail Platform ACPI Extras");
 MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL");
-MODULE_ALIAS("dmi:*:svnIntelCorporation:pnOakTrailplatform:*");
index fd73ea8..e2a34b4 100644 (file)
 #include <linux/delay.h>
 #include <linux/pci.h>
 #include <linux/backlight.h>
+#include <linux/leds.h>
 #include <linux/fb.h>
 #include <linux/dmi.h>
 #include <linux/platform_device.h>
 #include <linux/rfkill.h>
+#include <linux/acpi.h>
+#include <linux/seq_file.h>
+#include <linux/debugfs.h>
+#include <linux/ctype.h>
+#if (defined CONFIG_ACPI_VIDEO || defined CONFIG_ACPI_VIDEO_MODULE)
+#include <acpi/video.h>
+#endif
 
 /*
  * This driver is needed because a number of Samsung laptops do not hook
 #define SABI_IFACE_COMPLETE            0x04
 #define SABI_IFACE_DATA                        0x05
 
-/* Structure to get data back to the calling function */
-struct sabi_retval {
-       u8 retval[20];
+#define WL_STATUS_WLAN                 0x0
+#define WL_STATUS_BT                   0x2
+
+/* Structure get/set data using sabi */
+struct sabi_data {
+       union {
+               struct {
+                       u32 d0;
+                       u32 d1;
+                       u16 d2;
+                       u8  d3;
+               };
+               u8 data[11];
+       };
 };
 
 struct sabi_header_offsets {
@@ -60,8 +79,8 @@ struct sabi_commands {
         * Brightness is 0 - 8, as described above.
         * Value 0 is for the BIOS to use
         */
-       u8 get_brightness;
-       u8 set_brightness;
+       u16 get_brightness;
+       u16 set_brightness;
 
        /*
         * first byte:
@@ -72,40 +91,56 @@ struct sabi_commands {
         * 0x03 - 3G is on
         * TODO, verify 3G is correct, that doesn't seem right...
         */
-       u8 get_wireless_button;
-       u8 set_wireless_button;
+       u16 get_wireless_button;
+       u16 set_wireless_button;
 
        /* 0 is off, 1 is on */
-       u8 get_backlight;
-       u8 set_backlight;
+       u16 get_backlight;
+       u16 set_backlight;
 
        /*
         * 0x80 or 0x00 - no action
         * 0x81 - recovery key pressed
         */
-       u8 get_recovery_mode;
-       u8 set_recovery_mode;
+       u16 get_recovery_mode;
+       u16 set_recovery_mode;
 
        /*
         * on seclinux: 0 is low, 1 is high,
         * on swsmi: 0 is normal, 1 is silent, 2 is turbo
         */
-       u8 get_performance_level;
-       u8 set_performance_level;
+       u16 get_performance_level;
+       u16 set_performance_level;
+
+       /* 0x80 is off, 0x81 is on */
+       u16 get_battery_life_extender;
+       u16 set_battery_life_extender;
+
+       /* 0x80 is off, 0x81 is on */
+       u16 get_usb_charge;
+       u16 set_usb_charge;
+
+       /* the first byte is for bluetooth and the third one is for wlan */
+       u16 get_wireless_status;
+       u16 set_wireless_status;
+
+       /* 0x81 to read, (0x82 | level << 8) to set, 0xaabb to enable */
+       u16 kbd_backlight;
 
        /*
         * Tell the BIOS that Linux is running on this machine.
         * 81 is on, 80 is off
         */
-       u8 set_linux;
+       u16 set_linux;
 };
 
 struct sabi_performance_level {
        const char *name;
-       u8 value;
+       u16 value;
 };
 
 struct sabi_config {
+       int sabi_version;
        const char *test_string;
        u16 main_function;
        const struct sabi_header_offsets header_offsets;
@@ -117,6 +152,10 @@ struct sabi_config {
 
 static const struct sabi_config sabi_configs[] = {
        {
+               /* I don't know if it is really 2, but it it is
+                * less than 3 anyway */
+               .sabi_version = 2,
+
                .test_string = "SECLINUX",
 
                .main_function = 0x4c49,
@@ -146,6 +185,17 @@ static const struct sabi_config sabi_configs[] = {
                        .get_performance_level = 0x08,
                        .set_performance_level = 0x09,
 
+                       .get_battery_life_extender = 0xFFFF,
+                       .set_battery_life_extender = 0xFFFF,
+
+                       .get_usb_charge = 0xFFFF,
+                       .set_usb_charge = 0xFFFF,
+
+                       .get_wireless_status = 0xFFFF,
+                       .set_wireless_status = 0xFFFF,
+
+                       .kbd_backlight = 0xFFFF,
+
                        .set_linux = 0x0a,
                },
 
@@ -164,6 +214,8 @@ static const struct sabi_config sabi_configs[] = {
                .max_brightness = 8,
        },
        {
+               .sabi_version = 3,
+
                .test_string = "SwSmi@",
 
                .main_function = 0x5843,
@@ -193,6 +245,17 @@ static const struct sabi_config sabi_configs[] = {
                        .get_performance_level = 0x31,
                        .set_performance_level = 0x32,
 
+                       .get_battery_life_extender = 0x65,
+                       .set_battery_life_extender = 0x66,
+
+                       .get_usb_charge = 0x67,
+                       .set_usb_charge = 0x68,
+
+                       .get_wireless_status = 0x69,
+                       .set_wireless_status = 0x6a,
+
+                       .kbd_backlight = 0x78,
+
                        .set_linux = 0xff,
                },
 
@@ -217,16 +280,82 @@ static const struct sabi_config sabi_configs[] = {
        { },
 };
 
-static const struct sabi_config *sabi_config;
+/*
+ * samsung-laptop/    - debugfs root directory
+ *   f0000_segment    - dump f0000 segment
+ *   command          - current command
+ *   data             - current data
+ *   d0, d1, d2, d3   - data fields
+ *   call             - call SABI using command and data
+ *
+ * This allow to call arbitrary sabi commands wihout
+ * modifying the driver at all.
+ * For example, setting the keyboard backlight brightness to 5
+ *
+ *  echo 0x78 > command
+ *  echo 0x0582 > d0
+ *  echo 0 > d1
+ *  echo 0 > d2
+ *  echo 0 > d3
+ *  cat call
+ */
+
+struct samsung_laptop_debug {
+       struct dentry *root;
+       struct sabi_data data;
+       u16 command;
+
+       struct debugfs_blob_wrapper f0000_wrapper;
+       struct debugfs_blob_wrapper data_wrapper;
+       struct debugfs_blob_wrapper sdiag_wrapper;
+};
+
+struct samsung_laptop;
+
+struct samsung_rfkill {
+       struct samsung_laptop *samsung;
+       struct rfkill *rfkill;
+       enum rfkill_type type;
+};
+
+struct samsung_laptop {
+       const struct sabi_config *config;
+
+       void __iomem *sabi;
+       void __iomem *sabi_iface;
+       void __iomem *f0000_segment;
+
+       struct mutex sabi_mutex;
+
+       struct platform_device *platform_device;
+       struct backlight_device *backlight_device;
+
+       struct samsung_rfkill wlan;
+       struct samsung_rfkill bluetooth;
+
+       struct led_classdev kbd_led;
+       int kbd_led_wk;
+       struct workqueue_struct *led_workqueue;
+       struct work_struct kbd_led_work;
+
+       struct samsung_laptop_debug debug;
+       struct samsung_quirks *quirks;
+
+       bool handle_backlight;
+       bool has_stepping_quirk;
+
+       char sdiag[64];
+};
+
+struct samsung_quirks {
+       bool broken_acpi_video;
+};
+
+static struct samsung_quirks samsung_unknown = {};
 
-static void __iomem *sabi;
-static void __iomem *sabi_iface;
-static void __iomem *f0000_segment;
-static struct backlight_device *backlight_device;
-static struct mutex sabi_mutex;
-static struct platform_device *sdev;
-static struct rfkill *rfk;
-static bool has_stepping_quirk;
+static struct samsung_quirks samsung_broken_acpi_video = {
+       .broken_acpi_video = true,
+};
 
 static bool force;
 module_param(force, bool, 0);
@@ -237,176 +366,143 @@ static bool debug;
 module_param(debug, bool, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(debug, "Debug enabled or not");
 
-static int sabi_get_command(u8 command, struct sabi_retval *sretval)
+static int sabi_command(struct samsung_laptop *samsung, u16 command,
+                       struct sabi_data *in,
+                       struct sabi_data *out)
 {
-       int retval = 0;
-       u16 port = readw(sabi + sabi_config->header_offsets.port);
+       const struct sabi_config *config = samsung->config;
+       int ret = 0;
+       u16 port = readw(samsung->sabi + config->header_offsets.port);
        u8 complete, iface_data;
 
-       mutex_lock(&sabi_mutex);
-
-       /* enable memory to be able to write to it */
-       outb(readb(sabi + sabi_config->header_offsets.en_mem), port);
-
-       /* write out the command */
-       writew(sabi_config->main_function, sabi_iface + SABI_IFACE_MAIN);
-       writew(command, sabi_iface + SABI_IFACE_SUB);
-       writeb(0, sabi_iface + SABI_IFACE_COMPLETE);
-       outb(readb(sabi + sabi_config->header_offsets.iface_func), port);
-
-       /* write protect memory to make it safe */
-       outb(readb(sabi + sabi_config->header_offsets.re_mem), port);
+       mutex_lock(&samsung->sabi_mutex);
 
-       /* see if the command actually succeeded */
-       complete = readb(sabi_iface + SABI_IFACE_COMPLETE);
-       iface_data = readb(sabi_iface + SABI_IFACE_DATA);
-       if (complete != 0xaa || iface_data == 0xff) {
-               pr_warn("SABI get command 0x%02x failed with completion flag 0x%02x and data 0x%02x\n",
-                       command, complete, iface_data);
-               retval = -EINVAL;
-               goto exit;
+       if (debug) {
+               if (in)
+                       pr_info("SABI command:0x%04x "
+                               "data:{0x%08x, 0x%08x, 0x%04x, 0x%02x}",
+                               command, in->d0, in->d1, in->d2, in->d3);
+               else
+                       pr_info("SABI command:0x%04x", command);
        }
-       /*
-        * Save off the data into a structure so the caller use it.
-        * Right now we only want the first 4 bytes,
-        * There are commands that need more, but not for the ones we
-        * currently care about.
-        */
-       sretval->retval[0] = readb(sabi_iface + SABI_IFACE_DATA);
-       sretval->retval[1] = readb(sabi_iface + SABI_IFACE_DATA + 1);
-       sretval->retval[2] = readb(sabi_iface + SABI_IFACE_DATA + 2);
-       sretval->retval[3] = readb(sabi_iface + SABI_IFACE_DATA + 3);
-
-exit:
-       mutex_unlock(&sabi_mutex);
-       return retval;
-
-}
-
-static int sabi_set_command(u8 command, u8 data)
-{
-       int retval = 0;
-       u16 port = readw(sabi + sabi_config->header_offsets.port);
-       u8 complete, iface_data;
-
-       mutex_lock(&sabi_mutex);
 
        /* enable memory to be able to write to it */
-       outb(readb(sabi + sabi_config->header_offsets.en_mem), port);
+       outb(readb(samsung->sabi + config->header_offsets.en_mem), port);
 
        /* write out the command */
-       writew(sabi_config->main_function, sabi_iface + SABI_IFACE_MAIN);
-       writew(command, sabi_iface + SABI_IFACE_SUB);
-       writeb(0, sabi_iface + SABI_IFACE_COMPLETE);
-       writeb(data, sabi_iface + SABI_IFACE_DATA);
-       outb(readb(sabi + sabi_config->header_offsets.iface_func), port);
+       writew(config->main_function, samsung->sabi_iface + SABI_IFACE_MAIN);
+       writew(command, samsung->sabi_iface + SABI_IFACE_SUB);
+       writeb(0, samsung->sabi_iface + SABI_IFACE_COMPLETE);
+       if (in) {
+               writel(in->d0, samsung->sabi_iface + SABI_IFACE_DATA);
+               writel(in->d1, samsung->sabi_iface + SABI_IFACE_DATA + 4);
+               writew(in->d2, samsung->sabi_iface + SABI_IFACE_DATA + 8);
+               writeb(in->d3, samsung->sabi_iface + SABI_IFACE_DATA + 10);
+       }
+       outb(readb(samsung->sabi + config->header_offsets.iface_func), port);
 
        /* write protect memory to make it safe */
-       outb(readb(sabi + sabi_config->header_offsets.re_mem), port);
+       outb(readb(samsung->sabi + config->header_offsets.re_mem), port);
 
        /* see if the command actually succeeded */
-       complete = readb(sabi_iface + SABI_IFACE_COMPLETE);
-       iface_data = readb(sabi_iface + SABI_IFACE_DATA);
+       complete = readb(samsung->sabi_iface + SABI_IFACE_COMPLETE);
+       iface_data = readb(samsung->sabi_iface + SABI_IFACE_DATA);
+
+       /* iface_data = 0xFF happens when a command is not known
+        * so we only add a warning in debug mode since we will
+        * probably issue some unknown command at startup to find
+        * out which features are supported */
+       if (complete != 0xaa || (iface_data == 0xff && debug))
+               pr_warn("SABI command 0x%04x failed with"
+                       " completion flag 0x%02x and interface data 0x%02x",
+                       command, complete, iface_data);
+
        if (complete != 0xaa || iface_data == 0xff) {
-               pr_warn("SABI set command 0x%02x failed with completion flag 0x%02x and data 0x%02x\n",
-                      command, complete, iface_data);
-               retval = -EINVAL;
+               ret = -EINVAL;
+               goto exit;
        }
 
-       mutex_unlock(&sabi_mutex);
-       return retval;
-}
-
-static void test_backlight(void)
-{
-       struct sabi_retval sretval;
-
-       sabi_get_command(sabi_config->commands.get_backlight, &sretval);
-       printk(KERN_DEBUG "backlight = 0x%02x\n", sretval.retval[0]);
-
-       sabi_set_command(sabi_config->commands.set_backlight, 0);
-       printk(KERN_DEBUG "backlight should be off\n");
-
-       sabi_get_command(sabi_config->commands.get_backlight, &sretval);
-       printk(KERN_DEBUG "backlight = 0x%02x\n", sretval.retval[0]);
-
-       msleep(1000);
+       if (out) {
+               out->d0 = readl(samsung->sabi_iface + SABI_IFACE_DATA);
+               out->d1 = readl(samsung->sabi_iface + SABI_IFACE_DATA + 4);
+               out->d2 = readw(samsung->sabi_iface + SABI_IFACE_DATA + 2);
+               out->d3 = readb(samsung->sabi_iface + SABI_IFACE_DATA + 1);
+       }
 
-       sabi_set_command(sabi_config->commands.set_backlight, 1);
-       printk(KERN_DEBUG "backlight should be on\n");
+       if (debug && out) {
+               pr_info("SABI return data:{0x%08x, 0x%08x, 0x%04x, 0x%02x}",
+                       out->d0, out->d1, out->d2, out->d3);
+       }
 
-       sabi_get_command(sabi_config->commands.get_backlight, &sretval);
-       printk(KERN_DEBUG "backlight = 0x%02x\n", sretval.retval[0]);
+exit:
+       mutex_unlock(&samsung->sabi_mutex);
+       return ret;
 }
 
-static void test_wireless(void)
+/* simple wrappers usable with most commands */
+static int sabi_set_commandb(struct samsung_laptop *samsung,
+                            u16 command, u8 data)
 {
-       struct sabi_retval sretval;
+       struct sabi_data in = { { { .d0 = 0, .d1 = 0, .d2 = 0, .d3 = 0 } } };
 
-       sabi_get_command(sabi_config->commands.get_wireless_button, &sretval);
-       printk(KERN_DEBUG "wireless led = 0x%02x\n", sretval.retval[0]);
-
-       sabi_set_command(sabi_config->commands.set_wireless_button, 0);
-       printk(KERN_DEBUG "wireless led should be off\n");
-
-       sabi_get_command(sabi_config->commands.get_wireless_button, &sretval);
-       printk(KERN_DEBUG "wireless led = 0x%02x\n", sretval.retval[0]);
-
-       msleep(1000);
-
-       sabi_set_command(sabi_config->commands.set_wireless_button, 1);
-       printk(KERN_DEBUG "wireless led should be on\n");
-
-       sabi_get_command(sabi_config->commands.get_wireless_button, &sretval);
-       printk(KERN_DEBUG "wireless led = 0x%02x\n", sretval.retval[0]);
+       in.data[0] = data;
+       return sabi_command(samsung, command, &in, NULL);
 }
 
-static u8 read_brightness(void)
+static int read_brightness(struct samsung_laptop *samsung)
 {
-       struct sabi_retval sretval;
+       const struct sabi_config *config = samsung->config;
+       const struct sabi_commands *commands = &samsung->config->commands;
+       struct sabi_data sretval;
        int user_brightness = 0;
        int retval;
 
-       retval = sabi_get_command(sabi_config->commands.get_brightness,
-                                 &sretval);
-       if (!retval) {
-               user_brightness = sretval.retval[0];
-               if (user_brightness > sabi_config->min_brightness)
-                       user_brightness -= sabi_config->min_brightness;
-               else
-                       user_brightness = 0;
-       }
+       retval = sabi_command(samsung, commands->get_brightness,
+                             NULL, &sretval);
+       if (retval)
+               return retval;
+
+       user_brightness = sretval.data[0];
+       if (user_brightness > config->min_brightness)
+               user_brightness -= config->min_brightness;
+       else
+               user_brightness = 0;
+
        return user_brightness;
 }
 
-static void set_brightness(u8 user_brightness)
+static void set_brightness(struct samsung_laptop *samsung, u8 user_brightness)
 {
-       u8 user_level = user_brightness + sabi_config->min_brightness;
+       const struct sabi_config *config = samsung->config;
+       const struct sabi_commands *commands = &samsung->config->commands;
+       u8 user_level = user_brightness + config->min_brightness;
 
-       if (has_stepping_quirk && user_level != 0) {
+       if (samsung->has_stepping_quirk && user_level != 0) {
                /*
                 * short circuit if the specified level is what's already set
                 * to prevent the screen from flickering needlessly
                 */
-               if (user_brightness == read_brightness())
+               if (user_brightness == read_brightness(samsung))
                        return;
 
-               sabi_set_command(sabi_config->commands.set_brightness, 0);
+               sabi_set_commandb(samsung, commands->set_brightness, 0);
        }
 
-       sabi_set_command(sabi_config->commands.set_brightness, user_level);
+       sabi_set_commandb(samsung, commands->set_brightness, user_level);
 }
 
 static int get_brightness(struct backlight_device *bd)
 {
-       return (int)read_brightness();
+       struct samsung_laptop *samsung = bl_get_data(bd);
+
+       return read_brightness(samsung);
 }
 
-static void check_for_stepping_quirk(void)
+static void check_for_stepping_quirk(struct samsung_laptop *samsung)
 {
-       u8 initial_level;
-       u8 check_level;
-       u8 orig_level = read_brightness();
+       int initial_level;
+       int check_level;
+       int orig_level = read_brightness(samsung);
 
        /*
         * Some laptops exhibit the strange behaviour of stepping toward
@@ -416,34 +512,38 @@ static void check_for_stepping_quirk(void)
         */
 
        if (orig_level == 0)
-               set_brightness(1);
+               set_brightness(samsung, 1);
 
-       initial_level = read_brightness();
+       initial_level = read_brightness(samsung);
 
        if (initial_level <= 2)
                check_level = initial_level + 2;
        else
                check_level = initial_level - 2;
 
-       has_stepping_quirk = false;
-       set_brightness(check_level);
+       samsung->has_stepping_quirk = false;
+       set_brightness(samsung, check_level);
 
-       if (read_brightness() != check_level) {
-               has_stepping_quirk = true;
+       if (read_brightness(samsung) != check_level) {
+               samsung->has_stepping_quirk = true;
                pr_info("enabled workaround for brightness stepping quirk\n");
        }
 
-       set_brightness(orig_level);
+       set_brightness(samsung, orig_level);
 }
 
 static int update_status(struct backlight_device *bd)
 {
-       set_brightness(bd->props.brightness);
+       struct samsung_laptop *samsung = bl_get_data(bd);
+       const struct sabi_commands *commands = &samsung->config->commands;
+
+       set_brightness(samsung, bd->props.brightness);
 
        if (bd->props.power == FB_BLANK_UNBLANK)
-               sabi_set_command(sabi_config->commands.set_backlight, 1);
+               sabi_set_commandb(samsung, commands->set_backlight, 1);
        else
-               sabi_set_command(sabi_config->commands.set_backlight, 0);
+               sabi_set_commandb(samsung, commands->set_backlight, 0);
+
        return 0;
 }
 
@@ -452,66 +552,101 @@ static const struct backlight_ops backlight_ops = {
        .update_status  = update_status,
 };
 
-static int rfkill_set(void *data, bool blocked)
+static int seclinux_rfkill_set(void *data, bool blocked)
 {
-       /* Do something with blocked...*/
-       /*
-        * blocked == false is on
-        * blocked == true is off
-        */
-       if (blocked)
-               sabi_set_command(sabi_config->commands.set_wireless_button, 0);
-       else
-               sabi_set_command(sabi_config->commands.set_wireless_button, 1);
+       struct samsung_rfkill *srfkill = data;
+       struct samsung_laptop *samsung = srfkill->samsung;
+       const struct sabi_commands *commands = &samsung->config->commands;
 
-       return 0;
+       return sabi_set_commandb(samsung, commands->set_wireless_button,
+                                !blocked);
 }
 
-static struct rfkill_ops rfkill_ops = {
-       .set_block = rfkill_set,
+static struct rfkill_ops seclinux_rfkill_ops = {
+       .set_block = seclinux_rfkill_set,
 };
 
-static int init_wireless(struct platform_device *sdev)
+static int swsmi_wireless_status(struct samsung_laptop *samsung,
+                                struct sabi_data *data)
 {
-       int retval;
+       const struct sabi_commands *commands = &samsung->config->commands;
 
-       rfk = rfkill_alloc("samsung-wifi", &sdev->dev, RFKILL_TYPE_WLAN,
-                          &rfkill_ops, NULL);
-       if (!rfk)
-               return -ENOMEM;
-
-       retval = rfkill_register(rfk);
-       if (retval) {
-               rfkill_destroy(rfk);
-               return -ENODEV;
-       }
+       return sabi_command(samsung, commands->get_wireless_status,
+                           NULL, data);
+}
 
-       return 0;
+static int swsmi_rfkill_set(void *priv, bool blocked)
+{
+       struct samsung_rfkill *srfkill = priv;
+       struct samsung_laptop *samsung = srfkill->samsung;
+       const struct sabi_commands *commands = &samsung->config->commands;
+       struct sabi_data data;
+       int ret, i;
+
+       ret = swsmi_wireless_status(samsung, &data);
+       if (ret)
+               return ret;
+
+       /* Don't set the state for non-present devices */
+       for (i = 0; i < 4; i++)
+               if (data.data[i] == 0x02)
+                       data.data[1] = 0;
+
+       if (srfkill->type == RFKILL_TYPE_WLAN)
+               data.data[WL_STATUS_WLAN] = !blocked;
+       else if (srfkill->type == RFKILL_TYPE_BLUETOOTH)
+               data.data[WL_STATUS_BT] = !blocked;
+
+       return sabi_command(samsung, commands->set_wireless_status,
+                           &data, &data);
 }
 
-static void destroy_wireless(void)
+static void swsmi_rfkill_query(struct rfkill *rfkill, void *priv)
 {
-       rfkill_unregister(rfk);
-       rfkill_destroy(rfk);
+       struct samsung_rfkill *srfkill = priv;
+       struct samsung_laptop *samsung = srfkill->samsung;
+       struct sabi_data data;
+       int ret;
+
+       ret = swsmi_wireless_status(samsung, &data);
+       if (ret)
+               return ;
+
+       if (srfkill->type == RFKILL_TYPE_WLAN)
+               ret = data.data[WL_STATUS_WLAN];
+       else if (srfkill->type == RFKILL_TYPE_BLUETOOTH)
+               ret = data.data[WL_STATUS_BT];
+       else
+               return ;
+
+       rfkill_set_sw_state(rfkill, !ret);
 }
 
+static struct rfkill_ops swsmi_rfkill_ops = {
+       .set_block = swsmi_rfkill_set,
+       .query = swsmi_rfkill_query,
+};
+
 static ssize_t get_performance_level(struct device *dev,
                                     struct device_attribute *attr, char *buf)
 {
-       struct sabi_retval sretval;
+       struct samsung_laptop *samsung = dev_get_drvdata(dev);
+       const struct sabi_config *config = samsung->config;
+       const struct sabi_commands *commands = &config->commands;
+       struct sabi_data sretval;
        int retval;
        int i;
 
        /* Read the state */
-       retval = sabi_get_command(sabi_config->commands.get_performance_level,
-                                 &sretval);
+       retval = sabi_command(samsung, commands->get_performance_level,
+                             NULL, &sretval);
        if (retval)
                return retval;
 
        /* The logic is backwards, yeah, lots of fun... */
-       for (i = 0; sabi_config->performance_levels[i].name; ++i) {
-               if (sretval.retval[0] == sabi_config->performance_levels[i].value)
-                       return sprintf(buf, "%s\n", sabi_config->performance_levels[i].name);
+       for (i = 0; config->performance_levels[i].name; ++i) {
+               if (sretval.data[0] == config->performance_levels[i].value)
+                       return sprintf(buf, "%s\n", config->performance_levels[i].name);
        }
        return sprintf(buf, "%s\n", "unknown");
 }
@@ -520,280 +655,189 @@ static ssize_t set_performance_level(struct device *dev,
                                struct device_attribute *attr, const char *buf,
                                size_t count)
 {
-       if (count >= 1) {
-               int i;
-               for (i = 0; sabi_config->performance_levels[i].name; ++i) {
-                       const struct sabi_performance_level *level =
-                               &sabi_config->performance_levels[i];
-                       if (!strncasecmp(level->name, buf, strlen(level->name))) {
-                               sabi_set_command(sabi_config->commands.set_performance_level,
-                                                level->value);
-                               break;
-                       }
+       struct samsung_laptop *samsung = dev_get_drvdata(dev);
+       const struct sabi_config *config = samsung->config;
+       const struct sabi_commands *commands = &config->commands;
+       int i;
+
+       if (count < 1)
+               return count;
+
+       for (i = 0; config->performance_levels[i].name; ++i) {
+               const struct sabi_performance_level *level =
+                       &config->performance_levels[i];
+               if (!strncasecmp(level->name, buf, strlen(level->name))) {
+                       sabi_set_commandb(samsung,
+                                         commands->set_performance_level,
+                                         level->value);
+                       break;
                }
-               if (!sabi_config->performance_levels[i].name)
-                       return -EINVAL;
        }
+
+       if (!config->performance_levels[i].name)
+               return -EINVAL;
+
        return count;
 }
+
 static DEVICE_ATTR(performance_level, S_IWUSR | S_IRUGO,
                   get_performance_level, set_performance_level);
 
-
-static int __init dmi_check_cb(const struct dmi_system_id *id)
+static int read_battery_life_extender(struct samsung_laptop *samsung)
 {
-       pr_info("found laptop model '%s'\n",
-               id->ident);
-       return 1;
-}
+       const struct sabi_commands *commands = &samsung->config->commands;
+       struct sabi_data data;
+       int retval;
 
-static struct dmi_system_id __initdata samsung_dmi_table[] = {
-       {
-               .ident = "N128",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR,
-                                       "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "N128"),
-                       DMI_MATCH(DMI_BOARD_NAME, "N128"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "N130",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR,
-                                       "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "N130"),
-                       DMI_MATCH(DMI_BOARD_NAME, "N130"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "N510",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR,
-                                       "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "N510"),
-                       DMI_MATCH(DMI_BOARD_NAME, "N510"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "X125",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR,
-                                       "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "X125"),
-                       DMI_MATCH(DMI_BOARD_NAME, "X125"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "X120/X170",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR,
-                                       "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "X120/X170"),
-                       DMI_MATCH(DMI_BOARD_NAME, "X120/X170"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "NC10",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR,
-                                       "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "NC10"),
-                       DMI_MATCH(DMI_BOARD_NAME, "NC10"),
-               },
-               .callback = dmi_check_cb,
-       },
-               {
-               .ident = "NP-Q45",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR,
-                                       "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "SQ45S70S"),
-                       DMI_MATCH(DMI_BOARD_NAME, "SQ45S70S"),
-               },
-               .callback = dmi_check_cb,
-               },
-       {
-               .ident = "X360",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR,
-                                       "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "X360"),
-                       DMI_MATCH(DMI_BOARD_NAME, "X360"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "R410 Plus",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR,
-                                       "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "R410P"),
-                       DMI_MATCH(DMI_BOARD_NAME, "R460"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "R518",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR,
-                                       "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "R518"),
-                       DMI_MATCH(DMI_BOARD_NAME, "R518"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "R519/R719",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR,
-                                       "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "R519/R719"),
-                       DMI_MATCH(DMI_BOARD_NAME, "R519/R719"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "N150/N210/N220",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR,
-                                       "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "N150/N210/N220"),
-                       DMI_MATCH(DMI_BOARD_NAME, "N150/N210/N220"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "N220",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR,
-                                       "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "N220"),
-                       DMI_MATCH(DMI_BOARD_NAME, "N220"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "N150/N210/N220/N230",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR,
-                                       "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "N150/N210/N220/N230"),
-                       DMI_MATCH(DMI_BOARD_NAME, "N150/N210/N220/N230"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "N150P/N210P/N220P",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR,
-                                       "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "N150P/N210P/N220P"),
-                       DMI_MATCH(DMI_BOARD_NAME, "N150P/N210P/N220P"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "R700",
-               .matches = {
-                     DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
-                     DMI_MATCH(DMI_PRODUCT_NAME, "SR700"),
-                     DMI_MATCH(DMI_BOARD_NAME, "SR700"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "R530/R730",
-               .matches = {
-                     DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
-                     DMI_MATCH(DMI_PRODUCT_NAME, "R530/R730"),
-                     DMI_MATCH(DMI_BOARD_NAME, "R530/R730"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "NF110/NF210/NF310",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "NF110/NF210/NF310"),
-                       DMI_MATCH(DMI_BOARD_NAME, "NF110/NF210/NF310"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "N145P/N250P/N260P",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "N145P/N250P/N260P"),
-                       DMI_MATCH(DMI_BOARD_NAME, "N145P/N250P/N260P"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "R70/R71",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR,
-                                       "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "R70/R71"),
-                       DMI_MATCH(DMI_BOARD_NAME, "R70/R71"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "P460",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "P460"),
-                       DMI_MATCH(DMI_BOARD_NAME, "P460"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "R528/R728",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "R528/R728"),
-                       DMI_MATCH(DMI_BOARD_NAME, "R528/R728"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "NC210/NC110",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "NC210/NC110"),
-                       DMI_MATCH(DMI_BOARD_NAME, "NC210/NC110"),
-               },
-               .callback = dmi_check_cb,
-       },
-               {
-               .ident = "X520",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "X520"),
-                       DMI_MATCH(DMI_BOARD_NAME, "X520"),
-               },
-               .callback = dmi_check_cb,
-       },
-       { },
-};
-MODULE_DEVICE_TABLE(dmi, samsung_dmi_table);
+       if (commands->get_battery_life_extender == 0xFFFF)
+               return -ENODEV;
 
-static int find_signature(void __iomem *memcheck, const char *testStr)
-{
-       int i = 0;
-       int loca;
+       memset(&data, 0, sizeof(data));
+       data.data[0] = 0x80;
+       retval = sabi_command(samsung, commands->get_battery_life_extender,
+                             &data, &data);
 
-       for (loca = 0; loca < 0xffff; loca++) {
-               char temp = readb(memcheck + loca);
+       if (retval)
+               return retval;
 
-               if (temp == testStr[i]) {
-                       if (i == strlen(testStr)-1)
+       if (data.data[0] != 0 && data.data[0] != 1)
+               return -ENODEV;
+
+       return data.data[0];
+}
+
+static int write_battery_life_extender(struct samsung_laptop *samsung,
+                                      int enabled)
+{
+       const struct sabi_commands *commands = &samsung->config->commands;
+       struct sabi_data data;
+
+       memset(&data, 0, sizeof(data));
+       data.data[0] = 0x80 | enabled;
+       return sabi_command(samsung, commands->set_battery_life_extender,
+                           &data, NULL);
+}
+
+static ssize_t get_battery_life_extender(struct device *dev,
+                                        struct device_attribute *attr,
+                                        char *buf)
+{
+       struct samsung_laptop *samsung = dev_get_drvdata(dev);
+       int ret;
+
+       ret = read_battery_life_extender(samsung);
+       if (ret < 0)
+               return ret;
+
+       return sprintf(buf, "%d\n", ret);
+}
+
+static ssize_t set_battery_life_extender(struct device *dev,
+                                       struct device_attribute *attr,
+                                       const char *buf, size_t count)
+{
+       struct samsung_laptop *samsung = dev_get_drvdata(dev);
+       int ret, value;
+
+       if (!count || sscanf(buf, "%i", &value) != 1)
+               return -EINVAL;
+
+       ret = write_battery_life_extender(samsung, !!value);
+       if (ret < 0)
+               return ret;
+
+       return count;
+}
+
+static DEVICE_ATTR(battery_life_extender, S_IWUSR | S_IRUGO,
+                  get_battery_life_extender, set_battery_life_extender);
+
+static int read_usb_charge(struct samsung_laptop *samsung)
+{
+       const struct sabi_commands *commands = &samsung->config->commands;
+       struct sabi_data data;
+       int retval;
+
+       if (commands->get_usb_charge == 0xFFFF)
+               return -ENODEV;
+
+       memset(&data, 0, sizeof(data));
+       data.data[0] = 0x80;
+       retval = sabi_command(samsung, commands->get_usb_charge,
+                             &data, &data);
+
+       if (retval)
+               return retval;
+
+       if (data.data[0] != 0 && data.data[0] != 1)
+               return -ENODEV;
+
+       return data.data[0];
+}
+
+static int write_usb_charge(struct samsung_laptop *samsung,
+                           int enabled)
+{
+       const struct sabi_commands *commands = &samsung->config->commands;
+       struct sabi_data data;
+
+       memset(&data, 0, sizeof(data));
+       data.data[0] = 0x80 | enabled;
+       return sabi_command(samsung, commands->set_usb_charge,
+                           &data, NULL);
+}
+
+static ssize_t get_usb_charge(struct device *dev,
+                             struct device_attribute *attr,
+                             char *buf)
+{
+       struct samsung_laptop *samsung = dev_get_drvdata(dev);
+       int ret;
+
+       ret = read_usb_charge(samsung);
+       if (ret < 0)
+               return ret;
+
+       return sprintf(buf, "%d\n", ret);
+}
+
+static ssize_t set_usb_charge(struct device *dev,
+                             struct device_attribute *attr,
+                             const char *buf, size_t count)
+{
+       struct samsung_laptop *samsung = dev_get_drvdata(dev);
+       int ret, value;
+
+       if (!count || sscanf(buf, "%i", &value) != 1)
+               return -EINVAL;
+
+       ret = write_usb_charge(samsung, !!value);
+       if (ret < 0)
+               return ret;
+
+       return count;
+}
+
+static DEVICE_ATTR(usb_charge, S_IWUSR | S_IRUGO,
+                  get_usb_charge, set_usb_charge);
+
+static struct attribute *platform_attributes[] = {
+       &dev_attr_performance_level.attr,
+       &dev_attr_battery_life_extender.attr,
+       &dev_attr_usb_charge.attr,
+       NULL
+};
+
+static int find_signature(void __iomem *memcheck, const char *testStr)
+{
+       int i = 0;
+       int loca;
+
+       for (loca = 0; loca < 0xffff; loca++) {
+               char temp = readb(memcheck + loca);
+
+               if (temp == testStr[i]) {
+                       if (i == strlen(testStr)-1)
                                break;
                        ++i;
                } else {
@@ -803,153 +847,772 @@ static int find_signature(void __iomem *memcheck, const char *testStr)
        return loca;
 }
 
-static int __init samsung_init(void)
+static void samsung_rfkill_exit(struct samsung_laptop *samsung)
 {
-       struct backlight_properties props;
-       struct sabi_retval sretval;
-       unsigned int ifaceP;
-       int i;
-       int loca;
+       if (samsung->wlan.rfkill) {
+               rfkill_unregister(samsung->wlan.rfkill);
+               rfkill_destroy(samsung->wlan.rfkill);
+               samsung->wlan.rfkill = NULL;
+       }
+       if (samsung->bluetooth.rfkill) {
+               rfkill_unregister(samsung->bluetooth.rfkill);
+               rfkill_destroy(samsung->bluetooth.rfkill);
+               samsung->bluetooth.rfkill = NULL;
+       }
+}
+
+static int samsung_new_rfkill(struct samsung_laptop *samsung,
+                             struct samsung_rfkill *arfkill,
+                             const char *name, enum rfkill_type type,
+                             const struct rfkill_ops *ops,
+                             int blocked)
+{
+       struct rfkill **rfkill = &arfkill->rfkill;
+       int ret;
+
+       arfkill->type = type;
+       arfkill->samsung = samsung;
+
+       *rfkill = rfkill_alloc(name, &samsung->platform_device->dev,
+                              type, ops, arfkill);
+
+       if (!*rfkill)
+               return -EINVAL;
+
+       if (blocked != -1)
+               rfkill_init_sw_state(*rfkill, blocked);
+
+       ret = rfkill_register(*rfkill);
+       if (ret) {
+               rfkill_destroy(*rfkill);
+               *rfkill = NULL;
+               return ret;
+       }
+       return 0;
+}
+
+static int __init samsung_rfkill_init_seclinux(struct samsung_laptop *samsung)
+{
+       return samsung_new_rfkill(samsung, &samsung->wlan, "samsung-wlan",
+                                 RFKILL_TYPE_WLAN, &seclinux_rfkill_ops, -1);
+}
+
+static int __init samsung_rfkill_init_swsmi(struct samsung_laptop *samsung)
+{
+       struct sabi_data data;
+       int ret;
+
+       ret = swsmi_wireless_status(samsung, &data);
+       if (ret) {
+               /* Some swsmi laptops use the old seclinux way to control
+                * wireless devices */
+               if (ret == -EINVAL)
+                       ret = samsung_rfkill_init_seclinux(samsung);
+               return ret;
+       }
+
+       /* 0x02 seems to mean that the device is no present/available */
+
+       if (data.data[WL_STATUS_WLAN] != 0x02)
+               ret = samsung_new_rfkill(samsung, &samsung->wlan,
+                                        "samsung-wlan",
+                                        RFKILL_TYPE_WLAN,
+                                        &swsmi_rfkill_ops,
+                                        !data.data[WL_STATUS_WLAN]);
+       if (ret)
+               goto exit;
+
+       if (data.data[WL_STATUS_BT] != 0x02)
+               ret = samsung_new_rfkill(samsung, &samsung->bluetooth,
+                                        "samsung-bluetooth",
+                                        RFKILL_TYPE_BLUETOOTH,
+                                        &swsmi_rfkill_ops,
+                                        !data.data[WL_STATUS_BT]);
+       if (ret)
+               goto exit;
+
+exit:
+       if (ret)
+               samsung_rfkill_exit(samsung);
+
+       return ret;
+}
+
+static int __init samsung_rfkill_init(struct samsung_laptop *samsung)
+{
+       if (samsung->config->sabi_version == 2)
+               return samsung_rfkill_init_seclinux(samsung);
+       if (samsung->config->sabi_version == 3)
+               return samsung_rfkill_init_swsmi(samsung);
+       return 0;
+}
+
+static int kbd_backlight_enable(struct samsung_laptop *samsung)
+{
+       const struct sabi_commands *commands = &samsung->config->commands;
+       struct sabi_data data;
        int retval;
 
-       mutex_init(&sabi_mutex);
+       if (commands->kbd_backlight == 0xFFFF)
+               return -ENODEV;
 
-       if (!force && !dmi_check_system(samsung_dmi_table))
+       memset(&data, 0, sizeof(data));
+       data.d0 = 0xaabb;
+       retval = sabi_command(samsung, commands->kbd_backlight,
+                             &data, &data);
+
+       if (retval)
+               return retval;
+
+       if (data.d0 != 0xccdd)
                return -ENODEV;
+       return 0;
+}
 
-       f0000_segment = ioremap_nocache(0xf0000, 0xffff);
-       if (!f0000_segment) {
-               pr_err("Can't map the segment at 0xf0000\n");
-               return -EINVAL;
+static int kbd_backlight_read(struct samsung_laptop *samsung)
+{
+       const struct sabi_commands *commands = &samsung->config->commands;
+       struct sabi_data data;
+       int retval;
+
+       memset(&data, 0, sizeof(data));
+       data.data[0] = 0x81;
+       retval = sabi_command(samsung, commands->kbd_backlight,
+                             &data, &data);
+
+       if (retval)
+               return retval;
+
+       return data.data[0];
+}
+
+static int kbd_backlight_write(struct samsung_laptop *samsung, int brightness)
+{
+       const struct sabi_commands *commands = &samsung->config->commands;
+       struct sabi_data data;
+
+       memset(&data, 0, sizeof(data));
+       data.d0 = 0x82 | ((brightness & 0xFF) << 8);
+       return sabi_command(samsung, commands->kbd_backlight,
+                           &data, NULL);
+}
+
+static void kbd_led_update(struct work_struct *work)
+{
+       struct samsung_laptop *samsung;
+
+       samsung = container_of(work, struct samsung_laptop, kbd_led_work);
+       kbd_backlight_write(samsung, samsung->kbd_led_wk);
+}
+
+static void kbd_led_set(struct led_classdev *led_cdev,
+                       enum led_brightness value)
+{
+       struct samsung_laptop *samsung;
+
+       samsung = container_of(led_cdev, struct samsung_laptop, kbd_led);
+
+       if (value > samsung->kbd_led.max_brightness)
+               value = samsung->kbd_led.max_brightness;
+       else if (value < 0)
+               value = 0;
+
+       samsung->kbd_led_wk = value;
+       queue_work(samsung->led_workqueue, &samsung->kbd_led_work);
+}
+
+static enum led_brightness kbd_led_get(struct led_classdev *led_cdev)
+{
+       struct samsung_laptop *samsung;
+
+       samsung = container_of(led_cdev, struct samsung_laptop, kbd_led);
+       return kbd_backlight_read(samsung);
+}
+
+static void samsung_leds_exit(struct samsung_laptop *samsung)
+{
+       if (!IS_ERR_OR_NULL(samsung->kbd_led.dev))
+               led_classdev_unregister(&samsung->kbd_led);
+       if (samsung->led_workqueue)
+               destroy_workqueue(samsung->led_workqueue);
+}
+
+static int __init samsung_leds_init(struct samsung_laptop *samsung)
+{
+       int ret = 0;
+
+       samsung->led_workqueue = create_singlethread_workqueue("led_workqueue");
+       if (!samsung->led_workqueue)
+               return -ENOMEM;
+
+       if (kbd_backlight_enable(samsung) >= 0) {
+               INIT_WORK(&samsung->kbd_led_work, kbd_led_update);
+
+               samsung->kbd_led.name = "samsung::kbd_backlight";
+               samsung->kbd_led.brightness_set = kbd_led_set;
+               samsung->kbd_led.brightness_get = kbd_led_get;
+               samsung->kbd_led.max_brightness = 8;
+
+               ret = led_classdev_register(&samsung->platform_device->dev,
+                                          &samsung->kbd_led);
+       }
+
+       if (ret)
+               samsung_leds_exit(samsung);
+
+       return ret;
+}
+
+static void samsung_backlight_exit(struct samsung_laptop *samsung)
+{
+       if (samsung->backlight_device) {
+               backlight_device_unregister(samsung->backlight_device);
+               samsung->backlight_device = NULL;
+       }
+}
+
+static int __init samsung_backlight_init(struct samsung_laptop *samsung)
+{
+       struct backlight_device *bd;
+       struct backlight_properties props;
+
+       if (!samsung->handle_backlight)
+               return 0;
+
+       memset(&props, 0, sizeof(struct backlight_properties));
+       props.type = BACKLIGHT_PLATFORM;
+       props.max_brightness = samsung->config->max_brightness -
+               samsung->config->min_brightness;
+
+       bd = backlight_device_register("samsung",
+                                      &samsung->platform_device->dev,
+                                      samsung, &backlight_ops,
+                                      &props);
+       if (IS_ERR(bd))
+               return PTR_ERR(bd);
+
+       samsung->backlight_device = bd;
+       samsung->backlight_device->props.brightness = read_brightness(samsung);
+       samsung->backlight_device->props.power = FB_BLANK_UNBLANK;
+       backlight_update_status(samsung->backlight_device);
+
+       return 0;
+}
+
+static umode_t samsung_sysfs_is_visible(struct kobject *kobj,
+                                      struct attribute *attr, int idx)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct platform_device *pdev = to_platform_device(dev);
+       struct samsung_laptop *samsung = platform_get_drvdata(pdev);
+       bool ok = true;
+
+       if (attr == &dev_attr_performance_level.attr)
+               ok = !!samsung->config->performance_levels[0].name;
+       if (attr == &dev_attr_battery_life_extender.attr)
+               ok = !!(read_battery_life_extender(samsung) >= 0);
+       if (attr == &dev_attr_usb_charge.attr)
+               ok = !!(read_usb_charge(samsung) >= 0);
+
+       return ok ? attr->mode : 0;
+}
+
+static struct attribute_group platform_attribute_group = {
+       .is_visible = samsung_sysfs_is_visible,
+       .attrs = platform_attributes
+};
+
+static void samsung_sysfs_exit(struct samsung_laptop *samsung)
+{
+       struct platform_device *device = samsung->platform_device;
+
+       sysfs_remove_group(&device->dev.kobj, &platform_attribute_group);
+}
+
+static int __init samsung_sysfs_init(struct samsung_laptop *samsung)
+{
+       struct platform_device *device = samsung->platform_device;
+
+       return sysfs_create_group(&device->dev.kobj, &platform_attribute_group);
+
+}
+
+static int show_call(struct seq_file *m, void *data)
+{
+       struct samsung_laptop *samsung = m->private;
+       struct sabi_data *sdata = &samsung->debug.data;
+       int ret;
+
+       seq_printf(m, "SABI 0x%04x {0x%08x, 0x%08x, 0x%04x, 0x%02x}\n",
+                  samsung->debug.command,
+                  sdata->d0, sdata->d1, sdata->d2, sdata->d3);
+
+       ret = sabi_command(samsung, samsung->debug.command, sdata, sdata);
+
+       if (ret) {
+               seq_printf(m, "SABI command 0x%04x failed\n",
+                          samsung->debug.command);
+               return ret;
+       }
+
+       seq_printf(m, "SABI {0x%08x, 0x%08x, 0x%04x, 0x%02x}\n",
+                  sdata->d0, sdata->d1, sdata->d2, sdata->d3);
+       return 0;
+}
+
+static int samsung_debugfs_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, show_call, inode->i_private);
+}
+
+static const struct file_operations samsung_laptop_call_io_ops = {
+       .owner = THIS_MODULE,
+       .open = samsung_debugfs_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release,
+};
+
+static void samsung_debugfs_exit(struct samsung_laptop *samsung)
+{
+       debugfs_remove_recursive(samsung->debug.root);
+}
+
+static int samsung_debugfs_init(struct samsung_laptop *samsung)
+{
+       struct dentry *dent;
+
+       samsung->debug.root = debugfs_create_dir("samsung-laptop", NULL);
+       if (!samsung->debug.root) {
+               pr_err("failed to create debugfs directory");
+               goto error_debugfs;
        }
 
+       samsung->debug.f0000_wrapper.data = samsung->f0000_segment;
+       samsung->debug.f0000_wrapper.size = 0xffff;
+
+       samsung->debug.data_wrapper.data = &samsung->debug.data;
+       samsung->debug.data_wrapper.size = sizeof(samsung->debug.data);
+
+       samsung->debug.sdiag_wrapper.data = samsung->sdiag;
+       samsung->debug.sdiag_wrapper.size = strlen(samsung->sdiag);
+
+       dent = debugfs_create_u16("command", S_IRUGO | S_IWUSR,
+                                 samsung->debug.root, &samsung->debug.command);
+       if (!dent)
+               goto error_debugfs;
+
+       dent = debugfs_create_u32("d0", S_IRUGO | S_IWUSR, samsung->debug.root,
+                                 &samsung->debug.data.d0);
+       if (!dent)
+               goto error_debugfs;
+
+       dent = debugfs_create_u32("d1", S_IRUGO | S_IWUSR, samsung->debug.root,
+                                 &samsung->debug.data.d1);
+       if (!dent)
+               goto error_debugfs;
+
+       dent = debugfs_create_u16("d2", S_IRUGO | S_IWUSR, samsung->debug.root,
+                                 &samsung->debug.data.d2);
+       if (!dent)
+               goto error_debugfs;
+
+       dent = debugfs_create_u8("d3", S_IRUGO | S_IWUSR, samsung->debug.root,
+                                &samsung->debug.data.d3);
+       if (!dent)
+               goto error_debugfs;
+
+       dent = debugfs_create_blob("data", S_IRUGO | S_IWUSR,
+                                  samsung->debug.root,
+                                  &samsung->debug.data_wrapper);
+       if (!dent)
+               goto error_debugfs;
+
+       dent = debugfs_create_blob("f0000_segment", S_IRUSR | S_IWUSR,
+                                  samsung->debug.root,
+                                  &samsung->debug.f0000_wrapper);
+       if (!dent)
+               goto error_debugfs;
+
+       dent = debugfs_create_file("call", S_IFREG | S_IRUGO,
+                                  samsung->debug.root, samsung,
+                                  &samsung_laptop_call_io_ops);
+       if (!dent)
+               goto error_debugfs;
+
+       dent = debugfs_create_blob("sdiag", S_IRUGO | S_IWUSR,
+                                  samsung->debug.root,
+                                  &samsung->debug.sdiag_wrapper);
+       if (!dent)
+               goto error_debugfs;
+
+       return 0;
+
+error_debugfs:
+       samsung_debugfs_exit(samsung);
+       return -ENOMEM;
+}
+
+static void samsung_sabi_exit(struct samsung_laptop *samsung)
+{
+       const struct sabi_config *config = samsung->config;
+
+       /* Turn off "Linux" mode in the BIOS */
+       if (config && config->commands.set_linux != 0xff)
+               sabi_set_commandb(samsung, config->commands.set_linux, 0x80);
+
+       if (samsung->sabi_iface) {
+               iounmap(samsung->sabi_iface);
+               samsung->sabi_iface = NULL;
+       }
+       if (samsung->f0000_segment) {
+               iounmap(samsung->f0000_segment);
+               samsung->f0000_segment = NULL;
+       }
+
+       samsung->config = NULL;
+}
+
+static __init void samsung_sabi_infos(struct samsung_laptop *samsung, int loca,
+                                     unsigned int ifaceP)
+{
+       const struct sabi_config *config = samsung->config;
+
+       printk(KERN_DEBUG "This computer supports SABI==%x\n",
+              loca + 0xf0000 - 6);
+
+       printk(KERN_DEBUG "SABI header:\n");
+       printk(KERN_DEBUG " SMI Port Number = 0x%04x\n",
+              readw(samsung->sabi + config->header_offsets.port));
+       printk(KERN_DEBUG " SMI Interface Function = 0x%02x\n",
+              readb(samsung->sabi + config->header_offsets.iface_func));
+       printk(KERN_DEBUG " SMI enable memory buffer = 0x%02x\n",
+              readb(samsung->sabi + config->header_offsets.en_mem));
+       printk(KERN_DEBUG " SMI restore memory buffer = 0x%02x\n",
+              readb(samsung->sabi + config->header_offsets.re_mem));
+       printk(KERN_DEBUG " SABI data offset = 0x%04x\n",
+              readw(samsung->sabi + config->header_offsets.data_offset));
+       printk(KERN_DEBUG " SABI data segment = 0x%04x\n",
+              readw(samsung->sabi + config->header_offsets.data_segment));
+
+       printk(KERN_DEBUG " SABI pointer = 0x%08x\n", ifaceP);
+}
+
+static void __init samsung_sabi_diag(struct samsung_laptop *samsung)
+{
+       int loca = find_signature(samsung->f0000_segment, "SDiaG@");
+       int i;
+
+       if (loca == 0xffff)
+               return ;
+
+       /* Example:
+        * Ident: @SDiaG@686XX-N90X3A/966-SEC-07HL-S90X3A
+        *
+        * Product name: 90X3A
+        * BIOS Version: 07HL
+        */
+       loca += 1;
+       for (i = 0; loca < 0xffff && i < sizeof(samsung->sdiag) - 1; loca++) {
+               char temp = readb(samsung->f0000_segment + loca);
+
+               if (isalnum(temp) || temp == '/' || temp == '-')
+                       samsung->sdiag[i++] = temp;
+               else
+                       break ;
+       }
+
+       if (debug && samsung->sdiag[0])
+               pr_info("sdiag: %s", samsung->sdiag);
+}
+
+static int __init samsung_sabi_init(struct samsung_laptop *samsung)
+{
+       const struct sabi_config *config = NULL;
+       const struct sabi_commands *commands;
+       unsigned int ifaceP;
+       int ret = 0;
+       int i;
+       int loca;
+
+       samsung->f0000_segment = ioremap_nocache(0xf0000, 0xffff);
+       if (!samsung->f0000_segment) {
+               if (debug || force)
+                       pr_err("Can't map the segment at 0xf0000\n");
+               ret = -EINVAL;
+               goto exit;
+       }
+
+       samsung_sabi_diag(samsung);
+
        /* Try to find one of the signatures in memory to find the header */
        for (i = 0; sabi_configs[i].test_string != 0; ++i) {
-               sabi_config = &sabi_configs[i];
-               loca = find_signature(f0000_segment, sabi_config->test_string);
+               samsung->config = &sabi_configs[i];
+               loca = find_signature(samsung->f0000_segment,
+                                     samsung->config->test_string);
                if (loca != 0xffff)
                        break;
        }
 
        if (loca == 0xffff) {
-               pr_err("This computer does not support SABI\n");
-               goto error_no_signature;
+               if (debug || force)
+                       pr_err("This computer does not support SABI\n");
+               ret = -ENODEV;
+               goto exit;
        }
 
+       config = samsung->config;
+       commands = &config->commands;
+
        /* point to the SMI port Number */
        loca += 1;
-       sabi = (f0000_segment + loca);
-
-       if (debug) {
-               printk(KERN_DEBUG "This computer supports SABI==%x\n",
-                       loca + 0xf0000 - 6);
-               printk(KERN_DEBUG "SABI header:\n");
-               printk(KERN_DEBUG " SMI Port Number = 0x%04x\n",
-                       readw(sabi + sabi_config->header_offsets.port));
-               printk(KERN_DEBUG " SMI Interface Function = 0x%02x\n",
-                       readb(sabi + sabi_config->header_offsets.iface_func));
-               printk(KERN_DEBUG " SMI enable memory buffer = 0x%02x\n",
-                       readb(sabi + sabi_config->header_offsets.en_mem));
-               printk(KERN_DEBUG " SMI restore memory buffer = 0x%02x\n",
-                       readb(sabi + sabi_config->header_offsets.re_mem));
-               printk(KERN_DEBUG " SABI data offset = 0x%04x\n",
-                       readw(sabi + sabi_config->header_offsets.data_offset));
-               printk(KERN_DEBUG " SABI data segment = 0x%04x\n",
-                       readw(sabi + sabi_config->header_offsets.data_segment));
-       }
+       samsung->sabi = (samsung->f0000_segment + loca);
 
        /* Get a pointer to the SABI Interface */
-       ifaceP = (readw(sabi + sabi_config->header_offsets.data_segment) & 0x0ffff) << 4;
-       ifaceP += readw(sabi + sabi_config->header_offsets.data_offset) & 0x0ffff;
-       sabi_iface = ioremap_nocache(ifaceP, 16);
-       if (!sabi_iface) {
-               pr_err("Can't remap %x\n", ifaceP);
-               goto error_no_signature;
-       }
-       if (debug) {
-               printk(KERN_DEBUG "ifaceP = 0x%08x\n", ifaceP);
-               printk(KERN_DEBUG "sabi_iface = %p\n", sabi_iface);
+       ifaceP = (readw(samsung->sabi + config->header_offsets.data_segment) & 0x0ffff) << 4;
+       ifaceP += readw(samsung->sabi + config->header_offsets.data_offset) & 0x0ffff;
 
-               test_backlight();
-               test_wireless();
+       if (debug)
+               samsung_sabi_infos(samsung, loca, ifaceP);
 
-               retval = sabi_get_command(sabi_config->commands.get_brightness,
-                                         &sretval);
-               printk(KERN_DEBUG "brightness = 0x%02x\n", sretval.retval[0]);
+       samsung->sabi_iface = ioremap_nocache(ifaceP, 16);
+       if (!samsung->sabi_iface) {
+               pr_err("Can't remap %x\n", ifaceP);
+               ret = -EINVAL;
+               goto exit;
        }
 
        /* Turn on "Linux" mode in the BIOS */
-       if (sabi_config->commands.set_linux != 0xff) {
-               retval = sabi_set_command(sabi_config->commands.set_linux,
-                                         0x81);
+       if (commands->set_linux != 0xff) {
+               int retval = sabi_set_commandb(samsung,
+                                              commands->set_linux, 0x81);
                if (retval) {
                        pr_warn("Linux mode was not set!\n");
-                       goto error_no_platform;
+                       ret = -ENODEV;
+                       goto exit;
                }
        }
 
        /* Check for stepping quirk */
-       check_for_stepping_quirk();
+       if (samsung->handle_backlight)
+               check_for_stepping_quirk(samsung);
 
-       /* knock up a platform device to hang stuff off of */
-       sdev = platform_device_register_simple("samsung", -1, NULL, 0);
-       if (IS_ERR(sdev))
-               goto error_no_platform;
+       pr_info("detected SABI interface: %s\n",
+               samsung->config->test_string);
 
-       /* create a backlight device to talk to this one */
-       memset(&props, 0, sizeof(struct backlight_properties));
-       props.type = BACKLIGHT_PLATFORM;
-       props.max_brightness = sabi_config->max_brightness -
-                               sabi_config->min_brightness;
-       backlight_device = backlight_device_register("samsung", &sdev->dev,
-                                                    NULL, &backlight_ops,
-                                                    &props);
-       if (IS_ERR(backlight_device))
-               goto error_no_backlight;
-
-       backlight_device->props.brightness = read_brightness();
-       backlight_device->props.power = FB_BLANK_UNBLANK;
-       backlight_update_status(backlight_device);
-
-       retval = init_wireless(sdev);
-       if (retval)
-               goto error_no_rfk;
+exit:
+       if (ret)
+               samsung_sabi_exit(samsung);
 
-       retval = device_create_file(&sdev->dev, &dev_attr_performance_level);
-       if (retval)
-               goto error_file_create;
+       return ret;
+}
+
+static void samsung_platform_exit(struct samsung_laptop *samsung)
+{
+       if (samsung->platform_device) {
+               platform_device_unregister(samsung->platform_device);
+               samsung->platform_device = NULL;
+       }
+}
+
+static int __init samsung_platform_init(struct samsung_laptop *samsung)
+{
+       struct platform_device *pdev;
 
+       pdev = platform_device_register_simple("samsung", -1, NULL, 0);
+       if (IS_ERR(pdev))
+               return PTR_ERR(pdev);
+
+       samsung->platform_device = pdev;
+       platform_set_drvdata(samsung->platform_device, samsung);
        return 0;
+}
 
-error_file_create:
-       destroy_wireless();
+static struct samsung_quirks *quirks;
 
-error_no_rfk:
-       backlight_device_unregister(backlight_device);
+static int __init samsung_dmi_matched(const struct dmi_system_id *d)
+{
+       quirks = d->driver_data;
+       return 0;
+}
 
-error_no_backlight:
-       platform_device_unregister(sdev);
+static struct dmi_system_id __initdata samsung_dmi_table[] = {
+       {
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR,
+                                       "SAMSUNG ELECTRONICS CO., LTD."),
+                       DMI_MATCH(DMI_CHASSIS_TYPE, "8"), /* Portable */
+               },
+       },
+       {
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR,
+                                       "SAMSUNG ELECTRONICS CO., LTD."),
+                       DMI_MATCH(DMI_CHASSIS_TYPE, "9"), /* Laptop */
+               },
+       },
+       {
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR,
+                                       "SAMSUNG ELECTRONICS CO., LTD."),
+                       DMI_MATCH(DMI_CHASSIS_TYPE, "10"), /* Notebook */
+               },
+       },
+       {
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR,
+                                       "SAMSUNG ELECTRONICS CO., LTD."),
+                       DMI_MATCH(DMI_CHASSIS_TYPE, "14"), /* Sub-Notebook */
+               },
+       },
+       /* Specific DMI ids for laptop with quirks */
+       {
+        .callback = samsung_dmi_matched,
+        .ident = "N150P",
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
+               DMI_MATCH(DMI_PRODUCT_NAME, "N150P"),
+               DMI_MATCH(DMI_BOARD_NAME, "N150P"),
+               },
+        .driver_data = &samsung_broken_acpi_video,
+       },
+       {
+        .callback = samsung_dmi_matched,
+        .ident = "N145P/N250P/N260P",
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
+               DMI_MATCH(DMI_PRODUCT_NAME, "N145P/N250P/N260P"),
+               DMI_MATCH(DMI_BOARD_NAME, "N145P/N250P/N260P"),
+               },
+        .driver_data = &samsung_broken_acpi_video,
+       },
+       {
+        .callback = samsung_dmi_matched,
+        .ident = "N150/N210/N220",
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
+               DMI_MATCH(DMI_PRODUCT_NAME, "N150/N210/N220"),
+               DMI_MATCH(DMI_BOARD_NAME, "N150/N210/N220"),
+               },
+        .driver_data = &samsung_broken_acpi_video,
+       },
+       {
+        .callback = samsung_dmi_matched,
+        .ident = "NF110/NF210/NF310",
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
+               DMI_MATCH(DMI_PRODUCT_NAME, "NF110/NF210/NF310"),
+               DMI_MATCH(DMI_BOARD_NAME, "NF110/NF210/NF310"),
+               },
+        .driver_data = &samsung_broken_acpi_video,
+       },
+       { },
+};
+MODULE_DEVICE_TABLE(dmi, samsung_dmi_table);
+
+static struct platform_device *samsung_platform_device;
+
+static int __init samsung_init(void)
+{
+       struct samsung_laptop *samsung;
+       int ret;
+
+       quirks = &samsung_unknown;
+       if (!force && !dmi_check_system(samsung_dmi_table))
+               return -ENODEV;
+
+       samsung = kzalloc(sizeof(*samsung), GFP_KERNEL);
+       if (!samsung)
+               return -ENOMEM;
+
+       mutex_init(&samsung->sabi_mutex);
+       samsung->handle_backlight = true;
+       samsung->quirks = quirks;
 
-error_no_platform:
-       iounmap(sabi_iface);
 
-error_no_signature:
-       iounmap(f0000_segment);
-       return -EINVAL;
+#if (defined CONFIG_ACPI_VIDEO || defined CONFIG_ACPI_VIDEO_MODULE)
+       /* Don't handle backlight here if the acpi video already handle it */
+       if (acpi_video_backlight_support()) {
+               if (samsung->quirks->broken_acpi_video) {
+                       pr_info("Disabling ACPI video driver\n");
+                       acpi_video_unregister();
+               } else {
+                       samsung->handle_backlight = false;
+               }
+       }
+#endif
+
+       ret = samsung_platform_init(samsung);
+       if (ret)
+               goto error_platform;
+
+       ret = samsung_sabi_init(samsung);
+       if (ret)
+               goto error_sabi;
+
+#ifdef CONFIG_ACPI
+       /* Only log that if we are really on a sabi platform */
+       if (acpi_video_backlight_support() &&
+           !samsung->quirks->broken_acpi_video)
+               pr_info("Backlight controlled by ACPI video driver\n");
+#endif
+
+       ret = samsung_sysfs_init(samsung);
+       if (ret)
+               goto error_sysfs;
+
+       ret = samsung_backlight_init(samsung);
+       if (ret)
+               goto error_backlight;
+
+       ret = samsung_rfkill_init(samsung);
+       if (ret)
+               goto error_rfkill;
+
+       ret = samsung_leds_init(samsung);
+       if (ret)
+               goto error_leds;
+
+       ret = samsung_debugfs_init(samsung);
+       if (ret)
+               goto error_debugfs;
+
+       samsung_platform_device = samsung->platform_device;
+       return ret;
+
+error_debugfs:
+       samsung_leds_exit(samsung);
+error_leds:
+       samsung_rfkill_exit(samsung);
+error_rfkill:
+       samsung_backlight_exit(samsung);
+error_backlight:
+       samsung_sysfs_exit(samsung);
+error_sysfs:
+       samsung_sabi_exit(samsung);
+error_sabi:
+       samsung_platform_exit(samsung);
+error_platform:
+       kfree(samsung);
+       return ret;
 }
 
 static void __exit samsung_exit(void)
 {
-       /* Turn off "Linux" mode in the BIOS */
-       if (sabi_config->commands.set_linux != 0xff)
-               sabi_set_command(sabi_config->commands.set_linux, 0x80);
-
-       device_remove_file(&sdev->dev, &dev_attr_performance_level);
-       backlight_device_unregister(backlight_device);
-       destroy_wireless();
-       iounmap(sabi_iface);
-       iounmap(f0000_segment);
-       platform_device_unregister(sdev);
+       struct samsung_laptop *samsung;
+
+       samsung = platform_get_drvdata(samsung_platform_device);
+
+       samsung_debugfs_exit(samsung);
+       samsung_leds_exit(samsung);
+       samsung_rfkill_exit(samsung);
+       samsung_backlight_exit(samsung);
+       samsung_sysfs_exit(samsung);
+       samsung_sabi_exit(samsung);
+       samsung_platform_exit(samsung);
+
+       kfree(samsung);
+       samsung_platform_device = NULL;
 }
 
 module_init(samsung_init);
index c006dee..8a51795 100644 (file)
@@ -127,7 +127,7 @@ MODULE_PARM_DESC(minor,
                 "default is -1 (automatic)");
 #endif
 
-static int kbd_backlight;      /* = 1 */
+static int kbd_backlight = 1;
 module_param(kbd_backlight, int, 0444);
 MODULE_PARM_DESC(kbd_backlight,
                 "set this to 0 to disable keyboard backlight, "
@@ -347,6 +347,7 @@ static void sony_laptop_report_input_event(u8 event)
        struct input_dev *jog_dev = sony_laptop_input.jog_dev;
        struct input_dev *key_dev = sony_laptop_input.key_dev;
        struct sony_laptop_keypress kp = { NULL };
+       int scancode = -1;
 
        if (event == SONYPI_EVENT_FNKEY_RELEASED ||
                        event == SONYPI_EVENT_ANYBUTTON_RELEASED) {
@@ -380,8 +381,8 @@ static void sony_laptop_report_input_event(u8 event)
                        dprintk("sony_laptop_report_input_event, event not known: %d\n", event);
                        break;
                }
-               if (sony_laptop_input_index[event] != -1) {
-                       kp.key = sony_laptop_input_keycode_map[sony_laptop_input_index[event]];
+               if ((scancode = sony_laptop_input_index[event]) != -1) {
+                       kp.key = sony_laptop_input_keycode_map[scancode];
                        if (kp.key != KEY_UNKNOWN)
                                kp.dev = key_dev;
                }
@@ -389,9 +390,11 @@ static void sony_laptop_report_input_event(u8 event)
        }
 
        if (kp.dev) {
+               /* if we have a scancode we emit it so we can always
+                   remap the key */
+               if (scancode != -1)
+                       input_event(kp.dev, EV_MSC, MSC_SCAN, scancode);
                input_report_key(kp.dev, kp.key, 1);
-               /* we emit the scancode so we can always remap the key */
-               input_event(kp.dev, EV_MSC, MSC_SCAN, event);
                input_sync(kp.dev);
 
                /* schedule key release */
@@ -466,7 +469,7 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device)
        jog_dev->name = "Sony Vaio Jogdial";
        jog_dev->id.bustype = BUS_ISA;
        jog_dev->id.vendor = PCI_VENDOR_ID_SONY;
-       key_dev->dev.parent = &acpi_device->dev;
+       jog_dev->dev.parent = &acpi_device->dev;
 
        input_set_capability(jog_dev, EV_KEY, BTN_MIDDLE);
        input_set_capability(jog_dev, EV_REL, REL_WHEEL);
index ea0c607..d68c000 100644 (file)
@@ -8658,7 +8658,7 @@ static int __must_check __init get_thinkpad_model_data(
        }
 
        s = dmi_get_system_info(DMI_PRODUCT_VERSION);
-       if (s && !strnicmp(s, "ThinkPad", 8)) {
+       if (s && !(strnicmp(s, "ThinkPad", 8) && strnicmp(s, "Lenovo", 6))) {
                tp->model_str = kstrdup(s, GFP_KERNEL);
                if (!tp->model_str)
                        return -ENOMEM;
index dcdc1f4..ee79ce6 100644 (file)
@@ -52,6 +52,8 @@
 #include <linux/input/sparse-keymap.h>
 #include <linux/leds.h>
 #include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <linux/i8042.h>
 
 #include <asm/uaccess.h>
 
@@ -61,6 +63,11 @@ MODULE_AUTHOR("John Belmonte");
 MODULE_DESCRIPTION("Toshiba Laptop ACPI Extras Driver");
 MODULE_LICENSE("GPL");
 
+#define TOSHIBA_WMI_EVENT_GUID "59142400-C6A3-40FA-BADB-8A2652834100"
+
+/* Scan code for Fn key on TOS1900 models */
+#define TOS1900_FN_SCAN                0x6e
+
 /* Toshiba ACPI method paths */
 #define METHOD_VIDEO_OUT       "\\_SB_.VALX.DSSX"
 
@@ -95,6 +102,8 @@ MODULE_LICENSE("GPL");
 #define HCI_WIRELESS                   0x0056
 
 /* field definitions */
+#define HCI_HOTKEY_DISABLE             0x0b
+#define HCI_HOTKEY_ENABLE              0x09
 #define HCI_LCD_BRIGHTNESS_BITS                3
 #define HCI_LCD_BRIGHTNESS_SHIFT       (16-HCI_LCD_BRIGHTNESS_BITS)
 #define HCI_LCD_BRIGHTNESS_LEVELS      (1 << HCI_LCD_BRIGHTNESS_BITS)
@@ -111,6 +120,7 @@ struct toshiba_acpi_dev {
        const char *method_hci;
        struct rfkill *bt_rfk;
        struct input_dev *hotkey_dev;
+       struct work_struct hotkey_work;
        struct backlight_device *backlight_dev;
        struct led_classdev led_dev;
 
@@ -118,14 +128,18 @@ struct toshiba_acpi_dev {
        int last_key_event;
        int key_event_valid;
 
-       int illumination_supported:1;
-       int video_supported:1;
-       int fan_supported:1;
-       int system_event_supported:1;
+       unsigned int illumination_supported:1;
+       unsigned int video_supported:1;
+       unsigned int fan_supported:1;
+       unsigned int system_event_supported:1;
+       unsigned int ntfy_supported:1;
+       unsigned int info_supported:1;
 
        struct mutex mutex;
 };
 
+static struct toshiba_acpi_dev *toshiba_acpi;
+
 static const struct acpi_device_id toshiba_device_ids[] = {
        {"TOS6200", 0},
        {"TOS6208", 0},
@@ -138,6 +152,8 @@ static const struct key_entry toshiba_acpi_keymap[] __devinitconst = {
        { KE_KEY, 0x101, { KEY_MUTE } },
        { KE_KEY, 0x102, { KEY_ZOOMOUT } },
        { KE_KEY, 0x103, { KEY_ZOOMIN } },
+       { KE_KEY, 0x12c, { KEY_KBDILLUMTOGGLE } },
+       { KE_KEY, 0x139, { KEY_ZOOMRESET } },
        { KE_KEY, 0x13b, { KEY_COFFEE } },
        { KE_KEY, 0x13c, { KEY_BATTERY } },
        { KE_KEY, 0x13d, { KEY_SLEEP } },
@@ -146,7 +162,7 @@ static const struct key_entry toshiba_acpi_keymap[] __devinitconst = {
        { KE_KEY, 0x140, { KEY_BRIGHTNESSDOWN } },
        { KE_KEY, 0x141, { KEY_BRIGHTNESSUP } },
        { KE_KEY, 0x142, { KEY_WLAN } },
-       { KE_KEY, 0x143, { KEY_PROG1 } },
+       { KE_KEY, 0x143, { KEY_TOUCHPAD_TOGGLE } },
        { KE_KEY, 0x17f, { KEY_FN } },
        { KE_KEY, 0xb05, { KEY_PROG2 } },
        { KE_KEY, 0xb06, { KEY_WWW } },
@@ -156,6 +172,7 @@ static const struct key_entry toshiba_acpi_keymap[] __devinitconst = {
        { KE_KEY, 0xb32, { KEY_NEXTSONG } },
        { KE_KEY, 0xb33, { KEY_PLAYPAUSE } },
        { KE_KEY, 0xb5a, { KEY_MEDIA } },
+       { KE_IGNORE, 0x1430, { KEY_RESERVED } },
        { KE_END, 0 },
 };
 
@@ -847,10 +864,78 @@ static const struct backlight_ops toshiba_backlight_data = {
         .update_status  = set_lcd_status,
 };
 
+static bool toshiba_acpi_i8042_filter(unsigned char data, unsigned char str,
+                                     struct serio *port)
+{
+       if (str & 0x20)
+               return false;
+
+       if (unlikely(data == 0xe0))
+               return false;
+
+       if ((data & 0x7f) == TOS1900_FN_SCAN) {
+               schedule_work(&toshiba_acpi->hotkey_work);
+               return true;
+       }
+
+       return false;
+}
+
+static void toshiba_acpi_hotkey_work(struct work_struct *work)
+{
+       acpi_handle ec_handle = ec_get_handle();
+       acpi_status status;
+
+       if (!ec_handle)
+               return;
+
+       status = acpi_evaluate_object(ec_handle, "NTFY", NULL, NULL);
+       if (ACPI_FAILURE(status))
+               pr_err("ACPI NTFY method execution failed\n");
+}
+
+/*
+ * Returns hotkey scancode, or < 0 on failure.
+ */
+static int toshiba_acpi_query_hotkey(struct toshiba_acpi_dev *dev)
+{
+       struct acpi_buffer buf;
+       union acpi_object out_obj;
+       acpi_status status;
+
+       buf.pointer = &out_obj;
+       buf.length = sizeof(out_obj);
+
+       status = acpi_evaluate_object(dev->acpi_dev->handle, "INFO",
+                                     NULL, &buf);
+       if (ACPI_FAILURE(status) || out_obj.type != ACPI_TYPE_INTEGER) {
+               pr_err("ACPI INFO method execution failed\n");
+               return -EIO;
+       }
+
+       return out_obj.integer.value;
+}
+
+static void toshiba_acpi_report_hotkey(struct toshiba_acpi_dev *dev,
+                                      int scancode)
+{
+       if (scancode == 0x100)
+               return;
+
+       /* act on key press; ignore key release */
+       if (scancode & 0x80)
+               return;
+
+       if (!sparse_keymap_report_event(dev->hotkey_dev, scancode, 1, true))
+               pr_info("Unknown key %x\n", scancode);
+}
+
 static int __devinit toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev)
 {
        acpi_status status;
+       acpi_handle ec_handle, handle;
        int error;
+       u32 hci_result;
 
        dev->hotkey_dev = input_allocate_device();
        if (!dev->hotkey_dev) {
@@ -866,21 +951,67 @@ static int __devinit toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev)
        if (error)
                goto err_free_dev;
 
+       /*
+        * For some machines the SCI responsible for providing hotkey
+        * notification doesn't fire. We can trigger the notification
+        * whenever the Fn key is pressed using the NTFY method, if
+        * supported, so if it's present set up an i8042 key filter
+        * for this purpose.
+        */
+       status = AE_ERROR;
+       ec_handle = ec_get_handle();
+       if (ec_handle)
+               status = acpi_get_handle(ec_handle, "NTFY", &handle);
+
+       if (ACPI_SUCCESS(status)) {
+               INIT_WORK(&dev->hotkey_work, toshiba_acpi_hotkey_work);
+
+               error = i8042_install_filter(toshiba_acpi_i8042_filter);
+               if (error) {
+                       pr_err("Error installing key filter\n");
+                       goto err_free_keymap;
+               }
+
+               dev->ntfy_supported = 1;
+       }
+
+       /*
+        * Determine hotkey query interface. Prefer using the INFO
+        * method when it is available.
+        */
+       status = acpi_get_handle(dev->acpi_dev->handle, "INFO", &handle);
+       if (ACPI_SUCCESS(status)) {
+               dev->info_supported = 1;
+       } else {
+               hci_write1(dev, HCI_SYSTEM_EVENT, 1, &hci_result);
+               if (hci_result == HCI_SUCCESS)
+                       dev->system_event_supported = 1;
+       }
+
+       if (!dev->info_supported && !dev->system_event_supported) {
+               pr_warn("No hotkey query interface found\n");
+               goto err_remove_filter;
+       }
+
        status = acpi_evaluate_object(dev->acpi_dev->handle, "ENAB", NULL, NULL);
        if (ACPI_FAILURE(status)) {
                pr_info("Unable to enable hotkeys\n");
                error = -ENODEV;
-               goto err_free_keymap;
+               goto err_remove_filter;
        }
 
        error = input_register_device(dev->hotkey_dev);
        if (error) {
                pr_info("Unable to register input device\n");
-               goto err_free_keymap;
+               goto err_remove_filter;
        }
 
+       hci_write1(dev, HCI_HOTKEY_EVENT, HCI_HOTKEY_ENABLE, &hci_result);
        return 0;
 
+ err_remove_filter:
+       if (dev->ntfy_supported)
+               i8042_remove_filter(toshiba_acpi_i8042_filter);
  err_free_keymap:
        sparse_keymap_free(dev->hotkey_dev);
  err_free_dev:
@@ -895,6 +1026,11 @@ static int toshiba_acpi_remove(struct acpi_device *acpi_dev, int type)
 
        remove_toshiba_proc_entries(dev);
 
+       if (dev->ntfy_supported) {
+               i8042_remove_filter(toshiba_acpi_i8042_filter);
+               cancel_work_sync(&dev->hotkey_work);
+       }
+
        if (dev->hotkey_dev) {
                input_unregister_device(dev->hotkey_dev);
                sparse_keymap_free(dev->hotkey_dev);
@@ -911,6 +1047,9 @@ static int toshiba_acpi_remove(struct acpi_device *acpi_dev, int type)
        if (dev->illumination_supported)
                led_classdev_unregister(&dev->led_dev);
 
+       if (toshiba_acpi)
+               toshiba_acpi = NULL;
+
        kfree(dev);
 
        return 0;
@@ -936,12 +1075,14 @@ static int __devinit toshiba_acpi_add(struct acpi_device *acpi_dev)
 {
        struct toshiba_acpi_dev *dev;
        const char *hci_method;
-       u32 hci_result;
        u32 dummy;
        bool bt_present;
        int ret = 0;
        struct backlight_properties props;
 
+       if (toshiba_acpi)
+               return -EBUSY;
+
        pr_info("Toshiba Laptop ACPI Extras version %s\n",
               TOSHIBA_ACPI_VERSION);
 
@@ -963,11 +1104,6 @@ static int __devinit toshiba_acpi_add(struct acpi_device *acpi_dev)
 
        mutex_init(&dev->mutex);
 
-       /* enable event fifo */
-       hci_write1(dev, HCI_SYSTEM_EVENT, 1, &hci_result);
-       if (hci_result == HCI_SUCCESS)
-               dev->system_event_supported = 1;
-
        props.type = BACKLIGHT_PLATFORM;
        props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1;
        dev->backlight_dev = backlight_device_register("toshiba",
@@ -1024,6 +1160,8 @@ static int __devinit toshiba_acpi_add(struct acpi_device *acpi_dev)
 
        create_toshiba_proc_entries(dev);
 
+       toshiba_acpi = dev;
+
        return 0;
 
 error:
@@ -1036,40 +1174,64 @@ static void toshiba_acpi_notify(struct acpi_device *acpi_dev, u32 event)
        struct toshiba_acpi_dev *dev = acpi_driver_data(acpi_dev);
        u32 hci_result, value;
        int retries = 3;
+       int scancode;
 
-       if (!dev->system_event_supported || event != 0x80)
+       if (event != 0x80)
                return;
 
-       do {
-               hci_read1(dev, HCI_SYSTEM_EVENT, &value, &hci_result);
-               switch (hci_result) {
-               case HCI_SUCCESS:
-                       if (value == 0x100)
-                               continue;
-                       /* act on key press; ignore key release */
-                       if (value & 0x80)
-                               continue;
-
-                       if (!sparse_keymap_report_event(dev->hotkey_dev,
-                                                       value, 1, true)) {
-                               pr_info("Unknown key %x\n",
-                                      value);
+       if (dev->info_supported) {
+               scancode = toshiba_acpi_query_hotkey(dev);
+               if (scancode < 0)
+                       pr_err("Failed to query hotkey event\n");
+               else if (scancode != 0)
+                       toshiba_acpi_report_hotkey(dev, scancode);
+       } else if (dev->system_event_supported) {
+               do {
+                       hci_read1(dev, HCI_SYSTEM_EVENT, &value, &hci_result);
+                       switch (hci_result) {
+                       case HCI_SUCCESS:
+                               toshiba_acpi_report_hotkey(dev, (int)value);
+                               break;
+                       case HCI_NOT_SUPPORTED:
+                               /*
+                                * This is a workaround for an unresolved
+                                * issue on some machines where system events
+                                * sporadically become disabled.
+                                */
+                               hci_write1(dev, HCI_SYSTEM_EVENT, 1,
+                                          &hci_result);
+                               pr_notice("Re-enabled hotkeys\n");
+                               /* fall through */
+                       default:
+                               retries--;
+                               break;
                        }
-                       break;
-               case HCI_NOT_SUPPORTED:
-                       /* This is a workaround for an unresolved issue on
-                        * some machines where system events sporadically
-                        * become disabled. */
-                       hci_write1(dev, HCI_SYSTEM_EVENT, 1, &hci_result);
-                       pr_notice("Re-enabled hotkeys\n");
-                       /* fall through */
-               default:
-                       retries--;
-                       break;
-               }
-       } while (retries && hci_result != HCI_EMPTY);
+               } while (retries && hci_result != HCI_EMPTY);
+       }
+}
+
+static int toshiba_acpi_suspend(struct acpi_device *acpi_dev,
+                               pm_message_t state)
+{
+       struct toshiba_acpi_dev *dev = acpi_driver_data(acpi_dev);
+       u32 result;
+
+       if (dev->hotkey_dev)
+               hci_write1(dev, HCI_HOTKEY_EVENT, HCI_HOTKEY_DISABLE, &result);
+
+       return 0;
 }
 
+static int toshiba_acpi_resume(struct acpi_device *acpi_dev)
+{
+       struct toshiba_acpi_dev *dev = acpi_driver_data(acpi_dev);
+       u32 result;
+
+       if (dev->hotkey_dev)
+               hci_write1(dev, HCI_HOTKEY_EVENT, HCI_HOTKEY_ENABLE, &result);
+
+       return 0;
+}
 
 static struct acpi_driver toshiba_acpi_driver = {
        .name   = "Toshiba ACPI driver",
@@ -1080,6 +1242,8 @@ static struct acpi_driver toshiba_acpi_driver = {
                .add            = toshiba_acpi_add,
                .remove         = toshiba_acpi_remove,
                .notify         = toshiba_acpi_notify,
+               .suspend        = toshiba_acpi_suspend,
+               .resume         = toshiba_acpi_resume,
        },
 };
 
@@ -1087,6 +1251,14 @@ static int __init toshiba_acpi_init(void)
 {
        int ret;
 
+       /*
+        * Machines with this WMI guid aren't supported due to bugs in
+        * their AML. This check relies on wmi initializing before
+        * toshiba_acpi to guarantee guids have been identified.
+        */
+       if (wmi_has_guid(TOSHIBA_WMI_EVENT_GUID))
+               return -ENODEV;
+
        toshiba_proc_dir = proc_mkdir(PROC_TOSHIBA, acpi_root_dir);
        if (!toshiba_proc_dir) {
                pr_err("Unable to create proc dir " PROC_TOSHIBA "\n");
index e549eee..41781ed 100644 (file)
@@ -67,19 +67,8 @@ static struct platform_driver xo1_rfkill_driver = {
        .remove         = __devexit_p(xo1_rfkill_remove),
 };
 
-static int __init xo1_rfkill_init(void)
-{
-       return platform_driver_register(&xo1_rfkill_driver);
-}
-
-static void __exit xo1_rfkill_exit(void)
-{
-       platform_driver_unregister(&xo1_rfkill_driver);
-}
+module_platform_driver(xo1_rfkill_driver);
 
 MODULE_AUTHOR("Daniel Drake <dsd@laptop.org>");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:xo1-rfkill");
-
-module_init(xo1_rfkill_init);
-module_exit(xo1_rfkill_exit);
index b859d16..769d265 100644 (file)
@@ -17,7 +17,6 @@
 
 #include <asm/page.h>
 #include <asm/desc.h>
-#include <asm/system.h>
 #include <asm/byteorder.h>
 
 #include "pnpbios.h"
index cfe8685..9d42226 100644 (file)
@@ -65,7 +65,6 @@
 
 #include <asm/page.h>
 #include <asm/desc.h>
-#include <asm/system.h>
 #include <asm/byteorder.h>
 
 #include "../base.h"
index f04761e..afee0e8 100644 (file)
@@ -376,6 +376,9 @@ static int __devinit pm860x_rtc_probe(struct platform_device *pdev)
        INIT_DELAYED_WORK(&info->calib_work, calibrate_vrtc_work);
        schedule_delayed_work(&info->calib_work, VRTC_CALIB_INTERVAL);
 #endif /* VRTC_CALIBRATION */
+
+       device_init_wakeup(&pdev->dev, 1);
+
        return 0;
 out_rtc:
        free_irq(info->irq, info);
@@ -401,10 +404,34 @@ static int __devexit pm860x_rtc_remove(struct platform_device *pdev)
        return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int pm860x_rtc_suspend(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
+
+       if (device_may_wakeup(dev))
+               chip->wakeup_flag |= 1 << PM8607_IRQ_RTC;
+       return 0;
+}
+static int pm860x_rtc_resume(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
+
+       if (device_may_wakeup(dev))
+               chip->wakeup_flag &= ~(1 << PM8607_IRQ_RTC);
+       return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(pm860x_rtc_pm_ops, pm860x_rtc_suspend, pm860x_rtc_resume);
+
 static struct platform_driver pm860x_rtc_driver = {
        .driver         = {
                .name   = "88pm860x-rtc",
                .owner  = THIS_MODULE,
+               .pm     = &pm860x_rtc_pm_ops,
        },
        .probe          = pm860x_rtc_probe,
        .remove         = __devexit_p(pm860x_rtc_remove),
index 1300962..b2185f4 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/bcd.h>
 #include <linux/io.h>
 #include <linux/platform_device.h>
+#include <linux/of.h>
 #include <linux/delay.h>
 #include <linux/gfp.h>
 #include <linux/module.h>
@@ -294,11 +295,19 @@ static int __exit mv_rtc_remove(struct platform_device *pdev)
        return 0;
 }
 
+#ifdef CONFIG_OF
+static struct of_device_id rtc_mv_of_match_table[] = {
+       { .compatible = "mrvl,orion-rtc", },
+       {}
+};
+#endif
+
 static struct platform_driver mv_rtc_driver = {
        .remove         = __exit_p(mv_rtc_remove),
        .driver         = {
                .name   = "rtc-mv",
                .owner  = THIS_MODULE,
+               .of_match_table = of_match_ptr(rtc_mv_of_match_table),
        },
 };
 
index 168525a..231a1d8 100644 (file)
@@ -21,6 +21,7 @@
 #include <asm/chpid.h>
 #include <asm/sclp.h>
 #include <asm/setup.h>
+#include <asm/ctl_reg.h>
 
 #include "sclp.h"
 
index 425f741..d0a2dff 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/init.h>
 #include <linux/wait.h>
 #include <asm/crw.h>
+#include <asm/ctl_reg.h>
 
 static DEFINE_MUTEX(crw_handler_mutex);
 static crw_handler_t crw_handlers[NR_RSCS];
index 12ae181..7e9a72e 100644 (file)
 #include <asm/reset.h>
 #include <asm/airq.h>
 #include <linux/atomic.h>
-#include <asm/system.h>
 #include <asm/isc.h>
 #include <linux/hrtimer.h>
 #include <linux/ktime.h>
+#include <asm/facility.h>
 
 #include "ap_bus.h"
 
index 826157f..327657e 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/of.h>
 #include <linux/of_device.h>
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
index 8d6e508..2236aea 100644 (file)
@@ -40,7 +40,6 @@
 #include <linux/fs.h>
 #include <asm/oplib.h>
 #include <asm/prom.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/openpromio.h>
 #ifdef CONFIG_PCI
index 0b31658..a9e468c 100644 (file)
@@ -19,7 +19,6 @@
 
 #include <asm/openprom.h>
 #include <asm/oplib.h>
-#include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
index f672491..a3adfb4 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/device.h>
 #include <asm/dma.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/byteorder.h>
index f66c33b..d4da370 100644 (file)
@@ -47,7 +47,6 @@
 
 #include <asm/dma.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
index bfd618a..374c4ed 100644 (file)
@@ -41,7 +41,6 @@
 #include <linux/firmware.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/dma.h>
 
 #include <scsi/scsi_cmnd.h>
index f17c92c..19a3694 100644 (file)
 #include <asm/irq.h>
 #include <linux/io.h>
 #include <linux/blkdev.h>
-#include <asm/system.h>
 #include <linux/completion.h>
 #include <linux/errno.h>
 #include <linux/string.h>
index ed119ce..ede91f3 100644 (file)
@@ -42,7 +42,6 @@
 #include <linux/slab.h>
 
 #include <asm/dma.h>
-#include <asm/system.h>
 #include <asm/io.h>
 
 #include "scsi.h"
index 1c10b79..a3e6ed3 100644 (file)
@@ -53,7 +53,6 @@
 #include <linux/gfp.h>
 
 #include <asm/dma.h>
-#include <asm/system.h>
 #include <asm/io.h>
 
 #include "scsi.h"
index 2fe9e90..cbde1dc 100644 (file)
@@ -61,7 +61,6 @@
 #include <linux/aer.h>
 #include <asm/dma.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi.h>
index c454e44..b330438 100644 (file)
 #include <linux/stringify.h>
 #include <linux/io.h>
 
-#include <asm/system.h>
 #include <asm/ecard.h>
 
 #include "../scsi.h"
index a3398fe..c3b99c9 100644 (file)
@@ -12,7 +12,6 @@
 
 #include <asm/ecard.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include "../scsi.h"
 #include <scsi/scsi_host.h>
index 849cdf8..d25f944 100644 (file)
@@ -13,7 +13,6 @@
 
 #include <asm/ecard.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include "../scsi.h"
 #include <scsi/scsi_host.h>
index 7e6eca4..f29d512 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/blkdev.h>
 #include <linux/dma-mapping.h>
 #include <linux/slab.h>
-#include <asm/system.h>
 #include <asm/io.h>
 
 #include <scsi/scsi.h>
index c2677ba..4b11bb0 100644 (file)
@@ -72,7 +72,6 @@
 #endif
 
 
-#include <asm/system.h>
 #include <linux/module.h>
 #include <linux/signal.h>
 #include <linux/blkdev.h>
index a2c6135..53bfcaa 100644 (file)
@@ -93,7 +93,6 @@
 #include <linux/mca-legacy.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include "scsi.h"
 #include <scsi/scsi_host.h>
index 643f6d5..1a2a1e5 100644 (file)
 #include <linux/slab.h>
 #include <scsi/scsicam.h>
 
-#include <asm/system.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
index 81182ba..1a5954f 100644 (file)
 #undef NCR5380_STAT_LIMIT
 #endif
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <linux/signal.h>
 #include <linux/blkdev.h>
index d42ec92..5d72274 100644 (file)
 #include <linux/reboot.h>
 
 #include <asm/dma.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <linux/spinlock.h>
index 67fc8ff..cd09132 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/spinlock.h>
 #include <linux/init.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 
 #include "scsi.h"
index bdfa223..134a0ae 100644 (file)
@@ -4890,11 +4890,8 @@ static struct vio_driver ibmvfc_driver = {
        .probe = ibmvfc_probe,
        .remove = ibmvfc_remove,
        .get_desired_dma = ibmvfc_get_desired_dma,
-       .driver = {
-               .name = IBMVFC_NAME,
-               .owner = THIS_MODULE,
-               .pm = &ibmvfc_pm_ops,
-       }
+       .name = IBMVFC_NAME,
+       .pm = &ibmvfc_pm_ops,
 };
 
 static struct fc_function_template ibmvfc_transport_functions = {
index e984951..3a6c474 100644 (file)
@@ -2061,11 +2061,8 @@ static struct vio_driver ibmvscsi_driver = {
        .probe = ibmvscsi_probe,
        .remove = ibmvscsi_remove,
        .get_desired_dma = ibmvscsi_get_desired_dma,
-       .driver = {
-               .name = "ibmvscsi",
-               .owner = THIS_MODULE,
-               .pm = &ibmvscsi_pm_ops,
-       }
+       .name = "ibmvscsi",
+       .pm = &ibmvscsi_pm_ops,
 };
 
 static struct srp_function_template ibmvscsi_transport_functions = {
index 2256bab..aa7ed81 100644 (file)
@@ -918,10 +918,7 @@ static struct vio_driver ibmvstgt_driver = {
        .id_table = ibmvstgt_device_table,
        .probe = ibmvstgt_probe,
        .remove = ibmvstgt_remove,
-       .driver = {
-               .name = "ibmvscsis",
-               .owner = THIS_MODULE,
-       }
+       .name = "ibmvscsis",
 };
 
 static int get_system_info(void)
index 112f1be..deb5b6d 100644 (file)
 #include <linux/stat.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include "scsi.h"
 #include <scsi/scsi_host.h>
index e617337..e5cd8d8 100644 (file)
@@ -22,7 +22,6 @@
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/prom.h>
-#include <asm/system.h>
 #include <asm/pci-bridge.h>
 #include <asm/macio.h>
 
index 2bccfbe..24828b5 100644 (file)
@@ -43,7 +43,6 @@
 
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 
 #include <asm/macintosh.h>
 #include <asm/macints.h>
index 4944747..e8a04ae 100644 (file)
@@ -33,7 +33,6 @@
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/prom.h>
-#include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/hydra.h>
 #include <asm/processor.h>
index 4b3b475..5982a58 100644 (file)
 
 #include <asm/dma.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
index 0029249..62b6168 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/dma-mapping.h>
 
 #include <asm/dma.h>
-#include <asm/system.h>
 #include <asm/io.h>
 
 #include <scsi/scsi.h>
index de0b1a7..21883a2 100644 (file)
@@ -54,7 +54,6 @@ static const char * osst_version = "0.99.4";
 #include <linux/mutex.h>
 #include <asm/uaccess.h>
 #include <asm/dma.h>
-#include <asm/system.h>
 
 /* The driver prints some debugging information on the console if DEBUG
    is defined and non-zero. */
index f2018b4..2f72c98 100644 (file)
  
 #include <linux/module.h>
 
-#include <asm/system.h>
 #include <linux/signal.h>
 #include <linux/proc_fs.h>
 #include <asm/io.h>
index d838205..6c6486f 100644 (file)
 #include <asm/byteorder.h>
 #include <asm/processor.h>
 #include <asm/types.h>
-#include <asm/system.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
index e40dc1c..b191dd5 100644 (file)
@@ -35,7 +35,6 @@
 #include "qlogicpti.h"
 
 #include <asm/dma.h>
-#include <asm/system.h>
 #include <asm/ptrace.h>
 #include <asm/pgtable.h>
 #include <asm/oplib.h>
index 9262cdf..a15f691 100644 (file)
@@ -42,7 +42,6 @@ static const char *verstr = "20101219";
 
 #include <asm/uaccess.h>
 #include <asm/dma.h>
-#include <asm/system.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_dbg.h>
index baf7328..6e25889 100644 (file)
@@ -63,7 +63,6 @@
 #include <linux/blkdev.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include <asm/sun3ints.h>
 #include <asm/dvma.h>
index fbba78e..a3dd55d 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/blkdev.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include <asm/sun3ints.h>
 #include <asm/dvma.h>
index 012c86e..ac4eca6 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/proc_fs.h>
 #include <linux/spinlock.h>
 #include <asm/dma.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <linux/blkdev.h>
 #include <linux/isapnp.h>
index 041eaaa..d672d97 100644 (file)
  * $Log: t128.c,v $
  */
 
-#include <asm/system.h>
 #include <linux/signal.h>
 #include <linux/io.h>
 #include <linux/blkdev.h>
index 90e104d..9c216e5 100644 (file)
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/byteorder.h>
 #include <linux/proc_fs.h>
 #include <linux/blkdev.h>
index 7e22b73..14e0c40 100644 (file)
 #include <linux/delay.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/dma.h>
 
 #define ULTRASTOR_PRIVATE      /* Get the private stuff from ultrastor.h */
index 9ee0afe..d89a5df 100644 (file)
 #include <linux/stat.h>
 #include <linux/io.h>
 
-#include <asm/system.h>
 #include <asm/dma.h>
 
 #include <scsi/scsi.h>
index 610f739..9b0d716 100644 (file)
@@ -47,7 +47,6 @@
 #include <linux/spi/spi_bitbang.h>
 #include <linux/module.h>
 
-#include <asm/system.h>
 #include <asm/irq.h>
 #include <mach/hardware.h>
 #include <asm/io.h>
index 13448c8..e496f79 100644 (file)
@@ -359,11 +359,6 @@ static int orion_spi_setup(struct spi_device *spi)
 
        orion_spi = spi_master_get_devdata(spi->master);
 
-       /* Fix ac timing if required.   */
-       if (orion_spi->spi_info->enable_clock_fix)
-               orion_spi_setbits(orion_spi, ORION_SPI_IF_CONFIG_REG,
-                                 (1 << 14));
-
        if ((spi->max_speed_hz == 0)
                        || (spi->max_speed_hz > orion_spi->max_speed))
                spi->max_speed_hz = orion_spi->max_speed;
index db1fd63..bf185e2 100644 (file)
@@ -42,7 +42,6 @@
 #include <linux/cdev.h>
 #include <linux/dma-mapping.h>
 #include <linux/io.h>
-#include <asm/system.h>
 
 #include "comedidev.h"
 #include "internal.h"
index c9e8c47..915157d 100644 (file)
@@ -86,7 +86,6 @@ TODO:
 #include "../comedidev.h"
 #include <linux/delay.h>
 #include <linux/interrupt.h>
-#include <asm/system.h>
 
 #include "comedi_pci.h"
 #include "8253.h"
index fd274e9..13e9c80 100644 (file)
@@ -55,7 +55,6 @@
 #include "comedi_pci.h"
 #include "../comedidev.h"
 
-#include <asm/system.h>
 
 #define PCI_MITE_SIZE          4096
 #define PCI_DAQ_SIZE           4096
index 8cd51a7..647e116 100644 (file)
@@ -26,6 +26,8 @@
 #ifndef _BC_DTS_DEFS_H_
 #define _BC_DTS_DEFS_H_
 
+#include <linux/types.h>
+
 /* BIT Mask */
 #define BC_BIT(_x)             (1 << (_x))
 
index 3f4d795..b3a550b 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _CRYSTALHD_H_
 #define _CRYSTALHD_H_
 
-#include <asm/system.h>
 #include "bc_dts_defs.h"
 #include "crystalhd_misc.h"
 #include "bc_dts_glob_lnx.h"
index a81f929..a9e3633 100644 (file)
@@ -45,7 +45,6 @@
 #include <linux/io.h>
 #include <asm/irq.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 #include <linux/uaccess.h>
 
 #include "crystalhd.h"
index 84c8793..8cdaa7a 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/ioctl.h>
 #include <linux/dma-mapping.h>
 #include <linux/sched.h>
+#include "bc_dts_glob_lnx.h"
 
 /* Global log level variable defined in crystal_misc.c file */
 extern uint32_t g_linklog_level;
index 3f919ba..886f565 100644 (file)
@@ -70,7 +70,6 @@
 #include <linux/delay.h>
 #include <linux/bitops.h>
 #include <linux/io.h>
-#include <asm/system.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
index 7569aa0..c4a8a0a 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/interrupt.h>
 #include <linux/in.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/bitops.h>
 
 #include <linux/netdevice.h>
index 6c9279a..ece2dd1 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/mutex.h>
 #include <linux/uaccess.h>
 #include <linux/slab.h>
-#include <asm/system.h>
 #include <linux/videodev2.h>
 #include <media/tuner.h>
 #include <media/v4l2-common.h>
index b8cfa1a..6bc82aa 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/i2c.h>
 #include <linux/mutex.h>
 #include <linux/uaccess.h>
-#include <asm/system.h>
 
 #include "go7007-priv.h"
 #include "wis-i2c.h"
index f916586..3ef4cd8 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/i2c.h>
 #include <linux/mutex.h>
 #include <linux/uaccess.h>
-#include <asm/system.h>
 
 #include "go7007.h"
 #include "go7007-priv.h"
index d071c83..5af29ff 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/mutex.h>
 #include <linux/uaccess.h>
 #include <linux/slab.h>
-#include <asm/system.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/initval.h>
index 97352cf..3295ea6 100644 (file)
@@ -66,7 +66,6 @@
 #include <linux/poll.h>
 #include <linux/platform_device.h>
 
-#include <asm/system.h>
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/fcntl.h>
index c94382b..945d962 100644 (file)
@@ -49,7 +49,6 @@
 #include <linux/mm.h>
 #include <linux/delay.h>
 #include <linux/poll.h>
-#include <asm/system.h>
 #include <linux/io.h>
 #include <asm/irq.h>
 #include <linux/fcntl.h>
index a6910da..cf4c29d 100644 (file)
@@ -323,6 +323,7 @@ static int mei_wd_ops_set_timeout(struct watchdog_device *wd_dev, unsigned int t
        mutex_lock(&dev->device_lock);
 
        dev->wd_timeout = timeout;
+       wd_dev->timeout = timeout;
        mei_wd_set_start_timeout(dev, dev->wd_timeout);
 
        mutex_unlock(&dev->device_lock);
index 4683d5f..6183573 100644 (file)
@@ -58,7 +58,6 @@
 
 #include <linux/io.h>
 #include <linux/uaccess.h>
-#include <asm/system.h>
 
 #define LCD_MINOR              156
 #define KEYPAD_MINOR           185
index b458ff0..9a50bcc 100644 (file)
@@ -11,7 +11,6 @@
  */
 
 #include <linux/ip.h>
-#include <asm/system.h>
 #include "2t3e3.h"
 #include "ctrl.h"
 
index 176f469..e4c0335 100644 (file)
@@ -2,4 +2,4 @@
 # Makefile for the RMI4 touchscreen driver.
 #
 obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4) += synaptics_i2c_rmi4.o
-obj-$(CONFIG_MACH_U8500) += board-mop500-u8500uib-rmi4.o
+obj-$(CONFIG_MACH_MOP500) += board-mop500-u8500uib-rmi4.o
index 1915af2..1dd0b67 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/phonedev.h>
 #include <linux/init.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 
 #include <linux/kmod.h>
 #include <linux/sem.h>
index a2f31c6..ed00d3d 100644 (file)
@@ -17,7 +17,6 @@
 #ifndef _HOST_OS_H_
 #define _HOST_OS_H_
 
-#include <asm/system.h>
 #include <linux/atomic.h>
 #include <linux/semaphore.h>
 #include <linux/uaccess.h>
index a2cbb29..7084f41 100644 (file)
@@ -74,7 +74,6 @@
 #include <linux/in.h>
 #include <linux/delay.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/bitops.h>
 
 #include <linux/netdevice.h>
index dab603e..d5bf0a7 100644 (file)
@@ -86,8 +86,7 @@
 // #include <linux/in.h>
 // #include <linux/delay.h>
 // #include <asm/io.h>
-// #include <asm/system.h>
-// #include <asm/bitops.h>
+// // #include <asm/bitops.h>
 #include <linux/unistd.h>
 #include <asm/uaccess.h>
 
index 9c16f54..90820ff 100644 (file)
@@ -79,8 +79,7 @@
 // #include <linux/delay.h>
 // #include <linux/skbuff.h>
 // #include <asm/io.h>
-// #include <asm/system.h>
-// #include <asm/bitops.h>
+// // #include <asm/bitops.h>
 
 #include <linux/netdevice.h>
 #include <linux/ethtool.h>
index 2bd9b84..3df990c 100644 (file)
@@ -77,7 +77,6 @@
 #include <linux/interrupt.h>
 #include <linux/in.h>
 #include <linux/delay.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/bitops.h>
index b748a3f..f104e6f 100644 (file)
@@ -73,8 +73,7 @@
 // #include <linux/in.h>
 // #include <linux/delay.h>
 // #include <asm/io.h>
-// #include <asm/system.h>
-// #include <asm/bitops.h>
+// // #include <asm/bitops.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
index afadcd4..24145c3 100644 (file)
@@ -85,7 +85,6 @@ static char *serial_version = "4.30";
 
 #include <asm/setup.h>
 
-#include <asm/system.h>
 
 #include <asm/irq.h>
 
index 3a0d53d..ee30779 100644 (file)
@@ -310,11 +310,8 @@ static int __devexit hvc_vio_remove(struct vio_dev *vdev)
 static struct vio_driver hvc_vio_driver = {
        .id_table       = hvc_driver_table,
        .probe          = hvc_vio_probe,
-       .remove         = __devexit_p(hvc_vio_remove),
-       .driver         = {
-               .name   = hvc_driver_name,
-               .owner  = THIS_MODULE,
-       }
+       .remove         = hvc_vio_remove,
+       .name           = hvc_driver_name,
 };
 
 static int __init hvc_vio_init(void)
index d237591..3436436 100644 (file)
@@ -879,10 +879,7 @@ static struct vio_driver hvcs_vio_driver = {
        .id_table       = hvcs_driver_table,
        .probe          = hvcs_probe,
        .remove         = __devexit_p(hvcs_remove),
-       .driver         = {
-               .name   = hvcs_driver_name,
-               .owner  = THIS_MODULE,
-       }
+       .name           = hvcs_driver_name,
 };
 
 /* Only called from hvcs_get_pi please */
index 03c1497..794ecb4 100644 (file)
 
 #include <linux/uaccess.h>
 #include <linux/io.h>
-#include <asm/system.h>
 
 #include <linux/pci.h>
 
index 8a8d044..324467d 100644 (file)
@@ -46,7 +46,6 @@
 #include <linux/slab.h>
 #include <linux/ratelimit.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
index 17ff377..c6f372d 100644 (file)
@@ -41,7 +41,6 @@
 #include <linux/slab.h>
 #include <linux/ratelimit.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/uaccess.h>
index a09ce3e..1b2db9a 100644 (file)
 #include <linux/if.h>
 #include <linux/bitops.h>
 
-#include <asm/system.h>
 #include <asm/termios.h>
 #include <asm/uaccess.h>
 
index d2256d0..94b6eda 100644 (file)
@@ -50,7 +50,6 @@
 #include <linux/uaccess.h>
 #include <linux/module.h>
 
-#include <asm/system.h>
 
 /* number of characters left in xmit buffer before select has we have room */
 #define WAKEUP_CHARS 256
index f96ecae..eeae7fa 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/devpts_fs.h>
 #include <linux/slab.h>
 
-#include <asm/system.h>
 
 #ifdef CONFIG_UNIX98_PTYS
 static struct tty_driver *ptm_driver;
index f899996..a44345a 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <asm/irq.h>
 #include <asm/mach-types.h>
+#include <asm/system_info.h>
 #include <asm/hardware/dec21285.h>
 #include <mach/hardware.h>
 
index 7398390..5ce7825 100644 (file)
@@ -39,7 +39,6 @@
 
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/delay.h>
 #include <asm/uaccess.h>
 
index 8609060..29b695d 100644 (file)
@@ -43,7 +43,6 @@
 #include <linux/delay.h>
 #include <linux/major.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ciscode.h>
index 23d7916..5b07c0c 100644 (file)
@@ -34,9 +34,9 @@ static char *serial_version = "$Revision: 1.25 $";
 
 #include <asm/irq.h>
 #include <asm/dma.h>
-#include <asm/system.h>
 
 #include <arch/svinto.h>
+#include <arch/system.h>
 
 /* non-arch dependent serial structures are in linux/serial.h */
 #include <linux/serial.h>
index e3699a8..6491b86 100644 (file)
@@ -52,7 +52,6 @@
 #include <linux/atomic.h>
 #include <asm/bootinfo.h>
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include <asm/dec/interrupts.h>
 #include <asm/dec/kn01.h>
index d55709a..defc4e3 100644 (file)
@@ -52,7 +52,6 @@
 #include <linux/firmware.h>
 #include <linux/bitops.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/uaccess.h>
index 5e85e1e..fca13dc 100644 (file)
@@ -50,7 +50,6 @@
 
 #include <linux/atomic.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 
 #include <mach/hardware.h>
 #include <mach/dma.h>
index 3ba5d28..505961c 100644 (file)
@@ -23,6 +23,7 @@
 #include <asm/spitfire.h>
 #include <asm/prom.h>
 #include <asm/irq.h>
+#include <asm/setup.h>
 
 #if defined(CONFIG_MAGIC_SYSRQ)
 #define SUPPORT_SYSRQ
index 62dacd0..f0d93eb 100644 (file)
@@ -37,6 +37,7 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/prom.h>
+#include <asm/setup.h>
 
 #if defined(CONFIG_SERIAL_SUNSAB_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
 #define SUPPORT_SYSRQ
index d3ca6da..675303b 100644 (file)
@@ -41,6 +41,7 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/prom.h>
+#include <asm/setup.h>
 
 #if defined(CONFIG_SERIAL_SUNSU_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
 #define SUPPORT_SYSRQ
index da44158..b3b70b0 100644 (file)
@@ -37,6 +37,7 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/prom.h>
+#include <asm/setup.h>
 
 #if defined(CONFIG_SERIAL_SUNZILOG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
 #define SUPPORT_SYSRQ
index b7455b5..4001eee 100644 (file)
@@ -67,7 +67,6 @@
 #include <linux/types.h>
 
 #include <linux/atomic.h>
-#include <asm/system.h>
 
 #include <asm/dec/interrupts.h>
 #include <asm/dec/ioasic_addrs.h>
index 8e518da..593d40a 100644 (file)
@@ -86,7 +86,6 @@
 #include <linux/ioctl.h>
 #include <linux/synclink.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/dma.h>
index 34b1a3c..aa1debf 100644 (file)
@@ -73,7 +73,6 @@
 #include <linux/hdlc.h>
 #include <linux/synclink.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/dma.h>
index 4fb6c4b..a3dddc1 100644 (file)
@@ -58,7 +58,6 @@
 #include <linux/delay.h>
 #include <linux/ioctl.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/dma.h>
index dd8a938..d939bd7 100644 (file)
@@ -97,7 +97,6 @@
 #include <linux/ratelimit.h>
 
 #include <linux/uaccess.h>
-#include <asm/system.h>
 
 #include <linux/kbd_kern.h>
 #include <linux/vt_kern.h>
index 9314d93..a1b9a2f 100644 (file)
@@ -23,7 +23,6 @@
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 
 #undef TTY_DEBUG_WAIT_UNTIL_SENT
 
index 84c4a7d..3bdd4b1 100644 (file)
@@ -99,7 +99,6 @@
 #include <linux/notifier.h>
 #include <linux/device.h>
 #include <linux/io.h>
-#include <asm/system.h>
 #include <linux/uaccess.h>
 #include <linux/kdb.h>
 #include <linux/ctype.h>
index 48ac6e7..cbd8f5f 100644 (file)
@@ -44,7 +44,7 @@ config USB_ARCH_HAS_EHCI
        default y if PPC_MPC512x
        default y if ARCH_IXP4XX
        default y if ARCH_W90X900
-       default y if ARCH_AT91SAM9G45
+       default y if ARCH_AT91
        default y if ARCH_MXC
        default y if ARCH_OMAP3
        default y if ARCH_CNS3XXX
index 26c0b75..2633f75 100644 (file)
@@ -137,7 +137,7 @@ choice
 
 config USB_AT91
        tristate "Atmel AT91 USB Device Port"
-       depends on ARCH_AT91 && !ARCH_AT91SAM9RL && !ARCH_AT91SAM9G45
+       depends on ARCH_AT91
        help
           Many Atmel AT91 processors (such as the AT91RM2000) have a
           full speed USB Device Port with support for five configurable
index 2204a4c..7777927 100644 (file)
@@ -54,7 +54,6 @@
 #include <linux/prefetch.h>
 
 #include <asm/byteorder.h>
-#include <asm/system.h>
 #include <asm/unaligned.h>
 
 /* gadget stack */
index 2db5f68..0c935d7 100644 (file)
 #include <linux/clk.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
 
 #include <asm/byteorder.h>
 #include <mach/hardware.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/gpio.h>
 
 #include <mach/board.h>
@@ -1707,7 +1708,27 @@ static void at91udc_shutdown(struct platform_device *dev)
        spin_unlock_irqrestore(&udc->lock, flags);
 }
 
-static int __init at91udc_probe(struct platform_device *pdev)
+static void __devinit at91udc_of_init(struct at91_udc *udc,
+                                    struct device_node *np)
+{
+       struct at91_udc_data *board = &udc->board;
+       u32 val;
+       enum of_gpio_flags flags;
+
+       if (of_property_read_u32(np, "atmel,vbus-polled", &val) == 0)
+               board->vbus_polled = 1;
+
+       board->vbus_pin = of_get_named_gpio_flags(np, "atmel,vbus-gpio", 0,
+                                                 &flags);
+       board->vbus_active_low = (flags & OF_GPIO_ACTIVE_LOW) ? 1 : 0;
+
+       board->pullup_pin = of_get_named_gpio_flags(np, "atmel,pullup-gpio", 0,
+                                                 &flags);
+
+       board->pullup_active_low = (flags & OF_GPIO_ACTIVE_LOW) ? 1 : 0;
+}
+
+static int __devinit at91udc_probe(struct platform_device *pdev)
 {
        struct device   *dev = &pdev->dev;
        struct at91_udc *udc;
@@ -1742,7 +1763,11 @@ static int __init at91udc_probe(struct platform_device *pdev)
        /* init software state */
        udc = &controller;
        udc->gadget.dev.parent = dev;
-       udc->board = *(struct at91_udc_data *) dev->platform_data;
+       if (pdev->dev.of_node)
+               at91udc_of_init(udc, pdev->dev.of_node);
+       else
+               memcpy(&udc->board, dev->platform_data,
+                      sizeof(struct at91_udc_data));
        udc->pdev = pdev;
        udc->enabled = 0;
        spin_lock_init(&udc->lock);
@@ -1971,6 +1996,15 @@ static int at91udc_resume(struct platform_device *pdev)
 #define        at91udc_resume  NULL
 #endif
 
+#if defined(CONFIG_OF)
+static const struct of_device_id at91_udc_dt_ids[] = {
+       { .compatible = "atmel,at91rm9200-udc" },
+       { /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, at91_udc_dt_ids);
+#endif
+
 static struct platform_driver at91_udc_driver = {
        .remove         = __exit_p(at91udc_remove),
        .shutdown       = at91udc_shutdown,
@@ -1979,6 +2013,7 @@ static struct platform_driver at91_udc_driver = {
        .driver         = {
                .name   = (char *) driver_name,
                .owner  = THIS_MODULE,
+               .of_match_table = of_match_ptr(at91_udc_dt_ids),
        },
 };
 
index e1cd56c..a6dfd21 100644 (file)
@@ -44,7 +44,6 @@
 #include <asm/byteorder.h>
 #include <linux/io.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/unaligned.h>
 
 #define DRIVER_DESC    "USB Host+Gadget Emulator"
index b30e21f..5f94e79 100644 (file)
@@ -43,7 +43,6 @@
 
 #include <asm/byteorder.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/unaligned.h>
 #include <asm/dma.h>
 
index e1dfd32..e151d6b 100644 (file)
@@ -43,7 +43,6 @@
 #include <asm/byteorder.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/unaligned.h>
 
 
index edd52d9..f9cedd5 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/pm.h>
 #include <linux/io.h>
 #include <linux/irq.h>
-#include <asm/system.h>
 #include <asm/unaligned.h>
 
 #include "langwell_udc.h"
index 19bbe80..a73cf40 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <linux/platform_data/mv_usb.h>
-#include <asm/system.h>
 #include <asm/unaligned.h>
 
 #include "mv_udc.h"
index 01ae56f..43ac748 100644 (file)
@@ -42,7 +42,6 @@
 #include <linux/usb/gadget.h>
 
 #include <asm/byteorder.h>
-#include <asm/system.h>
 #include <asm/unaligned.h>
 
 #include "net2272.h"
index a5ccabc..ac335af 100644 (file)
@@ -59,7 +59,6 @@
 #include <asm/byteorder.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/unaligned.h>
 
 
index b44830d..3b4b6dd 100644 (file)
@@ -40,7 +40,6 @@
 #include <asm/byteorder.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/unaligned.h>
 #include <asm/mach-types.h>
 
index d83134b..4e4dc1f 100644 (file)
@@ -34,7 +34,6 @@
 #include <asm/byteorder.h>
 #include <linux/io.h>
 #include <linux/irq.h>
-#include <asm/system.h>
 #include <linux/uaccess.h>
 #include <asm/unaligned.h>
 
index 1b33634..41ed69c 100644 (file)
@@ -41,7 +41,6 @@
 #include <asm/byteorder.h>
 #include <asm/dma.h>
 #include <asm/gpio.h>
-#include <asm/system.h>
 #include <asm/mach-types.h>
 #include <asm/unaligned.h>
 
index d3cdffe..73a934a 100644 (file)
@@ -34,7 +34,6 @@
 
 #include <asm/io.h>
 #include <asm/byteorder.h>
-#include <asm/system.h>
 #include <asm/unaligned.h>
 
 
index ab9c65e..195524c 100644 (file)
@@ -37,7 +37,6 @@
 #include <asm/byteorder.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/unaligned.h>
 #include <mach/irqs.h>
 
index a5a3ef1..19f318a 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <linux/clk.h>
 #include <linux/platform_device.h>
+#include <linux/of_platform.h>
 
 /* interface and function clocks */
 static struct clk *iclk, *fclk;
@@ -115,6 +116,8 @@ static const struct hc_driver ehci_atmel_hc_driver = {
        .clear_tt_buffer_complete       = ehci_clear_tt_buffer_complete,
 };
 
+static u64 at91_ehci_dma_mask = DMA_BIT_MASK(32);
+
 static int __devinit ehci_atmel_drv_probe(struct platform_device *pdev)
 {
        struct usb_hcd *hcd;
@@ -137,6 +140,13 @@ static int __devinit ehci_atmel_drv_probe(struct platform_device *pdev)
                goto fail_create_hcd;
        }
 
+       /* Right now device-tree probed devices don't get dma_mask set.
+        * Since shared usb code relies on it, set it here for now.
+        * Once we have dma capability bindings this can go away.
+        */
+       if (!pdev->dev.dma_mask)
+               pdev->dev.dma_mask = &at91_ehci_dma_mask;
+
        hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
        if (!hcd) {
                retval = -ENOMEM;
@@ -225,9 +235,21 @@ static int __devexit ehci_atmel_drv_remove(struct platform_device *pdev)
        return 0;
 }
 
+#ifdef CONFIG_OF
+static const struct of_device_id atmel_ehci_dt_ids[] = {
+       { .compatible = "atmel,at91sam9g45-ehci" },
+       { /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, atmel_ehci_dt_ids);
+#endif
+
 static struct platform_driver ehci_atmel_driver = {
        .probe          = ehci_atmel_drv_probe,
        .remove         = __devexit_p(ehci_atmel_drv_remove),
        .shutdown       = usb_hcd_platform_shutdown,
-       .driver.name    = "atmel-ehci",
+       .driver         = {
+               .name   = "atmel-ehci",
+               .of_match_table = of_match_ptr(atmel_ehci_dt_ids),
+       },
 };
index aede637..057cdda 100644 (file)
@@ -45,7 +45,6 @@
 #include <asm/byteorder.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/unaligned.h>
 
 #if defined(CONFIG_PPC_PS3)
index 9248800..9e65e30 100644 (file)
@@ -70,7 +70,6 @@
 
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/byteorder.h>
 
 #include "isp116x.h"
index 9e63cdf..2ed112d 100644 (file)
@@ -84,7 +84,6 @@
 #include <linux/prefetch.h>
 
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/byteorder.h>
 #include <asm/unaligned.h>
 
index 8e855eb..db8963f 100644 (file)
@@ -14,6 +14,8 @@
 
 #include <linux/clk.h>
 #include <linux/platform_device.h>
+#include <linux/of_platform.h>
+#include <linux/of_gpio.h>
 
 #include <mach/hardware.h>
 #include <asm/gpio.h>
@@ -477,13 +479,109 @@ static irqreturn_t ohci_hcd_at91_overcurrent_irq(int irq, void *data)
        return IRQ_HANDLED;
 }
 
+#ifdef CONFIG_OF
+static const struct of_device_id at91_ohci_dt_ids[] = {
+       { .compatible = "atmel,at91rm9200-ohci" },
+       { /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, at91_ohci_dt_ids);
+
+static u64 at91_ohci_dma_mask = DMA_BIT_MASK(32);
+
+static int __devinit ohci_at91_of_init(struct platform_device *pdev)
+{
+       struct device_node *np = pdev->dev.of_node;
+       int i, ret, gpio;
+       enum of_gpio_flags flags;
+       struct at91_usbh_data   *pdata;
+       u32 ports;
+
+       if (!np)
+               return 0;
+
+       /* Right now device-tree probed devices don't get dma_mask set.
+        * Since shared usb code relies on it, set it here for now.
+        * Once we have dma capability bindings this can go away.
+        */
+       if (!pdev->dev.dma_mask)
+               pdev->dev.dma_mask = &at91_ohci_dma_mask;
+
+       pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+       if (!pdata)
+               return -ENOMEM;
+
+       if (!of_property_read_u32(np, "num-ports", &ports))
+               pdata->ports = ports;
+
+       for (i = 0; i < 2; i++) {
+               gpio = of_get_named_gpio_flags(np, "atmel,vbus-gpio", i, &flags);
+               pdata->vbus_pin[i] = gpio;
+               if (!gpio_is_valid(gpio))
+                       continue;
+               pdata->vbus_pin_active_low[i] = flags & OF_GPIO_ACTIVE_LOW;
+               ret = gpio_request(gpio, "ohci_vbus");
+               if (ret) {
+                       dev_warn(&pdev->dev, "can't request vbus gpio %d", gpio);
+                       continue;
+               }
+               ret = gpio_direction_output(gpio, !(flags & OF_GPIO_ACTIVE_LOW) ^ 1);
+               if (ret)
+                       dev_warn(&pdev->dev, "can't put vbus gpio %d as output %d",
+                                !(flags & OF_GPIO_ACTIVE_LOW) ^ 1, gpio);
+       }
+
+       for (i = 0; i < 2; i++) {
+               gpio = of_get_named_gpio_flags(np, "atmel,oc-gpio", i, &flags);
+               pdata->overcurrent_pin[i] = gpio;
+               if (!gpio_is_valid(gpio))
+                       continue;
+               ret = gpio_request(gpio, "ohci_overcurrent");
+               if (ret) {
+                       dev_err(&pdev->dev, "can't request overcurrent gpio %d", gpio);
+                       continue;
+               }
+
+               ret = gpio_direction_input(gpio);
+               if (ret) {
+                       dev_err(&pdev->dev, "can't configure overcurrent gpio %d as input", gpio);
+                       continue;
+               }
+
+               ret = request_irq(gpio_to_irq(gpio),
+                                 ohci_hcd_at91_overcurrent_irq,
+                                 IRQF_SHARED, "ohci_overcurrent", pdev);
+               if (ret) {
+                       gpio_free(gpio);
+                       dev_warn(& pdev->dev, "cannot get GPIO IRQ for overcurrent\n");
+               }
+       }
+
+       pdev->dev.platform_data = pdata;
+
+       return 0;
+}
+#else
+static int __devinit ohci_at91_of_init(struct platform_device *pdev)
+{
+       return 0;
+}
+#endif
+
 /*-------------------------------------------------------------------------*/
 
 static int ohci_hcd_at91_drv_probe(struct platform_device *pdev)
 {
-       struct at91_usbh_data   *pdata = pdev->dev.platform_data;
+       struct at91_usbh_data   *pdata;
        int                     i;
 
+       i = ohci_at91_of_init(pdev);
+
+       if (i)
+               return i;
+
+       pdata = pdev->dev.platform_data;
+
        if (pdata) {
                for (i = 0; i < ARRAY_SIZE(pdata->vbus_pin); i++) {
                        if (!gpio_is_valid(pdata->vbus_pin[i]))
@@ -596,5 +694,6 @@ static struct platform_driver ohci_hcd_at91_driver = {
        .driver         = {
                .name   = "at91_ohci",
                .owner  = THIS_MODULE,
+               .of_match_table = of_match_ptr(at91_ohci_dt_ids),
        },
 };
index 543e90e..235171f 100644 (file)
@@ -42,7 +42,6 @@
 
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/unaligned.h>
 #include <asm/byteorder.h>
 
index 015c7c6..3b38030 100644 (file)
@@ -40,7 +40,6 @@
 #include <linux/io.h>
 
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/unaligned.h>
 
 #include <linux/irq.h>
index 2a2cce2..91ce1c0 100644 (file)
@@ -51,7 +51,6 @@
 
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/byteorder.h>
 #include <asm/unaligned.h>
 
index 16dd6a6..dbbd1ba 100644 (file)
@@ -55,7 +55,6 @@
 #include <linux/mutex.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/byteorder.h>
 
        /* FIXME ohci.h is ONLY for internal use by the OHCI driver.
index e37dea8..e4db350 100644 (file)
@@ -45,7 +45,6 @@
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 
 #include "uhci-hcd.h"
 
index f23cae0..887df9d 100644 (file)
@@ -53,7 +53,6 @@
 #include <linux/platform_device.h>
 #include <linux/uaccess.h>
 
-#include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/amigahw.h>
 #include <asm/amigaints.h>
index 915943a..f49181c 100644 (file)
@@ -67,6 +67,28 @@ static inline int wled_idc(int port)
        return ret;
 }
 
+static int backlight_power_set(struct pm860x_chip *chip, int port,
+               int on)
+{
+       int ret = -EINVAL;
+
+       switch (port) {
+       case PM8606_BACKLIGHT1:
+               ret = on ? pm8606_osc_enable(chip, WLED1_DUTY) :
+                       pm8606_osc_disable(chip, WLED1_DUTY);
+               break;
+       case PM8606_BACKLIGHT2:
+               ret = on ? pm8606_osc_enable(chip, WLED2_DUTY) :
+                       pm8606_osc_disable(chip, WLED2_DUTY);
+               break;
+       case PM8606_BACKLIGHT3:
+               ret = on ? pm8606_osc_enable(chip, WLED3_DUTY) :
+                       pm8606_osc_disable(chip, WLED3_DUTY);
+               break;
+       }
+       return ret;
+}
+
 static int pm860x_backlight_set(struct backlight_device *bl, int brightness)
 {
        struct pm860x_backlight_data *data = bl_get_data(bl);
@@ -79,6 +101,9 @@ static int pm860x_backlight_set(struct backlight_device *bl, int brightness)
        else
                value = brightness;
 
+       if (brightness)
+               backlight_power_set(chip, data->port, 1);
+
        ret = pm860x_reg_write(data->i2c, wled_a(data->port), value);
        if (ret < 0)
                goto out;
@@ -115,6 +140,9 @@ static int pm860x_backlight_set(struct backlight_device *bl, int brightness)
        if (ret < 0)
                goto out;
 
+       if (brightness == 0)
+               backlight_power_set(chip, data->port, 0);
+
        dev_dbg(chip->dev, "set brightness %d\n", value);
        data->current_brightness = value;
        return 0;
@@ -170,7 +198,6 @@ static int pm860x_backlight_probe(struct platform_device *pdev)
        struct backlight_device *bl;
        struct resource *res;
        struct backlight_properties props;
-       unsigned char value;
        char name[MFD_NAME_SIZE];
        int ret;
 
@@ -217,26 +244,6 @@ static int pm860x_backlight_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, bl);
 
-       /* Enable reference VSYS */
-       ret = pm860x_reg_read(data->i2c, PM8606_VSYS);
-       if (ret < 0)
-               goto out;
-       if ((ret & PM8606_VSYS_EN) == 0) {
-               value = ret | PM8606_VSYS_EN;
-               ret = pm860x_reg_write(data->i2c, PM8606_VSYS, value);
-               if (ret < 0)
-                       goto out;
-       }
-       /* Enable reference OSC */
-       ret = pm860x_reg_read(data->i2c, PM8606_MISC);
-       if (ret < 0)
-               goto out;
-       if ((ret & PM8606_MISC_OSC_EN) == 0) {
-               value = ret | PM8606_MISC_OSC_EN;
-               ret = pm860x_reg_write(data->i2c, PM8606_MISC, value);
-               if (ret < 0)
-                       goto out;
-       }
        /* read current backlight */
        ret = pm860x_backlight_get_brightness(bl);
        if (ret < 0)
index be98d15..a523b25 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/io.h>
 #include <linux/pci.h>
 #include <linux/acpi.h>
+#include <linux/atomic.h>
 
 static struct backlight_device *apple_backlight_device;
 
@@ -221,14 +222,32 @@ static struct acpi_driver apple_bl_driver = {
        },
 };
 
+static atomic_t apple_bl_registered = ATOMIC_INIT(0);
+
+int apple_bl_register(void)
+{
+       if (atomic_xchg(&apple_bl_registered, 1) == 0)
+               return acpi_bus_register_driver(&apple_bl_driver);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(apple_bl_register);
+
+void apple_bl_unregister(void)
+{
+       if (atomic_xchg(&apple_bl_registered, 0) == 1)
+               acpi_bus_unregister_driver(&apple_bl_driver);
+}
+EXPORT_SYMBOL_GPL(apple_bl_unregister);
+
 static int __init apple_bl_init(void)
 {
-       return acpi_bus_register_driver(&apple_bl_driver);
+       return apple_bl_register();
 }
 
 static void __exit apple_bl_exit(void)
 {
-       acpi_bus_unregister_driver(&apple_bl_driver);
+       apple_bl_unregister();
 }
 
 module_init(apple_bl_init);
index c826f27..04e0cfb 100644 (file)
@@ -8,7 +8,6 @@
  *     archive for more details.
  */
 #include <linux/types.h>
-#include <asm/system.h>
 
 /*
  * Bt431 cursor generator registers, 32-bit aligned.
index b7591fe..80f61b0 100644 (file)
@@ -8,7 +8,6 @@
  *     archive for more details.
  */
 #include <linux/types.h>
-#include <asm/system.h>
 
 /*
  * Bt455 byte-wide registers, 32-bit aligned.
index 8745637..2e471c2 100644 (file)
@@ -77,7 +77,6 @@
 #include <linux/crc32.h> /* For counting font checksums */
 #include <asm/fb.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 
 #include "fbcon.h"
 
index a122d92..6d15966 100644 (file)
@@ -22,7 +22,6 @@
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/gio_device.h>
index 8503807..c1527f5 100644 (file)
@@ -51,7 +51,6 @@
 #include <linux/i2c-algo-bit.h>
 
 #include <asm/pgtable.h>
-#include <asm/system.h>
 
 #ifdef __arm__
 #include <asm/mach-types.h>
index ec56d25..49e3dda 100644 (file)
@@ -7,7 +7,6 @@
 #include <linux/platform_device.h>
 
 #include <asm/setup.h>
-#include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/amigahw.h>
 #include <asm/amigaints.h>
index fb3f673..afc9521 100644 (file)
@@ -71,7 +71,6 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 
 #ifdef CONFIG_MTRR
 #include <asm/mtrr.h>
index 0c69fa2..9b4a60b 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/types.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include <video/pmag-ba-fb.h>
 
index 22fcb9a..4e7a9c4 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/types.h>
 
 #include <asm/io.h>
-#include <asm/system.h>
 
 #include <video/pmagb-b-fb.h>
 
index f5a39f5..a104e8c 100644 (file)
@@ -20,7 +20,6 @@
 
 #include <asm/uaccess.h>
 #include <asm/setup.h>
-#include <asm/system.h>
 #include <asm/q40_master.h>
 #include <linux/fb.h>
 #include <linux/module.h>
index beb4950..cee7803 100644 (file)
@@ -56,7 +56,6 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/pgtable.h>
-#include <asm/system.h>
 
 #ifdef CONFIG_MTRR
 #include <asm/mtrr.h>
index 983d482..f70bcd2 100644 (file)
@@ -9,5 +9,4 @@
 #include <linux/virtio.h>
 #include <linux/virtio_config.h>
 #include <linux/bug.h>
-#include <asm/system.h>
 
index 0e7366d..3709624 100644 (file)
@@ -55,6 +55,7 @@ comment "Watchdog Device Drivers"
 
 config SOFT_WATCHDOG
        tristate "Software watchdog"
+       select WATCHDOG_CORE
        help
          A software monitoring watchdog. This will fail to reboot your system
          from some situations that the hardware watchdog will recover
@@ -74,6 +75,7 @@ config WM831X_WATCHDOG
 config WM8350_WATCHDOG
        tristate "WM8350 watchdog"
        depends on MFD_WM8350
+       select WATCHDOG_CORE
        help
          Support for the watchdog in the WM8350 AudioPlus PMIC.  When
          the watchdog triggers the system will be reset.
@@ -217,6 +219,7 @@ config MPCORE_WATCHDOG
 config EP93XX_WATCHDOG
        tristate "EP93xx Watchdog"
        depends on ARCH_EP93XX
+       select WATCHDOG_CORE
        help
          Say Y here if to include support for the watchdog timer
          embedded in the Cirrus Logic EP93xx family of devices.
@@ -234,6 +237,7 @@ config OMAP_WATCHDOG
 config PNX4008_WATCHDOG
        tristate "PNX4008 and LPC32XX Watchdog"
        depends on ARCH_PNX4008 || ARCH_LPC32XX
+       select WATCHDOG_CORE
        help
          Say Y here if to include support for the watchdog timer
          in the PNX4008 or LPC32XX processor.
@@ -283,6 +287,7 @@ config COH901327_WATCHDOG
        bool "ST-Ericsson COH 901 327 watchdog"
        depends on ARCH_U300
        default y if MACH_U300
+       select WATCHDOG_CORE
        help
          Say Y here to include Watchdog timer support for the
          watchdog embedded into the ST-Ericsson U300 series platforms.
@@ -328,6 +333,7 @@ config TS72XX_WATCHDOG
 config MAX63XX_WATCHDOG
        tristate "Max63xx watchdog"
        depends on ARM && HAS_IOMEM
+       select WATCHDOG_CORE
        help
          Support for memory mapped max63{69,70,71,72,73,74} watchdog timer.
 
@@ -955,6 +961,7 @@ config INDYDOG
 config JZ4740_WDT
        tristate "Ingenic jz4740 SoC hardware watchdog"
        depends on MACH_JZ4740
+       select WATCHDOG_CORE
        help
          Hardware driver for the built-in watchdog timer on Ingenic jz4740 SoCs.
 
@@ -996,6 +1003,7 @@ config AR7_WDT
 config TXX9_WDT
        tristate "Toshiba TXx9 Watchdog Timer"
        depends on CPU_TX39XX || CPU_TX49XX
+       select WATCHDOG_CORE
        help
          Hardware driver for the built-in watchdog timer on TXx9 MIPS SoCs.
 
index b6a2b58..4397881 100644 (file)
@@ -52,6 +52,8 @@
  *     Includes, defines, variables, module parameters, ...
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 /* Includes */
 #include <linux/module.h>              /* For module specific items */
 #include <linux/moduleparam.h>         /* For new moduleparam's */
@@ -70,7 +72,6 @@
 
 /* Module information */
 #define DRV_NAME "acquirewdt"
-#define PFX DRV_NAME ": "
 #define WATCHDOG_NAME "Acquire WDT"
 /* There is no way to see what the correct time-out period is */
 #define WATCHDOG_HEARTBEAT 0
@@ -92,8 +93,8 @@ static int wdt_start = 0x443;
 module_param(wdt_start, int, 0);
 MODULE_PARM_DESC(wdt_start, "Acquire WDT 'start' io port (default 0x443)");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
        "Watchdog cannot be stopped once started (default="
        __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -208,8 +209,7 @@ static int acq_close(struct inode *inode, struct file *file)
        if (expect_close == 42) {
                acq_stop();
        } else {
-               printk(KERN_CRIT PFX
-                       "Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
                acq_keepalive();
        }
        clear_bit(0, &acq_is_open);
@@ -246,27 +246,24 @@ static int __devinit acq_probe(struct platform_device *dev)
 
        if (wdt_stop != wdt_start) {
                if (!request_region(wdt_stop, 1, WATCHDOG_NAME)) {
-                       printk(KERN_ERR PFX
-                           "I/O address 0x%04x already in use\n", wdt_stop);
+                       pr_err("I/O address 0x%04x already in use\n", wdt_stop);
                        ret = -EIO;
                        goto out;
                }
        }
 
        if (!request_region(wdt_start, 1, WATCHDOG_NAME)) {
-               printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
-                       wdt_start);
+               pr_err("I/O address 0x%04x already in use\n", wdt_start);
                ret = -EIO;
                goto unreg_stop;
        }
        ret = misc_register(&acq_miscdev);
        if (ret != 0) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                                                       WATCHDOG_MINOR, ret);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      WATCHDOG_MINOR, ret);
                goto unreg_regions;
        }
-       printk(KERN_INFO PFX "initialized. (nowayout=%d)\n", nowayout);
+       pr_info("initialized. (nowayout=%d)\n", nowayout);
 
        return 0;
 unreg_regions:
@@ -308,8 +305,7 @@ static int __init acq_init(void)
 {
        int err;
 
-       printk(KERN_INFO
-             "WDT driver for Acquire single board computer initialising.\n");
+       pr_info("WDT driver for Acquire single board computer initialising\n");
 
        err = platform_driver_register(&acquirewdt_driver);
        if (err)
@@ -332,7 +328,7 @@ static void __exit acq_exit(void)
 {
        platform_device_unregister(acq_platform_device);
        platform_driver_unregister(&acquirewdt_driver);
-       printk(KERN_INFO PFX "Watchdog Module Unloaded.\n");
+       pr_info("Watchdog Module Unloaded\n");
 }
 
 module_init(acq_init);
index 4d40965..64ae9e9 100644 (file)
@@ -28,6 +28,8 @@
  *         add wdt_start and wdt_stop as parameters.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/io.h>
 #include <linux/uaccess.h>
 
-#include <asm/system.h>
 
 #define DRV_NAME "advantechwdt"
-#define PFX DRV_NAME ": "
 #define WATCHDOG_NAME "Advantech WDT"
 #define WATCHDOG_TIMEOUT 60            /* 60 sec default timeout */
 
@@ -77,8 +77,8 @@ MODULE_PARM_DESC(timeout,
        "Watchdog timeout in seconds. 1<= timeout <=63, default="
                __MODULE_STRING(WATCHDOG_TIMEOUT) ".");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
        "Watchdog cannot be stopped once started (default="
                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -207,8 +207,7 @@ static int advwdt_close(struct inode *inode, struct file *file)
        if (adv_expect_close == 42) {
                advwdt_disable();
        } else {
-               printk(KERN_CRIT PFX
-                               "Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
                advwdt_ping();
        }
        clear_bit(0, &advwdt_is_open);
@@ -245,18 +244,15 @@ static int __devinit advwdt_probe(struct platform_device *dev)
 
        if (wdt_stop != wdt_start) {
                if (!request_region(wdt_stop, 1, WATCHDOG_NAME)) {
-                       printk(KERN_ERR PFX
-                               "I/O address 0x%04x already in use\n",
-                                                               wdt_stop);
+                       pr_err("I/O address 0x%04x already in use\n",
+                              wdt_stop);
                        ret = -EIO;
                        goto out;
                }
        }
 
        if (!request_region(wdt_start, 1, WATCHDOG_NAME)) {
-               printk(KERN_ERR PFX
-                               "I/O address 0x%04x already in use\n",
-                                                               wdt_start);
+               pr_err("I/O address 0x%04x already in use\n", wdt_start);
                ret = -EIO;
                goto unreg_stop;
        }
@@ -265,18 +261,16 @@ static int __devinit advwdt_probe(struct platform_device *dev)
         * if not reset to the default */
        if (advwdt_set_heartbeat(timeout)) {
                advwdt_set_heartbeat(WATCHDOG_TIMEOUT);
-               printk(KERN_INFO PFX
-                       "timeout value must be 1<=x<=63, using %d\n", timeout);
+               pr_info("timeout value must be 1<=x<=63, using %d\n", timeout);
        }
 
        ret = misc_register(&advwdt_miscdev);
        if (ret != 0) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                                                       WATCHDOG_MINOR, ret);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      WATCHDOG_MINOR, ret);
                goto unreg_regions;
        }
-       printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n",
+       pr_info("initialized. timeout=%d sec (nowayout=%d)\n",
                timeout, nowayout);
 out:
        return ret;
@@ -318,8 +312,7 @@ static int __init advwdt_init(void)
 {
        int err;
 
-       printk(KERN_INFO
-            "WDT driver for Advantech single board computer initialising.\n");
+       pr_info("WDT driver for Advantech single board computer initialising\n");
 
        err = platform_driver_register(&advwdt_driver);
        if (err)
@@ -343,7 +336,7 @@ static void __exit advwdt_exit(void)
 {
        platform_device_unregister(advwdt_platform_device);
        platform_driver_unregister(&advwdt_driver);
-       printk(KERN_INFO PFX "Watchdog Module Unloaded.\n");
+       pr_info("Watchdog Module Unloaded\n");
 }
 
 module_init(advwdt_init);
index f16dcbd..41b8493 100644 (file)
@@ -7,6 +7,8 @@
  *     2 of the License, or (at your option) any later version.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
@@ -22,7 +24,6 @@
 #include <linux/io.h>
 
 #define WATCHDOG_NAME "ALi_M1535"
-#define PFX WATCHDOG_NAME ": "
 #define WATCHDOG_TIMEOUT 60    /* 60 sec default timeout */
 
 /* internal variables */
@@ -39,8 +40,8 @@ MODULE_PARM_DESC(timeout,
                "Watchdog timeout in seconds. (0 < timeout < 18000, default="
                                __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -268,8 +269,7 @@ static int ali_release(struct inode *inode, struct file *file)
        if (ali_expect_release == 42)
                ali_stop();
        else {
-               printk(KERN_CRIT PFX
-                               "Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
                ali_keepalive();
        }
        clear_bit(0, &ali_is_open);
@@ -399,9 +399,8 @@ static int __init watchdog_init(void)
           if not reset to the default */
        if (timeout < 1 || timeout >= 18000) {
                timeout = WATCHDOG_TIMEOUT;
-               printk(KERN_INFO PFX
-                    "timeout value must be 0 < timeout < 18000, using %d\n",
-                                                       timeout);
+               pr_info("timeout value must be 0 < timeout < 18000, using %d\n",
+                       timeout);
        }
 
        /* Calculate the watchdog's timeout */
@@ -409,20 +408,18 @@ static int __init watchdog_init(void)
 
        ret = register_reboot_notifier(&ali_notifier);
        if (ret != 0) {
-               printk(KERN_ERR PFX
-                       "cannot register reboot notifier (err=%d)\n", ret);
+               pr_err("cannot register reboot notifier (err=%d)\n", ret);
                goto out;
        }
 
        ret = misc_register(&ali_miscdev);
        if (ret != 0) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                                               WATCHDOG_MINOR, ret);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      WATCHDOG_MINOR, ret);
                goto unreg_reboot;
        }
 
-       printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n",
+       pr_info("initialized. timeout=%d sec (nowayout=%d)\n",
                timeout, nowayout);
 
 out:
index 46f4b85..5eee550 100644 (file)
@@ -19,6 +19,8 @@
  *                  -- Mike Waychison <michael.waychison@sun.com>
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/io.h>
 #include <linux/uaccess.h>
 
-#include <asm/system.h>
-
-#define OUR_NAME "alim7101_wdt"
-#define PFX OUR_NAME ": "
 
 #define WDT_ENABLE 0x9C
 #define WDT_DISABLE 0x8C
@@ -79,8 +77,8 @@ static unsigned long wdt_is_open;
 static char wdt_expect_close;
 static struct pci_dev *alim7101_pmu;
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -112,8 +110,7 @@ static void wdt_timer_ping(unsigned long data)
                                        ALI_7101_GPIO_O, tmp & ~0x20);
                }
        } else {
-               printk(KERN_WARNING PFX
-                       "Heartbeat lost! Will not ping the watchdog\n");
+               pr_warn("Heartbeat lost! Will not ping the watchdog\n");
        }
        /* Re-set the timer interval */
        mod_timer(&timer, jiffies + WDT_INTERVAL);
@@ -162,7 +159,7 @@ static void wdt_startup(void)
        /* Start the timer */
        mod_timer(&timer, jiffies + WDT_INTERVAL);
 
-       printk(KERN_INFO PFX "Watchdog timer is now enabled.\n");
+       pr_info("Watchdog timer is now enabled\n");
 }
 
 static void wdt_turnoff(void)
@@ -170,7 +167,7 @@ static void wdt_turnoff(void)
        /* Stop the timer */
        del_timer_sync(&timer);
        wdt_change(WDT_DISABLE);
-       printk(KERN_INFO PFX "Watchdog timer is now disabled...\n");
+       pr_info("Watchdog timer is now disabled...\n");
 }
 
 static void wdt_keepalive(void)
@@ -226,8 +223,7 @@ static int fop_close(struct inode *inode, struct file *file)
                wdt_turnoff();
        else {
                /* wim: shouldn't there be a: del_timer(&timer); */
-               printk(KERN_CRIT PFX
-                 "device file closed unexpectedly. Will not stop the WDT!\n");
+               pr_crit("device file closed unexpectedly. Will not stop the WDT!\n");
        }
        clear_bit(0, &wdt_is_open);
        wdt_expect_close = 0;
@@ -322,8 +318,7 @@ static int wdt_notify_sys(struct notifier_block *this,
                 * watchdog on reboot with no heartbeat
                 */
                wdt_change(WDT_ENABLE);
-               printk(KERN_INFO PFX "Watchdog timer is now enabled "
-                       "with no heartbeat - should reboot in ~1 second.\n");
+               pr_info("Watchdog timer is now enabled with no heartbeat - should reboot in ~1 second\n");
        }
        return NOTIFY_DONE;
 }
@@ -352,12 +347,11 @@ static int __init alim7101_wdt_init(void)
        struct pci_dev *ali1543_south;
        char tmp;
 
-       printk(KERN_INFO PFX "Steve Hill <steve@navaho.co.uk>.\n");
+       pr_info("Steve Hill <steve@navaho.co.uk>\n");
        alim7101_pmu = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101,
                NULL);
        if (!alim7101_pmu) {
-               printk(KERN_INFO PFX
-                       "ALi M7101 PMU not present - WDT not set\n");
+               pr_info("ALi M7101 PMU not present - WDT not set\n");
                return -EBUSY;
        }
 
@@ -367,56 +361,46 @@ static int __init alim7101_wdt_init(void)
        ali1543_south = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533,
                NULL);
        if (!ali1543_south) {
-               printk(KERN_INFO PFX
-                       "ALi 1543 South-Bridge not present - WDT not set\n");
+               pr_info("ALi 1543 South-Bridge not present - WDT not set\n");
                goto err_out;
        }
        pci_read_config_byte(ali1543_south, 0x5e, &tmp);
        pci_dev_put(ali1543_south);
        if ((tmp & 0x1e) == 0x00) {
                if (!use_gpio) {
-                       printk(KERN_INFO PFX
-                               "Detected old alim7101 revision 'a1d'.  "
-                               "If this is a cobalt board, set the 'use_gpio' "
-                               "module parameter.\n");
+                       pr_info("Detected old alim7101 revision 'a1d'.  If this is a cobalt board, set the 'use_gpio' module parameter.\n");
                        goto err_out;
                }
                nowayout = 1;
        } else if ((tmp & 0x1e) != 0x12 && (tmp & 0x1e) != 0x00) {
-               printk(KERN_INFO PFX
-                       "ALi 1543 South-Bridge does not have the correct "
-                       "revision number (???1001?) - WDT not set\n");
+               pr_info("ALi 1543 South-Bridge does not have the correct revision number (???1001?) - WDT not set\n");
                goto err_out;
        }
 
        if (timeout < 1 || timeout > 3600) {
                /* arbitrary upper limit */
                timeout = WATCHDOG_TIMEOUT;
-               printk(KERN_INFO PFX
-                       "timeout value must be 1 <= x <= 3600, using %d\n",
-                                                               timeout);
+               pr_info("timeout value must be 1 <= x <= 3600, using %d\n",
+                       timeout);
        }
 
        rc = register_reboot_notifier(&wdt_notifier);
        if (rc) {
-               printk(KERN_ERR PFX
-                       "cannot register reboot notifier (err=%d)\n", rc);
+               pr_err("cannot register reboot notifier (err=%d)\n", rc);
                goto err_out;
        }
 
        rc = misc_register(&wdt_miscdev);
        if (rc) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                       wdt_miscdev.minor, rc);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      wdt_miscdev.minor, rc);
                goto err_out_reboot;
        }
 
        if (nowayout)
                __module_get(THIS_MODULE);
 
-       printk(KERN_INFO PFX "WDT driver for ALi M7101 initialised. "
-                                       "timeout=%d sec (nowayout=%d)\n",
+       pr_info("WDT driver for ALi M7101 initialised. timeout=%d sec (nowayout=%d)\n",
                timeout, nowayout);
        return 0;
 
index 502773a..639ae9a 100644 (file)
@@ -23,6 +23,8 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/errno.h>
@@ -39,7 +41,6 @@
 #include <asm/addrspace.h>
 #include <asm/mach-ar7/ar7.h>
 
-#define DRVNAME "ar7_wdt"
 #define LONGNAME "TI AR7 Watchdog Timer"
 
 MODULE_AUTHOR("Nicolas Thill <nico@openwrt.org>");
@@ -51,8 +52,8 @@ static int margin = 60;
 module_param(margin, int, 0);
 MODULE_PARM_DESC(margin, "Watchdog margin in seconds");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close");
 
 #define READ_REG(x) readl((void __iomem *)&(x))
@@ -93,7 +94,7 @@ static void ar7_wdt_kick(u32 value)
                        return;
                }
        }
-       printk(KERN_ERR DRVNAME ": failed to unlock WDT kick reg\n");
+       pr_err("failed to unlock WDT kick reg\n");
 }
 
 static void ar7_wdt_prescale(u32 value)
@@ -106,7 +107,7 @@ static void ar7_wdt_prescale(u32 value)
                        return;
                }
        }
-       printk(KERN_ERR DRVNAME ": failed to unlock WDT prescale reg\n");
+       pr_err("failed to unlock WDT prescale reg\n");
 }
 
 static void ar7_wdt_change(u32 value)
@@ -119,7 +120,7 @@ static void ar7_wdt_change(u32 value)
                        return;
                }
        }
-       printk(KERN_ERR DRVNAME ": failed to unlock WDT change reg\n");
+       pr_err("failed to unlock WDT change reg\n");
 }
 
 static void ar7_wdt_disable(u32 value)
@@ -135,7 +136,7 @@ static void ar7_wdt_disable(u32 value)
                        }
                }
        }
-       printk(KERN_ERR DRVNAME ": failed to unlock WDT disable reg\n");
+       pr_err("failed to unlock WDT disable reg\n");
 }
 
 static void ar7_wdt_update_margin(int new_margin)
@@ -151,21 +152,20 @@ static void ar7_wdt_update_margin(int new_margin)
                change = 0xffff;
        ar7_wdt_change(change);
        margin = change * prescale_value / vbus_rate;
-       printk(KERN_INFO DRVNAME
-              ": timer margin %d seconds (prescale %d, change %d, freq %d)\n",
-              margin, prescale_value, change, vbus_rate);
+       pr_info("timer margin %d seconds (prescale %d, change %d, freq %d)\n",
+               margin, prescale_value, change, vbus_rate);
 }
 
 static void ar7_wdt_enable_wdt(void)
 {
-       printk(KERN_DEBUG DRVNAME ": enabling watchdog timer\n");
+       pr_debug("enabling watchdog timer\n");
        ar7_wdt_disable(1);
        ar7_wdt_kick(1);
 }
 
 static void ar7_wdt_disable_wdt(void)
 {
-       printk(KERN_DEBUG DRVNAME ": disabling watchdog timer\n");
+       pr_debug("disabling watchdog timer\n");
        ar7_wdt_disable(0);
 }
 
@@ -183,9 +183,7 @@ static int ar7_wdt_open(struct inode *inode, struct file *file)
 static int ar7_wdt_release(struct inode *inode, struct file *file)
 {
        if (!expect_close)
-               printk(KERN_WARNING DRVNAME
-               ": watchdog device closed unexpectedly,"
-               "will not disable the watchdog timer\n");
+               pr_warn("watchdog device closed unexpectedly, will not disable the watchdog timer\n");
        else if (!nowayout)
                ar7_wdt_disable_wdt();
        clear_bit(0, &wdt_is_open);
@@ -283,28 +281,28 @@ static int __devinit ar7_wdt_probe(struct platform_device *pdev)
        ar7_regs_wdt =
                platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
        if (!ar7_regs_wdt) {
-               printk(KERN_ERR DRVNAME ": could not get registers resource\n");
+               pr_err("could not get registers resource\n");
                rc = -ENODEV;
                goto out;
        }
 
        if (!request_mem_region(ar7_regs_wdt->start,
                                resource_size(ar7_regs_wdt), LONGNAME)) {
-               printk(KERN_WARNING DRVNAME ": watchdog I/O region busy\n");
+               pr_warn("watchdog I/O region busy\n");
                rc = -EBUSY;
                goto out;
        }
 
        ar7_wdt = ioremap(ar7_regs_wdt->start, resource_size(ar7_regs_wdt));
        if (!ar7_wdt) {
-               printk(KERN_ERR DRVNAME ": could not ioremap registers\n");
+               pr_err("could not ioremap registers\n");
                rc = -ENXIO;
                goto out_mem_region;
        }
 
        vbus_clk = clk_get(NULL, "vbus");
        if (IS_ERR(vbus_clk)) {
-               printk(KERN_ERR DRVNAME ": could not get vbus clock\n");
+               pr_err("could not get vbus clock\n");
                rc = PTR_ERR(vbus_clk);
                goto out_mem_region;
        }
@@ -315,7 +313,7 @@ static int __devinit ar7_wdt_probe(struct platform_device *pdev)
 
        rc = misc_register(&ar7_wdt_miscdev);
        if (rc) {
-               printk(KERN_ERR DRVNAME ": unable to register misc device\n");
+               pr_err("unable to register misc device\n");
                goto out_alloc;
        }
        goto out;
index 4ca5d40..2896430 100644 (file)
@@ -45,8 +45,8 @@ MODULE_PARM_DESC(timeout,
                "Timeout value. Limited to be 1 or 2 seconds. (default="
                __MODULE_STRING(TIMEOUT_DEFAULT) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
index 7ceefd2..7ef99a1 100644 (file)
@@ -9,6 +9,8 @@
  * 2 of the License, or (at your option) any later version.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/bitops.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
 #define WDT_MAX_TIME           256     /* seconds */
 
 static int wdt_time = WDT_DEFAULT_TIME;
-static int nowayout = WATCHDOG_NOWAYOUT;
+static bool nowayout = WATCHDOG_NOWAYOUT;
 
 module_param(wdt_time, int, 0);
 MODULE_PARM_DESC(wdt_time, "Watchdog time in seconds. (default="
                                __MODULE_STRING(WDT_DEFAULT_TIME) ")");
 
 #ifdef CONFIG_WATCHDOG_NOWAYOUT
-module_param(nowayout, int, 0);
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -209,8 +211,8 @@ static int __devinit at91wdt_probe(struct platform_device *pdev)
        if (res)
                return res;
 
-       printk(KERN_INFO "AT91 Watchdog Timer enabled (%d seconds%s)\n",
-                               wdt_time, nowayout ? ", nowayout" : "");
+       pr_info("AT91 Watchdog Timer enabled (%d seconds%s)\n",
+               wdt_time, nowayout ? ", nowayout" : "");
        return 0;
 }
 
@@ -268,8 +270,8 @@ static int __init at91_wdt_init(void)
           if not reset to the default */
        if (at91_wdt_settimeout(wdt_time)) {
                at91_wdt_settimeout(WDT_DEFAULT_TIME);
-               pr_info("at91_wdt: wdt_time value must be 1 <= wdt_time <= 256"
-                                               ", using %d\n", wdt_time);
+               pr_info("wdt_time value must be 1 <= wdt_time <= 256, using %d\n",
+                       wdt_time);
        }
 
        return platform_driver_register(&at91wdt_driver);
index 0056256..05e1be8 100644 (file)
@@ -15,6 +15,8 @@
  * bootloader doesn't write to this register.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/init.h>
@@ -60,8 +62,8 @@ module_param(heartbeat, int, 0);
 MODULE_PARM_DESC(heartbeat, "Watchdog heartbeats in seconds. "
        "(default = " __MODULE_STRING(WDT_HEARTBEAT) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
        "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
@@ -96,7 +98,7 @@ static void at91_ping(unsigned long data)
                at91_wdt_reset();
                mod_timer(&at91wdt_private.timer, jiffies + WDT_TIMEOUT);
        } else
-               printk(KERN_CRIT DRV_NAME": I will reset your machine !\n");
+               pr_crit("I will reset your machine !\n");
 }
 
 /*
@@ -140,7 +142,7 @@ static int at91_wdt_settimeout(unsigned int timeout)
        /* Check if disabled */
        mr = wdt_read(AT91_WDT_MR);
        if (mr & AT91_WDT_WDDIS) {
-               printk(KERN_ERR DRV_NAME": sorry, watchdog is disabled\n");
+               pr_err("sorry, watchdog is disabled\n");
                return -EIO;
        }
 
@@ -283,7 +285,7 @@ static int __init at91wdt_probe(struct platform_device *pdev)
        setup_timer(&at91wdt_private.timer, at91_ping, 0);
        mod_timer(&at91wdt_private.timer, jiffies + WDT_TIMEOUT);
 
-       printk(KERN_INFO DRV_NAME " enabled (heartbeat=%d sec, nowayout=%d)\n",
+       pr_info("enabled (heartbeat=%d sec, nowayout=%d)\n",
                heartbeat, nowayout);
 
        return 0;
index 9db8083..1f9371f 100644 (file)
@@ -17,6 +17,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/bitops.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
@@ -45,8 +47,8 @@
 #define WDOG_CTRL_ACTION_NMI   2       /* NMI */
 #define WDOG_CTRL_ACTION_FCR   3       /* full chip reset */
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
                           "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
@@ -114,8 +116,7 @@ static int ath79_wdt_release(struct inode *inode, struct file *file)
        if (test_bit(WDT_FLAGS_EXPECT_CLOSE, &wdt_flags))
                ath79_wdt_disable();
        else {
-               pr_crit(DRIVER_NAME ": device closed unexpectedly, "
-                       "watchdog timer will not stop!\n");
+               pr_crit("device closed unexpectedly, watchdog timer will not stop!\n");
                ath79_wdt_keepalive();
        }
 
index 5c5f4b1..bc0e91e 100644 (file)
@@ -10,6 +10,8 @@
  *  2 of the License, or (at your option) any later version.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/bitops.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
 #define WDT_MAX_TIME           255     /* seconds */
 
 static int wdt_time = WDT_DEFAULT_TIME;
-static int nowayout = WATCHDOG_NOWAYOUT;
+static bool nowayout = WATCHDOG_NOWAYOUT;
 
 module_param(wdt_time, int, 0);
 MODULE_PARM_DESC(wdt_time, "Watchdog time in seconds. (default="
                                __MODULE_STRING(WDT_DEFAULT_TIME) ")");
 
 #ifdef CONFIG_WATCHDOG_NOWAYOUT
-module_param(nowayout, int, 0);
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -91,7 +93,7 @@ static void bcm47xx_timer_tick(unsigned long unused)
                bcm47xx_wdt_hw_start();
                mod_timer(&wdt_timer, jiffies + HZ);
        } else {
-               printk(KERN_CRIT DRV_NAME "Watchdog will fire soon!!!\n");
+               pr_crit("Watchdog will fire soon!!!\n");
        }
 }
 
@@ -140,8 +142,7 @@ static int bcm47xx_wdt_release(struct inode *inode, struct file *file)
        if (expect_release == 42) {
                bcm47xx_wdt_stop();
        } else {
-               printk(KERN_CRIT DRV_NAME
-                       ": Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
                bcm47xx_wdt_start();
        }
 
@@ -270,8 +271,7 @@ static int __init bcm47xx_wdt_init(void)
 
        if (bcm47xx_wdt_settimeout(wdt_time)) {
                bcm47xx_wdt_settimeout(WDT_DEFAULT_TIME);
-               printk(KERN_INFO DRV_NAME ": "
-                       "wdt_time value must be 0 < wdt_time < %d, using %d\n",
+               pr_info("wdt_time value must be 0 < wdt_time < %d, using %d\n",
                        (WDT_MAX_TIME + 1), wdt_time);
        }
 
@@ -285,8 +285,8 @@ static int __init bcm47xx_wdt_init(void)
                return ret;
        }
 
-       printk(KERN_INFO "BCM47xx Watchdog Timer enabled (%d seconds%s)\n",
-                               wdt_time, nowayout ? ", nowayout" : "");
+       pr_info("BCM47xx Watchdog Timer enabled (%d seconds%s)\n",
+               wdt_time, nowayout ? ", nowayout" : "");
        return 0;
 }
 
index 8dc7de6..8379dc3 100644 (file)
@@ -10,6 +10,8 @@
  *  2 of the License, or (at your option) any later version.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/bitops.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
@@ -50,8 +52,8 @@ static struct {
 static int expect_close;
 
 static int wdt_time = WDT_DEFAULT_TIME;
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
        __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
@@ -82,7 +84,7 @@ static void bcm63xx_timer_tick(unsigned long unused)
                bcm63xx_wdt_hw_start();
                mod_timer(&bcm63xx_wdt_device.timer, jiffies + HZ);
        } else
-               printk(KERN_CRIT PFX ": watchdog will restart system\n");
+               pr_crit("watchdog will restart system\n");
 }
 
 static void bcm63xx_wdt_pet(void)
@@ -126,8 +128,7 @@ static int bcm63xx_wdt_release(struct inode *inode, struct file *file)
        if (expect_close == 42)
                bcm63xx_wdt_pause();
        else {
-               printk(KERN_CRIT PFX
-                       ": Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
                bcm63xx_wdt_start();
        }
        clear_bit(0, &bcm63xx_wdt_device.inuse);
index b9fa9b7..38bc383 100644 (file)
@@ -11,6 +11,8 @@
  * Licensed under the GPL-2 or later.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/platform_device.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #define stamp(fmt, args...) \
        pr_debug("%s:%i: " fmt "\n", __func__, __LINE__, ## args)
 #define stampit() stamp("here i am")
-#define pr_devinit(fmt, args...) \
-       ({ static const __devinitconst char __fmt[] = fmt; \
-       printk(__fmt, ## args); })
-#define pr_init(fmt, args...) \
-       ({ static const __initconst char __fmt[] = fmt; \
-       printk(__fmt, ## args); })
 
 #define WATCHDOG_NAME "bfin-wdt"
-#define PFX WATCHDOG_NAME ": "
 
 /* The BF561 has two watchdogs (one per core), but since Linux
  * only runs on core A, we'll just work with that one.
@@ -54,7 +49,7 @@
 #define WATCHDOG_TIMEOUT 20
 
 static unsigned int timeout = WATCHDOG_TIMEOUT;
-static int nowayout = WATCHDOG_NOWAYOUT;
+static bool nowayout = WATCHDOG_NOWAYOUT;
 static const struct watchdog_info bfin_wdt_info;
 static unsigned long open_check;
 static char expect_close;
@@ -126,7 +121,7 @@ static int bfin_wdt_set_timeout(unsigned long t)
        stamp("maxtimeout=%us newtimeout=%lus (cnt=%#x)", max_t, t, cnt);
 
        if (t > max_t) {
-               printk(KERN_WARNING PFX "timeout value is too large\n");
+               pr_warn("timeout value is too large\n");
                return -EINVAL;
        }
 
@@ -182,8 +177,7 @@ static int bfin_wdt_release(struct inode *inode, struct file *file)
        if (expect_close == 42)
                bfin_wdt_stop();
        else {
-               printk(KERN_CRIT PFX
-                       "Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
                bfin_wdt_keepalive();
        }
        expect_close = 0;
@@ -368,14 +362,13 @@ static int __devinit bfin_wdt_probe(struct platform_device *pdev)
 
        ret = misc_register(&bfin_wdt_miscdev);
        if (ret) {
-               pr_devinit(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                               WATCHDOG_MINOR, ret);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      WATCHDOG_MINOR, ret);
                return ret;
        }
 
-       pr_devinit(KERN_INFO PFX "initialized: timeout=%d sec (nowayout=%d)\n",
-              timeout, nowayout);
+       pr_info("initialized: timeout=%d sec (nowayout=%d)\n",
+               timeout, nowayout);
 
        return 0;
 }
@@ -439,14 +432,14 @@ static int __init bfin_wdt_init(void)
         */
        ret = platform_driver_register(&bfin_wdt_driver);
        if (ret) {
-               pr_init(KERN_ERR PFX "unable to register driver\n");
+               pr_err("unable to register driver\n");
                return ret;
        }
 
        bfin_wdt_device = platform_device_register_simple(WATCHDOG_NAME,
                                                                -1, NULL, 0);
        if (IS_ERR(bfin_wdt_device)) {
-               pr_init(KERN_ERR PFX "unable to register device\n");
+               pr_err("unable to register device\n");
                platform_driver_unregister(&bfin_wdt_driver);
                return PTR_ERR(bfin_wdt_device);
        }
@@ -479,7 +472,7 @@ MODULE_PARM_DESC(timeout,
        "Watchdog timeout in seconds. (1<=timeout<=((2^32)/SCLK), default="
                __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
 
-module_param(nowayout, int, 0);
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
        "Watchdog cannot be stopped once started (default="
                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
index 7c0fdfc..ce0ab44 100644 (file)
@@ -12,6 +12,8 @@
  * option) any later version.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/smp.h>
@@ -21,7 +23,6 @@
 #include <linux/uaccess.h>
 
 #include <asm/reg_booke.h>
-#include <asm/system.h>
 #include <asm/time.h>
 #include <asm/div64.h>
 
@@ -225,8 +226,8 @@ static int booke_wdt_open(struct inode *inode, struct file *file)
        if (booke_wdt_enabled == 0) {
                booke_wdt_enabled = 1;
                on_each_cpu(__booke_wdt_enable, NULL, 0);
-               pr_debug("booke_wdt: watchdog enabled (timeout = %llu sec)\n",
-                       period_to_sec(booke_wdt_period));
+               pr_debug("watchdog enabled (timeout = %llu sec)\n",
+                        period_to_sec(booke_wdt_period));
        }
        spin_unlock(&booke_wdt_lock);
 
@@ -243,7 +244,7 @@ static int booke_wdt_release(struct inode *inode, struct file *file)
         */
        on_each_cpu(__booke_wdt_disable, NULL, 0);
        booke_wdt_enabled = 0;
-       pr_debug("booke_wdt: watchdog disabled\n");
+       pr_debug("watchdog disabled\n");
 #endif
 
        clear_bit(0, &wdt_is_active);
@@ -275,19 +276,19 @@ static int __init booke_wdt_init(void)
 {
        int ret = 0;
 
-       pr_info("booke_wdt: powerpc book-e watchdog driver loaded\n");
+       pr_info("powerpc book-e watchdog driver loaded\n");
        ident.firmware_version = cur_cpu_spec->pvr_value;
 
        ret = misc_register(&booke_wdt_miscdev);
        if (ret) {
-               pr_err("booke_wdt: cannot register device (minor=%u, ret=%i)\n",
+               pr_err("cannot register device (minor=%u, ret=%i)\n",
                       WATCHDOG_MINOR, ret);
                return ret;
        }
 
        spin_lock(&booke_wdt_lock);
        if (booke_wdt_enabled == 1) {
-               pr_info("booke_wdt: watchdog enabled (timeout = %llu sec)\n",
+               pr_info("watchdog enabled (timeout = %llu sec)\n",
                        period_to_sec(booke_wdt_period));
                on_each_cpu(__booke_wdt_enable, NULL, 0);
        }
index 5b89f7d..6876430 100644 (file)
@@ -8,17 +8,15 @@
  */
 #include <linux/module.h>
 #include <linux/types.h>
-#include <linux/fs.h>
-#include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include <linux/interrupt.h>
 #include <linux/pm.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/bitops.h>
-#include <linux/uaccess.h>
 #include <linux/clk.h>
 #include <linux/delay.h>
+#include <linux/err.h>
 
 #define DRV_NAME "WDOG COH 901 327"
 
 #define U300_WDOG_IFR_WILL_BARK_IRQ_FORCE_ENABLE                       0x0001U
 
 /* Default timeout in seconds = 1 minute */
-static int margin = 60;
+static unsigned int margin = 60;
 static resource_size_t phybase;
 static resource_size_t physize;
 static int irq;
 static void __iomem *virtbase;
-static unsigned long coh901327_users;
-static unsigned long boot_status;
 static struct device *parent;
 
 /*
@@ -155,34 +151,35 @@ static void coh901327_disable(void)
                        __func__, val);
 }
 
-static void coh901327_start(void)
+static int coh901327_start(struct watchdog_device *wdt_dev)
 {
-       coh901327_enable(margin * 100);
+       coh901327_enable(wdt_dev->timeout * 100);
+       return 0;
+}
+
+static int coh901327_stop(struct watchdog_device *wdt_dev)
+{
+       coh901327_disable();
+       return 0;
 }
 
-static void coh901327_keepalive(void)
+static int coh901327_ping(struct watchdog_device *wdd)
 {
        clk_enable(clk);
        /* Feed the watchdog */
        writew(U300_WDOG_FR_FEED_RESTART_TIMER,
               virtbase + U300_WDOG_FR);
        clk_disable(clk);
+       return 0;
 }
 
-static int coh901327_settimeout(int time)
+static int coh901327_settimeout(struct watchdog_device *wdt_dev,
+                               unsigned int time)
 {
-       /*
-        * Max margin is 327 since the 10ms
-        * timeout register is max
-        * 0x7FFF = 327670ms ~= 327s.
-        */
-       if (time <= 0 || time > 327)
-               return -EINVAL;
-
-       margin = time;
+       wdt_dev->timeout = time;
        clk_enable(clk);
        /* Set new timeout value */
-       writew(margin * 100, virtbase + U300_WDOG_TR);
+       writew(time * 100, virtbase + U300_WDOG_TR);
        /* Feed the dog */
        writew(U300_WDOG_FR_FEED_RESTART_TIMER,
               virtbase + U300_WDOG_FR);
@@ -190,6 +187,23 @@ static int coh901327_settimeout(int time)
        return 0;
 }
 
+static unsigned int coh901327_gettimeleft(struct watchdog_device *wdt_dev)
+{
+       u16 val;
+
+       clk_enable(clk);
+       /* Read repeatedly until the value is stable! */
+       val = readw(virtbase + U300_WDOG_CR);
+       while (val & U300_WDOG_CR_VALID_IND)
+               val = readw(virtbase + U300_WDOG_CR);
+       val &= U300_WDOG_CR_COUNT_VALUE_MASK;
+       clk_disable(clk);
+       if (val != 0)
+               val /= 100;
+
+       return val;
+}
+
 /*
  * This interrupt occurs 10 ms before the watchdog WILL bark.
  */
@@ -218,130 +232,35 @@ static irqreturn_t coh901327_interrupt(int irq, void *data)
        return IRQ_HANDLED;
 }
 
-/*
- * Allow only one user (daemon) to open the watchdog
- */
-static int coh901327_open(struct inode *inode, struct file *file)
-{
-       if (test_and_set_bit(1, &coh901327_users))
-               return -EBUSY;
-       coh901327_start();
-       return nonseekable_open(inode, file);
-}
-
-static int coh901327_release(struct inode *inode, struct file *file)
-{
-       clear_bit(1, &coh901327_users);
-       coh901327_disable();
-       return 0;
-}
-
-static ssize_t coh901327_write(struct file *file, const char __user *data,
-                              size_t len, loff_t *ppos)
-{
-       if (len)
-               coh901327_keepalive();
-       return len;
-}
-
-static long coh901327_ioctl(struct file *file, unsigned int cmd,
-                           unsigned long arg)
-{
-       int ret = -ENOTTY;
-       u16 val;
-       int time;
-       int new_options;
-       union {
-               struct watchdog_info __user *ident;
-               int __user *i;
-       } uarg;
-       static const struct watchdog_info ident = {
-               .options                = WDIOF_CARDRESET |
-                                         WDIOF_SETTIMEOUT |
-                                         WDIOF_KEEPALIVEPING,
-               .identity               = "COH 901 327 Watchdog",
-               .firmware_version       = 1,
-       };
-       uarg.i = (int __user *)arg;
-
-       switch (cmd) {
-       case WDIOC_GETSUPPORT:
-               ret = copy_to_user(uarg.ident, &ident,
-                                  sizeof(ident)) ? -EFAULT : 0;
-               break;
-
-       case WDIOC_GETSTATUS:
-               ret = put_user(0, uarg.i);
-               break;
-
-       case WDIOC_GETBOOTSTATUS:
-               ret = put_user(boot_status, uarg.i);
-               break;
-
-       case WDIOC_SETOPTIONS:
-               ret = get_user(new_options, uarg.i);
-               if (ret)
-                       break;
-               if (new_options & WDIOS_DISABLECARD)
-                       coh901327_disable();
-               if (new_options & WDIOS_ENABLECARD)
-                       coh901327_start();
-               ret = 0;
-               break;
-
-       case WDIOC_KEEPALIVE:
-               coh901327_keepalive();
-               ret = 0;
-               break;
-
-       case WDIOC_SETTIMEOUT:
-               ret = get_user(time, uarg.i);
-               if (ret)
-                       break;
-
-               ret = coh901327_settimeout(time);
-               if (ret)
-                       break;
-               /* Then fall through to return set value */
-
-       case WDIOC_GETTIMEOUT:
-               ret = put_user(margin, uarg.i);
-               break;
-
-       case WDIOC_GETTIMELEFT:
-               clk_enable(clk);
-               /* Read repeatedly until the value is stable! */
-               val = readw(virtbase + U300_WDOG_CR);
-               while (val & U300_WDOG_CR_VALID_IND)
-                       val = readw(virtbase + U300_WDOG_CR);
-               val &= U300_WDOG_CR_COUNT_VALUE_MASK;
-               clk_disable(clk);
-               if (val != 0)
-                       val /= 100;
-               ret = put_user(val, uarg.i);
-               break;
-       }
-       return ret;
-}
+static const struct watchdog_info coh901327_ident = {
+       .options = WDIOF_CARDRESET | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
+       .identity = DRV_NAME,
+};
 
-static const struct file_operations coh901327_fops = {
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .write          = coh901327_write,
-       .unlocked_ioctl = coh901327_ioctl,
-       .open           = coh901327_open,
-       .release        = coh901327_release,
+static struct watchdog_ops coh901327_ops = {
+       .owner = THIS_MODULE,
+       .start = coh901327_start,
+       .stop = coh901327_stop,
+       .ping = coh901327_ping,
+       .set_timeout = coh901327_settimeout,
+       .get_timeleft = coh901327_gettimeleft,
 };
 
-static struct miscdevice coh901327_miscdev = {
-       .minor          = WATCHDOG_MINOR,
-       .name           = "watchdog",
-       .fops           = &coh901327_fops,
+static struct watchdog_device coh901327_wdt = {
+       .info = &coh901327_ident,
+       .ops = &coh901327_ops,
+       /*
+        * Max timeout is 327 since the 10ms
+        * timeout register is max
+        * 0x7FFF = 327670ms ~= 327s.
+        */
+       .min_timeout = 0,
+       .max_timeout = 327,
 };
 
 static int __exit coh901327_remove(struct platform_device *pdev)
 {
-       misc_deregister(&coh901327_miscdev);
+       watchdog_unregister_device(&coh901327_wdt);
        coh901327_disable();
        free_irq(irq, pdev);
        clk_put(clk);
@@ -350,7 +269,6 @@ static int __exit coh901327_remove(struct platform_device *pdev)
        return 0;
 }
 
-
 static int __init coh901327_probe(struct platform_device *pdev)
 {
        int ret;
@@ -393,7 +311,7 @@ static int __init coh901327_probe(struct platform_device *pdev)
        case U300_WDOG_SR_STATUS_TIMED_OUT:
                dev_info(&pdev->dev,
                        "watchdog timed out since last chip reset!\n");
-               boot_status = WDIOF_CARDRESET;
+               coh901327_wdt.bootstatus |= WDIOF_CARDRESET;
                /* Status will be cleared below */
                break;
        case U300_WDOG_SR_STATUS_NORMAL:
@@ -435,7 +353,11 @@ static int __init coh901327_probe(struct platform_device *pdev)
 
        clk_disable(clk);
 
-       ret = misc_register(&coh901327_miscdev);
+       if (margin < 1 || margin > 327)
+               margin = 60;
+       coh901327_wdt.timeout = margin;
+
+       ret = watchdog_register_device(&coh901327_wdt);
        if (ret == 0)
                dev_info(&pdev->dev,
                         "initialized. timer margin=%d sec\n", margin);
@@ -543,8 +465,8 @@ module_exit(coh901327_exit);
 MODULE_AUTHOR("Linus Walleij <linus.walleij@stericsson.com>");
 MODULE_DESCRIPTION("COH 901 327 Watchdog");
 
-module_param(margin, int, 0);
+module_param(margin, uint, 0);
 MODULE_PARM_DESC(margin, "Watchdog margin in seconds (default 60s)");
 
 MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+MODULE_ALIAS("platform:coh901327-watchdog");
index 251c863..7e88839 100644 (file)
@@ -19,6 +19,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
@@ -71,7 +73,7 @@ static struct {
 static void cpu5wdt_trigger(unsigned long unused)
 {
        if (verbose > 2)
-               printk(KERN_DEBUG PFX "trigger at %i ticks\n", ticks);
+               pr_debug("trigger at %i ticks\n", ticks);
 
        if (cpu5wdt_device.running)
                ticks--;
@@ -96,7 +98,7 @@ static void cpu5wdt_reset(void)
        ticks = cpu5wdt_device.default_ticks;
 
        if (verbose)
-               printk(KERN_DEBUG PFX "reset (%i ticks)\n", (int) ticks);
+               pr_debug("reset (%i ticks)\n", (int) ticks);
 
 }
 
@@ -129,7 +131,7 @@ static int cpu5wdt_stop(void)
        ticks = cpu5wdt_device.default_ticks;
        spin_unlock_irqrestore(&cpu5wdt_lock, flags);
        if (verbose)
-               printk(KERN_CRIT PFX "stop not possible\n");
+               pr_crit("stop not possible\n");
        return -EIO;
 }
 
@@ -219,8 +221,7 @@ static int __devinit cpu5wdt_init(void)
        int err;
 
        if (verbose)
-               printk(KERN_DEBUG PFX
-                               "port=0x%x, verbose=%i\n", port, verbose);
+               pr_debug("port=0x%x, verbose=%i\n", port, verbose);
 
        init_completion(&cpu5wdt_device.stop);
        cpu5wdt_device.queue = 0;
@@ -228,7 +229,7 @@ static int __devinit cpu5wdt_init(void)
        cpu5wdt_device.default_ticks = ticks;
 
        if (!request_region(port, CPU5WDT_EXTENT, PFX)) {
-               printk(KERN_ERR PFX "request_region failed\n");
+               pr_err("request_region failed\n");
                err = -EBUSY;
                goto no_port;
        }
@@ -237,16 +238,16 @@ static int __devinit cpu5wdt_init(void)
        val = inb(port + CPU5WDT_STATUS_REG);
        val = (val >> 2) & 1;
        if (!val)
-               printk(KERN_INFO PFX "sorry, was my fault\n");
+               pr_info("sorry, was my fault\n");
 
        err = misc_register(&cpu5wdt_misc);
        if (err < 0) {
-               printk(KERN_ERR PFX "misc_register failed\n");
+               pr_err("misc_register failed\n");
                goto no_misc;
        }
 
 
-       printk(KERN_INFO PFX "init success\n");
+       pr_info("init success\n");
        return 0;
 
 no_misc:
index 1b793df..95b1b95 100644 (file)
@@ -14,6 +14,8 @@
  * Copyright (C) 2008 David S. Miller <davem@davemloft.net>
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/fs.h>
@@ -35,7 +37,6 @@
 #include <asm/watchdog.h>
 
 #define DRIVER_NAME    "cpwd"
-#define PFX            DRIVER_NAME ": "
 
 #define WD_OBPNAME     "watchdog"
 #define WD_BADMODEL    "SUNW,501-5336"
@@ -385,8 +386,7 @@ static int cpwd_open(struct inode *inode, struct file *f)
        if (!p->initialized) {
                if (request_irq(p->irq, &cpwd_interrupt,
                                IRQF_SHARED, DRIVER_NAME, p)) {
-                       printk(KERN_ERR PFX "Cannot register IRQ %d\n",
-                               p->irq);
+                       pr_err("Cannot register IRQ %d\n", p->irq);
                        mutex_unlock(&cpwd_mutex);
                        return -EBUSY;
                }
@@ -542,7 +542,7 @@ static int __devinit cpwd_probe(struct platform_device *op)
        p = kzalloc(sizeof(*p), GFP_KERNEL);
        err = -ENOMEM;
        if (!p) {
-               printk(KERN_ERR PFX "Unable to allocate struct cpwd.\n");
+               pr_err("Unable to allocate struct cpwd\n");
                goto out;
        }
 
@@ -553,14 +553,14 @@ static int __devinit cpwd_probe(struct platform_device *op)
        p->regs = of_ioremap(&op->resource[0], 0,
                             4 * WD_TIMER_REGSZ, DRIVER_NAME);
        if (!p->regs) {
-               printk(KERN_ERR PFX "Unable to map registers.\n");
+               pr_err("Unable to map registers\n");
                goto out_free;
        }
 
        options = of_find_node_by_path("/options");
        err = -ENODEV;
        if (!options) {
-               printk(KERN_ERR PFX "Unable to find /options node.\n");
+               pr_err("Unable to find /options node\n");
                goto out_iounmap;
        }
 
@@ -605,8 +605,8 @@ static int __devinit cpwd_probe(struct platform_device *op)
 
                err = misc_register(&p->devs[i].misc);
                if (err) {
-                       printk(KERN_ERR "Could not register misc device for "
-                              "dev %d\n", i);
+                       pr_err("Could not register misc device for dev %d\n",
+                              i);
                        goto out_unregister;
                }
        }
@@ -617,8 +617,8 @@ static int __devinit cpwd_probe(struct platform_device *op)
                cpwd_timer.data         = (unsigned long) p;
                cpwd_timer.expires      = WD_BTIMEOUT;
 
-               printk(KERN_INFO PFX "PLD defect workaround enabled for "
-                      "model " WD_BADMODEL ".\n");
+               pr_info("PLD defect workaround enabled for model %s\n",
+                       WD_BADMODEL);
        }
 
        dev_set_drvdata(&op->dev, p);
index 63d7b58..06de121 100644 (file)
@@ -16,7 +16,8 @@
  * If we receive an expected close for the watchdog then we keep the timer
  * running, otherwise the timer is stopped and the watchdog will expire.
  */
-#define pr_fmt(fmt) "dw_wdt: " fmt
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/bitops.h>
 #include <linux/clk.h>
@@ -45,8 +46,8 @@
 /* The maximum TOP (timeout period) value that can be set in the watchdog. */
 #define DW_WDT_MAX_TOP         15
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
                 "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
index 09cd888..7705003 100644 (file)
@@ -8,6 +8,9 @@
  * Authors: Ray Lehtiniemi <rayl@mail.com>,
  *     Alessandro Zummo <a.zummo@towertech.it>
  *
+ * Copyright (c) 2012 H Hartley Sweeten <hsweeten@visionengravers.com>
+ *     Convert to a platform device and use the watchdog framework API
+ *
  * 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/platform_device.h>
 #include <linux/module.h>
-#include <linux/fs.h>
 #include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include <linux/timer.h>
-#include <linux/uaccess.h>
 #include <linux/io.h>
 
-#define WDT_VERSION    "0.3"
-#define PFX            "ep93xx_wdt: "
+#define WDT_VERSION    "0.4"
 
 /* default timeout (secs) */
 #define WDT_TIMEOUT 30
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-static int timeout = WDT_TIMEOUT;
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
+
+static unsigned int timeout = WDT_TIMEOUT;
+module_param(timeout, uint, 0);
+MODULE_PARM_DESC(timeout,
+       "Watchdog timeout in seconds. (1<=timeout<=3600, default="
+                               __MODULE_STRING(WDT_TIMEOUT) ")");
 
 static void __iomem *mmio_base;
 static struct timer_list timer;
 static unsigned long next_heartbeat;
-static unsigned long wdt_status;
-static unsigned long boot_status;
-
-#define WDT_IN_USE             0
-#define WDT_OK_TO_CLOSE                1
 
 #define EP93XX_WATCHDOG                0x00
 #define EP93XX_WDSTATUS                0x04
 
-/* reset the wdt every ~200ms */
+/* reset the wdt every ~200ms - the heartbeat of the device is 0.250 seconds*/
 #define WDT_INTERVAL (HZ/5)
 
-static void wdt_enable(void)
+static void ep93xx_wdt_timer_ping(unsigned long data)
 {
-       writel(0xaaaa, mmio_base + EP93XX_WATCHDOG);
-}
-
-static void wdt_disable(void)
-{
-       writel(0xaa55, mmio_base + EP93XX_WATCHDOG);
-}
+       if (time_before(jiffies, next_heartbeat))
+               writel(0x5555, mmio_base + EP93XX_WATCHDOG);
 
-static inline void wdt_ping(void)
-{
-       writel(0x5555, mmio_base + EP93XX_WATCHDOG);
+       /* Re-set the timer interval */
+       mod_timer(&timer, jiffies + WDT_INTERVAL);
 }
 
-static void wdt_startup(void)
+static int ep93xx_wdt_start(struct watchdog_device *wdd)
 {
        next_heartbeat = jiffies + (timeout * HZ);
 
-       wdt_enable();
+       writel(0xaaaa, mmio_base + EP93XX_WATCHDOG);
        mod_timer(&timer, jiffies + WDT_INTERVAL);
+
+       return 0;
 }
 
-static void wdt_shutdown(void)
+static int ep93xx_wdt_stop(struct watchdog_device *wdd)
 {
        del_timer_sync(&timer);
-       wdt_disable();
+       writel(0xaa55, mmio_base + EP93XX_WATCHDOG);
+
+       return 0;
 }
 
-static void wdt_keepalive(void)
+static int ep93xx_wdt_keepalive(struct watchdog_device *wdd)
 {
        /* user land ping */
        next_heartbeat = jiffies + (timeout * HZ);
-}
-
-static int ep93xx_wdt_open(struct inode *inode, struct file *file)
-{
-       if (test_and_set_bit(WDT_IN_USE, &wdt_status))
-               return -EBUSY;
-
-       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
-
-       wdt_startup();
-
-       return nonseekable_open(inode, file);
-}
-
-static ssize_t
-ep93xx_wdt_write(struct file *file, const char __user *data, size_t len,
-                loff_t *ppos)
-{
-       if (len) {
-               if (!nowayout) {
-                       size_t i;
-
-                       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
-
-                       for (i = 0; i != len; i++) {
-                               char c;
-
-                               if (get_user(c, data + i))
-                                       return -EFAULT;
-
-                               if (c == 'V')
-                                       set_bit(WDT_OK_TO_CLOSE, &wdt_status);
-                               else
-                                       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
-                       }
-               }
-               wdt_keepalive();
-       }
 
-       return len;
+       return 0;
 }
 
-static const struct watchdog_info ident = {
-       .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE,
-       .identity = "EP93xx Watchdog",
+static const struct watchdog_info ep93xx_wdt_ident = {
+       .options        = WDIOF_CARDRESET |
+                         WDIOF_MAGICCLOSE |
+                         WDIOF_KEEPALIVEPING,
+       .identity       = "EP93xx Watchdog",
 };
 
-static long ep93xx_wdt_ioctl(struct file *file,
-                                       unsigned int cmd, unsigned long arg)
-{
-       int ret = -ENOTTY;
-
-       switch (cmd) {
-       case WDIOC_GETSUPPORT:
-               ret = copy_to_user((struct watchdog_info __user *)arg, &ident,
-                               sizeof(ident)) ? -EFAULT : 0;
-               break;
-
-       case WDIOC_GETSTATUS:
-               ret = put_user(0, (int __user *)arg);
-               break;
-
-       case WDIOC_GETBOOTSTATUS:
-               ret = put_user(boot_status, (int __user *)arg);
-               break;
-
-       case WDIOC_KEEPALIVE:
-               wdt_keepalive();
-               ret = 0;
-               break;
-
-       case WDIOC_GETTIMEOUT:
-               /* actually, it is 0.250 seconds.... */
-               ret = put_user(1, (int __user *)arg);
-               break;
-       }
-       return ret;
-}
-
-static int ep93xx_wdt_release(struct inode *inode, struct file *file)
-{
-       if (test_bit(WDT_OK_TO_CLOSE, &wdt_status))
-               wdt_shutdown();
-       else
-               printk(KERN_CRIT PFX
-                       "Device closed unexpectedly - timer will not stop\n");
-
-       clear_bit(WDT_IN_USE, &wdt_status);
-       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
-
-       return 0;
-}
-
-static const struct file_operations ep93xx_wdt_fops = {
+static struct watchdog_ops ep93xx_wdt_ops = {
        .owner          = THIS_MODULE,
-       .write          = ep93xx_wdt_write,
-       .unlocked_ioctl = ep93xx_wdt_ioctl,
-       .open           = ep93xx_wdt_open,
-       .release        = ep93xx_wdt_release,
-       .llseek         = no_llseek,
+       .start          = ep93xx_wdt_start,
+       .stop           = ep93xx_wdt_stop,
+       .ping           = ep93xx_wdt_keepalive,
 };
 
-static struct miscdevice ep93xx_wdt_miscdev = {
-       .minor          = WATCHDOG_MINOR,
-       .name           = "watchdog",
-       .fops           = &ep93xx_wdt_fops,
+static struct watchdog_device ep93xx_wdt_wdd = {
+       .info           = &ep93xx_wdt_ident,
+       .ops            = &ep93xx_wdt_ops,
 };
 
-static void ep93xx_timer_ping(unsigned long data)
-{
-       if (time_before(jiffies, next_heartbeat))
-               wdt_ping();
-
-       /* Re-set the timer interval */
-       mod_timer(&timer, jiffies + WDT_INTERVAL);
-}
-
 static int __devinit ep93xx_wdt_probe(struct platform_device *pdev)
 {
        struct resource *res;
@@ -224,30 +130,35 @@ static int __devinit ep93xx_wdt_probe(struct platform_device *pdev)
        if (!mmio_base)
                return -ENXIO;
 
-       err = misc_register(&ep93xx_wdt_miscdev);
-
-       val = readl(mmio_base + EP93XX_WATCHDOG);
-       boot_status = val & 0x01 ? 1 : 0;
-
-       printk(KERN_INFO PFX "EP93XX watchdog, driver version "
-               WDT_VERSION "%s\n",
-               (val & 0x08) ? " (nCS1 disable detected)" : "");
-
        if (timeout < 1 || timeout > 3600) {
                timeout = WDT_TIMEOUT;
-               printk(KERN_INFO PFX
+               dev_warn(&pdev->dev,
                        "timeout value must be 1<=x<=3600, using %d\n",
                        timeout);
        }
 
-       setup_timer(&timer, ep93xx_timer_ping, 1);
-       return err;
+       val = readl(mmio_base + EP93XX_WATCHDOG);
+       ep93xx_wdt_wdd.bootstatus = (val & 0x01) ? WDIOF_CARDRESET : 0;
+       ep93xx_wdt_wdd.timeout = timeout;
+
+       watchdog_set_nowayout(&ep93xx_wdt_wdd, nowayout);
+
+       setup_timer(&timer, ep93xx_wdt_timer_ping, 1);
+
+       err = watchdog_register_device(&ep93xx_wdt_wdd);
+       if (err)
+               return err;
+
+       dev_info(&pdev->dev,
+               "EP93XX watchdog, driver version " WDT_VERSION "%s\n",
+               (val & 0x08) ? " (nCS1 disable detected)" : "");
+
+       return 0;
 }
 
 static int __devexit ep93xx_wdt_remove(struct platform_device *pdev)
 {
-       wdt_shutdown();
-       misc_deregister(&ep93xx_wdt_miscdev);
+       watchdog_unregister_device(&ep93xx_wdt_wdd);
        return 0;
 }
 
@@ -262,16 +173,9 @@ static struct platform_driver ep93xx_wdt_driver = {
 
 module_platform_driver(ep93xx_wdt_driver);
 
-module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
-
-module_param(timeout, int, 0);
-MODULE_PARM_DESC(timeout,
-       "Watchdog timeout in seconds. (1<=timeout<=3600, default="
-                               __MODULE_STRING(WDT_TIMEOUT) ")");
-
 MODULE_AUTHOR("Ray Lehtiniemi <rayl@mail.com>,"
-               "Alessandro Zummo <a.zummo@towertech.it>");
+               "Alessandro Zummo <a.zummo@towertech.it>,"
+               "H Hartley Sweeten <hsweeten@visionengravers.com>");
 MODULE_DESCRIPTION("EP93xx Watchdog");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(WDT_VERSION);
index 3946c51..cd31b8a 100644 (file)
@@ -45,6 +45,8 @@
  *     of the on-board SUPER I/O device SMSC FDC 37B782.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
@@ -59,7 +61,6 @@
 #include <linux/io.h>
 #include <linux/uaccess.h>
 
-#include <asm/system.h>
 
 static unsigned long eurwdt_is_open;
 static int eurwdt_timeout;
@@ -76,8 +77,8 @@ static char *ev = "int";
 
 #define WDT_TIMEOUT            60                /* 1 minute */
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -144,11 +145,11 @@ static void eurwdt_activate_timer(void)
 
        /* Setting interrupt line */
        if (irq == 2 || irq > 15 || irq < 0) {
-               printk(KERN_ERR ": invalid irq number\n");
+               pr_err("invalid irq number\n");
                irq = 0;        /* if invalid we disable interrupt */
        }
        if (irq == 0)
-               printk(KERN_INFO ": interrupt disabled\n");
+               pr_info("interrupt disabled\n");
 
        eurwdt_write_reg(WDT_TIMER_CFG, irq << 4);
 
@@ -163,12 +164,12 @@ static void eurwdt_activate_timer(void)
 
 static irqreturn_t eurwdt_interrupt(int irq, void *dev_id)
 {
-       printk(KERN_CRIT "timeout WDT timeout\n");
+       pr_crit("timeout WDT timeout\n");
 
 #ifdef ONLY_TESTING
-       printk(KERN_CRIT "Would Reboot.\n");
+       pr_crit("Would Reboot\n");
 #else
-       printk(KERN_CRIT "Initiating system reboot.\n");
+       pr_crit("Initiating system reboot\n");
        emergency_restart();
 #endif
        return IRQ_HANDLED;
@@ -335,8 +336,7 @@ static int eurwdt_release(struct inode *inode, struct file *file)
        if (eur_expect_close == 42)
                eurwdt_disable_timer();
        else {
-               printk(KERN_CRIT
-                       "eurwdt: Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
                eurwdt_ping();
        }
        clear_bit(0, &eurwdt_is_open);
@@ -429,35 +429,32 @@ static int __init eurwdt_init(void)
 
        ret = request_irq(irq, eurwdt_interrupt, 0, "eurwdt", NULL);
        if (ret) {
-               printk(KERN_ERR "eurwdt: IRQ %d is not free.\n", irq);
+               pr_err("IRQ %d is not free\n", irq);
                goto out;
        }
 
        if (!request_region(io, 2, "eurwdt")) {
-               printk(KERN_ERR "eurwdt: IO %X is not free.\n", io);
+               pr_err("IO %X is not free\n", io);
                ret = -EBUSY;
                goto outirq;
        }
 
        ret = register_reboot_notifier(&eurwdt_notifier);
        if (ret) {
-               printk(KERN_ERR
-                   "eurwdt: can't register reboot notifier (err=%d)\n", ret);
+               pr_err("can't register reboot notifier (err=%d)\n", ret);
                goto outreg;
        }
 
        ret = misc_register(&eurwdt_miscdev);
        if (ret) {
-               printk(KERN_ERR "eurwdt: can't misc_register on minor=%d\n",
-               WATCHDOG_MINOR);
+               pr_err("can't misc_register on minor=%d\n", WATCHDOG_MINOR);
                goto outreboot;
        }
 
        eurwdt_unlock_chip();
 
        ret = 0;
-       printk(KERN_INFO "Eurotech WDT driver 0.01 at %X (Interrupt %d)"
-               " - timeout event: %s\n",
+       pr_info("Eurotech WDT driver 0.01 at %X (Interrupt %d) - timeout event: %s\n",
                io, irq, (!strcmp("int", ev) ? "int" : "reboot"));
 
 out:
index e45ca2b..c65b0a5 100644 (file)
@@ -19,6 +19,8 @@
  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  ***************************************************************************/
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/err.h>
 #include <linux/fs.h>
 #include <linux/init.h>
@@ -189,8 +191,7 @@ static inline int superio_enter(int base)
 {
        /* Don't step on other drivers' I/O space by accident */
        if (!request_muxed_region(base, 2, DRVNAME)) {
-               printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n",
-                               (int)base);
+               pr_err("I/O address 0x%04x already in use\n", (int)base);
                return -EBUSY;
        }
 
@@ -217,7 +218,7 @@ static int watchdog_set_timeout(int timeout)
 {
        if (timeout <= 0
         || timeout >  max_timeout) {
-               printk(KERN_ERR DRVNAME ": watchdog timeout out of range\n");
+               pr_err("watchdog timeout out of range\n");
                return -EINVAL;
        }
 
@@ -252,7 +253,7 @@ static int watchdog_set_pulse_width(unsigned int pw)
        } else if (pw <= 5000) {
                watchdog.pulse_val = 3;
        } else {
-               printk(KERN_ERR DRVNAME ": pulse width out of range\n");
+               pr_err("pulse width out of range\n");
                err = -EINVAL;
                goto exit_unlock;
        }
@@ -309,8 +310,7 @@ static int f71862fg_pin_configure(unsigned short ioaddr)
                if (ioaddr)
                        superio_set_bit(ioaddr, SIO_REG_MFUNCT1, 1);
        } else {
-               printk(KERN_ERR DRVNAME ": Invalid argument f71862fg_pin=%d\n",
-                               f71862fg_pin);
+               pr_err("Invalid argument f71862fg_pin=%d\n", f71862fg_pin);
                return -EINVAL;
        }
        return 0;
@@ -487,8 +487,7 @@ static int watchdog_release(struct inode *inode, struct file *file)
 
        if (!watchdog.expect_close) {
                watchdog_keepalive();
-               printk(KERN_CRIT DRVNAME
-                       ": Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
        } else if (!nowayout) {
                watchdog_stop();
        }
@@ -672,25 +671,22 @@ static int __init watchdog_init(int sioaddr)
 
        err = misc_register(&watchdog_miscdev);
        if (err) {
-               printk(KERN_ERR DRVNAME
-                       ": cannot register miscdev on minor=%d\n",
-                               watchdog_miscdev.minor);
+               pr_err("cannot register miscdev on minor=%d\n",
+                      watchdog_miscdev.minor);
                goto exit_reboot;
        }
 
        if (start_withtimeout) {
                if (start_withtimeout <= 0
                 || start_withtimeout >  max_timeout) {
-                       printk(KERN_ERR DRVNAME
-                               ": starting timeout out of range\n");
+                       pr_err("starting timeout out of range\n");
                        err = -EINVAL;
                        goto exit_miscdev;
                }
 
                err = watchdog_start();
                if (err) {
-                       printk(KERN_ERR DRVNAME
-                               ": cannot start watchdog timer\n");
+                       pr_err("cannot start watchdog timer\n");
                        goto exit_miscdev;
                }
 
@@ -720,8 +716,7 @@ static int __init watchdog_init(int sioaddr)
                if (nowayout)
                        __module_get(THIS_MODULE);
 
-               printk(KERN_INFO DRVNAME
-                       ": watchdog started with initial timeout of %u sec\n",
+               pr_info("watchdog started with initial timeout of %u sec\n",
                        start_withtimeout);
        }
 
@@ -746,7 +741,7 @@ static int __init f71808e_find(int sioaddr)
 
        devid = superio_inw(sioaddr, SIO_REG_MANID);
        if (devid != SIO_FINTEK_ID) {
-               pr_debug(DRVNAME ": Not a Fintek device\n");
+               pr_debug("Not a Fintek device\n");
                err = -ENODEV;
                goto exit;
        }
@@ -774,13 +769,13 @@ static int __init f71808e_find(int sioaddr)
                err = -ENODEV;
                goto exit;
        default:
-               printk(KERN_INFO DRVNAME ": Unrecognized Fintek device: %04x\n",
-                      (unsigned int)devid);
+               pr_info("Unrecognized Fintek device: %04x\n",
+                       (unsigned int)devid);
                err = -ENODEV;
                goto exit;
        }
 
-       printk(KERN_INFO DRVNAME ": Found %s watchdog chip, revision %d\n",
+       pr_info("Found %s watchdog chip, revision %d\n",
                f71808e_names[watchdog.type],
                (int)superio_inb(sioaddr, SIO_REG_DEVREV));
 exit:
@@ -808,8 +803,7 @@ static int __init f71808e_init(void)
 static void __exit f71808e_exit(void)
 {
        if (watchdog_is_running()) {
-               printk(KERN_WARNING DRVNAME
-                       ": Watchdog timer still running, stopping it\n");
+               pr_warn("Watchdog timer still running, stopping it\n");
                watchdog_stop();
        }
        misc_deregister(&watchdog_miscdev);
index b146082..17f4cae 100644 (file)
@@ -24,6 +24,8 @@
  * capabilities) a kernel-based watchdog.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/compiler.h>
 #include <linux/init.h>
@@ -68,8 +70,8 @@ static unsigned int bus_clk;
 static char expect_close;
 static DEFINE_SPINLOCK(gef_wdt_spinlock);
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
        __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
@@ -110,7 +112,7 @@ static void gef_wdt_handler_enable(void)
        if (gef_wdt_toggle_wdc(GEF_WDC_ENABLED_FALSE,
                                   GEF_WDC_ENABLE_SHIFT)) {
                gef_wdt_service();
-               printk(KERN_NOTICE "gef_wdt: watchdog activated\n");
+               pr_notice("watchdog activated\n");
        }
 }
 
@@ -118,7 +120,7 @@ static void gef_wdt_handler_disable(void)
 {
        if (gef_wdt_toggle_wdc(GEF_WDC_ENABLED_TRUE,
                                   GEF_WDC_ENABLE_SHIFT))
-               printk(KERN_NOTICE "gef_wdt: watchdog deactivated\n");
+               pr_notice("watchdog deactivated\n");
 }
 
 static void gef_wdt_set_timeout(unsigned int timeout)
@@ -234,8 +236,7 @@ static int gef_wdt_release(struct inode *inode, struct file *file)
        if (expect_close == 42)
                gef_wdt_handler_disable();
        else {
-               printk(KERN_CRIT
-                      "gef_wdt: unexpected close, not stopping timer!\n");
+               pr_crit("unexpected close, not stopping timer!\n");
                gef_wdt_service();
        }
        expect_close = 0;
@@ -313,7 +314,7 @@ static struct platform_driver gef_wdt_driver = {
 
 static int __init gef_wdt_init(void)
 {
-       printk(KERN_INFO "GE watchdog driver\n");
+       pr_info("GE watchdog driver\n");
        return platform_driver_register(&gef_wdt_driver);
 }
 
index 9b49b12..dc563b6 100644 (file)
@@ -9,6 +9,7 @@
  * 2 of the License, or (at your option) any later version.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/module.h>
 #include <linux/moduleparam.h>
@@ -39,8 +40,8 @@ MODULE_PARM_DESC(timeout,
        "Watchdog timeout in seconds. 1<= timeout <=131, default="
                                __MODULE_STRING(WATCHDOG_TIMEOUT) ".");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
        "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -100,7 +101,7 @@ static int geodewdt_release(struct inode *inode, struct file *file)
                geodewdt_disable();
                module_put(THIS_MODULE);
        } else {
-               printk(KERN_CRIT "Unexpected close - watchdog is not stopping.\n");
+               pr_crit("Unexpected close - watchdog is not stopping\n");
                geodewdt_ping();
 
                set_bit(WDT_FLAGS_ORPHAN, &wdt_flags);
@@ -220,7 +221,7 @@ static int __devinit geodewdt_probe(struct platform_device *dev)
 
        wdt_timer = cs5535_mfgpt_alloc_timer(MFGPT_TIMER_ANY, MFGPT_DOMAIN_WORKING);
        if (!wdt_timer) {
-               printk(KERN_ERR "geodewdt:  No timers were available\n");
+               pr_err("No timers were available\n");
                return -ENODEV;
        }
 
index 3c166d3..cbc7cee 100644 (file)
@@ -13,6 +13,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/device.h>
 #include <linux/fs.h>
 #include <linux/init.h>
@@ -45,7 +47,7 @@
 
 static unsigned int soft_margin = DEFAULT_MARGIN;      /* in seconds */
 static unsigned int reload;                    /* the computed soft_margin */
-static int nowayout = WATCHDOG_NOWAYOUT;
+static bool nowayout = WATCHDOG_NOWAYOUT;
 static char expect_release;
 static unsigned long hpwdt_is_open;
 
@@ -235,8 +237,7 @@ static int __devinit cru_detect(unsigned long map_entry,
        asminline_call(&cmn_regs, bios32_entrypoint);
 
        if (cmn_regs.u1.ral != 0) {
-               printk(KERN_WARNING
-                       "hpwdt: Call succeeded but with an error: 0x%x\n",
+               pr_warn("Call succeeded but with an error: 0x%x\n",
                        cmn_regs.u1.ral);
        } else {
                physical_bios_base = cmn_regs.u2.rebx;
@@ -256,14 +257,10 @@ static int __devinit cru_detect(unsigned long map_entry,
                        }
                }
 
-               printk(KERN_DEBUG "hpwdt: CRU Base Address:   0x%lx\n",
-                       physical_bios_base);
-               printk(KERN_DEBUG "hpwdt: CRU Offset Address: 0x%lx\n",
-                       physical_bios_offset);
-               printk(KERN_DEBUG "hpwdt: CRU Length:         0x%lx\n",
-                       cru_length);
-               printk(KERN_DEBUG "hpwdt: CRU Mapped Address: %p\n",
-                       &cru_rom_addr);
+               pr_debug("CRU Base Address:   0x%lx\n", physical_bios_base);
+               pr_debug("CRU Offset Address: 0x%lx\n", physical_bios_offset);
+               pr_debug("CRU Length:         0x%lx\n", cru_length);
+               pr_debug("CRU Mapped Address: %p\n", &cru_rom_addr);
        }
        iounmap(bios32_map);
        return retval;
@@ -458,16 +455,13 @@ static void hpwdt_ping(void)
 static int hpwdt_change_timer(int new_margin)
 {
        if (new_margin < 1 || new_margin > HPWDT_MAX_TIMER) {
-               printk(KERN_WARNING
-                       "hpwdt: New value passed in is invalid: %d seconds.\n",
+               pr_warn("New value passed in is invalid: %d seconds\n",
                        new_margin);
                return -EINVAL;
        }
 
        soft_margin = new_margin;
-       printk(KERN_DEBUG
-               "hpwdt: New timer passed in is %d seconds.\n",
-               new_margin);
+       pr_debug("New timer passed in is %d seconds\n", new_margin);
        reload = SECS_TO_TICKS(soft_margin);
 
        return 0;
@@ -535,8 +529,7 @@ static int hpwdt_release(struct inode *inode, struct file *file)
        if (expect_release == 42) {
                hpwdt_stop();
        } else {
-               printk(KERN_CRIT
-                       "hpwdt: Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
                hpwdt_ping();
        }
 
@@ -881,7 +874,7 @@ MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
 module_param(soft_margin, int, 0);
 MODULE_PARM_DESC(soft_margin, "Watchdog timeout in seconds");
 
-module_param(nowayout, int, 0);
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
index db45091..738032a 100644 (file)
@@ -27,6 +27,8 @@
  *      Includes, defines, variables, module parameters, ...
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
@@ -44,7 +46,6 @@
 #define ESB_VERSION "0.05"
 #define ESB_MODULE_NAME "i6300ESB timer"
 #define ESB_DRIVER_NAME ESB_MODULE_NAME ", v" ESB_VERSION
-#define PFX ESB_MODULE_NAME ": "
 
 /* PCI configuration registers */
 #define ESB_CONFIG_REG  0x60            /* Config register                   */
@@ -94,8 +95,8 @@ MODULE_PARM_DESC(heartbeat,
                "Watchdog heartbeat in seconds. (1<heartbeat<2046, default="
                                __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -213,8 +214,7 @@ static int esb_release(struct inode *inode, struct file *file)
        if (esb_expect_close == 42)
                esb_timer_stop();
        else {
-               printk(KERN_CRIT PFX
-                               "Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
                esb_timer_keepalive();
        }
        clear_bit(0, &timer_alive);
@@ -347,19 +347,19 @@ MODULE_DEVICE_TABLE(pci, esb_pci_tbl);
 static unsigned char __devinit esb_getdevice(struct pci_dev *pdev)
 {
        if (pci_enable_device(pdev)) {
-               printk(KERN_ERR PFX "failed to enable device\n");
+               pr_err("failed to enable device\n");
                goto err_devput;
        }
 
        if (pci_request_region(pdev, 0, ESB_MODULE_NAME)) {
-               printk(KERN_ERR PFX "failed to request region\n");
+               pr_err("failed to request region\n");
                goto err_disable;
        }
 
        BASEADDR = pci_ioremap_bar(pdev, 0);
        if (BASEADDR == NULL) {
                /* Something's wrong here, BASEADDR has to be set */
-               printk(KERN_ERR PFX "failed to get BASEADDR\n");
+               pr_err("failed to get BASEADDR\n");
                goto err_release;
        }
 
@@ -397,7 +397,7 @@ static void __devinit esb_initdevice(void)
        /* Check that the WDT isn't already locked */
        pci_read_config_byte(esb_pci, ESB_LOCK_REG, &val1);
        if (val1 & ESB_WDT_LOCK)
-               printk(KERN_WARNING PFX "nowayout already set\n");
+               pr_warn("nowayout already set\n");
 
        /* Set the timer to watchdog mode and disable it for now */
        pci_write_config_byte(esb_pci, ESB_LOCK_REG, 0x00);
@@ -423,11 +423,11 @@ static int __devinit esb_probe(struct pci_dev *pdev,
 
        cards_found++;
        if (cards_found == 1)
-               printk(KERN_INFO PFX "Intel 6300ESB WatchDog Timer Driver v%s\n",
+               pr_info("Intel 6300ESB WatchDog Timer Driver v%s\n",
                        ESB_VERSION);
 
        if (cards_found > 1) {
-               printk(KERN_ERR PFX "This driver only supports 1 device\n");
+               pr_err("This driver only supports 1 device\n");
                return -ENODEV;
        }
 
@@ -439,9 +439,8 @@ static int __devinit esb_probe(struct pci_dev *pdev,
           if not reset to the default */
        if (heartbeat < 0x1 || heartbeat > 2 * 0x03ff) {
                heartbeat = WATCHDOG_HEARTBEAT;
-               printk(KERN_INFO PFX
-                       "heartbeat value must be 1<heartbeat<2046, using %d\n",
-                                                               heartbeat);
+               pr_info("heartbeat value must be 1<heartbeat<2046, using %d\n",
+                       heartbeat);
        }
 
        /* Initialize the watchdog and make sure it does not run */
@@ -450,14 +449,12 @@ static int __devinit esb_probe(struct pci_dev *pdev,
        /* Register the watchdog so that userspace has access to it */
        ret = misc_register(&esb_miscdev);
        if (ret != 0) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                                                       WATCHDOG_MINOR, ret);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      WATCHDOG_MINOR, ret);
                goto err_unmap;
        }
-       printk(KERN_INFO PFX
-               "initialized (0x%p). heartbeat=%d sec (nowayout=%d)\n",
-                                               BASEADDR, heartbeat, nowayout);
+       pr_info("initialized (0x%p). heartbeat=%d sec (nowayout=%d)\n",
+               BASEADDR, heartbeat, nowayout);
        return 0;
 
 err_unmap:
@@ -503,7 +500,7 @@ static int __init watchdog_init(void)
 static void __exit watchdog_cleanup(void)
 {
        pci_unregister_driver(&esb_driver);
-       printk(KERN_INFO PFX "Watchdog Module Unloaded.\n");
+       pr_info("Watchdog Module Unloaded\n");
 }
 
 module_init(watchdog_init);
index 481d1ad..2721d29 100644 (file)
  *     Includes, defines, variables, module parameters, ...
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 /* Module and version information */
 #define DRV_NAME       "iTCO_vendor_support"
 #define DRV_VERSION    "1.04"
-#define PFX            DRV_NAME ": "
 
 /* Includes */
 #include <linux/module.h>              /* For module specific items */
@@ -355,13 +356,13 @@ EXPORT_SYMBOL(iTCO_vendor_check_noreboot_on);
 
 static int __init iTCO_vendor_init_module(void)
 {
-       printk(KERN_INFO PFX "vendor-support=%d\n", vendorsupport);
+       pr_info("vendor-support=%d\n", vendorsupport);
        return 0;
 }
 
 static void __exit iTCO_vendor_exit_module(void)
 {
-       printk(KERN_INFO PFX "Module Unloaded\n");
+       pr_info("Module Unloaded\n");
 }
 
 module_init(iTCO_vendor_init_module);
index bdf401b..9fecb95 100644 (file)
  *     Includes, defines, variables, module parameters, ...
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 /* Module and version information */
 #define DRV_NAME       "iTCO_wdt"
 #define DRV_VERSION    "1.07"
-#define PFX            DRV_NAME ": "
 
 /* Includes */
 #include <linux/module.h>              /* For module specific items */
@@ -413,8 +414,8 @@ MODULE_PARM_DESC(heartbeat, "Watchdog timeout in seconds. "
        "5..76 (TCO v1) or 3..614 (TCO v2), default="
                                __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
        "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -489,8 +490,7 @@ static int iTCO_wdt_start(void)
        /* disable chipset's NO_REBOOT bit */
        if (iTCO_wdt_unset_NO_REBOOT_bit()) {
                spin_unlock(&iTCO_wdt_private.io_lock);
-               printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, "
-                                       "reboot disabled by hardware/BIOS\n");
+               pr_err("failed to reset NO_REBOOT flag, reboot disabled by hardware/BIOS\n");
                return -EIO;
        }
 
@@ -661,8 +661,7 @@ static int iTCO_wdt_release(struct inode *inode, struct file *file)
        if (expect_release == 42) {
                iTCO_wdt_stop();
        } else {
-               printk(KERN_CRIT PFX
-                       "Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
                iTCO_wdt_keepalive();
        }
        clear_bit(0, &is_active);
@@ -804,8 +803,7 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
        base_address &= 0x0000ff80;
        if (base_address == 0x00000000) {
                /* Something's wrong here, ACPIBASE has to be set */
-               printk(KERN_ERR PFX "failed to get TCOBASE address, "
-                                       "device disabled by hardware/BIOS\n");
+               pr_err("failed to get TCOBASE address, device disabled by hardware/BIOS\n");
                return -ENODEV;
        }
        iTCO_wdt_private.iTCO_version =
@@ -820,8 +818,7 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
        if (iTCO_wdt_private.iTCO_version == 2) {
                pci_read_config_dword(pdev, 0xf0, &base_address);
                if ((base_address & 1) == 0) {
-                       printk(KERN_ERR PFX "RCBA is disabled by hardware"
-                                               "/BIOS, device disabled\n");
+                       pr_err("RCBA is disabled by hardware/BIOS, device disabled\n");
                        ret = -ENODEV;
                        goto out;
                }
@@ -831,8 +828,7 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
 
        /* Check chipset's NO_REBOOT bit */
        if (iTCO_wdt_unset_NO_REBOOT_bit() && iTCO_vendor_check_noreboot_on()) {
-               printk(KERN_INFO PFX "unable to reset NO_REBOOT flag, "
-                                       "device disabled by hardware/BIOS\n");
+               pr_info("unable to reset NO_REBOOT flag, device disabled by hardware/BIOS\n");
                ret = -ENODEV;  /* Cannot reset NO_REBOOT bit */
                goto out_unmap;
        }
@@ -842,9 +838,8 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
 
        /* The TCO logic uses the TCO_EN bit in the SMI_EN register */
        if (!request_region(SMI_EN, 4, "iTCO_wdt")) {
-               printk(KERN_ERR PFX
-                       "I/O address 0x%04lx already in use, "
-                                               "device disabled\n", SMI_EN);
+               pr_err("I/O address 0x%04lx already in use, device disabled\n",
+                      SMI_EN);
                ret = -EIO;
                goto out_unmap;
        }
@@ -858,17 +853,16 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
        /* The TCO I/O registers reside in a 32-byte range pointed to
           by the TCOBASE value */
        if (!request_region(TCOBASE, 0x20, "iTCO_wdt")) {
-               printk(KERN_ERR PFX "I/O address 0x%04lx already in use "
-                                               "device disabled\n", TCOBASE);
+               pr_err("I/O address 0x%04lx already in use, device disabled\n",
+                      TCOBASE);
                ret = -EIO;
                goto unreg_smi_en;
        }
 
-       printk(KERN_INFO PFX
-               "Found a %s TCO device (Version=%d, TCOBASE=0x%04lx)\n",
-                       iTCO_chipset_info[ent->driver_data].name,
-                       iTCO_chipset_info[ent->driver_data].iTCO_version,
-                       TCOBASE);
+       pr_info("Found a %s TCO device (Version=%d, TCOBASE=0x%04lx)\n",
+               iTCO_chipset_info[ent->driver_data].name,
+               iTCO_chipset_info[ent->driver_data].iTCO_version,
+               TCOBASE);
 
        /* Clear out the (probably old) status */
        outw(0x0008, TCO1_STS); /* Clear the Time Out Status bit */
@@ -882,20 +876,18 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
           if not reset to the default */
        if (iTCO_wdt_set_heartbeat(heartbeat)) {
                iTCO_wdt_set_heartbeat(WATCHDOG_HEARTBEAT);
-               printk(KERN_INFO PFX
-                       "timeout value out of range, using %d\n", heartbeat);
+               pr_info("timeout value out of range, using %d\n", heartbeat);
        }
 
        ret = misc_register(&iTCO_wdt_miscdev);
        if (ret != 0) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                                                       WATCHDOG_MINOR, ret);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      WATCHDOG_MINOR, ret);
                goto unreg_region;
        }
 
-       printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n",
-                                                       heartbeat, nowayout);
+       pr_info("initialized. heartbeat=%d sec (nowayout=%d)\n",
+               heartbeat, nowayout);
 
        return 0;
 
@@ -947,7 +939,7 @@ static int __devinit iTCO_wdt_probe(struct platform_device *dev)
        }
 
        if (!found)
-               printk(KERN_INFO PFX "No device detected.\n");
+               pr_info("No device detected\n");
 
        return ret;
 }
@@ -979,8 +971,7 @@ static int __init iTCO_wdt_init_module(void)
 {
        int err;
 
-       printk(KERN_INFO PFX "Intel TCO WatchDog Timer Driver v%s\n",
-               DRV_VERSION);
+       pr_info("Intel TCO WatchDog Timer Driver v%s\n", DRV_VERSION);
 
        err = platform_driver_register(&iTCO_wdt_driver);
        if (err)
@@ -1004,7 +995,7 @@ static void __exit iTCO_wdt_cleanup_module(void)
 {
        platform_device_unregister(iTCO_wdt_platform_device);
        platform_driver_unregister(&iTCO_wdt_driver);
-       printk(KERN_INFO PFX "Watchdog Module Unloaded.\n");
+       pr_info("Watchdog Module Unloaded\n");
 }
 
 module_init(iTCO_wdt_init_module);
index 0149d8d..184c0bf 100644 (file)
@@ -31,6 +31,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/miscdevice.h>
@@ -44,7 +46,6 @@
 #include <linux/io.h>
 #include <linux/uaccess.h>
 
-#include <asm/system.h>
 
 static struct platform_device *ibwdt_platform_device;
 static unsigned long ibwdt_is_open;
@@ -53,7 +54,6 @@ static char expect_close;
 
 /* Module information */
 #define DRV_NAME "ib700wdt"
-#define PFX DRV_NAME ": "
 
 /*
  *
@@ -102,8 +102,8 @@ MODULE_PARM_DESC(timeout,
        "Watchdog timeout in seconds. 0<= timeout <=30, default="
                __MODULE_STRING(WATCHDOG_TIMEOUT) ".");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -246,8 +246,7 @@ static int ibwdt_close(struct inode *inode, struct file *file)
        if (expect_close == 42) {
                ibwdt_disable();
        } else {
-               printk(KERN_CRIT PFX
-                    "WDT device closed unexpectedly.  WDT will not stop!\n");
+               pr_crit("WDT device closed unexpectedly.  WDT will not stop!\n");
                ibwdt_ping();
        }
        clear_bit(0, &ibwdt_is_open);
@@ -284,16 +283,14 @@ static int __devinit ibwdt_probe(struct platform_device *dev)
 
 #if WDT_START != WDT_STOP
        if (!request_region(WDT_STOP, 1, "IB700 WDT")) {
-               printk(KERN_ERR PFX "STOP method I/O %X is not available.\n",
-                                                               WDT_STOP);
+               pr_err("STOP method I/O %X is not available\n", WDT_STOP);
                res = -EIO;
                goto out_nostopreg;
        }
 #endif
 
        if (!request_region(WDT_START, 1, "IB700 WDT")) {
-               printk(KERN_ERR PFX "START method I/O %X is not available.\n",
-                                                               WDT_START);
+               pr_err("START method I/O %X is not available\n", WDT_START);
                res = -EIO;
                goto out_nostartreg;
        }
@@ -302,13 +299,12 @@ static int __devinit ibwdt_probe(struct platform_device *dev)
         * if not reset to the default */
        if (ibwdt_set_heartbeat(timeout)) {
                ibwdt_set_heartbeat(WATCHDOG_TIMEOUT);
-               printk(KERN_INFO PFX
-                       "timeout value must be 0<=x<=30, using %d\n", timeout);
+               pr_info("timeout value must be 0<=x<=30, using %d\n", timeout);
        }
 
        res = misc_register(&ibwdt_miscdev);
        if (res) {
-               printk(KERN_ERR PFX "failed to register misc device\n");
+               pr_err("failed to register misc device\n");
                goto out_nomisc;
        }
        return 0;
@@ -353,8 +349,7 @@ static int __init ibwdt_init(void)
 {
        int err;
 
-       printk(KERN_INFO PFX
-               "WDT driver for IB700 single board computer initialising.\n");
+       pr_info("WDT driver for IB700 single board computer initialising\n");
 
        err = platform_driver_register(&ibwdt_driver);
        if (err)
@@ -378,7 +373,7 @@ static void __exit ibwdt_exit(void)
 {
        platform_device_unregister(ibwdt_platform_device);
        platform_driver_unregister(&ibwdt_driver);
-       printk(KERN_INFO PFX "Watchdog Module Unloaded.\n");
+       pr_info("Watchdog Module Unloaded\n");
 }
 
 module_init(ibwdt_init);
index c7481ad..bc3fb8f 100644 (file)
@@ -10,6 +10,8 @@
  * of the GNU Public License, incorporated herein by reference.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/fs.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -31,8 +33,6 @@ enum {
        ASMTYPE_SPRUCE,
 };
 
-#define PFX "ibmasr: "
-
 #define TOPAZ_ASR_REG_OFFSET   4
 #define TOPAZ_ASR_TOGGLE       0x40
 #define TOPAZ_ASR_DISABLE      0x80
@@ -60,7 +60,7 @@ enum {
 #define SPRUCE_ASR_TOGGLE_MASK 0x02    /* bit 0: 0, then 1, then 0 */
 
 
-static int nowayout = WATCHDOG_NOWAYOUT;
+static bool nowayout = WATCHDOG_NOWAYOUT;
 
 static unsigned long asr_is_open;
 static char asr_expect_close;
@@ -234,12 +234,11 @@ static int __init asr_get_base_address(void)
        }
 
        if (!request_region(asr_base, asr_length, "ibmasr")) {
-               printk(KERN_ERR PFX "address %#x already in use\n",
-                       asr_base);
+               pr_err("address %#x already in use\n", asr_base);
                return -EBUSY;
        }
 
-       printk(KERN_INFO PFX "found %sASR @ addr %#x\n", type, asr_base);
+       pr_info("found %sASR @ addr %#x\n", type, asr_base);
 
        return 0;
 }
@@ -332,8 +331,7 @@ static int asr_release(struct inode *inode, struct file *file)
        if (asr_expect_close == 42)
                asr_disable();
        else {
-               printk(KERN_CRIT PFX
-                               "unexpected close, not stopping watchdog!\n");
+               pr_crit("unexpected close, not stopping watchdog!\n");
                asr_toggle();
        }
        clear_bit(0, &asr_is_open);
@@ -393,7 +391,7 @@ static int __init ibmasr_init(void)
        rc = misc_register(&asr_miscdev);
        if (rc < 0) {
                release_region(asr_base, asr_length);
-               printk(KERN_ERR PFX "failed to register misc device\n");
+               pr_err("failed to register misc device\n");
                return rc;
        }
 
@@ -413,7 +411,7 @@ static void __exit ibmasr_exit(void)
 module_init(ibmasr_init);
 module_exit(ibmasr_exit);
 
-module_param(nowayout, int, 0);
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
        "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
index c44c333..7a2b734 100644 (file)
@@ -46,6 +46,9 @@
 #define IMX2_WDT_SEQ1          0x5555          /* -> service sequence 1 */
 #define IMX2_WDT_SEQ2          0xAAAA          /* -> service sequence 2 */
 
+#define IMX2_WDT_WRSR          0x04            /* Reset Status Register */
+#define IMX2_WDT_WRSR_TOUT     (1 << 1)        /* -> Reset due to Timeout */
+
 #define IMX2_WDT_MAX_TIME      128
 #define IMX2_WDT_DEFAULT_TIME  60              /* in seconds */
 
@@ -65,8 +68,8 @@ static struct {
 
 static struct miscdevice imx2_wdt_miscdev;
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
@@ -175,6 +178,7 @@ static long imx2_wdt_ioctl(struct file *file, unsigned int cmd,
        void __user *argp = (void __user *)arg;
        int __user *p = argp;
        int new_value;
+       u16 val;
 
        switch (cmd) {
        case WDIOC_GETSUPPORT:
@@ -182,9 +186,13 @@ static long imx2_wdt_ioctl(struct file *file, unsigned int cmd,
                        sizeof(struct watchdog_info)) ? -EFAULT : 0;
 
        case WDIOC_GETSTATUS:
-       case WDIOC_GETBOOTSTATUS:
                return put_user(0, p);
 
+       case WDIOC_GETBOOTSTATUS:
+               val = __raw_readw(imx2_wdt.base + IMX2_WDT_WRSR);
+               new_value = val & IMX2_WDT_WRSR_TOUT ? WDIOF_CARDRESET : 0;
+               return put_user(new_value, p);
+
        case WDIOC_KEEPALIVE:
                imx2_wdt_ping();
                return 0;
index 1475e09..6d90f7a 100644 (file)
@@ -12,6 +12,8 @@
  *     based on softdog.c by Alan Cox <alan@lxorguk.ukuu.org.uk>
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/uaccess.h>
 #include <asm/sgi/mc.h>
 
-#define PFX "indydog: "
 static unsigned long indydog_alive;
 static DEFINE_SPINLOCK(indydog_lock);
 
 #define WATCHDOG_TIMEOUT 30            /* 30 sec default timeout */
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -60,7 +61,7 @@ static void indydog_stop(void)
        sgimc->cpuctrl0 = mc_ctrl0;
        spin_unlock(&indydog_lock);
 
-       printk(KERN_INFO PFX "Stopped watchdog timer.\n");
+       pr_info("Stopped watchdog timer\n");
 }
 
 static void indydog_ping(void)
@@ -83,7 +84,7 @@ static int indydog_open(struct inode *inode, struct file *file)
        indydog_start();
        indydog_ping();
 
-       printk(KERN_INFO "Started watchdog timer.\n");
+       pr_info("Started watchdog timer\n");
 
        return nonseekable_open(inode, file);
 }
@@ -178,30 +179,25 @@ static struct notifier_block indydog_notifier = {
        .notifier_call = indydog_notify_sys,
 };
 
-static char banner[] __initdata =
-       KERN_INFO PFX "Hardware Watchdog Timer for SGI IP22: 0.3\n";
-
 static int __init watchdog_init(void)
 {
        int ret;
 
        ret = register_reboot_notifier(&indydog_notifier);
        if (ret) {
-               printk(KERN_ERR PFX
-                       "cannot register reboot notifier (err=%d)\n", ret);
+               pr_err("cannot register reboot notifier (err=%d)\n", ret);
                return ret;
        }
 
        ret = misc_register(&indydog_miscdev);
        if (ret) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                                                       WATCHDOG_MINOR, ret);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      WATCHDOG_MINOR, ret);
                unregister_reboot_notifier(&indydog_notifier);
                return ret;
        }
 
-       printk(banner);
+       pr_info("Hardware Watchdog Timer for SGI IP22: 0.3\n");
 
        return 0;
 }
index 1abdc04..9dda2d0 100644 (file)
@@ -22,6 +22,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/compiler.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -96,15 +98,14 @@ static struct intel_scu_watchdog_dev watchdog_device;
 static void watchdog_fire(void)
 {
        if (force_boot) {
-               printk(KERN_CRIT PFX "Initiating system reboot.\n");
+               pr_crit("Initiating system reboot\n");
                emergency_restart();
-               printk(KERN_CRIT PFX "Reboot didn't ?????\n");
+               pr_crit("Reboot didn't ?????\n");
        }
 
        else {
-               printk(KERN_CRIT PFX "Immediate Reboot Disabled\n");
-               printk(KERN_CRIT PFX
-                       "System will reset when watchdog timer times out!\n");
+               pr_crit("Immediate Reboot Disabled\n");
+               pr_crit("System will reset when watchdog timer times out!\n");
        }
 }
 
@@ -112,8 +113,8 @@ static int check_timer_margin(int new_margin)
 {
        if ((new_margin < MIN_TIME_CYCLE) ||
            (new_margin > MAX_TIME - timer_set)) {
-               pr_debug("Watchdog timer: value of new_margin %d is out of the range %d to %d\n",
-                         new_margin, MIN_TIME_CYCLE, MAX_TIME - timer_set);
+               pr_debug("value of new_margin %d is out of the range %d to %d\n",
+                        new_margin, MIN_TIME_CYCLE, MAX_TIME - timer_set);
                return -EINVAL;
        }
        return 0;
@@ -156,14 +157,14 @@ static irqreturn_t watchdog_timer_interrupt(int irq, void *dev_id)
        int int_status;
        int_status = ioread32(watchdog_device.timer_interrupt_status_addr);
 
-       pr_debug("Watchdog timer: irq, int_status: %x\n", int_status);
+       pr_debug("irq, int_status: %x\n", int_status);
 
        if (int_status != 0)
                return IRQ_NONE;
 
        /* has the timer been started? If not, then this is spurious */
        if (watchdog_device.timer_started == 0) {
-               pr_debug("Watchdog timer: spurious interrupt received\n");
+               pr_debug("spurious interrupt received\n");
                return IRQ_HANDLED;
        }
 
@@ -220,16 +221,15 @@ static int intel_scu_set_heartbeat(u32 t)
                (watchdog_device.timer_set - timer_margin)
                * watchdog_device.timer_tbl_ptr->freq_hz;
 
-       pr_debug("Watchdog timer: set_heartbeat: timer freq is %d\n",
-               watchdog_device.timer_tbl_ptr->freq_hz);
-       pr_debug("Watchdog timer: set_heartbeat: timer_set is %x (hex)\n",
-               watchdog_device.timer_set);
-       pr_debug("Watchdog timer: set_hearbeat: timer_margin is %x (hex)\n",
-               timer_margin);
-       pr_debug("Watchdog timer: set_heartbeat: threshold is %x (hex)\n",
-               watchdog_device.threshold);
-       pr_debug("Watchdog timer: set_heartbeat: soft_threshold is %x (hex)\n",
-               watchdog_device.soft_threshold);
+       pr_debug("set_heartbeat: timer freq is %d\n",
+                watchdog_device.timer_tbl_ptr->freq_hz);
+       pr_debug("set_heartbeat: timer_set is %x (hex)\n",
+                watchdog_device.timer_set);
+       pr_debug("set_hearbeat: timer_margin is %x (hex)\n", timer_margin);
+       pr_debug("set_heartbeat: threshold is %x (hex)\n",
+                watchdog_device.threshold);
+       pr_debug("set_heartbeat: soft_threshold is %x (hex)\n",
+                watchdog_device.soft_threshold);
 
        /* Adjust thresholds by FREQ_ADJUSTMENT factor, to make the */
        /* watchdog timing come out right. */
@@ -264,7 +264,7 @@ static int intel_scu_set_heartbeat(u32 t)
 
                if (MAX_RETRY < retry_count++) {
                        /* Unable to set timer value */
-                       pr_err("Watchdog timer: Unable to set timer\n");
+                       pr_err("Unable to set timer\n");
                        return -ENODEV;
                }
 
@@ -321,18 +321,17 @@ static int intel_scu_release(struct inode *inode, struct file *file)
         */
 
        if (!test_and_clear_bit(0, &watchdog_device.driver_open)) {
-               pr_debug("Watchdog timer: intel_scu_release, without open\n");
+               pr_debug("intel_scu_release, without open\n");
                return -ENOTTY;
        }
 
        if (!watchdog_device.timer_started) {
                /* Just close, since timer has not been started */
-               pr_debug("Watchdog timer: closed, without starting timer\n");
+               pr_debug("closed, without starting timer\n");
                return 0;
        }
 
-       printk(KERN_CRIT PFX
-              "Unexpected close of /dev/watchdog!\n");
+       pr_crit("Unexpected close of /dev/watchdog!\n");
 
        /* Since the timer was started, prevent future reopens */
        watchdog_device.driver_closed = 1;
@@ -454,9 +453,8 @@ static int __init intel_scu_watchdog_init(void)
        /* Check value of timer_set boot parameter */
        if ((timer_set < MIN_TIME_CYCLE) ||
            (timer_set > MAX_TIME - MIN_TIME_CYCLE)) {
-               pr_err("Watchdog timer: value of timer_set %x (hex) "
-                 "is out of range from %x to %x (hex)\n",
-                 timer_set, MIN_TIME_CYCLE, MAX_TIME - MIN_TIME_CYCLE);
+               pr_err("value of timer_set %x (hex) is out of range from %x to %x (hex)\n",
+                      timer_set, MIN_TIME_CYCLE, MAX_TIME - MIN_TIME_CYCLE);
                return -EINVAL;
        }
 
@@ -467,19 +465,18 @@ static int __init intel_scu_watchdog_init(void)
        watchdog_device.timer_tbl_ptr = sfi_get_mtmr(sfi_mtimer_num-1);
 
        if (watchdog_device.timer_tbl_ptr == NULL) {
-               pr_debug("Watchdog timer - Intel SCU watchdog: timer is not available\n");
+               pr_debug("timer is not available\n");
                return -ENODEV;
        }
        /* make sure the timer exists */
        if (watchdog_device.timer_tbl_ptr->phys_addr == 0) {
-               pr_debug("Watchdog timer - Intel SCU watchdog - timer %d does not have valid physical memory\n",
-                                                               sfi_mtimer_num);
+               pr_debug("timer %d does not have valid physical memory\n",
+                        sfi_mtimer_num);
                return -ENODEV;
        }
 
        if (watchdog_device.timer_tbl_ptr->irq == 0) {
-               pr_debug("Watchdog timer: timer %d invalid irq\n",
-                                                       sfi_mtimer_num);
+               pr_debug("timer %d invalid irq\n", sfi_mtimer_num);
                return -ENODEV;
        }
 
@@ -487,7 +484,7 @@ static int __init intel_scu_watchdog_init(void)
                        20);
 
        if (tmp_addr == NULL) {
-               pr_debug("Watchdog timer: timer unable to ioremap\n");
+               pr_debug("timer unable to ioremap\n");
                return -ENOMEM;
        }
 
@@ -512,7 +509,7 @@ static int __init intel_scu_watchdog_init(void)
 
        ret = register_reboot_notifier(&watchdog_device.intel_scu_notifier);
        if (ret) {
-               pr_err("Watchdog timer: cannot register notifier %d)\n", ret);
+               pr_err("cannot register notifier %d)\n", ret);
                goto register_reboot_error;
        }
 
@@ -522,8 +519,8 @@ static int __init intel_scu_watchdog_init(void)
 
        ret = misc_register(&watchdog_device.miscdev);
        if (ret) {
-               pr_err("Watchdog timer: cannot register miscdev %d err =%d\n",
-                                                       WATCHDOG_MINOR, ret);
+               pr_err("cannot register miscdev %d err =%d\n",
+                      WATCHDOG_MINOR, ret);
                goto misc_register_error;
        }
 
@@ -532,7 +529,7 @@ static int __init intel_scu_watchdog_init(void)
                IRQF_SHARED, "watchdog",
                &watchdog_device.timer_load_count_addr);
        if (ret) {
-               pr_err("Watchdog timer: error requesting irq %d\n", ret);
+               pr_err("error requesting irq %d\n", ret);
                goto request_irq_error;
        }
        /* Make sure timer is disabled before returning */
index d2b074a..f3ac608 100644 (file)
@@ -25,7 +25,6 @@
 #ifndef __INTEL_SCU_WATCHDOG_H
 #define __INTEL_SCU_WATCHDOG_H
 
-#define PFX "Intel_SCU: "
 #define WDT_VER "0.3"
 
 /* minimum time between interrupts */
index 82fa7a9..d964faf 100644 (file)
@@ -24,6 +24,8 @@
  *     Dan Williams <dan.j.williams@intel.com>
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/fs.h>
@@ -34,7 +36,7 @@
 #include <linux/uaccess.h>
 #include <mach/hardware.h>
 
-static int nowayout = WATCHDOG_NOWAYOUT;
+static bool nowayout = WATCHDOG_NOWAYOUT;
 static unsigned long wdt_status;
 static unsigned long boot_status;
 static DEFINE_SPINLOCK(wdt_lock);
@@ -85,7 +87,7 @@ static int wdt_disable(void)
                write_wdtcr(IOP_WDTCR_DIS);
                clear_bit(WDT_ENABLED, &wdt_status);
                spin_unlock(&wdt_lock);
-               printk(KERN_INFO "WATCHDOG: Disabled\n");
+               pr_info("Disabled\n");
                return 0;
        } else
                return 1;
@@ -197,8 +199,8 @@ static int iop_wdt_release(struct inode *inode, struct file *file)
         */
        if (state != 0) {
                wdt_enable();
-               printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - "
-                      "reset in %lu seconds\n", iop_watchdog_timeout());
+               pr_crit("Device closed unexpectedly - reset in %lu seconds\n",
+                       iop_watchdog_timeout());
        }
 
        clear_bit(WDT_IN_USE, &wdt_status);
@@ -238,8 +240,7 @@ static int __init iop_wdt_init(void)
           with an open */
        ret = misc_register(&iop_wdt_miscdev);
        if (ret == 0)
-               printk(KERN_INFO "iop watchdog timer: timeout %lu sec\n",
-                      iop_watchdog_timeout());
+               pr_info("timeout %lu sec\n", iop_watchdog_timeout());
 
        return ret;
 }
@@ -252,7 +253,7 @@ static void __exit iop_wdt_exit(void)
 module_init(iop_wdt_init);
 module_exit(iop_wdt_exit);
 
-module_param(nowayout, int, 0);
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
 
 MODULE_AUTHOR("Curt E Bruns <curt.e.bruns@intel.com>");
index 8d2d850..f4cce6d 100644 (file)
@@ -20,6 +20,8 @@
  *     software is provided AS-IS with no warranties.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
@@ -33,6 +35,7 @@
 #include <linux/io.h>
 #include <linux/ioport.h>
 
+#define DEBUG
 #define NAME "it8712f_wdt"
 
 MODULE_AUTHOR("Jorge Boncompte - DTI2 <jorge@dti2.net>");
@@ -45,8 +48,8 @@ static int margin = 60;               /* in seconds */
 module_param(margin, int, 0);
 MODULE_PARM_DESC(margin, "Watchdog margin in seconds");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close");
 
 static unsigned long wdt_open;
@@ -158,10 +161,10 @@ static void it8712f_wdt_update_margin(void)
         */
        if (units <= max_units) {
                config |= WDT_UNIT_SEC; /* else UNIT is MINUTES */
-               printk(KERN_INFO NAME ": timer margin %d seconds\n", units);
+               pr_info("timer margin %d seconds\n", units);
        } else {
                units /= 60;
-               printk(KERN_INFO NAME ": timer margin %d minutes\n", units);
+               pr_info("timer margin %d minutes\n", units);
        }
        superio_outb(config, WDT_CONFIG);
 
@@ -184,7 +187,7 @@ static int it8712f_wdt_enable(void)
        if (ret)
                return ret;
 
-       printk(KERN_DEBUG NAME ": enabling watchdog timer\n");
+       pr_debug("enabling watchdog timer\n");
        superio_select(LDN_GPIO);
 
        superio_outb(wdt_control_reg, WDT_CONTROL);
@@ -204,7 +207,7 @@ static int it8712f_wdt_disable(void)
        if (ret)
                return ret;
 
-       printk(KERN_DEBUG NAME ": disabling watchdog timer\n");
+       pr_debug("disabling watchdog timer\n");
        superio_select(LDN_GPIO);
 
        superio_outb(0, WDT_CONFIG);
@@ -331,12 +334,10 @@ static int it8712f_wdt_open(struct inode *inode, struct file *file)
 static int it8712f_wdt_release(struct inode *inode, struct file *file)
 {
        if (expect_close != 42) {
-               printk(KERN_WARNING NAME
-                       ": watchdog device closed unexpectedly, will not"
-                       " disable the watchdog timer\n");
+               pr_warn("watchdog device closed unexpectedly, will not disable the watchdog timer\n");
        } else if (!nowayout) {
                if (it8712f_wdt_disable())
-                       printk(KERN_WARNING NAME "Watchdog disable failed\n");
+                       pr_warn("Watchdog disable failed\n");
        }
        expect_close = 0;
        clear_bit(0, &wdt_open);
@@ -374,13 +375,13 @@ static int __init it8712f_wdt_find(unsigned short *address)
        superio_select(LDN_GAME);
        superio_outb(1, ACT_REG);
        if (!(superio_inb(ACT_REG) & 0x01)) {
-               printk(KERN_ERR NAME ": Device not activated, skipping\n");
+               pr_err("Device not activated, skipping\n");
                goto exit;
        }
 
        *address = superio_inw(BASE_REG);
        if (*address == 0) {
-               printk(KERN_ERR NAME ": Base address not set, skipping\n");
+               pr_err("Base address not set, skipping\n");
                goto exit;
        }
 
@@ -394,8 +395,7 @@ static int __init it8712f_wdt_find(unsigned short *address)
        if (margin > (max_units * 60))
                margin = (max_units * 60);
 
-       printk(KERN_INFO NAME ": Found IT%04xF chip revision %d - "
-               "using DogFood address 0x%x\n",
+       pr_info("Found IT%04xF chip revision %d - using DogFood address 0x%x\n",
                chip_type, revision, *address);
 
 exit:
@@ -411,27 +411,26 @@ static int __init it8712f_wdt_init(void)
                return -ENODEV;
 
        if (!request_region(address, 1, "IT8712F Watchdog")) {
-               printk(KERN_WARNING NAME ": watchdog I/O region busy\n");
+               pr_warn("watchdog I/O region busy\n");
                return -EBUSY;
        }
 
        err = it8712f_wdt_disable();
        if (err) {
-               printk(KERN_ERR NAME ": unable to disable watchdog timer.\n");
+               pr_err("unable to disable watchdog timer\n");
                goto out;
        }
 
        err = register_reboot_notifier(&it8712f_wdt_notifier);
        if (err) {
-               printk(KERN_ERR NAME ": unable to register reboot notifier\n");
+               pr_err("unable to register reboot notifier\n");
                goto out;
        }
 
        err = misc_register(&it8712f_wdt_miscdev);
        if (err) {
-               printk(KERN_ERR NAME
-                       ": cannot register miscdev on minor=%d (err=%d)\n",
-                       WATCHDOG_MINOR, err);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      WATCHDOG_MINOR, err);
                goto reboot_out;
        }
 
index a2d9a12..8a741bc 100644 (file)
@@ -29,6 +29,8 @@
  *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/uaccess.h>
 #include <linux/io.h>
 
-#include <asm/system.h>
 
 #define WATCHDOG_VERSION       "1.14"
 #define WATCHDOG_NAME          "IT87 WDT"
-#define PFX                    WATCHDOG_NAME ": "
 #define DRIVER_VERSION         WATCHDOG_NAME " driver, v" WATCHDOG_VERSION "\n"
 #define WD_MAGIC               'V'
 
@@ -142,7 +142,7 @@ static      int nogameport = DEFAULT_NOGAMEPORT;
 static int exclusive  = DEFAULT_EXCLUSIVE;
 static int timeout    = DEFAULT_TIMEOUT;
 static int testmode   = DEFAULT_TESTMODE;
-static int nowayout   = DEFAULT_NOWAYOUT;
+static bool nowayout   = DEFAULT_NOWAYOUT;
 
 module_param(nogameport, int, 0);
 MODULE_PARM_DESC(nogameport, "Forbid the activation of game port, default="
@@ -156,7 +156,7 @@ MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds, default="
 module_param(testmode, int, 0);
 MODULE_PARM_DESC(testmode, "Watchdog test mode (1 = no reboot), default="
                __MODULE_STRING(DEFAULT_TESTMODE));
-module_param(nowayout, int, 0);
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started, default="
                __MODULE_STRING(WATCHDOG_NOWAYOUT));
 
@@ -428,8 +428,7 @@ static int wdt_release(struct inode *inode, struct file *file)
                        clear_bit(WDTS_TIMER_RUN, &wdt_status);
                } else {
                        wdt_keepalive();
-                       printk(KERN_CRIT PFX
-                              "unexpected close, not stopping watchdog!\n");
+                       pr_crit("unexpected close, not stopping watchdog!\n");
                }
        }
        clear_bit(WDTS_DEV_OPEN, &wdt_status);
@@ -621,16 +620,14 @@ static int __init it87_wdt_init(void)
                try_gameport = 0;
                break;
        case IT8705_ID:
-               printk(KERN_ERR PFX
-                      "Unsupported Chip found, Chip %04x Revision %02x\n",
+               pr_err("Unsupported Chip found, Chip %04x Revision %02x\n",
                       chip_type, chip_rev);
                return -ENODEV;
        case NO_DEV_ID:
-               printk(KERN_ERR PFX "no device\n");
+               pr_err("no device\n");
                return -ENODEV;
        default:
-               printk(KERN_ERR PFX
-                      "Unknown Chip found, Chip %04x Revision %04x\n",
+               pr_err("Unknown Chip found, Chip %04x Revision %04x\n",
                       chip_type, chip_rev);
                return -ENODEV;
        }
@@ -663,13 +660,11 @@ static int __init it87_wdt_init(void)
        if (!test_bit(WDTS_USE_GP, &wdt_status)) {
                if (!request_region(CIR_BASE, 8, WATCHDOG_NAME)) {
                        if (gp_rreq_fail)
-                               printk(KERN_ERR PFX
-                                       "I/O Address 0x%04x and 0x%04x"
-                                       " already in use\n", base, CIR_BASE);
+                               pr_err("I/O Address 0x%04x and 0x%04x already in use\n",
+                                      base, CIR_BASE);
                        else
-                               printk(KERN_ERR PFX
-                                       "I/O Address 0x%04x already in use\n",
-                                       CIR_BASE);
+                               pr_err("I/O Address 0x%04x already in use\n",
+                                      CIR_BASE);
                        rc = -EIO;
                        goto err_out;
                }
@@ -688,9 +683,8 @@ static int __init it87_wdt_init(void)
 
        if (timeout < 1 || timeout > max_units * 60) {
                timeout = DEFAULT_TIMEOUT;
-               printk(KERN_WARNING PFX
-                      "Timeout value out of range, use default %d sec\n",
-                      DEFAULT_TIMEOUT);
+               pr_warn("Timeout value out of range, use default %d sec\n",
+                       DEFAULT_TIMEOUT);
        }
 
        if (timeout > max_units)
@@ -698,16 +692,14 @@ static int __init it87_wdt_init(void)
 
        rc = register_reboot_notifier(&wdt_notifier);
        if (rc) {
-               printk(KERN_ERR PFX
-                      "Cannot register reboot notifier (err=%d)\n", rc);
+               pr_err("Cannot register reboot notifier (err=%d)\n", rc);
                goto err_out_region;
        }
 
        rc = misc_register(&wdt_miscdev);
        if (rc) {
-               printk(KERN_ERR PFX
-                      "Cannot register miscdev on minor=%d (err=%d)\n",
-                       wdt_miscdev.minor, rc);
+               pr_err("Cannot register miscdev on minor=%d (err=%d)\n",
+                      wdt_miscdev.minor, rc);
                goto err_out_reboot;
        }
 
@@ -722,9 +714,8 @@ static int __init it87_wdt_init(void)
                outb(0x09, CIR_IER(base));
        }
 
-       printk(KERN_INFO PFX "Chip IT%04x revision %d initialized. "
-               "timeout=%d sec (nowayout=%d testmode=%d exclusive=%d "
-               "nogameport=%d)\n", chip_type, chip_rev, timeout,
+       pr_info("Chip IT%04x revision %d initialized. timeout=%d sec (nowayout=%d testmode=%d exclusive=%d nogameport=%d)\n",
+               chip_type, chip_rev, timeout,
                nowayout, testmode, exclusive, nogameport);
 
        superio_exit();
index 084f71a..3f047a5 100644 (file)
@@ -16,6 +16,8 @@
  * warranty of any kind, whether express or implied.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
@@ -29,7 +31,7 @@
 #include <linux/uaccess.h>
 #include <mach/hardware.h>
 
-static int nowayout = WATCHDOG_NOWAYOUT;
+static bool nowayout = WATCHDOG_NOWAYOUT;
 static unsigned int heartbeat = 60;    /* (secs) Default is 1 minute */
 static unsigned long wdt_status;
 static DEFINE_SPINLOCK(wdt_lock);
@@ -158,8 +160,7 @@ static int ixp2000_wdt_release(struct inode *inode, struct file *file)
        if (test_bit(WDT_OK_TO_CLOSE, &wdt_status))
                wdt_disable();
        else
-               printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - "
-                                       "timer will not stop\n");
+               pr_crit("Device closed unexpectedly - timer will not stop\n");
        clear_bit(WDT_IN_USE, &wdt_status);
        clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
 
@@ -185,7 +186,7 @@ static struct miscdevice ixp2000_wdt_miscdev = {
 static int __init ixp2000_wdt_init(void)
 {
        if ((*IXP2000_PRODUCT_ID & 0x001ffef0) == 0x00000000) {
-               printk(KERN_INFO "Unable to use IXP2000 watchdog due to IXP2800 erratum #25.\n");
+               pr_info("Unable to use IXP2000 watchdog due to IXP2800 erratum #25\n");
                return -EIO;
        }
        wdt_tick_rate = (*IXP2000_T1_CLD * HZ) / 256;
@@ -206,7 +207,7 @@ MODULE_DESCRIPTION("IXP2000 Network Processor Watchdog");
 module_param(heartbeat, int, 0);
 MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds (default 60s)");
 
-module_param(nowayout, int, 0);
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
 
 MODULE_LICENSE("GPL");
index 4fc2e9a..5580b4f 100644 (file)
@@ -13,6 +13,8 @@
  * warranty of any kind, whether express or implied.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
@@ -25,7 +27,7 @@
 #include <linux/uaccess.h>
 #include <mach/hardware.h>
 
-static int nowayout = WATCHDOG_NOWAYOUT;
+static bool nowayout = WATCHDOG_NOWAYOUT;
 static int heartbeat = 60;     /* (secs) Default is 1 minute */
 static unsigned long wdt_status;
 static unsigned long boot_status;
@@ -147,8 +149,7 @@ static int ixp4xx_wdt_release(struct inode *inode, struct file *file)
        if (test_bit(WDT_OK_TO_CLOSE, &wdt_status))
                wdt_disable();
        else
-               printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - "
-                                       "timer will not stop\n");
+               pr_crit("Device closed unexpectedly - timer will not stop\n");
        clear_bit(WDT_IN_USE, &wdt_status);
        clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
 
@@ -176,8 +177,7 @@ static int __init ixp4xx_wdt_init(void)
        int ret;
 
        if (!(read_cpuid_id() & 0xf) && !cpu_is_ixp46x()) {
-               printk(KERN_ERR "IXP4XXX Watchdog: Rev. A0 IXP42x CPU detected"
-                       " - watchdog disabled\n");
+               pr_err("Rev. A0 IXP42x CPU detected - watchdog disabled\n");
 
                return -ENODEV;
        }
@@ -185,8 +185,7 @@ static int __init ixp4xx_wdt_init(void)
                        WDIOF_CARDRESET : 0;
        ret = misc_register(&ixp4xx_wdt_miscdev);
        if (ret == 0)
-               printk(KERN_INFO "IXP4xx Watchdog Timer: heartbeat %d sec\n",
-                       heartbeat);
+               pr_info("timer heartbeat %d sec\n", heartbeat);
        return ret;
 }
 
@@ -205,7 +204,7 @@ MODULE_DESCRIPTION("IXP4xx Network Processor Watchdog");
 module_param(heartbeat, int, 0);
 MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds (default 60s)");
 
-module_param(nowayout, int, 0);
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
 
 MODULE_LICENSE("GPL");
index 17ef300..978615e 100644 (file)
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/fs.h>
 #include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include <linux/init.h>
-#include <linux/bitops.h>
 #include <linux/platform_device.h>
-#include <linux/spinlock.h>
-#include <linux/uaccess.h>
 #include <linux/io.h>
 #include <linux/device.h>
 #include <linux/clk.h>
 #include <linux/slab.h>
+#include <linux/err.h>
 
 #include <asm/mach-jz4740/timer.h>
 
@@ -41,9 +38,6 @@
 #define JZ_WDT_CLOCK_RTC  0x2
 #define JZ_WDT_CLOCK_EXT  0x4
 
-#define WDT_IN_USE        0
-#define WDT_OK_TO_CLOSE   1
-
 #define JZ_WDT_CLOCK_DIV_SHIFT   3
 
 #define JZ_WDT_CLOCK_DIV_1    (0 << JZ_WDT_CLOCK_DIV_SHIFT)
 #define DEFAULT_HEARTBEAT 5
 #define MAX_HEARTBEAT     2048
 
-static struct {
-       void __iomem *base;
-       struct resource *mem;
-       struct clk *rtc_clk;
-       unsigned long status;
-} jz4740_wdt;
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
+MODULE_PARM_DESC(nowayout,
+                "Watchdog cannot be stopped once started (default="
+                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
-static int heartbeat = DEFAULT_HEARTBEAT;
+static unsigned int heartbeat = DEFAULT_HEARTBEAT;
+module_param(heartbeat, uint, 0);
+MODULE_PARM_DESC(heartbeat,
+               "Watchdog heartbeat period in seconds from 1 to "
+               __MODULE_STRING(MAX_HEARTBEAT) ", default "
+               __MODULE_STRING(DEFAULT_HEARTBEAT));
 
+struct jz4740_wdt_drvdata {
+       struct watchdog_device wdt;
+       void __iomem *base;
+       struct clk *rtc_clk;
+};
 
-static void jz4740_wdt_service(void)
+static int jz4740_wdt_ping(struct watchdog_device *wdt_dev)
 {
-       writew(0x0, jz4740_wdt.base + JZ_REG_WDT_TIMER_COUNTER);
+       struct jz4740_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
+
+       writew(0x0, drvdata->base + JZ_REG_WDT_TIMER_COUNTER);
+       return 0;
 }
 
-static void jz4740_wdt_set_heartbeat(int new_heartbeat)
+static int jz4740_wdt_set_timeout(struct watchdog_device *wdt_dev,
+                                   unsigned int new_timeout)
 {
+       struct jz4740_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
        unsigned int rtc_clk_rate;
        unsigned int timeout_value;
        unsigned short clock_div = JZ_WDT_CLOCK_DIV_1;
 
-       heartbeat = new_heartbeat;
-
-       rtc_clk_rate = clk_get_rate(jz4740_wdt.rtc_clk);
+       rtc_clk_rate = clk_get_rate(drvdata->rtc_clk);
 
-       timeout_value = rtc_clk_rate * heartbeat;
+       timeout_value = rtc_clk_rate * new_timeout;
        while (timeout_value > 0xffff) {
                if (clock_div == JZ_WDT_CLOCK_DIV_1024) {
                        /* Requested timeout too high;
@@ -93,199 +99,115 @@ static void jz4740_wdt_set_heartbeat(int new_heartbeat)
                clock_div += (1 << JZ_WDT_CLOCK_DIV_SHIFT);
        }
 
-       writeb(0x0, jz4740_wdt.base + JZ_REG_WDT_COUNTER_ENABLE);
-       writew(clock_div, jz4740_wdt.base + JZ_REG_WDT_TIMER_CONTROL);
+       writeb(0x0, drvdata->base + JZ_REG_WDT_COUNTER_ENABLE);
+       writew(clock_div, drvdata->base + JZ_REG_WDT_TIMER_CONTROL);
 
-       writew((u16)timeout_value, jz4740_wdt.base + JZ_REG_WDT_TIMER_DATA);
-       writew(0x0, jz4740_wdt.base + JZ_REG_WDT_TIMER_COUNTER);
+       writew((u16)timeout_value, drvdata->base + JZ_REG_WDT_TIMER_DATA);
+       writew(0x0, drvdata->base + JZ_REG_WDT_TIMER_COUNTER);
        writew(clock_div | JZ_WDT_CLOCK_RTC,
-               jz4740_wdt.base + JZ_REG_WDT_TIMER_CONTROL);
+               drvdata->base + JZ_REG_WDT_TIMER_CONTROL);
 
-       writeb(0x1, jz4740_wdt.base + JZ_REG_WDT_COUNTER_ENABLE);
-}
+       writeb(0x1, drvdata->base + JZ_REG_WDT_COUNTER_ENABLE);
 
-static void jz4740_wdt_enable(void)
-{
-       jz4740_timer_enable_watchdog();
-       jz4740_wdt_set_heartbeat(heartbeat);
-}
-
-static void jz4740_wdt_disable(void)
-{
-       jz4740_timer_disable_watchdog();
-       writeb(0x0, jz4740_wdt.base + JZ_REG_WDT_COUNTER_ENABLE);
+       wdt_dev->timeout = new_timeout;
+       return 0;
 }
 
-static int jz4740_wdt_open(struct inode *inode, struct file *file)
+static int jz4740_wdt_start(struct watchdog_device *wdt_dev)
 {
-       if (test_and_set_bit(WDT_IN_USE, &jz4740_wdt.status))
-               return -EBUSY;
-
-       jz4740_wdt_enable();
+       jz4740_timer_enable_watchdog();
+       jz4740_wdt_set_timeout(wdt_dev, wdt_dev->timeout);
 
-       return nonseekable_open(inode, file);
+       return 0;
 }
 
-static ssize_t jz4740_wdt_write(struct file *file, const char *data,
-               size_t len, loff_t *ppos)
+static int jz4740_wdt_stop(struct watchdog_device *wdt_dev)
 {
-       if (len) {
-               size_t i;
-
-               clear_bit(WDT_OK_TO_CLOSE, &jz4740_wdt.status);
-               for (i = 0; i != len; i++) {
-                       char c;
+       struct jz4740_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
 
-                       if (get_user(c, data + i))
-                               return -EFAULT;
-
-                       if (c == 'V')
-                               set_bit(WDT_OK_TO_CLOSE, &jz4740_wdt.status);
-               }
-               jz4740_wdt_service();
-       }
+       jz4740_timer_disable_watchdog();
+       writeb(0x0, drvdata->base + JZ_REG_WDT_COUNTER_ENABLE);
 
-       return len;
+       return 0;
 }
 
-static const struct watchdog_info ident = {
-       .options = WDIOF_KEEPALIVEPING,
+static const struct watchdog_info jz4740_wdt_info = {
+       .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
        .identity = "jz4740 Watchdog",
 };
 
-static long jz4740_wdt_ioctl(struct file *file,
-                                       unsigned int cmd, unsigned long arg)
-{
-       int ret = -ENOTTY;
-       int heartbeat_seconds;
-
-       switch (cmd) {
-       case WDIOC_GETSUPPORT:
-               ret = copy_to_user((struct watchdog_info *)arg, &ident,
-                               sizeof(ident)) ? -EFAULT : 0;
-               break;
-
-       case WDIOC_GETSTATUS:
-       case WDIOC_GETBOOTSTATUS:
-               ret = put_user(0, (int *)arg);
-               break;
-
-       case WDIOC_KEEPALIVE:
-               jz4740_wdt_service();
-               return 0;
-
-       case WDIOC_SETTIMEOUT:
-               if (get_user(heartbeat_seconds, (int __user *)arg))
-                       return -EFAULT;
-
-               jz4740_wdt_set_heartbeat(heartbeat_seconds);
-               return 0;
-
-       case WDIOC_GETTIMEOUT:
-               return put_user(heartbeat, (int *)arg);
-
-       default:
-               break;
-       }
-
-       return ret;
-}
-
-static int jz4740_wdt_release(struct inode *inode, struct file *file)
-{
-       jz4740_wdt_service();
-
-       if (test_and_clear_bit(WDT_OK_TO_CLOSE, &jz4740_wdt.status))
-               jz4740_wdt_disable();
-
-       clear_bit(WDT_IN_USE, &jz4740_wdt.status);
-       return 0;
-}
-
-static const struct file_operations jz4740_wdt_fops = {
+static const struct watchdog_ops jz4740_wdt_ops = {
        .owner = THIS_MODULE,
-       .llseek = no_llseek,
-       .write = jz4740_wdt_write,
-       .unlocked_ioctl = jz4740_wdt_ioctl,
-       .open = jz4740_wdt_open,
-       .release = jz4740_wdt_release,
-};
-
-static struct miscdevice jz4740_wdt_miscdev = {
-       .minor = WATCHDOG_MINOR,
-       .name = "watchdog",
-       .fops = &jz4740_wdt_fops,
+       .start = jz4740_wdt_start,
+       .stop = jz4740_wdt_stop,
+       .ping = jz4740_wdt_ping,
+       .set_timeout = jz4740_wdt_set_timeout,
 };
 
 static int __devinit jz4740_wdt_probe(struct platform_device *pdev)
 {
-       int ret = 0, size;
-       struct resource *res;
-       struct device *dev = &pdev->dev;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (res == NULL) {
-               dev_err(dev, "failed to get memory region resource\n");
-               return -ENXIO;
+       struct jz4740_wdt_drvdata *drvdata;
+       struct watchdog_device *jz4740_wdt;
+       struct resource *res;
+       int ret;
+
+       drvdata = devm_kzalloc(&pdev->dev, sizeof(struct jz4740_wdt_drvdata),
+                              GFP_KERNEL);
+       if (!drvdata) {
+               dev_err(&pdev->dev, "Unable to alloacate watchdog device\n");
+               return -ENOMEM;
        }
 
-       size = resource_size(res);
-       jz4740_wdt.mem = request_mem_region(res->start, size, pdev->name);
-       if (jz4740_wdt.mem == NULL) {
-               dev_err(dev, "failed to get memory region\n");
-               return -EBUSY;
-       }
+       if (heartbeat < 1 || heartbeat > MAX_HEARTBEAT)
+               heartbeat = DEFAULT_HEARTBEAT;
 
-       jz4740_wdt.base = ioremap_nocache(res->start, size);
-       if (jz4740_wdt.base == NULL) {
-               dev_err(dev, "failed to map memory region\n");
+       jz4740_wdt = &drvdata->wdt;
+       jz4740_wdt->info = &jz4740_wdt_info;
+       jz4740_wdt->ops = &jz4740_wdt_ops;
+       jz4740_wdt->timeout = heartbeat;
+       jz4740_wdt->min_timeout = 1;
+       jz4740_wdt->max_timeout = MAX_HEARTBEAT;
+       watchdog_set_nowayout(jz4740_wdt, nowayout);
+       watchdog_set_drvdata(jz4740_wdt, drvdata);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       drvdata->base = devm_request_and_ioremap(&pdev->dev, res);
+       if (drvdata->base == NULL) {
                ret = -EBUSY;
-               goto err_release_region;
+               goto err_out;
        }
 
-       jz4740_wdt.rtc_clk = clk_get(NULL, "rtc");
-       if (IS_ERR(jz4740_wdt.rtc_clk)) {
-               dev_err(dev, "cannot find RTC clock\n");
-               ret = PTR_ERR(jz4740_wdt.rtc_clk);
-               goto err_iounmap;
+       drvdata->rtc_clk = clk_get(NULL, "rtc");
+       if (IS_ERR(drvdata->rtc_clk)) {
+               dev_err(&pdev->dev, "cannot find RTC clock\n");
+               ret = PTR_ERR(drvdata->rtc_clk);
+               goto err_out;
        }
 
-       ret = misc_register(&jz4740_wdt_miscdev);
-       if (ret < 0) {
-               dev_err(dev, "cannot register misc device\n");
+       ret = watchdog_register_device(&drvdata->wdt);
+       if (ret < 0)
                goto err_disable_clk;
-       }
 
+       platform_set_drvdata(pdev, drvdata);
        return 0;
 
 err_disable_clk:
-       clk_put(jz4740_wdt.rtc_clk);
-err_iounmap:
-       iounmap(jz4740_wdt.base);
-err_release_region:
-       release_mem_region(jz4740_wdt.mem->start,
-                       resource_size(jz4740_wdt.mem));
+       clk_put(drvdata->rtc_clk);
+err_out:
        return ret;
 }
 
-
 static int __devexit jz4740_wdt_remove(struct platform_device *pdev)
 {
-       jz4740_wdt_disable();
-       misc_deregister(&jz4740_wdt_miscdev);
-       clk_put(jz4740_wdt.rtc_clk);
+       struct jz4740_wdt_drvdata *drvdata = platform_get_drvdata(pdev);
 
-       iounmap(jz4740_wdt.base);
-       jz4740_wdt.base = NULL;
-
-       release_mem_region(jz4740_wdt.mem->start,
-                               resource_size(jz4740_wdt.mem));
-       jz4740_wdt.mem = NULL;
+       jz4740_wdt_stop(&drvdata->wdt);
+       watchdog_unregister_device(&drvdata->wdt);
+       clk_put(drvdata->rtc_clk);
 
        return 0;
 }
 
-
 static struct platform_driver jz4740_wdt_driver = {
        .probe = jz4740_wdt_probe,
        .remove = __devexit_p(jz4740_wdt_remove),
@@ -299,13 +221,6 @@ module_platform_driver(jz4740_wdt_driver);
 
 MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");
 MODULE_DESCRIPTION("jz4740 Watchdog Driver");
-
-module_param(heartbeat, int, 0);
-MODULE_PARM_DESC(heartbeat,
-               "Watchdog heartbeat period in seconds from 1 to "
-               __MODULE_STRING(MAX_HEARTBEAT) ", default "
-               __MODULE_STRING(DEFAULT_HEARTBEAT));
-
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
 MODULE_ALIAS("platform:jz4740-wdt");
index 51757a5..59e75d9 100644 (file)
@@ -8,6 +8,8 @@
  * published by the Free Software Foundation.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/bitops.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
 #define WDT_MAX_TIME           171     /* seconds */
 
 static int wdt_time = WDT_DEFAULT_TIME;
-static int nowayout = WATCHDOG_NOWAYOUT;
+static bool nowayout = WATCHDOG_NOWAYOUT;
 
 module_param(wdt_time, int, 0);
 MODULE_PARM_DESC(wdt_time, "Watchdog time in seconds. (default="
                                        __MODULE_STRING(WDT_DEFAULT_TIME) ")");
 
 #ifdef CONFIG_WATCHDOG_NOWAYOUT
-module_param(nowayout, int, 0);
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 #endif
@@ -233,8 +235,8 @@ static int __devinit ks8695wdt_probe(struct platform_device *pdev)
        if (res)
                return res;
 
-       printk(KERN_INFO "KS8695 Watchdog Timer enabled (%d seconds%s)\n",
-                               wdt_time, nowayout ? ", nowayout" : "");
+       pr_info("KS8695 Watchdog Timer enabled (%d seconds%s)\n",
+               wdt_time, nowayout ? ", nowayout" : "");
        return 0;
 }
 
index d3a63be..a9593a3 100644 (file)
@@ -7,6 +7,8 @@
  *  Based on EP93xx wdt driver
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/miscdevice.h>
@@ -38,7 +40,7 @@
 #define LTQ_WDT_DIVIDER                0x40000
 #define LTQ_MAX_TIMEOUT                ((1 << 16) - 1) /* the reload field is 16 bit */
 
-static int nowayout = WATCHDOG_NOWAYOUT;
+static bool nowayout = WATCHDOG_NOWAYOUT;
 
 static void __iomem *ltq_wdt_membase;
 static unsigned long ltq_io_region_clk_rate;
@@ -160,7 +162,7 @@ ltq_wdt_release(struct inode *inode, struct file *file)
        if (ltq_wdt_ok_to_close)
                ltq_wdt_disable();
        else
-               pr_err("ltq_wdt: watchdog closed without warning\n");
+               pr_err("watchdog closed without warning\n");
        ltq_wdt_ok_to_close = 0;
        clear_bit(0, &ltq_wdt_in_use);
 
@@ -249,7 +251,7 @@ exit_ltq_wdt(void)
 module_init(init_ltq_wdt);
 module_exit(exit_ltq_wdt);
 
-module_param(nowayout, int, 0);
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
 
 MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
index 4d43286..663cad8 100644 (file)
@@ -16,6 +16,8 @@
  * warranty of any kind, whether express or implied.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
@@ -32,7 +34,7 @@
 #include <asm/m54xxsim.h>
 #include <asm/m54xxgpt.h>
 
-static int nowayout = WATCHDOG_NOWAYOUT;
+static bool nowayout = WATCHDOG_NOWAYOUT;
 static unsigned int heartbeat = 30;    /* (secs) Default is 0.5 minute */
 static unsigned long wdt_status;
 
@@ -166,8 +168,7 @@ static int m54xx_wdt_release(struct inode *inode, struct file *file)
        if (test_bit(WDT_OK_TO_CLOSE, &wdt_status))
                wdt_disable();
        else {
-               printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - "
-                                       "timer will not stop\n");
+               pr_crit("Device closed unexpectedly - timer will not stop\n");
                wdt_keepalive();
        }
        clear_bit(WDT_IN_USE, &wdt_status);
@@ -196,11 +197,10 @@ static int __init m54xx_wdt_init(void)
 {
        if (!request_mem_region(MCF_MBAR + MCF_GPT_GCIR0, 4,
                                                "Coldfire M54xx Watchdog")) {
-               printk(KERN_WARNING
-                               "Coldfire M54xx Watchdog : I/O region busy\n");
+               pr_warn("I/O region busy\n");
                return -EBUSY;
        }
-       printk(KERN_INFO "ColdFire watchdog driver is loaded.\n");
+       pr_info("driver is loaded\n");
 
        return misc_register(&m54xx_wdt_miscdev);
 }
@@ -220,7 +220,7 @@ MODULE_DESCRIPTION("Coldfire M54xx Watchdog");
 module_param(heartbeat, int, 0);
 MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds (default 30s)");
 
-module_param(nowayout, int, 0);
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
 
 MODULE_LICENSE("GPL");
index 1332b83..bf84f78 100644 (file)
@@ -28,6 +28,8 @@
  *      Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
@@ -43,7 +45,6 @@
 #include <linux/io.h>
 #include <linux/uaccess.h>
 
-#include <asm/system.h>
 
 /* ports */
 #define ZF_IOBASE      0x218
@@ -93,8 +94,8 @@ MODULE_DESCRIPTION("MachZ ZF-Logic Watchdog driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -141,10 +142,10 @@ static unsigned long next_heartbeat;
 #define ZF_CTIMEOUT 0xffff
 
 #ifndef ZF_DEBUG
-#      define dprintk(format, args...)
+#define dprintk(format, args...)
 #else
-#      define dprintk(format, args...) printk(KERN_DEBUG PFX \
-                               ":%s:%d: " format, __func__, __LINE__ , ## args)
+#define dprintk(format, args...)                                       \
+       pr_debug(":%s:%d: " format, __func__, __LINE__ , ## args)
 #endif
 
 
@@ -203,7 +204,7 @@ static void zf_timer_off(void)
        zf_set_control(ctrl_reg);
        spin_unlock_irqrestore(&zf_port_lock, flags);
 
-       printk(KERN_INFO PFX ": Watchdog timer is now disabled\n");
+       pr_info("Watchdog timer is now disabled\n");
 }
 
 
@@ -233,7 +234,7 @@ static void zf_timer_on(void)
        zf_set_control(ctrl_reg);
        spin_unlock_irqrestore(&zf_port_lock, flags);
 
-       printk(KERN_INFO PFX ": Watchdog timer is now enabled\n");
+       pr_info("Watchdog timer is now enabled\n");
 }
 
 
@@ -263,7 +264,7 @@ static void zf_ping(unsigned long data)
 
                mod_timer(&zf_timer, jiffies + ZF_HW_TIMEO);
        } else
-               printk(KERN_CRIT PFX ": I will reset your machine\n");
+               pr_crit("I will reset your machine\n");
 }
 
 static ssize_t zf_write(struct file *file, const char __user *buf, size_t count,
@@ -342,8 +343,7 @@ static int zf_close(struct inode *inode, struct file *file)
                zf_timer_off();
        else {
                del_timer(&zf_timer);
-               printk(KERN_ERR PFX ": device file closed unexpectedly. "
-                                               "Will not stop the WDT!\n");
+               pr_err("device file closed unexpectedly. Will not stop the WDT!\n");
        }
        clear_bit(0, &zf_is_open);
        zf_expect_close = 0;
@@ -390,19 +390,18 @@ static void __init zf_show_action(int act)
 {
        static const char * const str[] = { "RESET", "SMI", "NMI", "SCI" };
 
-       printk(KERN_INFO PFX ": Watchdog using action = %s\n", str[act]);
+       pr_info("Watchdog using action = %s\n", str[act]);
 }
 
 static int __init zf_init(void)
 {
        int ret;
 
-       printk(KERN_INFO PFX
-               ": MachZ ZF-Logic Watchdog driver initializing.\n");
+       pr_info("MachZ ZF-Logic Watchdog driver initializing\n");
 
        ret = zf_get_ZFL_version();
        if (!ret || ret == 0xffff) {
-               printk(KERN_WARNING PFX ": no ZF-Logic found\n");
+               pr_warn("no ZF-Logic found\n");
                return -ENODEV;
        }
 
@@ -414,23 +413,20 @@ static int __init zf_init(void)
        zf_show_action(action);
 
        if (!request_region(ZF_IOBASE, 3, "MachZ ZFL WDT")) {
-               printk(KERN_ERR "cannot reserve I/O ports at %d\n",
-                                                       ZF_IOBASE);
+               pr_err("cannot reserve I/O ports at %d\n", ZF_IOBASE);
                ret = -EBUSY;
                goto no_region;
        }
 
        ret = register_reboot_notifier(&zf_notifier);
        if (ret) {
-               printk(KERN_ERR "can't register reboot notifier (err=%d)\n",
-                                                                       ret);
+               pr_err("can't register reboot notifier (err=%d)\n", ret);
                goto no_reboot;
        }
 
        ret = misc_register(&zf_miscdev);
        if (ret) {
-               printk(KERN_ERR "can't misc_register on minor=%d\n",
-                                                       WATCHDOG_MINOR);
+               pr_err("can't misc_register on minor=%d\n", WATCHDOG_MINOR);
                goto no_misc;
        }
 
index af63ecf..8f4a74e 100644 (file)
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/fs.h>
 #include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include <linux/init.h>
 #include <linux/bitops.h>
 #include <linux/platform_device.h>
 #include <linux/spinlock.h>
-#include <linux/uaccess.h>
 #include <linux/io.h>
-#include <linux/device.h>
 #include <linux/slab.h>
 
 #define DEFAULT_HEARTBEAT 60
 #define MAX_HEARTBEAT     60
 
-static int heartbeat = DEFAULT_HEARTBEAT;
-static int nowayout  = WATCHDOG_NOWAYOUT;
+static unsigned int heartbeat = DEFAULT_HEARTBEAT;
+static bool nowayout  = WATCHDOG_NOWAYOUT;
 
 /*
  * Memory mapping: a single byte, 3 first lower bits to select bit 3
@@ -45,15 +42,8 @@ static int nowayout  = WATCHDOG_NOWAYOUT;
 
 static DEFINE_SPINLOCK(io_lock);
 
-static unsigned long wdt_status;
-#define WDT_IN_USE     0
-#define WDT_RUNNING    1
-#define WDT_OK_TO_CLOSE 2
-
 static int nodelay;
-static struct resource *wdt_mem;
 static void __iomem    *wdt_base;
-static struct platform_device *max63xx_pdev;
 
 /*
  * The timeout values used are actually the absolute minimum the chip
@@ -117,7 +107,7 @@ max63xx_select_timeout(struct max63xx_timeout *table, int value)
        return NULL;
 }
 
-static void max63xx_wdt_ping(void)
+static int max63xx_wdt_ping(struct watchdog_device *wdd)
 {
        u8 val;
 
@@ -129,15 +119,14 @@ static void max63xx_wdt_ping(void)
        __raw_writeb(val & ~MAX6369_WDI, wdt_base);
 
        spin_unlock(&io_lock);
+       return 0;
 }
 
-static void max63xx_wdt_enable(struct max63xx_timeout *entry)
+static int max63xx_wdt_start(struct watchdog_device *wdd)
 {
+       struct max63xx_timeout *entry = watchdog_get_drvdata(wdd);
        u8 val;
 
-       if (test_and_set_bit(WDT_RUNNING, &wdt_status))
-               return;
-
        spin_lock(&io_lock);
 
        val = __raw_readb(wdt_base);
@@ -149,10 +138,11 @@ static void max63xx_wdt_enable(struct max63xx_timeout *entry)
 
        /* check for a edge triggered startup */
        if (entry->tdelay == 0)
-               max63xx_wdt_ping();
+               max63xx_wdt_ping(wdd);
+       return 0;
 }
 
-static void max63xx_wdt_disable(void)
+static int max63xx_wdt_stop(struct watchdog_device *wdd)
 {
        u8 val;
 
@@ -164,113 +154,29 @@ static void max63xx_wdt_disable(void)
        __raw_writeb(val, wdt_base);
 
        spin_unlock(&io_lock);
-
-       clear_bit(WDT_RUNNING, &wdt_status);
-}
-
-static int max63xx_wdt_open(struct inode *inode, struct file *file)
-{
-       if (test_and_set_bit(WDT_IN_USE, &wdt_status))
-               return -EBUSY;
-
-       max63xx_wdt_enable(current_timeout);
-       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
-
-       return nonseekable_open(inode, file);
-}
-
-static ssize_t max63xx_wdt_write(struct file *file, const char *data,
-                                size_t len, loff_t *ppos)
-{
-       if (len) {
-               if (!nowayout) {
-                       size_t i;
-
-                       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
-                       for (i = 0; i != len; i++) {
-                               char c;
-
-                               if (get_user(c, data + i))
-                                       return -EFAULT;
-
-                               if (c == 'V')
-                                       set_bit(WDT_OK_TO_CLOSE, &wdt_status);
-                       }
-               }
-
-               max63xx_wdt_ping();
-       }
-
-       return len;
+       return 0;
 }
 
-static const struct watchdog_info ident = {
-       .options = WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
+static const struct watchdog_info max63xx_wdt_info = {
+       .options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
        .identity = "max63xx Watchdog",
 };
 
-static long max63xx_wdt_ioctl(struct file *file, unsigned int cmd,
-                             unsigned long arg)
-{
-       int ret = -ENOTTY;
-
-       switch (cmd) {
-       case WDIOC_GETSUPPORT:
-               ret = copy_to_user((struct watchdog_info *)arg, &ident,
-                                  sizeof(ident)) ? -EFAULT : 0;
-               break;
-
-       case WDIOC_GETSTATUS:
-       case WDIOC_GETBOOTSTATUS:
-               ret = put_user(0, (int *)arg);
-               break;
-
-       case WDIOC_KEEPALIVE:
-               max63xx_wdt_ping();
-               ret = 0;
-               break;
-
-       case WDIOC_GETTIMEOUT:
-               ret = put_user(heartbeat, (int *)arg);
-               break;
-       }
-       return ret;
-}
-
-static int max63xx_wdt_release(struct inode *inode, struct file *file)
-{
-       if (test_bit(WDT_OK_TO_CLOSE, &wdt_status))
-               max63xx_wdt_disable();
-       else
-               dev_crit(&max63xx_pdev->dev,
-                        "device closed unexpectedly - timer will not stop\n");
-
-       clear_bit(WDT_IN_USE, &wdt_status);
-       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
-
-       return 0;
-}
-
-static const struct file_operations max63xx_wdt_fops = {
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .write          = max63xx_wdt_write,
-       .unlocked_ioctl = max63xx_wdt_ioctl,
-       .open           = max63xx_wdt_open,
-       .release        = max63xx_wdt_release,
+static const struct watchdog_ops max63xx_wdt_ops = {
+       .owner = THIS_MODULE,
+       .start = max63xx_wdt_start,
+       .stop = max63xx_wdt_stop,
+       .ping = max63xx_wdt_ping,
 };
 
-static struct miscdevice max63xx_wdt_miscdev = {
-       .minor  = WATCHDOG_MINOR,
-       .name   = "watchdog",
-       .fops   = &max63xx_wdt_fops,
+static struct watchdog_device max63xx_wdt_dev = {
+       .info = &max63xx_wdt_info,
+       .ops = &max63xx_wdt_ops,
 };
 
 static int __devinit max63xx_wdt_probe(struct platform_device *pdev)
 {
-       int ret = 0;
-       int size;
-       struct device *dev = &pdev->dev;
+       struct resource *wdt_mem;
        struct max63xx_timeout *table;
 
        table = (struct max63xx_timeout *)pdev->id_entry->driver_data;
@@ -278,68 +184,34 @@ static int __devinit max63xx_wdt_probe(struct platform_device *pdev)
        if (heartbeat < 1 || heartbeat > MAX_HEARTBEAT)
                heartbeat = DEFAULT_HEARTBEAT;
 
-       dev_info(dev, "requesting %ds heartbeat\n", heartbeat);
+       dev_info(&pdev->dev, "requesting %ds heartbeat\n", heartbeat);
        current_timeout = max63xx_select_timeout(table, heartbeat);
 
        if (!current_timeout) {
-               dev_err(dev, "unable to satisfy heartbeat request\n");
+               dev_err(&pdev->dev, "unable to satisfy heartbeat request\n");
                return -EINVAL;
        }
 
-       dev_info(dev, "using %ds heartbeat with %ds initial delay\n",
+       dev_info(&pdev->dev, "using %ds heartbeat with %ds initial delay\n",
                 current_timeout->twd, current_timeout->tdelay);
 
        heartbeat = current_timeout->twd;
 
-       max63xx_pdev = pdev;
-
        wdt_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (wdt_mem == NULL) {
-               dev_err(dev, "failed to get memory region resource\n");
-               return -ENOENT;
-       }
+       wdt_base = devm_request_and_ioremap(&pdev->dev, wdt_mem);
+       if (!wdt_base)
+               return -ENOMEM;
 
-       size = resource_size(wdt_mem);
-       if (!request_mem_region(wdt_mem->start, size, pdev->name)) {
-               dev_err(dev, "failed to get memory region\n");
-               return -ENOENT;
-       }
-
-       wdt_base = ioremap(wdt_mem->start, size);
-       if (!wdt_base) {
-               dev_err(dev, "failed to map memory region\n");
-               ret = -ENOMEM;
-               goto out_request;
-       }
+       max63xx_wdt_dev.timeout = heartbeat;
+       watchdog_set_nowayout(&max63xx_wdt_dev, nowayout);
+       watchdog_set_drvdata(&max63xx_wdt_dev, current_timeout);
 
-       ret = misc_register(&max63xx_wdt_miscdev);
-       if (ret < 0) {
-               dev_err(dev, "cannot register misc device\n");
-               goto out_unmap;
-       }
-
-       return 0;
-
-out_unmap:
-       iounmap(wdt_base);
-out_request:
-       release_mem_region(wdt_mem->start, size);
-       wdt_mem = NULL;
-
-       return ret;
+       return watchdog_register_device(&max63xx_wdt_dev);
 }
 
 static int __devexit max63xx_wdt_remove(struct platform_device *pdev)
 {
-       misc_deregister(&max63xx_wdt_miscdev);
-       if (wdt_mem) {
-               release_mem_region(wdt_mem->start, resource_size(wdt_mem));
-               wdt_mem = NULL;
-       }
-
-       if (wdt_base)
-               iounmap(wdt_base);
-
+       watchdog_unregister_device(&max63xx_wdt_dev);
        return 0;
 }
 
@@ -375,7 +247,7 @@ MODULE_PARM_DESC(heartbeat,
                 __MODULE_STRING(MAX_HEARTBEAT) ", default "
                 __MODULE_STRING(DEFAULT_HEARTBEAT));
 
-module_param(nowayout, int, 0);
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
                 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
index bc820d1..37e4b52 100644 (file)
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define VERSION "0.6"
 #define WATCHDOG_NAME "mixcomwd"
-#define PFX WATCHDOG_NAME ": "
 
 #include <linux/module.h>
 #include <linux/moduleparam.h>
@@ -107,8 +108,8 @@ static int mixcomwd_timer_alive;
 static DEFINE_TIMER(mixcomwd_timer, mixcomwd_timerfun, 0, 0);
 static char expect_close;
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -156,15 +157,13 @@ static int mixcomwd_release(struct inode *inode, struct file *file)
 {
        if (expect_close == 42) {
                if (mixcomwd_timer_alive) {
-                       printk(KERN_ERR PFX
-                               "release called while internal timer alive");
+                       pr_err("release called while internal timer alive\n");
                        return -EBUSY;
                }
                mixcomwd_timer_alive = 1;
                mod_timer(&mixcomwd_timer, jiffies + 5 * HZ);
        } else
-               printk(KERN_CRIT PFX
-                   "WDT device closed unexpectedly.  WDT will not stop!\n");
+               pr_crit("WDT device closed unexpectedly.  WDT will not stop!\n");
 
        clear_bit(0, &mixcomwd_opened);
        expect_close = 0;
@@ -274,22 +273,19 @@ static int __init mixcomwd_init(void)
        }
 
        if (!found) {
-               printk(KERN_ERR PFX
-                       "No card detected, or port not available.\n");
+               pr_err("No card detected, or port not available\n");
                return -ENODEV;
        }
 
        ret = misc_register(&mixcomwd_miscdev);
        if (ret) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                                       WATCHDOG_MINOR, ret);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      WATCHDOG_MINOR, ret);
                goto error_misc_register_watchdog;
        }
 
-       printk(KERN_INFO
-               "MixCOM watchdog driver v%s, watchdog port at 0x%3x\n",
-                                       VERSION, watchdog_port);
+       pr_info("MixCOM watchdog driver v%s, watchdog port at 0x%3x\n",
+               VERSION, watchdog_port);
 
        return 0;
 
@@ -303,8 +299,7 @@ static void __exit mixcomwd_exit(void)
 {
        if (!nowayout) {
                if (mixcomwd_timer_alive) {
-                       printk(KERN_WARNING PFX "I quit now, hardware will"
-                              " probably reboot!\n");
+                       pr_warn("I quit now, hardware will probably reboot!\n");
                        del_timer_sync(&mixcomwd_timer);
                        mixcomwd_timer_alive = 0;
                }
index 20feb4d..40f7bf1 100644 (file)
@@ -17,6 +17,8 @@
  * option) any later version.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/fs.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -60,8 +62,8 @@ module_param(reset, bool, 0);
 MODULE_PARM_DESC(reset,
        "Watchdog Interrupt/Reset Mode. 0 = interrupt, 1 = reset");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
                 "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
@@ -96,7 +98,7 @@ static void mpc8xxx_wdt_timer_ping(unsigned long arg)
 
 static void mpc8xxx_wdt_pr_warn(const char *msg)
 {
-       pr_crit("mpc8xxx_wdt: %s, expect the %s soon!\n", msg,
+       pr_crit("%s, expect the %s soon!\n", msg,
                reset ? "reset" : "machine check exception");
 }
 
@@ -209,7 +211,7 @@ static int __devinit mpc8xxx_wdt_probe(struct platform_device *ofdev)
 
        enabled = in_be32(&wd_base->swcrr) & SWCRR_SWEN;
        if (!enabled && wdt_type->hw_enabled) {
-               pr_info("mpc8xxx_wdt: could not be enabled in software\n");
+               pr_info("could not be enabled in software\n");
                ret = -ENOSYS;
                goto err_unmap;
        }
@@ -226,9 +228,8 @@ static int __devinit mpc8xxx_wdt_probe(struct platform_device *ofdev)
                goto err_unmap;
 #endif
 
-       pr_info("WDT driver for MPC8xxx initialized. mode:%s timeout=%d "
-               "(%d seconds)\n", reset ? "reset" : "interrupt", timeout,
-               timeout_sec);
+       pr_info("WDT driver for MPC8xxx initialized. mode:%s timeout=%d (%d seconds)\n",
+               reset ? "reset" : "interrupt", timeout, timeout_sec);
 
        /*
         * If the watchdog was previously enabled or we're running on
@@ -303,7 +304,7 @@ static int mpc8xxx_wdt_init_late(void)
        ret = misc_register(&mpc8xxx_wdt_miscdev);
        if (ret) {
                pr_err("cannot register miscdev on minor=%d (err=%d)\n",
-                       WATCHDOG_MINOR, ret);
+                      WATCHDOG_MINOR, ret);
                return ret;
        }
        return 0;
index 82ccd36..7c741dc 100644 (file)
@@ -19,6 +19,9 @@
  *     (c) Copyright 1995    Alan Cox <alan@lxorguk.ukuu.org.uk>
  *
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
@@ -44,7 +47,7 @@ struct mpcore_wdt {
        char            expect_close;
 };
 
-static struct platform_device *mpcore_wdt_dev;
+static struct platform_device *mpcore_wdt_pdev;
 static DEFINE_SPINLOCK(wdt_lock);
 
 #define TIMER_MARGIN   60
@@ -54,8 +57,8 @@ MODULE_PARM_DESC(mpcore_margin,
        "MPcore timer margin in seconds. (0 < mpcore_margin < 65536, default="
                                __MODULE_STRING(TIMER_MARGIN) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
        "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -148,7 +151,7 @@ static int mpcore_wdt_set_heartbeat(int t)
  */
 static int mpcore_wdt_open(struct inode *inode, struct file *file)
 {
-       struct mpcore_wdt *wdt = platform_get_drvdata(mpcore_wdt_dev);
+       struct mpcore_wdt *wdt = platform_get_drvdata(mpcore_wdt_pdev);
 
        if (test_and_set_bit(0, &wdt->timer_alive))
                return -EBUSY;
@@ -298,9 +301,9 @@ static long mpcore_wdt_ioctl(struct file *file, unsigned int cmd,
  *     System shutdown handler.  Turn off the watchdog if we're
  *     restarting or halting the system.
  */
-static void mpcore_wdt_shutdown(struct platform_device *dev)
+static void mpcore_wdt_shutdown(struct platform_device *pdev)
 {
-       struct mpcore_wdt *wdt = platform_get_drvdata(dev);
+       struct mpcore_wdt *wdt = platform_get_drvdata(pdev);
 
        if (system_state == SYSTEM_RESTART || system_state == SYSTEM_HALT)
                mpcore_wdt_stop(wdt);
@@ -324,99 +327,79 @@ static struct miscdevice mpcore_wdt_miscdev = {
        .fops           = &mpcore_wdt_fops,
 };
 
-static int __devinit mpcore_wdt_probe(struct platform_device *dev)
+static int __devinit mpcore_wdt_probe(struct platform_device *pdev)
 {
        struct mpcore_wdt *wdt;
        struct resource *res;
        int ret;
 
        /* We only accept one device, and it must have an id of -1 */
-       if (dev->id != -1)
+       if (pdev->id != -1)
                return -ENODEV;
 
-       res = platform_get_resource(dev, IORESOURCE_MEM, 0);
-       if (!res) {
-               ret = -ENODEV;
-               goto err_out;
-       }
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res)
+               return -ENODEV;
 
-       wdt = kzalloc(sizeof(struct mpcore_wdt), GFP_KERNEL);
-       if (!wdt) {
-               ret = -ENOMEM;
-               goto err_out;
+       wdt = devm_kzalloc(&pdev->dev, sizeof(struct mpcore_wdt), GFP_KERNEL);
+       if (!wdt)
+               return -ENOMEM;
+
+       wdt->dev = &pdev->dev;
+       wdt->irq = platform_get_irq(pdev, 0);
+       if (wdt->irq >= 0) {
+               ret = devm_request_irq(wdt->dev, 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);
+                       return ret;
+               }
        }
 
-       wdt->dev = &dev->dev;
-       wdt->irq = platform_get_irq(dev, 0);
-       if (wdt->irq < 0) {
-               ret = -ENXIO;
-               goto err_free;
-       }
-       wdt->base = ioremap(res->start, resource_size(res));
-       if (!wdt->base) {
-               ret = -ENOMEM;
-               goto err_free;
-       }
+       wdt->base = devm_ioremap(wdt->dev, res->start, resource_size(res));
+       if (!wdt->base)
+               return -ENOMEM;
 
-       mpcore_wdt_miscdev.parent = &dev->dev;
+       mpcore_wdt_miscdev.parent = &pdev->dev;
        ret = misc_register(&mpcore_wdt_miscdev);
        if (ret) {
                dev_printk(KERN_ERR, wdt->dev,
                        "cannot register miscdev on minor=%d (err=%d)\n",
                                                        WATCHDOG_MINOR, ret);
-               goto err_misc;
-       }
-
-       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);
-               goto err_irq;
+               return ret;
        }
 
        mpcore_wdt_stop(wdt);
-       platform_set_drvdata(dev, wdt);
-       mpcore_wdt_dev = dev;
+       platform_set_drvdata(pdev, wdt);
+       mpcore_wdt_pdev = pdev;
 
        return 0;
-
-err_irq:
-       misc_deregister(&mpcore_wdt_miscdev);
-err_misc:
-       iounmap(wdt->base);
-err_free:
-       kfree(wdt);
-err_out:
-       return ret;
 }
 
-static int __devexit mpcore_wdt_remove(struct platform_device *dev)
+static int __devexit mpcore_wdt_remove(struct platform_device *pdev)
 {
-       struct mpcore_wdt *wdt = platform_get_drvdata(dev);
-
-       platform_set_drvdata(dev, NULL);
+       platform_set_drvdata(pdev, NULL);
 
        misc_deregister(&mpcore_wdt_miscdev);
 
-       mpcore_wdt_dev = NULL;
+       mpcore_wdt_pdev = NULL;
 
-       free_irq(wdt->irq, wdt);
-       iounmap(wdt->base);
-       kfree(wdt);
        return 0;
 }
 
 #ifdef CONFIG_PM
-static int mpcore_wdt_suspend(struct platform_device *dev, pm_message_t msg)
+static int mpcore_wdt_suspend(struct platform_device *pdev, pm_message_t msg)
 {
-       struct mpcore_wdt *wdt = platform_get_drvdata(dev);
+       struct mpcore_wdt *wdt = platform_get_drvdata(pdev);
        mpcore_wdt_stop(wdt);           /* Turn the WDT off */
        return 0;
 }
 
-static int mpcore_wdt_resume(struct platform_device *dev)
+static int mpcore_wdt_resume(struct platform_device *pdev)
 {
-       struct mpcore_wdt *wdt = platform_get_drvdata(dev);
+       struct mpcore_wdt *wdt = platform_get_drvdata(pdev);
        /* re-activate timer */
        if (test_bit(0, &wdt->timer_alive))
                mpcore_wdt_start(wdt);
@@ -442,9 +425,6 @@ static struct platform_driver mpcore_wdt_driver = {
        },
 };
 
-static char banner[] __initdata = KERN_INFO "MPcore Watchdog Timer: 0.1. "
-               "mpcore_noboot=%d mpcore_margin=%d sec (nowayout= %d)\n";
-
 static int __init mpcore_wdt_init(void)
 {
        /*
@@ -453,11 +433,12 @@ static int __init mpcore_wdt_init(void)
         */
        if (mpcore_wdt_set_heartbeat(mpcore_margin)) {
                mpcore_wdt_set_heartbeat(TIMER_MARGIN);
-               printk(KERN_INFO "mpcore_margin value must be 0 < mpcore_margin < 65536, using %d\n",
+               pr_info("mpcore_margin value must be 0 < mpcore_margin < 65536, using %d\n",
                        TIMER_MARGIN);
        }
 
-       printk(banner, mpcore_noboot, mpcore_margin, nowayout);
+       pr_info("MPcore Watchdog Timer: 0.1. mpcore_noboot=%d mpcore_margin=%d sec (nowayout= %d)\n",
+               mpcore_noboot, mpcore_margin, nowayout);
 
        return platform_driver_register(&mpcore_wdt_driver);
 }
index 97f8a48..c53d025 100644 (file)
@@ -15,6 +15,8 @@
  * or implied.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/fs.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -58,8 +60,8 @@ static unsigned int bus_clk;
 static char expect_close;
 static DEFINE_SPINLOCK(mv64x60_wdt_spinlock);
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -100,7 +102,7 @@ static void mv64x60_wdt_handler_enable(void)
        if (mv64x60_wdt_toggle_wdc(MV64x60_WDC_ENABLED_FALSE,
                                   MV64x60_WDC_ENABLE_SHIFT)) {
                mv64x60_wdt_service();
-               printk(KERN_NOTICE "mv64x60_wdt: watchdog activated\n");
+               pr_notice("watchdog activated\n");
        }
 }
 
@@ -108,7 +110,7 @@ static void mv64x60_wdt_handler_disable(void)
 {
        if (mv64x60_wdt_toggle_wdc(MV64x60_WDC_ENABLED_TRUE,
                                   MV64x60_WDC_ENABLE_SHIFT))
-               printk(KERN_NOTICE "mv64x60_wdt: watchdog deactivated\n");
+               pr_notice("watchdog deactivated\n");
 }
 
 static void mv64x60_wdt_set_timeout(unsigned int timeout)
@@ -139,8 +141,7 @@ static int mv64x60_wdt_release(struct inode *inode, struct file *file)
        if (expect_close == 42)
                mv64x60_wdt_handler_disable();
        else {
-               printk(KERN_CRIT
-                      "mv64x60_wdt: unexpected close, not stopping timer!\n");
+               pr_crit("unexpected close, not stopping timer!\n");
                mv64x60_wdt_service();
        }
        expect_close = 0;
@@ -308,7 +309,7 @@ static struct platform_driver mv64x60_wdt_driver = {
 
 static int __init mv64x60_wdt_init(void)
 {
-       printk(KERN_INFO "MV64x60 watchdog driver\n");
+       pr_info("MV64x60 watchdog driver\n");
 
        return platform_driver_register(&mv64x60_wdt_driver);
 }
index 529085b..ea4c744 100644 (file)
@@ -55,8 +55,8 @@ module_param(heartbeat, int, 0);
 MODULE_PARM_DESC(heartbeat, "Watchdog heartbeats in seconds. "
        "(default = " __MODULE_STRING(WDT_HEARTBEAT) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
        "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
index 809f41c..6bbb9ef 100644 (file)
@@ -21,6 +21,8 @@
  *     Includes, defines, variables, module parameters, ...
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
@@ -41,7 +43,6 @@
 #define TCO_VERSION "0.01"
 #define TCO_MODULE_NAME "NV_TCO"
 #define TCO_DRIVER_NAME   TCO_MODULE_NAME ", v" TCO_VERSION
-#define PFX TCO_MODULE_NAME ": "
 
 /* internal variables */
 static unsigned int tcobase;
@@ -60,8 +61,8 @@ module_param(heartbeat, int, 0);
 MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (2<heartbeat<39, "
                            "default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started"
                " (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
@@ -169,8 +170,7 @@ static int nv_tco_release(struct inode *inode, struct file *file)
        if (tco_expect_close == 42) {
                tco_timer_stop();
        } else {
-               printk(KERN_CRIT PFX "Unexpected close, not stopping "
-                      "watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
                tco_timer_keepalive();
        }
        clear_bit(0, &timer_alive);
@@ -323,15 +323,14 @@ static unsigned char __devinit nv_tco_getdevice(void)
        val &= 0xffff;
        if (val == 0x0001 || val == 0x0000) {
                /* Something is wrong here, bar isn't setup */
-               printk(KERN_ERR PFX "failed to get tcobase address\n");
+               pr_err("failed to get tcobase address\n");
                return 0;
        }
        val &= 0xff00;
        tcobase = val + 0x40;
 
        if (!request_region(tcobase, 0x10, "NV TCO")) {
-               printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
-                      tcobase);
+               pr_err("I/O address 0x%04x already in use\n", tcobase);
                return 0;
        }
 
@@ -347,7 +346,7 @@ static unsigned char __devinit nv_tco_getdevice(void)
 
        /* Disable SMI caused by TCO */
        if (!request_region(MCP51_SMI_EN(tcobase), 4, "NV TCO")) {
-               printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
+               pr_err("I/O address 0x%04x already in use\n",
                       MCP51_SMI_EN(tcobase));
                goto out;
        }
@@ -357,7 +356,7 @@ static unsigned char __devinit nv_tco_getdevice(void)
        val = inl(MCP51_SMI_EN(tcobase));
        release_region(MCP51_SMI_EN(tcobase), 4);
        if (val & MCP51_SMI_EN_TCO) {
-               printk(KERN_ERR PFX "Could not disable SMI caused by TCO\n");
+               pr_err("Could not disable SMI caused by TCO\n");
                goto out;
        }
 
@@ -367,8 +366,7 @@ static unsigned char __devinit nv_tco_getdevice(void)
        pci_write_config_dword(tco_pci, MCP51_SMBUS_SETUP_B, val);
        pci_read_config_dword(tco_pci, MCP51_SMBUS_SETUP_B, &val);
        if (!(val & MCP51_SMBUS_SETUP_B_TCO_REBOOT)) {
-               printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, reboot "
-                      "disabled by hardware\n");
+               pr_err("failed to reset NO_REBOOT flag, reboot disabled by hardware\n");
                goto out;
        }
 
@@ -387,8 +385,8 @@ static int __devinit nv_tco_init(struct platform_device *dev)
                return -ENODEV;
 
        /* Check to see if last reboot was due to watchdog timeout */
-       printk(KERN_INFO PFX "Watchdog reboot %sdetected.\n",
-              inl(TCO_STS(tcobase)) & TCO_STS_TCO2TO_STS ? "" : "not ");
+       pr_info("Watchdog reboot %sdetected\n",
+               inl(TCO_STS(tcobase)) & TCO_STS_TCO2TO_STS ? "" : "not ");
 
        /* Clear out the old status */
        outl(TCO_STS_RESET, TCO_STS(tcobase));
@@ -400,14 +398,14 @@ static int __devinit nv_tco_init(struct platform_device *dev)
        if (tco_timer_set_heartbeat(heartbeat)) {
                heartbeat = WATCHDOG_HEARTBEAT;
                tco_timer_set_heartbeat(heartbeat);
-               printk(KERN_INFO PFX "heartbeat value must be 2<heartbeat<39, "
-                      "using %d\n", heartbeat);
+               pr_info("heartbeat value must be 2<heartbeat<39, using %d\n",
+                       heartbeat);
        }
 
        ret = misc_register(&nv_tco_miscdev);
        if (ret != 0) {
-               printk(KERN_ERR PFX "cannot register miscdev on minor=%d "
-                      "(err=%d)\n", WATCHDOG_MINOR, ret);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      WATCHDOG_MINOR, ret);
                goto unreg_region;
        }
 
@@ -415,8 +413,8 @@ static int __devinit nv_tco_init(struct platform_device *dev)
 
        tco_timer_stop();
 
-       printk(KERN_INFO PFX "initialized (0x%04x). heartbeat=%d sec "
-              "(nowayout=%d)\n", tcobase, heartbeat, nowayout);
+       pr_info("initialized (0x%04x). heartbeat=%d sec (nowayout=%d)\n",
+               tcobase, heartbeat, nowayout);
 
        return 0;
 
@@ -439,8 +437,7 @@ static void __devexit nv_tco_cleanup(void)
        pci_write_config_dword(tco_pci, MCP51_SMBUS_SETUP_B, val);
        pci_read_config_dword(tco_pci, MCP51_SMBUS_SETUP_B, &val);
        if (val & MCP51_SMBUS_SETUP_B_TCO_REBOOT) {
-               printk(KERN_CRIT PFX "Couldn't unset REBOOT bit.  Machine may "
-                      "soon reset\n");
+               pr_crit("Couldn't unset REBOOT bit.  Machine may soon reset\n");
        }
 
        /* Deregister */
@@ -483,8 +480,7 @@ static int __init nv_tco_init_module(void)
 {
        int err;
 
-       printk(KERN_INFO PFX "NV TCO WatchDog Timer Driver v%s\n",
-              TCO_VERSION);
+       pr_info("NV TCO WatchDog Timer Driver v%s\n", TCO_VERSION);
 
        err = platform_driver_register(&nv_tco_driver);
        if (err)
@@ -508,7 +504,7 @@ static void __exit nv_tco_cleanup_module(void)
 {
        platform_device_unregister(nv_tco_platform_device);
        platform_driver_unregister(&nv_tco_driver);
-       printk(KERN_INFO PFX "NV TCO Watchdog Module Unloaded.\n");
+       pr_info("NV TCO Watchdog Module Unloaded\n");
 }
 
 module_init(nv_tco_init_module);
index 7c0d863..4612088 100644 (file)
@@ -52,6 +52,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/miscdevice.h>
 #include <linux/interrupt.h>
 #include <linux/watchdog.h>
@@ -95,8 +97,8 @@ MODULE_PARM_DESC(heartbeat,
        "Watchdog heartbeat in seconds. (0 < heartbeat, default="
                                __MODULE_STRING(WD_TIMO) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, S_IRUGO);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, S_IRUGO);
 MODULE_PARM_DESC(nowayout,
        "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -201,7 +203,7 @@ static void __init octeon_wdt_build_stage1(void)
        uasm_resolve_relocs(relocs, labels);
 
        len = (int)(p - nmi_stage1_insns);
-       pr_debug("Synthesized NMI stage 1 handler (%d instructions).\n", len);
+       pr_debug("Synthesized NMI stage 1 handler (%d instructions)\n", len);
 
        pr_debug("\t.set push\n");
        pr_debug("\t.set noreorder\n");
@@ -627,7 +629,7 @@ static int octeon_wdt_release(struct inode *inode, struct file *file)
                do_coundown = 0;
                octeon_wdt_ping();
        } else {
-               pr_crit("octeon_wdt: WDT device closed unexpectedly.  WDT will not stop!\n");
+               pr_crit("WDT device closed unexpectedly.  WDT will not stop!\n");
        }
        clear_bit(0, &octeon_wdt_is_open);
        expect_close = 0;
@@ -684,12 +686,12 @@ static int __init octeon_wdt_init(void)
 
        octeon_wdt_calc_parameters(heartbeat);
 
-       pr_info("octeon_wdt: Initial granularity %d Sec.\n", timeout_sec);
+       pr_info("Initial granularity %d Sec\n", timeout_sec);
 
        ret = misc_register(&octeon_wdt_miscdev);
        if (ret) {
-               pr_err("octeon_wdt: cannot register miscdev on minor=%d (err=%d)\n",
-                       WATCHDOG_MINOR, ret);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      WATCHDOG_MINOR, ret);
                goto out;
        }
 
index f359ab8..55d2f66 100644 (file)
@@ -19,6 +19,8 @@
 *                know the wdt reset interval
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
@@ -99,7 +101,7 @@ static void xwdt_stop(void)
        iowrite32(0, xdev.base + XWT_TWCSR1_OFFSET);
 
        spin_unlock(&spinlock);
-       printk(KERN_INFO PFX "Stopped!\n");
+       pr_info("Stopped!\n");
 }
 
 static void xwdt_keepalive(void)
@@ -165,7 +167,7 @@ static int xwdt_open(struct inode *inode, struct file *file)
                __module_get(THIS_MODULE);
 
        xwdt_start();
-       printk(KERN_INFO PFX "Started...\n");
+       pr_info("Started...\n");
 
        return nonseekable_open(inode, file);
 }
@@ -175,8 +177,7 @@ static int xwdt_release(struct inode *inode, struct file *file)
        if (expect_close == 42) {
                xwdt_stop();
        } else {
-               printk(KERN_CRIT PFX
-                       "Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
                xwdt_keepalive();
        }
 
@@ -300,22 +301,20 @@ static int __devinit xwdt_probe(struct platform_device *pdev)
                                        "clock-frequency", NULL);
 
        if (pfreq == NULL) {
-               printk(KERN_WARNING PFX
-                       "The watchdog clock frequency cannot be obtained!\n");
+               pr_warn("The watchdog clock frequency cannot be obtained!\n");
                no_timeout = 1;
        }
 
        rc = of_address_to_resource(pdev->dev.of_node, 0, &xdev.res);
        if (rc) {
-               printk(KERN_WARNING PFX "invalid address!\n");
+               pr_warn("invalid address!\n");
                return rc;
        }
 
        tmptr = (u32 *)of_get_property(pdev->dev.of_node,
                                        "xlnx,wdt-interval", NULL);
        if (tmptr == NULL) {
-               printk(KERN_WARNING PFX "Parameter \"xlnx,wdt-interval\""
-                                       " not found in device tree!\n");
+               pr_warn("Parameter \"xlnx,wdt-interval\" not found in device tree!\n");
                no_timeout = 1;
        } else {
                xdev.wdt_interval = *tmptr;
@@ -324,8 +323,7 @@ static int __devinit xwdt_probe(struct platform_device *pdev)
        tmptr = (u32 *)of_get_property(pdev->dev.of_node,
                                        "xlnx,wdt-enable-once", NULL);
        if (tmptr == NULL) {
-               printk(KERN_WARNING PFX "Parameter \"xlnx,wdt-enable-once\""
-                                       " not found in device tree!\n");
+               pr_warn("Parameter \"xlnx,wdt-enable-once\" not found in device tree!\n");
                xdev.nowayout = WATCHDOG_NOWAYOUT;
        }
 
@@ -339,20 +337,20 @@ static int __devinit xwdt_probe(struct platform_device *pdev)
        if (!request_mem_region(xdev.res.start,
                        xdev.res.end - xdev.res.start + 1, WATCHDOG_NAME)) {
                rc = -ENXIO;
-               printk(KERN_ERR PFX "memory request failure!\n");
+               pr_err("memory request failure!\n");
                goto err_out;
        }
 
        xdev.base = ioremap(xdev.res.start, xdev.res.end - xdev.res.start + 1);
        if (xdev.base == NULL) {
                rc = -ENOMEM;
-               printk(KERN_ERR PFX "ioremap failure!\n");
+               pr_err("ioremap failure!\n");
                goto release_mem;
        }
 
        rc = xwdt_selftest();
        if (rc == XWT_TIMER_FAILED) {
-               printk(KERN_ERR PFX "SelfTest routine error!\n");
+               pr_err("SelfTest routine error!\n");
                goto unmap_io;
        }
 
@@ -360,20 +358,17 @@ static int __devinit xwdt_probe(struct platform_device *pdev)
 
        rc = misc_register(&xwdt_miscdev);
        if (rc) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                                               xwdt_miscdev.minor, rc);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      xwdt_miscdev.minor, rc);
                goto unmap_io;
        }
 
        if (no_timeout)
-               printk(KERN_INFO PFX
-                       "driver loaded (timeout=? sec, nowayout=%d)\n",
-                                                   xdev.nowayout);
+               pr_info("driver loaded (timeout=? sec, nowayout=%d)\n",
+                       xdev.nowayout);
        else
-               printk(KERN_INFO PFX
-                       "driver loaded (timeout=%d sec, nowayout=%d)\n",
-                                       timeout, xdev.nowayout);
+               pr_info("driver loaded (timeout=%d sec, nowayout=%d)\n",
+                       timeout, xdev.nowayout);
 
        expect_close = 0;
        clear_bit(0, &driver_open);
index d19ff51..8285d65 100644 (file)
@@ -26,6 +26,8 @@
  *     Use the driver model and standard identifiers; handle bigger timeouts.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
@@ -183,7 +185,7 @@ static int omap_wdt_release(struct inode *inode, struct file *file)
 
        pm_runtime_put_sync(wdev->dev);
 #else
-       printk(KERN_CRIT "omap_wdt: Unexpected close, not stopping!\n");
+       pr_crit("Unexpected close, not stopping!\n");
 #endif
        wdev->omap_wdt_users = 0;
 
index 4ad78f8..788aa15 100644 (file)
@@ -10,6 +10,8 @@
  * warranty of any kind, whether express or implied.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 /*
  * Watchdog timer block registers.
  */
-#define TIMER_CTRL             (TIMER_VIRT_BASE + 0x0000)
+#define TIMER_CTRL             0x0000
 #define  WDT_EN                        0x0010
-#define WDT_VAL                        (TIMER_VIRT_BASE + 0x0024)
+#define WDT_VAL                        0x0024
 
 #define WDT_MAX_CYCLE_COUNT    0xffffffff
 #define WDT_IN_USE             0
 #define WDT_OK_TO_CLOSE                1
 
-static int nowayout = WATCHDOG_NOWAYOUT;
+static bool nowayout = WATCHDOG_NOWAYOUT;
 static int heartbeat = -1;             /* module parameter (seconds) */
 static unsigned int wdt_max_duration;  /* (seconds) */
 static unsigned int wdt_tclk;
+static void __iomem *wdt_reg;
 static unsigned long wdt_status;
 static DEFINE_SPINLOCK(wdt_lock);
 
@@ -48,7 +51,7 @@ static void orion_wdt_ping(void)
        spin_lock(&wdt_lock);
 
        /* Reload watchdog duration */
-       writel(wdt_tclk * heartbeat, WDT_VAL);
+       writel(wdt_tclk * heartbeat, wdt_reg + WDT_VAL);
 
        spin_unlock(&wdt_lock);
 }
@@ -60,7 +63,7 @@ static void orion_wdt_enable(void)
        spin_lock(&wdt_lock);
 
        /* Set watchdog duration */
-       writel(wdt_tclk * heartbeat, WDT_VAL);
+       writel(wdt_tclk * heartbeat, wdt_reg + WDT_VAL);
 
        /* Clear watchdog timer interrupt */
        reg = readl(BRIDGE_CAUSE);
@@ -68,9 +71,9 @@ static void orion_wdt_enable(void)
        writel(reg, BRIDGE_CAUSE);
 
        /* Enable watchdog timer */
-       reg = readl(TIMER_CTRL);
+       reg = readl(wdt_reg + TIMER_CTRL);
        reg |= WDT_EN;
-       writel(reg, TIMER_CTRL);
+       writel(reg, wdt_reg + TIMER_CTRL);
 
        /* Enable reset on watchdog */
        reg = readl(RSTOUTn_MASK);
@@ -92,9 +95,9 @@ static void orion_wdt_disable(void)
        writel(reg, RSTOUTn_MASK);
 
        /* Disable watchdog timer */
-       reg = readl(TIMER_CTRL);
+       reg = readl(wdt_reg + TIMER_CTRL);
        reg &= ~WDT_EN;
-       writel(reg, TIMER_CTRL);
+       writel(reg, wdt_reg + TIMER_CTRL);
 
        spin_unlock(&wdt_lock);
 }
@@ -102,7 +105,7 @@ static void orion_wdt_disable(void)
 static int orion_wdt_get_timeleft(int *time_left)
 {
        spin_lock(&wdt_lock);
-       *time_left = readl(WDT_VAL) / wdt_tclk;
+       *time_left = readl(wdt_reg + WDT_VAL) / wdt_tclk;
        spin_unlock(&wdt_lock);
        return 0;
 }
@@ -209,8 +212,7 @@ static int orion_wdt_release(struct inode *inode, struct file *file)
        if (test_bit(WDT_OK_TO_CLOSE, &wdt_status))
                orion_wdt_disable();
        else
-               printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - "
-                                       "timer will not stop\n");
+               pr_crit("Device closed unexpectedly - timer will not stop\n");
        clear_bit(WDT_IN_USE, &wdt_status);
        clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
 
@@ -236,15 +238,20 @@ static struct miscdevice orion_wdt_miscdev = {
 static int __devinit orion_wdt_probe(struct platform_device *pdev)
 {
        struct orion_wdt_platform_data *pdata = pdev->dev.platform_data;
+       struct resource *res;
        int ret;
 
        if (pdata) {
                wdt_tclk = pdata->tclk;
        } else {
-               printk(KERN_ERR "Orion Watchdog misses platform data\n");
+               pr_err("misses platform data\n");
                return -ENODEV;
        }
 
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+       wdt_reg = ioremap(res->start, resource_size(res));
+
        if (orion_wdt_miscdev.parent)
                return -EBUSY;
        orion_wdt_miscdev.parent = &pdev->dev;
@@ -257,8 +264,8 @@ static int __devinit orion_wdt_probe(struct platform_device *pdev)
        if (ret)
                return ret;
 
-       printk(KERN_INFO "Orion Watchdog Timer: Initial timeout %d sec%s\n",
-                               heartbeat, nowayout ? ", nowayout" : "");
+       pr_info("Initial timeout %d sec%s\n",
+               heartbeat, nowayout ? ", nowayout" : "");
        return 0;
 }
 
@@ -302,7 +309,7 @@ MODULE_DESCRIPTION("Orion Processor Watchdog");
 module_param(heartbeat, int, 0);
 MODULE_PARM_DESC(heartbeat, "Initial watchdog heartbeat in seconds");
 
-module_param(nowayout, int, 0);
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
index e78d899..5afb89b 100644 (file)
@@ -18,6 +18,8 @@
  *      Release 1.1
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/miscdevice.h>
@@ -33,7 +35,6 @@
 #include <linux/io.h>
 #include <linux/uaccess.h>
 
-#include <asm/system.h>
 
 /* #define DEBUG 1 */
 
@@ -42,7 +43,6 @@
 
 #define VERSION             "1.1"
 #define MODNAME             "pc87413 WDT"
-#define PFX                 MODNAME ": "
 #define DPFX                MODNAME " - DEBUG: "
 
 #define WDT_INDEX_IO_PORT   (io+0)     /* I/O port base (index register) */
@@ -65,7 +65,7 @@ static char expect_close;             /* is the close expected? */
 
 static DEFINE_SPINLOCK(io_lock);       /* to guard us from io races */
 
-static int nowayout = WATCHDOG_NOWAYOUT;
+static bool nowayout = WATCHDOG_NOWAYOUT;
 
 /* -- Low level function ----------------------------------------*/
 
@@ -87,7 +87,7 @@ static inline void pc87413_select_wdt_out(void)
        outb_p(cr_data, WDT_DATA_IO_PORT);
 
 #ifdef DEBUG
-       printk(KERN_INFO DPFX
+       pr_info(DPFX
                "Select multiple pin,pin55,as WDT output: Bit7 to 1: %d\n",
                                                                cr_data);
 #endif
@@ -111,7 +111,7 @@ static inline void pc87413_enable_swc(void)
        outb_p(cr_data, WDT_DATA_IO_PORT);      /* Index0x30_bit0P1 */
 
 #ifdef DEBUG
-       printk(KERN_INFO DPFX "pc87413 - Enable SWC functions\n");
+       pr_info(DPFX "pc87413 - Enable SWC functions\n");
 #endif
 }
 
@@ -132,7 +132,7 @@ static void pc87413_get_swc_base_addr(void)
 
        swc_base_addr = (addr_h << 8) + addr_l;
 #ifdef DEBUG
-       printk(KERN_INFO DPFX
+       pr_info(DPFX
                "Read SWC I/O Base Address: low %d, high %d, res %d\n",
                                                addr_l, addr_h, swc_base_addr);
 #endif
@@ -145,7 +145,7 @@ static inline void pc87413_swc_bank3(void)
        /* Step 4: Select Bank3 of SWC */
        outb_p(inb(swc_base_addr + 0x0f) | 0x03, swc_base_addr + 0x0f);
 #ifdef DEBUG
-       printk(KERN_INFO DPFX "Select Bank3 of SWC\n");
+       pr_info(DPFX "Select Bank3 of SWC\n");
 #endif
 }
 
@@ -156,7 +156,7 @@ static inline void pc87413_programm_wdto(char pc87413_time)
        /* Step 5: Programm WDTO, Twd. */
        outb_p(pc87413_time, swc_base_addr + WDTO);
 #ifdef DEBUG
-       printk(KERN_INFO DPFX "Set WDTO to %d minutes\n", pc87413_time);
+       pr_info(DPFX "Set WDTO to %d minutes\n", pc87413_time);
 #endif
 }
 
@@ -167,7 +167,7 @@ static inline void pc87413_enable_wden(void)
        /* Step 6: Enable WDEN */
        outb_p(inb(swc_base_addr + WDCTL) | 0x01, swc_base_addr + WDCTL);
 #ifdef DEBUG
-       printk(KERN_INFO DPFX "Enable WDEN\n");
+       pr_info(DPFX "Enable WDEN\n");
 #endif
 }
 
@@ -177,7 +177,7 @@ static inline void pc87413_enable_sw_wd_tren(void)
        /* Enable SW_WD_TREN */
        outb_p(inb(swc_base_addr + WDCFG) | 0x80, swc_base_addr + WDCFG);
 #ifdef DEBUG
-       printk(KERN_INFO DPFX "Enable SW_WD_TREN\n");
+       pr_info(DPFX "Enable SW_WD_TREN\n");
 #endif
 }
 
@@ -188,7 +188,7 @@ static inline void pc87413_disable_sw_wd_tren(void)
        /* Disable SW_WD_TREN */
        outb_p(inb(swc_base_addr + WDCFG) & 0x7f, swc_base_addr + WDCFG);
 #ifdef DEBUG
-       printk(KERN_INFO DPFX "pc87413 - Disable SW_WD_TREN\n");
+       pr_info(DPFX "pc87413 - Disable SW_WD_TREN\n");
 #endif
 }
 
@@ -199,7 +199,7 @@ static inline void pc87413_enable_sw_wd_trg(void)
        /* Enable SW_WD_TRG */
        outb_p(inb(swc_base_addr + WDCTL) | 0x80, swc_base_addr + WDCTL);
 #ifdef DEBUG
-       printk(KERN_INFO DPFX "pc87413 - Enable SW_WD_TRG\n");
+       pr_info(DPFX "pc87413 - Enable SW_WD_TRG\n");
 #endif
 }
 
@@ -210,7 +210,7 @@ static inline void pc87413_disable_sw_wd_trg(void)
        /* Disable SW_WD_TRG */
        outb_p(inb(swc_base_addr + WDCTL) & 0x7f, swc_base_addr + WDCTL);
 #ifdef DEBUG
-       printk(KERN_INFO DPFX "Disable SW_WD_TRG\n");
+       pr_info(DPFX "Disable SW_WD_TRG\n");
 #endif
 }
 
@@ -284,8 +284,7 @@ static int pc87413_open(struct inode *inode, struct file *file)
        /* Reload and activate timer */
        pc87413_refresh();
 
-       printk(KERN_INFO MODNAME
-               "Watchdog enabled. Timeout set to %d minute(s).\n", timeout);
+       pr_info("Watchdog enabled. Timeout set to %d minute(s).\n", timeout);
 
        return nonseekable_open(inode, file);
 }
@@ -308,11 +307,9 @@ static int pc87413_release(struct inode *inode, struct file *file)
 
        if (expect_close == 42) {
                pc87413_disable();
-               printk(KERN_INFO MODNAME
-                               "Watchdog disabled, sleeping again...\n");
+               pr_info("Watchdog disabled, sleeping again...\n");
        } else {
-               printk(KERN_CRIT MODNAME
-                               "Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
                pc87413_refresh();
        }
        clear_bit(0, &timer_enabled);
@@ -428,7 +425,7 @@ static long pc87413_ioctl(struct file *file, unsigned int cmd,
        case WDIOC_KEEPALIVE:
                pc87413_refresh();
 #ifdef DEBUG
-               printk(KERN_INFO DPFX "keepalive\n");
+               pr_info(DPFX "keepalive\n");
 #endif
                return 0;
        case WDIOC_SETTIMEOUT:
@@ -508,7 +505,7 @@ static int __init pc87413_init(void)
 {
        int ret;
 
-       printk(KERN_INFO PFX "Version " VERSION " at io 0x%X\n",
+       pr_info("Version " VERSION " at io 0x%X\n",
                                                        WDT_INDEX_IO_PORT);
 
        if (!request_muxed_region(io, 2, MODNAME))
@@ -516,26 +513,23 @@ static int __init pc87413_init(void)
 
        ret = register_reboot_notifier(&pc87413_notifier);
        if (ret != 0) {
-               printk(KERN_ERR PFX
-                       "cannot register reboot notifier (err=%d)\n", ret);
+               pr_err("cannot register reboot notifier (err=%d)\n", ret);
        }
 
        ret = misc_register(&pc87413_miscdev);
        if (ret != 0) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                       WATCHDOG_MINOR, ret);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      WATCHDOG_MINOR, ret);
                goto reboot_unreg;
        }
-       printk(KERN_INFO PFX "initialized. timeout=%d min \n", timeout);
+       pr_info("initialized. timeout=%d min\n", timeout);
 
        pc87413_select_wdt_out();
        pc87413_enable_swc();
        pc87413_get_swc_base_addr();
 
        if (!request_region(swc_base_addr, 0x20, MODNAME)) {
-               printk(KERN_ERR PFX
-                       "cannot request SWC region at 0x%x\n", swc_base_addr);
+               pr_err("cannot request SWC region at 0x%x\n", swc_base_addr);
                ret = -EBUSY;
                goto misc_unreg;
        }
@@ -568,14 +562,14 @@ static void __exit pc87413_exit(void)
        /* Stop the timer before we leave */
        if (!nowayout) {
                pc87413_disable();
-               printk(KERN_INFO MODNAME "Watchdog disabled.\n");
+               pr_info("Watchdog disabled\n");
        }
 
        misc_deregister(&pc87413_miscdev);
        unregister_reboot_notifier(&pc87413_notifier);
        release_region(swc_base_addr, 0x20);
 
-       printk(KERN_INFO MODNAME " watchdog component driver removed.\n");
+       pr_info("watchdog component driver removed\n");
 }
 
 module_init(pc87413_init);
@@ -597,7 +591,7 @@ MODULE_PARM_DESC(timeout,
                "Watchdog timeout in minutes (default="
                                __MODULE_STRING(DEFAULT_TIMEOUT) ").");
 
-module_param(nowayout, int, 0);
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
index 06f7922..75694cf 100644 (file)
@@ -51,6 +51,8 @@
  *     http://www.pcwatchdog.com/
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>      /* For module specific items */
 #include <linux/moduleparam.h> /* For new moduleparam's */
 #include <linux/types.h>       /* For standard types (like size_t) */
@@ -75,7 +77,6 @@
 #define WATCHDOG_DATE "18 Feb 2007"
 #define WATCHDOG_DRIVER_NAME "ISA-PC Watchdog"
 #define WATCHDOG_NAME "pcwd"
-#define PFX WATCHDOG_NAME ": "
 #define DRIVER_VERSION WATCHDOG_DRIVER_NAME " driver, v" WATCHDOG_VERSION "\n"
 
 /*
@@ -203,8 +204,8 @@ MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. "
        "(2 <= heartbeat <= 7200 or 0=delay-time from dip-switches, default="
                                __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -220,8 +221,7 @@ static int send_isa_command(int cmd)
        int port0, last_port0;  /* Double read for stabilising */
 
        if (debug >= DEBUG)
-               printk(KERN_DEBUG PFX "sending following data cmd=0x%02x\n",
-                       cmd);
+               pr_debug("sending following data cmd=0x%02x\n", cmd);
 
        /* The WCMD bit must be 1 and the command is only 4 bits in size */
        control_status = (cmd & 0x0F) | WD_WCMD;
@@ -240,9 +240,8 @@ static int send_isa_command(int cmd)
        }
 
        if (debug >= DEBUG)
-               printk(KERN_DEBUG PFX "received following data for "
-                       "cmd=0x%02x: port0=0x%02x last_port0=0x%02x\n",
-                       cmd, port0, last_port0);
+               pr_debug("received following data for cmd=0x%02x: port0=0x%02x last_port0=0x%02x\n",
+                        cmd, port0, last_port0);
 
        return port0;
 }
@@ -271,8 +270,7 @@ static int set_command_mode(void)
        pcwd_private.command_mode = found;
 
        if (debug >= DEBUG)
-               printk(KERN_DEBUG PFX "command_mode=%d\n",
-                               pcwd_private.command_mode);
+               pr_debug("command_mode=%d\n", pcwd_private.command_mode);
 
        return found;
 }
@@ -288,8 +286,7 @@ static void unset_command_mode(void)
        pcwd_private.command_mode = 0;
 
        if (debug >= DEBUG)
-               printk(KERN_DEBUG PFX "command_mode=%d\n",
-                               pcwd_private.command_mode);
+               pr_debug("command_mode=%d\n", pcwd_private.command_mode);
 }
 
 static inline void pcwd_check_temperature_support(void)
@@ -336,17 +333,14 @@ static void pcwd_show_card_info(void)
 
        /* Get some extra info from the hardware (in command/debug/diag mode) */
        if (pcwd_private.revision == PCWD_REVISION_A)
-               printk(KERN_INFO PFX
-                       "ISA-PC Watchdog (REV.A) detected at port 0x%04x\n",
-                                                       pcwd_private.io_addr);
+               pr_info("ISA-PC Watchdog (REV.A) detected at port 0x%04x\n",
+                       pcwd_private.io_addr);
        else if (pcwd_private.revision == PCWD_REVISION_C) {
                pcwd_get_firmware();
-               printk(KERN_INFO PFX "ISA-PC Watchdog (REV.C) detected at port "
-                       "0x%04x (Firmware version: %s)\n",
+               pr_info("ISA-PC Watchdog (REV.C) detected at port 0x%04x (Firmware version: %s)\n",
                        pcwd_private.io_addr, pcwd_private.fw_ver_str);
                option_switches = pcwd_get_option_switches();
-               printk(KERN_INFO PFX "Option switches (0x%02x): "
-                       "Temperature Reset Enable=%s, Power On Delay=%s\n",
+               pr_info("Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n",
                        option_switches,
                        ((option_switches & 0x10) ? "ON" : "OFF"),
                        ((option_switches & 0x08) ? "ON" : "OFF"));
@@ -359,22 +353,18 @@ static void pcwd_show_card_info(void)
        }
 
        if (pcwd_private.supports_temp)
-               printk(KERN_INFO PFX "Temperature Option Detected\n");
+               pr_info("Temperature Option Detected\n");
 
        if (pcwd_private.boot_status & WDIOF_CARDRESET)
-               printk(KERN_INFO PFX
-                       "Previous reboot was caused by the card\n");
+               pr_info("Previous reboot was caused by the card\n");
 
        if (pcwd_private.boot_status & WDIOF_OVERHEAT) {
-               printk(KERN_EMERG PFX
-                       "Card senses a CPU Overheat. Panicking!\n");
-               printk(KERN_EMERG PFX
-                       "CPU Overheat\n");
+               pr_emerg("Card senses a CPU Overheat. Panicking!\n");
+               pr_emerg("CPU Overheat\n");
        }
 
        if (pcwd_private.boot_status == 0)
-               printk(KERN_INFO PFX
-                       "No previous trip detected - Cold boot or reset\n");
+               pr_info("No previous trip detected - Cold boot or reset\n");
 }
 
 static void pcwd_timer_ping(unsigned long data)
@@ -404,8 +394,7 @@ static void pcwd_timer_ping(unsigned long data)
 
                spin_unlock(&pcwd_private.io_lock);
        } else {
-               printk(KERN_WARNING PFX
-                       "Heartbeat lost! Will not ping the watchdog\n");
+               pr_warn("Heartbeat lost! Will not ping the watchdog\n");
        }
 }
 
@@ -426,13 +415,13 @@ static int pcwd_start(void)
                stat_reg = inb_p(pcwd_private.io_addr + 2);
                spin_unlock(&pcwd_private.io_lock);
                if (stat_reg & WD_WDIS) {
-                       printk(KERN_INFO PFX "Could not start watchdog\n");
+                       pr_info("Could not start watchdog\n");
                        return -EIO;
                }
        }
 
        if (debug >= VERBOSE)
-               printk(KERN_DEBUG PFX "Watchdog started\n");
+               pr_debug("Watchdog started\n");
 
        return 0;
 }
@@ -454,13 +443,13 @@ static int pcwd_stop(void)
                stat_reg = inb_p(pcwd_private.io_addr + 2);
                spin_unlock(&pcwd_private.io_lock);
                if ((stat_reg & WD_WDIS) == 0) {
-                       printk(KERN_INFO PFX "Could not stop watchdog\n");
+                       pr_info("Could not stop watchdog\n");
                        return -EIO;
                }
        }
 
        if (debug >= VERBOSE)
-               printk(KERN_DEBUG PFX "Watchdog stopped\n");
+               pr_debug("Watchdog stopped\n");
 
        return 0;
 }
@@ -471,7 +460,7 @@ static int pcwd_keepalive(void)
        pcwd_private.next_heartbeat = jiffies + (heartbeat * HZ);
 
        if (debug >= DEBUG)
-               printk(KERN_DEBUG PFX "Watchdog keepalive signal send\n");
+               pr_debug("Watchdog keepalive signal send\n");
 
        return 0;
 }
@@ -484,8 +473,7 @@ static int pcwd_set_heartbeat(int t)
        heartbeat = t;
 
        if (debug >= VERBOSE)
-               printk(KERN_DEBUG PFX "New heartbeat: %d\n",
-                      heartbeat);
+               pr_debug("New heartbeat: %d\n", heartbeat);
 
        return 0;
 }
@@ -518,8 +506,7 @@ static int pcwd_get_status(int *status)
                if (control_status & WD_T110) {
                        *status |= WDIOF_OVERHEAT;
                        if (temp_panic) {
-                               printk(KERN_INFO PFX
-                                       "Temperature overheat trip!\n");
+                               pr_info("Temperature overheat trip!\n");
                                kernel_power_off();
                        }
                }
@@ -530,8 +517,7 @@ static int pcwd_get_status(int *status)
                if (control_status & WD_REVC_TTRP) {
                        *status |= WDIOF_OVERHEAT;
                        if (temp_panic) {
-                               printk(KERN_INFO PFX
-                                       "Temperature overheat trip!\n");
+                               pr_info("Temperature overheat trip!\n");
                                kernel_power_off();
                        }
                }
@@ -548,16 +534,14 @@ static int pcwd_clear_status(void)
                spin_lock(&pcwd_private.io_lock);
 
                if (debug >= VERBOSE)
-                       printk(KERN_INFO PFX
-                                       "clearing watchdog trip status\n");
+                       pr_info("clearing watchdog trip status\n");
 
                control_status = inb_p(pcwd_private.io_addr + 1);
 
                if (debug >= DEBUG) {
-                       printk(KERN_DEBUG PFX "status was: 0x%02x\n",
-                               control_status);
-                       printk(KERN_DEBUG PFX "sending: 0x%02x\n",
-                               (control_status & WD_REVC_R2DS));
+                       pr_debug("status was: 0x%02x\n", control_status);
+                       pr_debug("sending: 0x%02x\n",
+                                (control_status & WD_REVC_R2DS));
                }
 
                /* clear reset status & Keep Relay 2 disable state as it is */
@@ -588,8 +572,7 @@ static int pcwd_get_temperature(int *temperature)
        spin_unlock(&pcwd_private.io_lock);
 
        if (debug >= DEBUG) {
-               printk(KERN_DEBUG PFX "temperature is: %d F\n",
-                       *temperature);
+               pr_debug("temperature is: %d F\n", *temperature);
        }
 
        return 0;
@@ -720,8 +703,7 @@ static int pcwd_close(struct inode *inode, struct file *file)
        if (expect_close == 42)
                pcwd_stop();
        else {
-               printk(KERN_CRIT PFX
-                       "Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
                pcwd_keepalive();
        }
        expect_close = 0;
@@ -828,11 +810,10 @@ static int __devinit pcwd_isa_match(struct device *dev, unsigned int id)
        int retval;
 
        if (debug >= DEBUG)
-               printk(KERN_DEBUG PFX "pcwd_isa_match id=%d\n",
-                       id);
+               pr_debug("pcwd_isa_match id=%d\n", id);
 
        if (!request_region(base_addr, 4, "PCWD")) {
-               printk(KERN_INFO PFX "Port 0x%04x unavailable\n", base_addr);
+               pr_info("Port 0x%04x unavailable\n", base_addr);
                return 0;
        }
 
@@ -870,21 +851,20 @@ static int __devinit pcwd_isa_probe(struct device *dev, unsigned int id)
        int ret;
 
        if (debug >= DEBUG)
-               printk(KERN_DEBUG PFX "pcwd_isa_probe id=%d\n",
-                       id);
+               pr_debug("pcwd_isa_probe id=%d\n", id);
 
        cards_found++;
        if (cards_found == 1)
-               printk(KERN_INFO PFX "v%s Ken Hollis (kenji@bitgate.com)\n",
+               pr_info("v%s Ken Hollis (kenji@bitgate.com)\n",
                                                        WATCHDOG_VERSION);
 
        if (cards_found > 1) {
-               printk(KERN_ERR PFX "This driver only supports 1 device\n");
+               pr_err("This driver only supports 1 device\n");
                return -ENODEV;
        }
 
        if (pcwd_ioports[id] == 0x0000) {
-               printk(KERN_ERR PFX "No I/O-Address for card detected\n");
+               pr_err("No I/O-Address for card detected\n");
                return -ENODEV;
        }
        pcwd_private.io_addr = pcwd_ioports[id];
@@ -896,8 +876,8 @@ static int __devinit pcwd_isa_probe(struct device *dev, unsigned int id)
 
        if (!request_region(pcwd_private.io_addr,
                (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4, "PCWD")) {
-               printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
-                       pcwd_private.io_addr);
+               pr_err("I/O address 0x%04x already in use\n",
+                      pcwd_private.io_addr);
                ret = -EIO;
                goto error_request_region;
        }
@@ -932,30 +912,27 @@ static int __devinit pcwd_isa_probe(struct device *dev, unsigned int id)
           if not reset to the default */
        if (pcwd_set_heartbeat(heartbeat)) {
                pcwd_set_heartbeat(WATCHDOG_HEARTBEAT);
-               printk(KERN_INFO PFX
-                 "heartbeat value must be 2 <= heartbeat <= 7200, using %d\n",
-                                                       WATCHDOG_HEARTBEAT);
+               pr_info("heartbeat value must be 2 <= heartbeat <= 7200, using %d\n",
+                       WATCHDOG_HEARTBEAT);
        }
 
        if (pcwd_private.supports_temp) {
                ret = misc_register(&temp_miscdev);
                if (ret) {
-                       printk(KERN_ERR PFX
-                           "cannot register miscdev on minor=%d (err=%d)\n",
-                                                       TEMP_MINOR, ret);
+                       pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                              TEMP_MINOR, ret);
                        goto error_misc_register_temp;
                }
        }
 
        ret = misc_register(&pcwd_miscdev);
        if (ret) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                                       WATCHDOG_MINOR, ret);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      WATCHDOG_MINOR, ret);
                goto error_misc_register_watchdog;
        }
 
-       printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n",
+       pr_info("initialized. heartbeat=%d sec (nowayout=%d)\n",
                heartbeat, nowayout);
 
        return 0;
@@ -975,8 +952,7 @@ error_request_region:
 static int __devexit pcwd_isa_remove(struct device *dev, unsigned int id)
 {
        if (debug >= DEBUG)
-               printk(KERN_DEBUG PFX "pcwd_isa_remove id=%d\n",
-                       id);
+               pr_debug("pcwd_isa_remove id=%d\n", id);
 
        if (!pcwd_private.io_addr)
                return 1;
@@ -1000,8 +976,7 @@ static int __devexit pcwd_isa_remove(struct device *dev, unsigned int id)
 static void pcwd_isa_shutdown(struct device *dev, unsigned int id)
 {
        if (debug >= DEBUG)
-               printk(KERN_DEBUG PFX "pcwd_isa_shutdown id=%d\n",
-                       id);
+               pr_debug("pcwd_isa_shutdown id=%d\n", id);
 
        pcwd_stop();
 }
@@ -1025,7 +1000,7 @@ static int __init pcwd_init_module(void)
 static void __exit pcwd_cleanup_module(void)
 {
        isa_unregister_driver(&pcwd_isa_driver);
-       printk(KERN_INFO PFX "Watchdog Module Unloaded.\n");
+       pr_info("Watchdog Module Unloaded\n");
 }
 
 module_init(pcwd_init_module);
index b8d14f8..c891399 100644 (file)
@@ -32,6 +32,8 @@
  *     Includes, defines, variables, module parameters, ...
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>      /* For module specific items */
 #include <linux/moduleparam.h> /* For new moduleparam's */
 #include <linux/types.h>       /* For standard types (like size_t) */
@@ -54,8 +56,7 @@
 #define WATCHDOG_VERSION "1.03"
 #define WATCHDOG_DRIVER_NAME "PCI-PC Watchdog"
 #define WATCHDOG_NAME "pcwd_pci"
-#define PFX WATCHDOG_NAME ": "
-#define DRIVER_VERSION WATCHDOG_DRIVER_NAME " driver, v" WATCHDOG_VERSION "\n"
+#define DRIVER_VERSION WATCHDOG_DRIVER_NAME " driver, v" WATCHDOG_VERSION
 
 /* Stuff for the PCI ID's  */
 #ifndef PCI_VENDOR_ID_QUICKLOGIC
@@ -145,8 +146,8 @@ MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. "
        "(0<heartbeat<65536 or 0=delay-time from dip-switches, default="
                                __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
                                        __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
@@ -159,8 +160,8 @@ static int send_command(int cmd, int *msb, int *lsb)
        int got_response, count;
 
        if (debug >= DEBUG)
-               printk(KERN_DEBUG PFX "sending following data "
-               "cmd=0x%02x msb=0x%02x lsb=0x%02x\n", cmd, *msb, *lsb);
+               pr_debug("sending following data cmd=0x%02x msb=0x%02x lsb=0x%02x\n",
+                        cmd, *msb, *lsb);
 
        spin_lock(&pcipcwd_private.io_lock);
        /* If a command requires data it should be written first.
@@ -185,12 +186,10 @@ static int send_command(int cmd, int *msb, int *lsb)
 
        if (debug >= DEBUG) {
                if (got_response) {
-                       printk(KERN_DEBUG PFX
-                               "time to process command was: %d ms\n",
-                               count);
+                       pr_debug("time to process command was: %d ms\n",
+                                count);
                } else {
-                       printk(KERN_DEBUG PFX
-                               "card did not respond on command!\n");
+                       pr_debug("card did not respond on command!\n");
                }
        }
 
@@ -203,9 +202,8 @@ static int send_command(int cmd, int *msb, int *lsb)
                inb_p(pcipcwd_private.io_addr + 6);
 
                if (debug >= DEBUG)
-                       printk(KERN_DEBUG PFX "received following data for "
-                               "cmd=0x%02x: msb=0x%02x lsb=0x%02x\n",
-                               cmd, *msb, *lsb);
+                       pr_debug("received following data for cmd=0x%02x: msb=0x%02x lsb=0x%02x\n",
+                                cmd, *msb, *lsb);
        }
 
        spin_unlock(&pcipcwd_private.io_lock);
@@ -243,27 +241,23 @@ static void pcipcwd_show_card_info(void)
        /* Get switch settings */
        option_switches = pcipcwd_get_option_switches();
 
-       printk(KERN_INFO PFX "Found card at port "
-               "0x%04x (Firmware: %s) %s temp option\n",
+       pr_info("Found card at port 0x%04x (Firmware: %s) %s temp option\n",
                (int) pcipcwd_private.io_addr, fw_ver_str,
                (pcipcwd_private.supports_temp ? "with" : "without"));
 
-       printk(KERN_INFO PFX "Option switches (0x%02x): "
-               "Temperature Reset Enable=%s, Power On Delay=%s\n",
+       pr_info("Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n",
                option_switches,
                ((option_switches & 0x10) ? "ON" : "OFF"),
                ((option_switches & 0x08) ? "ON" : "OFF"));
 
        if (pcipcwd_private.boot_status & WDIOF_CARDRESET)
-               printk(KERN_INFO PFX
-                       "Previous reset was caused by the Watchdog card\n");
+               pr_info("Previous reset was caused by the Watchdog card\n");
 
        if (pcipcwd_private.boot_status & WDIOF_OVERHEAT)
-               printk(KERN_INFO PFX "Card sensed a CPU Overheat\n");
+               pr_info("Card sensed a CPU Overheat\n");
 
        if (pcipcwd_private.boot_status == 0)
-               printk(KERN_INFO PFX
-                       "No previous trip detected - Cold boot or reset\n");
+               pr_info("No previous trip detected - Cold boot or reset\n");
 }
 
 static int pcipcwd_start(void)
@@ -278,12 +272,12 @@ static int pcipcwd_start(void)
        spin_unlock(&pcipcwd_private.io_lock);
 
        if (stat_reg & WD_PCI_WDIS) {
-               printk(KERN_ERR PFX "Card timer not enabled\n");
+               pr_err("Card timer not enabled\n");
                return -1;
        }
 
        if (debug >= VERBOSE)
-               printk(KERN_DEBUG PFX "Watchdog started\n");
+               pr_debug("Watchdog started\n");
 
        return 0;
 }
@@ -303,13 +297,12 @@ static int pcipcwd_stop(void)
        spin_unlock(&pcipcwd_private.io_lock);
 
        if (!(stat_reg & WD_PCI_WDIS)) {
-               printk(KERN_ERR PFX
-                       "Card did not acknowledge disable attempt\n");
+               pr_err("Card did not acknowledge disable attempt\n");
                return -1;
        }
 
        if (debug >= VERBOSE)
-               printk(KERN_DEBUG PFX "Watchdog stopped\n");
+               pr_debug("Watchdog stopped\n");
 
        return 0;
 }
@@ -322,7 +315,7 @@ static int pcipcwd_keepalive(void)
        spin_unlock(&pcipcwd_private.io_lock);
 
        if (debug >= DEBUG)
-               printk(KERN_DEBUG PFX "Watchdog keepalive signal send\n");
+               pr_debug("Watchdog keepalive signal send\n");
 
        return 0;
 }
@@ -340,8 +333,7 @@ static int pcipcwd_set_heartbeat(int t)
 
        heartbeat = t;
        if (debug >= VERBOSE)
-               printk(KERN_DEBUG PFX "New heartbeat: %d\n",
-                      heartbeat);
+               pr_debug("New heartbeat: %d\n", heartbeat);
 
        return 0;
 }
@@ -357,12 +349,11 @@ static int pcipcwd_get_status(int *status)
        if (control_status & WD_PCI_TTRP) {
                *status |= WDIOF_OVERHEAT;
                if (temp_panic)
-                       panic(PFX "Temperature overheat trip!\n");
+                       panic(KBUILD_MODNAME ": Temperature overheat trip!\n");
        }
 
        if (debug >= DEBUG)
-               printk(KERN_DEBUG PFX "Control Status #1: 0x%02x\n",
-                      control_status);
+               pr_debug("Control Status #1: 0x%02x\n", control_status);
 
        return 0;
 }
@@ -374,14 +365,14 @@ static int pcipcwd_clear_status(void)
        int reset_counter;
 
        if (debug >= VERBOSE)
-               printk(KERN_INFO PFX "clearing watchdog trip status & LED\n");
+               pr_info("clearing watchdog trip status & LED\n");
 
        control_status = inb_p(pcipcwd_private.io_addr + 1);
 
        if (debug >= DEBUG) {
-               printk(KERN_DEBUG PFX "status was: 0x%02x\n", control_status);
-               printk(KERN_DEBUG PFX "sending: 0x%02x\n",
-                      (control_status & WD_PCI_R2DS) | WD_PCI_WTRP);
+               pr_debug("status was: 0x%02x\n", control_status);
+               pr_debug("sending: 0x%02x\n",
+                        (control_status & WD_PCI_R2DS) | WD_PCI_WTRP);
        }
 
        /* clear trip status & LED and keep mode of relay 2 */
@@ -394,8 +385,7 @@ static int pcipcwd_clear_status(void)
        send_command(CMD_GET_CLEAR_RESET_COUNT, &msb, &reset_counter);
 
        if (debug >= DEBUG) {
-               printk(KERN_DEBUG PFX "reset count was: 0x%02x\n",
-                      reset_counter);
+               pr_debug("reset count was: 0x%02x\n", reset_counter);
        }
 
        return 0;
@@ -418,8 +408,7 @@ static int pcipcwd_get_temperature(int *temperature)
        *temperature = (*temperature * 9 / 5) + 32;
 
        if (debug >= DEBUG) {
-               printk(KERN_DEBUG PFX "temperature is: %d F\n",
-                      *temperature);
+               pr_debug("temperature is: %d F\n", *temperature);
        }
 
        return 0;
@@ -437,8 +426,7 @@ static int pcipcwd_get_timeleft(int *time_left)
        *time_left = (msb << 8) + lsb;
 
        if (debug >= VERBOSE)
-               printk(KERN_DEBUG PFX "Time left before next reboot: %d\n",
-                      *time_left);
+               pr_debug("Time left before next reboot: %d\n", *time_left);
 
        return 0;
 }
@@ -583,8 +571,7 @@ static int pcipcwd_open(struct inode *inode, struct file *file)
        /* /dev/watchdog can only be opened once */
        if (test_and_set_bit(0, &is_active)) {
                if (debug >= VERBOSE)
-                       printk(KERN_ERR PFX
-                               "Attempt to open already opened device.\n");
+                       pr_err("Attempt to open already opened device\n");
                return -EBUSY;
        }
 
@@ -602,8 +589,7 @@ static int pcipcwd_release(struct inode *inode, struct file *file)
        if (expect_release == 42) {
                pcipcwd_stop();
        } else {
-               printk(KERN_CRIT PFX
-                       "Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
                pcipcwd_keepalive();
        }
        expect_release = 0;
@@ -703,20 +689,20 @@ static int __devinit pcipcwd_card_init(struct pci_dev *pdev,
 
        cards_found++;
        if (cards_found == 1)
-               printk(KERN_INFO PFX DRIVER_VERSION);
+               pr_info("%s\n", DRIVER_VERSION);
 
        if (cards_found > 1) {
-               printk(KERN_ERR PFX "This driver only supports 1 device\n");
+               pr_err("This driver only supports 1 device\n");
                return -ENODEV;
        }
 
        if (pci_enable_device(pdev)) {
-               printk(KERN_ERR PFX "Not possible to enable PCI Device\n");
+               pr_err("Not possible to enable PCI Device\n");
                return -ENODEV;
        }
 
        if (pci_resource_start(pdev, 0) == 0x0000) {
-               printk(KERN_ERR PFX "No I/O-Address for card detected\n");
+               pr_err("No I/O-Address for card detected\n");
                ret = -ENODEV;
                goto err_out_disable_device;
        }
@@ -725,8 +711,8 @@ static int __devinit pcipcwd_card_init(struct pci_dev *pdev,
        pcipcwd_private.io_addr = pci_resource_start(pdev, 0);
 
        if (pci_request_regions(pdev, WATCHDOG_NAME)) {
-               printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
-                       (int) pcipcwd_private.io_addr);
+               pr_err("I/O address 0x%04x already in use\n",
+                      (int) pcipcwd_private.io_addr);
                ret = -EIO;
                goto err_out_disable_device;
        }
@@ -755,36 +741,33 @@ static int __devinit pcipcwd_card_init(struct pci_dev *pdev,
         * if not reset to the default */
        if (pcipcwd_set_heartbeat(heartbeat)) {
                pcipcwd_set_heartbeat(WATCHDOG_HEARTBEAT);
-               printk(KERN_INFO PFX
-                       "heartbeat value must be 0<heartbeat<65536, using %d\n",
+               pr_info("heartbeat value must be 0<heartbeat<65536, using %d\n",
                        WATCHDOG_HEARTBEAT);
        }
 
        ret = register_reboot_notifier(&pcipcwd_notifier);
        if (ret != 0) {
-               printk(KERN_ERR PFX
-                       "cannot register reboot notifier (err=%d)\n", ret);
+               pr_err("cannot register reboot notifier (err=%d)\n", ret);
                goto err_out_release_region;
        }
 
        if (pcipcwd_private.supports_temp) {
                ret = misc_register(&pcipcwd_temp_miscdev);
                if (ret != 0) {
-                       printk(KERN_ERR PFX "cannot register miscdev on "
-                               "minor=%d (err=%d)\n", TEMP_MINOR, ret);
+                       pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                              TEMP_MINOR, ret);
                        goto err_out_unregister_reboot;
                }
        }
 
        ret = misc_register(&pcipcwd_miscdev);
        if (ret != 0) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                       WATCHDOG_MINOR, ret);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      WATCHDOG_MINOR, ret);
                goto err_out_misc_deregister;
        }
 
-       printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n",
+       pr_info("initialized. heartbeat=%d sec (nowayout=%d)\n",
                heartbeat, nowayout);
 
        return 0;
@@ -842,7 +825,7 @@ static void __exit pcipcwd_cleanup_module(void)
 {
        pci_unregister_driver(&pcipcwd_driver);
 
-       printk(KERN_INFO PFX "Watchdog Module Unloaded.\n");
+       pr_info("Watchdog Module Unloaded\n");
 }
 
 module_init(pcipcwd_init_module);
index d8de1dd..7b14d18 100644 (file)
@@ -24,6 +24,8 @@
  *     http://www.berkprod.com/ or http://www.pcwatchdog.com/
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>      /* For module specific items */
 #include <linux/moduleparam.h> /* For new moduleparam's */
 #include <linux/types.h>       /* For standard types (like size_t) */
 #include <linux/hid.h>         /* For HID_REQ_SET_REPORT & HID_DT_REPORT */
 #include <linux/uaccess.h>     /* For copy_to_user/put_user/... */
 
-
 #ifdef CONFIG_USB_DEBUG
-       static int debug = 1;
+static int debug = 1;
 #else
-       static int debug;
+static int debug;
 #endif
 
 /* Use our own dbg macro */
+
 #undef dbg
-#define dbg(format, arg...) \
-       do { if (debug) printk(KERN_DEBUG PFX format "\n" , ## arg); } while (0)
+#ifndef DEBUG
+#define DEBUG
+#endif
+#define dbg(format, ...)                               \
+do {                                                   \
+       if (debug)                                      \
+               pr_debug(format "\n", ##__VA_ARGS__);   \
+} while (0)
 
 /* Module and Version Information */
 #define DRIVER_VERSION "1.02"
@@ -60,7 +68,6 @@
 #define DRIVER_DESC "Berkshire USB-PC Watchdog driver"
 #define DRIVER_LICENSE "GPL"
 #define DRIVER_NAME "pcwd_usb"
-#define PFX DRIVER_NAME ": "
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
@@ -80,8 +87,8 @@ MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. "
        "(0<heartbeat<65536 or 0=delay-time from dip-switches, default="
                                __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
@@ -220,8 +227,8 @@ static void usb_pcwd_intr_done(struct urb *urb)
 resubmit:
        retval = usb_submit_urb(urb, GFP_ATOMIC);
        if (retval)
-               printk(KERN_ERR PFX "can't resubmit intr, "
-                       "usb_submit_urb failed with result %d\n", retval);
+               pr_err("can't resubmit intr, usb_submit_urb failed with result %d\n",
+                      retval);
 }
 
 static int usb_pcwd_send_command(struct usb_pcwd_private *usb_pcwd,
@@ -284,8 +291,7 @@ static int usb_pcwd_start(struct usb_pcwd_private *usb_pcwd)
                                                                &msb, &lsb);
 
        if ((retval == 0) || (lsb == 0)) {
-               printk(KERN_ERR PFX
-                               "Card did not acknowledge enable attempt\n");
+               pr_err("Card did not acknowledge enable attempt\n");
                return -1;
        }
 
@@ -303,8 +309,7 @@ static int usb_pcwd_stop(struct usb_pcwd_private *usb_pcwd)
                                                                &msb, &lsb);
 
        if ((retval == 0) || (lsb != 0)) {
-               printk(KERN_ERR PFX
-                       "Card did not acknowledge disable attempt\n");
+               pr_err("Card did not acknowledge disable attempt\n");
                return -1;
        }
 
@@ -506,8 +511,7 @@ static int usb_pcwd_release(struct inode *inode, struct file *file)
        if (expect_release == 42) {
                usb_pcwd_stop(usb_pcwd_device);
        } else {
-               printk(KERN_CRIT PFX
-                       "Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
                usb_pcwd_keepalive(usb_pcwd_device);
        }
        expect_release = 0;
@@ -627,7 +631,7 @@ static int usb_pcwd_probe(struct usb_interface *interface,
 
        cards_found++;
        if (cards_found > 1) {
-               printk(KERN_ERR PFX "This driver only supports 1 device\n");
+               pr_err("This driver only supports 1 device\n");
                return -ENODEV;
        }
 
@@ -636,8 +640,7 @@ static int usb_pcwd_probe(struct usb_interface *interface,
 
        /* check out that we have a HID device */
        if (!(iface_desc->desc.bInterfaceClass == USB_CLASS_HID)) {
-               printk(KERN_ERR PFX
-                       "The device isn't a Human Interface Device\n");
+               pr_err("The device isn't a Human Interface Device\n");
                return -ENODEV;
        }
 
@@ -646,7 +649,7 @@ static int usb_pcwd_probe(struct usb_interface *interface,
 
        if (!usb_endpoint_is_int_in(endpoint)) {
                /* we didn't find a Interrupt endpoint with direction IN */
-               printk(KERN_ERR PFX "Couldn't find an INTR & IN endpoint\n");
+               pr_err("Couldn't find an INTR & IN endpoint\n");
                return -ENODEV;
        }
 
@@ -657,7 +660,7 @@ static int usb_pcwd_probe(struct usb_interface *interface,
        /* allocate memory for our device and initialize it */
        usb_pcwd = kzalloc(sizeof(struct usb_pcwd_private), GFP_KERNEL);
        if (usb_pcwd == NULL) {
-               printk(KERN_ERR PFX "Out of memory\n");
+               pr_err("Out of memory\n");
                goto error;
        }
 
@@ -674,14 +677,14 @@ static int usb_pcwd_probe(struct usb_interface *interface,
        usb_pcwd->intr_buffer = usb_alloc_coherent(udev, usb_pcwd->intr_size,
                                        GFP_ATOMIC, &usb_pcwd->intr_dma);
        if (!usb_pcwd->intr_buffer) {
-               printk(KERN_ERR PFX "Out of memory\n");
+               pr_err("Out of memory\n");
                goto error;
        }
 
        /* allocate the urb's */
        usb_pcwd->intr_urb = usb_alloc_urb(0, GFP_KERNEL);
        if (!usb_pcwd->intr_urb) {
-               printk(KERN_ERR PFX "Out of memory\n");
+               pr_err("Out of memory\n");
                goto error;
        }
 
@@ -694,7 +697,7 @@ static int usb_pcwd_probe(struct usb_interface *interface,
 
        /* register our interrupt URB with the USB system */
        if (usb_submit_urb(usb_pcwd->intr_urb, GFP_KERNEL)) {
-               printk(KERN_ERR PFX "Problem registering interrupt URB\n");
+               pr_err("Problem registering interrupt URB\n");
                retval = -EIO; /* failure */
                goto error;
        }
@@ -713,15 +716,13 @@ static int usb_pcwd_probe(struct usb_interface *interface,
        else
                sprintf(fw_ver_str, "<card no answer>");
 
-       printk(KERN_INFO PFX "Found card (Firmware: %s) with temp option\n",
-               fw_ver_str);
+       pr_info("Found card (Firmware: %s) with temp option\n", fw_ver_str);
 
        /* Get switch settings */
        usb_pcwd_send_command(usb_pcwd, CMD_GET_DIP_SWITCH_SETTINGS, &dummy,
                                                        &option_switches);
 
-       printk(KERN_INFO PFX "Option switches (0x%02x): "
-               "Temperature Reset Enable=%s, Power On Delay=%s\n",
+       pr_info("Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n",
                option_switches,
                ((option_switches & 0x10) ? "ON" : "OFF"),
                ((option_switches & 0x08) ? "ON" : "OFF"));
@@ -734,39 +735,34 @@ static int usb_pcwd_probe(struct usb_interface *interface,
         * if not reset to the default */
        if (usb_pcwd_set_heartbeat(usb_pcwd, heartbeat)) {
                usb_pcwd_set_heartbeat(usb_pcwd, WATCHDOG_HEARTBEAT);
-               printk(KERN_INFO PFX
-                       "heartbeat value must be 0<heartbeat<65536, using %d\n",
+               pr_info("heartbeat value must be 0<heartbeat<65536, using %d\n",
                        WATCHDOG_HEARTBEAT);
        }
 
        retval = register_reboot_notifier(&usb_pcwd_notifier);
        if (retval != 0) {
-               printk(KERN_ERR PFX
-                       "cannot register reboot notifier (err=%d)\n",
-                       retval);
+               pr_err("cannot register reboot notifier (err=%d)\n", retval);
                goto error;
        }
 
        retval = misc_register(&usb_pcwd_temperature_miscdev);
        if (retval != 0) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                       TEMP_MINOR, retval);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      TEMP_MINOR, retval);
                goto err_out_unregister_reboot;
        }
 
        retval = misc_register(&usb_pcwd_miscdev);
        if (retval != 0) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                       WATCHDOG_MINOR, retval);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      WATCHDOG_MINOR, retval);
                goto err_out_misc_deregister;
        }
 
        /* we can register the device now, as it is ready */
        usb_set_intfdata(interface, usb_pcwd);
 
-       printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n",
+       pr_info("initialized. heartbeat=%d sec (nowayout=%d)\n",
                heartbeat, nowayout);
 
        return 0;
@@ -824,7 +820,7 @@ static void usb_pcwd_disconnect(struct usb_interface *interface)
 
        mutex_unlock(&disconnect_mutex);
 
-       printk(KERN_INFO PFX "USB PC Watchdog disconnected\n");
+       pr_info("USB PC Watchdog disconnected\n");
 }
 
 module_usb_driver(usb_pcwd_driver);
index 2d22e99..7d3d471 100644 (file)
@@ -5,6 +5,8 @@
  *   Sean MacLennan <smaclennan@pikatech.com>
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/module.h>
@@ -23,7 +25,6 @@
 #include <linux/of_platform.h>
 
 #define DRV_NAME "PIKA-WDT"
-#define PFX DRV_NAME ": "
 
 /* Hardware timeout in seconds */
 #define WDT_HW_TIMEOUT 2
@@ -38,8 +39,8 @@ module_param(heartbeat, int, 0);
 MODULE_PARM_DESC(heartbeat, "Watchdog heartbeats in seconds. "
        "(default = " __MODULE_STRING(WDT_HEARTBEAT) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
        "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
@@ -90,7 +91,7 @@ static void pikawdt_ping(unsigned long data)
                pikawdt_reset();
                mod_timer(&pikawdt_private.timer, jiffies + WDT_TIMEOUT);
        } else
-               printk(KERN_CRIT PFX "I will reset your machine !\n");
+               pr_crit("I will reset your machine !\n");
 }
 
 
@@ -228,14 +229,14 @@ static int __init pikawdt_init(void)
 
        np = of_find_compatible_node(NULL, NULL, "pika,fpga");
        if (np == NULL) {
-               printk(KERN_ERR PFX "Unable to find fpga.\n");
+               pr_err("Unable to find fpga\n");
                return -ENOENT;
        }
 
        pikawdt_private.fpga = of_iomap(np, 0);
        of_node_put(np);
        if (pikawdt_private.fpga == NULL) {
-               printk(KERN_ERR PFX "Unable to map fpga.\n");
+               pr_err("Unable to map fpga\n");
                return -ENOMEM;
        }
 
@@ -244,7 +245,7 @@ static int __init pikawdt_init(void)
        /* POST information is in the sd area. */
        np = of_find_compatible_node(NULL, NULL, "pika,fpga-sd");
        if (np == NULL) {
-               printk(KERN_ERR PFX "Unable to find fpga-sd.\n");
+               pr_err("Unable to find fpga-sd\n");
                ret = -ENOENT;
                goto out;
        }
@@ -252,7 +253,7 @@ static int __init pikawdt_init(void)
        fpga = of_iomap(np, 0);
        of_node_put(np);
        if (fpga == NULL) {
-               printk(KERN_ERR PFX "Unable to map fpga-sd.\n");
+               pr_err("Unable to map fpga-sd\n");
                ret = -ENOMEM;
                goto out;
        }
@@ -271,12 +272,12 @@ static int __init pikawdt_init(void)
 
        ret = misc_register(&pikawdt_miscdev);
        if (ret) {
-               printk(KERN_ERR PFX "Unable to register miscdev.\n");
+               pr_err("Unable to register miscdev\n");
                goto out;
        }
 
-       printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n",
-                                                       heartbeat, nowayout);
+       pr_info("initialized. heartbeat=%d sec (nowayout=%d)\n",
+               heartbeat, nowayout);
        return 0;
 
 out:
index dfae030..6b8432f 100644 (file)
@@ -8,33 +8,32 @@
  * Based on sa1100 driver,
  * Copyright (C) 2000 Oleg Drokin <green@crimea.edu>
  *
- * 2005-2006 (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.
+ * 2005-2006 (c) MontaVista Software, Inc.
+ *
+ * (C) 2012 Wolfram Sang, Pengutronix
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/fs.h>
 #include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include <linux/init.h>
-#include <linux/bitops.h>
-#include <linux/ioport.h>
-#include <linux/device.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <linux/spinlock.h>
-#include <linux/uaccess.h>
 #include <linux/io.h>
 #include <linux/slab.h>
+#include <linux/err.h>
 #include <mach/hardware.h>
 
-#define MODULE_NAME "PNX4008-WDT: "
-
 /* WatchDog Timer - Chapter 23 Page 207 */
 
 #define DEFAULT_HEARTBEAT 19
 
 #define WDOG_COUNTER_RATE 13000000     /*the counter clock is 13 MHz fixed */
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-static int heartbeat = DEFAULT_HEARTBEAT;
+static bool nowayout = WATCHDOG_NOWAYOUT;
+static unsigned int heartbeat = DEFAULT_HEARTBEAT;
 
 static DEFINE_SPINLOCK(io_lock);
-static unsigned long wdt_status;
-#define WDT_IN_USE        0
-#define WDT_OK_TO_CLOSE   1
-#define WDT_REGION_INITED 2
-#define WDT_DEVICE_INITED 3
-
-static unsigned long boot_status;
-
-static struct resource *wdt_mem;
 static void __iomem    *wdt_base;
 struct clk             *wdt_clk;
 
-static void wdt_enable(void)
+static int pnx4008_wdt_start(struct watchdog_device *wdd)
 {
        spin_lock(&io_lock);
 
        /* stop counter, initiate counter reset */
-       __raw_writel(RESET_COUNT, WDTIM_CTRL(wdt_base));
+       writel(RESET_COUNT, WDTIM_CTRL(wdt_base));
        /*wait for reset to complete. 100% guarantee event */
-       while (__raw_readl(WDTIM_COUNTER(wdt_base)))
+       while (readl(WDTIM_COUNTER(wdt_base)))
                cpu_relax();
        /* internal and external reset, stop after that */
-       __raw_writel(M_RES2 | STOP_COUNT0 | RESET_COUNT0,
-               WDTIM_MCTRL(wdt_base));
+       writel(M_RES2 | STOP_COUNT0 | RESET_COUNT0, WDTIM_MCTRL(wdt_base));
        /* configure match output */
-       __raw_writel(MATCH_OUTPUT_HIGH, WDTIM_EMR(wdt_base));
+       writel(MATCH_OUTPUT_HIGH, WDTIM_EMR(wdt_base));
        /* clear interrupt, just in case */
-       __raw_writel(MATCH_INT, WDTIM_INT(wdt_base));
+       writel(MATCH_INT, WDTIM_INT(wdt_base));
        /* the longest pulse period 65541/(13*10^6) seconds ~ 5 ms. */
-       __raw_writel(0xFFFF, WDTIM_PULSE(wdt_base));
-       __raw_writel(heartbeat * WDOG_COUNTER_RATE, WDTIM_MATCH0(wdt_base));
+       writel(0xFFFF, WDTIM_PULSE(wdt_base));
+       writel(wdd->timeout * WDOG_COUNTER_RATE, WDTIM_MATCH0(wdt_base));
        /*enable counter, stop when debugger active */
-       __raw_writel(COUNT_ENAB | DEBUG_EN, WDTIM_CTRL(wdt_base));
+       writel(COUNT_ENAB | DEBUG_EN, WDTIM_CTRL(wdt_base));
 
        spin_unlock(&io_lock);
+       return 0;
 }
 
-static void wdt_disable(void)
+static int pnx4008_wdt_stop(struct watchdog_device *wdd)
 {
        spin_lock(&io_lock);
 
-       __raw_writel(0, WDTIM_CTRL(wdt_base));  /*stop counter */
+       writel(0, WDTIM_CTRL(wdt_base));        /*stop counter */
 
        spin_unlock(&io_lock);
+       return 0;
 }
 
-static int pnx4008_wdt_open(struct inode *inode, struct file *file)
-{
-       int ret;
-
-       if (test_and_set_bit(WDT_IN_USE, &wdt_status))
-               return -EBUSY;
-
-       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
-
-       ret = clk_enable(wdt_clk);
-       if (ret) {
-               clear_bit(WDT_IN_USE, &wdt_status);
-               return ret;
-       }
-
-       wdt_enable();
-
-       return nonseekable_open(inode, file);
-}
-
-static ssize_t pnx4008_wdt_write(struct file *file, const char *data,
-                                       size_t len, loff_t *ppos)
+static int pnx4008_wdt_set_timeout(struct watchdog_device *wdd,
+                                   unsigned int new_timeout)
 {
-       if (len) {
-               if (!nowayout) {
-                       size_t i;
-
-                       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
-
-                       for (i = 0; i != len; i++) {
-                               char c;
-
-                               if (get_user(c, data + i))
-                                       return -EFAULT;
-                               if (c == 'V')
-                                       set_bit(WDT_OK_TO_CLOSE, &wdt_status);
-                       }
-               }
-               wdt_enable();
-       }
-
-       return len;
+       wdd->timeout = new_timeout;
+       return 0;
 }
 
-static const struct watchdog_info ident = {
+static const struct watchdog_info pnx4008_wdt_ident = {
        .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE |
            WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
        .identity = "PNX4008 Watchdog",
 };
 
-static long pnx4008_wdt_ioctl(struct file *file, unsigned int cmd,
-                               unsigned long arg)
-{
-       int ret = -ENOTTY;
-       int time;
-
-       switch (cmd) {
-       case WDIOC_GETSUPPORT:
-               ret = copy_to_user((struct watchdog_info *)arg, &ident,
-                                  sizeof(ident)) ? -EFAULT : 0;
-               break;
-
-       case WDIOC_GETSTATUS:
-               ret = put_user(0, (int *)arg);
-               break;
-
-       case WDIOC_GETBOOTSTATUS:
-               ret = put_user(boot_status, (int *)arg);
-               break;
-
-       case WDIOC_KEEPALIVE:
-               wdt_enable();
-               ret = 0;
-               break;
-
-       case WDIOC_SETTIMEOUT:
-               ret = get_user(time, (int *)arg);
-               if (ret)
-                       break;
-
-               if (time <= 0 || time > MAX_HEARTBEAT) {
-                       ret = -EINVAL;
-                       break;
-               }
-
-               heartbeat = time;
-               wdt_enable();
-               /* Fall through */
-
-       case WDIOC_GETTIMEOUT:
-               ret = put_user(heartbeat, (int *)arg);
-               break;
-       }
-       return ret;
-}
-
-static int pnx4008_wdt_release(struct inode *inode, struct file *file)
-{
-       if (!test_bit(WDT_OK_TO_CLOSE, &wdt_status))
-               printk(KERN_WARNING "WATCHDOG: Device closed unexpectedly\n");
-
-       wdt_disable();
-       clk_disable(wdt_clk);
-       clear_bit(WDT_IN_USE, &wdt_status);
-       clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
-
-       return 0;
-}
-
-static const struct file_operations pnx4008_wdt_fops = {
+static const struct watchdog_ops pnx4008_wdt_ops = {
        .owner = THIS_MODULE,
-       .llseek = no_llseek,
-       .write = pnx4008_wdt_write,
-       .unlocked_ioctl = pnx4008_wdt_ioctl,
-       .open = pnx4008_wdt_open,
-       .release = pnx4008_wdt_release,
+       .start = pnx4008_wdt_start,
+       .stop = pnx4008_wdt_stop,
+       .set_timeout = pnx4008_wdt_set_timeout,
 };
 
-static struct miscdevice pnx4008_wdt_miscdev = {
-       .minor = WATCHDOG_MINOR,
-       .name = "watchdog",
-       .fops = &pnx4008_wdt_fops,
+static struct watchdog_device pnx4008_wdd = {
+       .info = &pnx4008_wdt_ident,
+       .ops = &pnx4008_wdt_ops,
+       .min_timeout = 1,
+       .max_timeout = MAX_HEARTBEAT,
 };
 
 static int __devinit pnx4008_wdt_probe(struct platform_device *pdev)
 {
-       int ret = 0, size;
+       struct resource *r;
+       int ret = 0;
 
        if (heartbeat < 1 || heartbeat > MAX_HEARTBEAT)
                heartbeat = DEFAULT_HEARTBEAT;
 
-       printk(KERN_INFO MODULE_NAME
-               "PNX4008 Watchdog Timer: heartbeat %d sec\n", heartbeat);
-
-       wdt_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (wdt_mem == NULL) {
-               printk(KERN_INFO MODULE_NAME
-                       "failed to get memory region resource\n");
-               return -ENOENT;
-       }
-
-       size = resource_size(wdt_mem);
-
-       if (!request_mem_region(wdt_mem->start, size, pdev->name)) {
-               printk(KERN_INFO MODULE_NAME "failed to get memory region\n");
-               return -ENOENT;
-       }
-       wdt_base = (void __iomem *)IO_ADDRESS(wdt_mem->start);
+       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       wdt_base = devm_request_and_ioremap(&pdev->dev, r);
+       if (!wdt_base)
+               return -EADDRINUSE;
 
        wdt_clk = clk_get(&pdev->dev, NULL);
-       if (IS_ERR(wdt_clk)) {
-               ret = PTR_ERR(wdt_clk);
-               release_mem_region(wdt_mem->start, size);
-               wdt_mem = NULL;
-               goto out;
-       }
+       if (IS_ERR(wdt_clk))
+               return PTR_ERR(wdt_clk);
 
        ret = clk_enable(wdt_clk);
-       if (ret) {
-               release_mem_region(wdt_mem->start, size);
-               wdt_mem = NULL;
-               clk_put(wdt_clk);
+       if (ret)
                goto out;
-       }
 
-       ret = misc_register(&pnx4008_wdt_miscdev);
+       pnx4008_wdd.timeout = heartbeat;
+       pnx4008_wdd.bootstatus = (readl(WDTIM_RES(wdt_base)) & WDOG_RESET) ?
+                       WDIOF_CARDRESET : 0;
+       watchdog_set_nowayout(&pnx4008_wdd, nowayout);
+
+       pnx4008_wdt_stop(&pnx4008_wdd); /* disable for now */
+
+       ret = watchdog_register_device(&pnx4008_wdd);
        if (ret < 0) {
-               printk(KERN_ERR MODULE_NAME "cannot register misc device\n");
-               release_mem_region(wdt_mem->start, size);
-               wdt_mem = NULL;
-               clk_disable(wdt_clk);
-               clk_put(wdt_clk);
-       } else {
-               boot_status = (__raw_readl(WDTIM_RES(wdt_base)) & WDOG_RESET) ?
-                   WDIOF_CARDRESET : 0;
-               wdt_disable();          /*disable for now */
-               clk_disable(wdt_clk);
-               set_bit(WDT_DEVICE_INITED, &wdt_status);
+               dev_err(&pdev->dev, "cannot register watchdog device\n");
+               goto disable_clk;
        }
 
+       dev_info(&pdev->dev, "PNX4008 Watchdog Timer: heartbeat %d sec\n",
+                       heartbeat);
+
+       return 0;
+
+disable_clk:
+       clk_disable(wdt_clk);
 out:
+       clk_put(wdt_clk);
        return ret;
 }
 
 static int __devexit pnx4008_wdt_remove(struct platform_device *pdev)
 {
-       misc_deregister(&pnx4008_wdt_miscdev);
+       watchdog_unregister_device(&pnx4008_wdd);
 
        clk_disable(wdt_clk);
        clk_put(wdt_clk);
 
-       if (wdt_mem) {
-               release_mem_region(wdt_mem->start, resource_size(wdt_mem));
-               wdt_mem = NULL;
-       }
        return 0;
 }
 
@@ -337,15 +213,16 @@ static struct platform_driver platform_wdt_driver = {
 module_platform_driver(platform_wdt_driver);
 
 MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>");
+MODULE_AUTHOR("Wolfram Sang <w.sang@pengutronix.de>");
 MODULE_DESCRIPTION("PNX4008 Watchdog Driver");
 
-module_param(heartbeat, int, 0);
+module_param(heartbeat, uint, 0);
 MODULE_PARM_DESC(heartbeat,
                 "Watchdog heartbeat period in seconds from 1 to "
                 __MODULE_STRING(MAX_HEARTBEAT) ", default "
                 __MODULE_STRING(DEFAULT_HEARTBEAT));
 
-module_param(nowayout, int, 0);
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                 "Set to 1 to keep watchdog running after device release");
 
index a7b5ad2..1b62a7d 100644 (file)
@@ -17,6 +17,8 @@
  * based on softdog.c by Alan Cox <alan@redhat.com>
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
@@ -30,7 +32,6 @@
 #include <linux/init.h>
 #include <asm/mach-pnx833x/pnx833x.h>
 
-#define PFX "pnx833x: "
 #define WATCHDOG_TIMEOUT 30            /* 30 sec Maximum timeout */
 #define WATCHDOG_COUNT_FREQUENCY 68000000U /* Watchdog counts at 68MHZ. */
 #define        PNX_WATCHDOG_TIMEOUT    (WATCHDOG_TIMEOUT * WATCHDOG_COUNT_FREQUENCY)
@@ -54,8 +55,8 @@ module_param(pnx833x_wdt_timeout, int, 0);
 MODULE_PARM_DESC(timeout, "Watchdog timeout in Mhz. (68Mhz clock), default="
                        __MODULE_STRING(PNX_TIMEOUT_VALUE) "(30 seconds).");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
                                        __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
@@ -76,7 +77,7 @@ static void pnx833x_wdt_start(void)
        PNX833X_REG(PNX833X_CONFIG +
                                PNX833X_CONFIG_CPU_COUNTERS_CONTROL) |= 0x1;
 
-       printk(KERN_INFO PFX "Started watchdog timer.\n");
+       pr_info("Started watchdog timer\n");
 }
 
 static void pnx833x_wdt_stop(void)
@@ -87,7 +88,7 @@ static void pnx833x_wdt_stop(void)
        PNX833X_REG(PNX833X_CONFIG +
                        PNX833X_CONFIG_CPU_COUNTERS_CONTROL) &= 0xFFFFFFFE;
 
-       printk(KERN_INFO PFX "Stopped watchdog timer.\n");
+       pr_info("Stopped watchdog timer\n");
 }
 
 static void pnx833x_wdt_ping(void)
@@ -113,7 +114,7 @@ static int pnx833x_wdt_open(struct inode *inode, struct file *file)
 
        pnx833x_wdt_ping();
 
-       printk(KERN_INFO "Started watchdog timer.\n");
+       pr_info("Started watchdog timer\n");
 
        return nonseekable_open(inode, file);
 }
@@ -232,9 +233,6 @@ static struct notifier_block pnx833x_wdt_notifier = {
        .notifier_call = pnx833x_wdt_notify_sys,
 };
 
-static char banner[] __initdata =
-       KERN_INFO PFX "Hardware Watchdog Timer for PNX833x: Version 0.1\n";
-
 static int __init watchdog_init(void)
 {
        int ret, cause;
@@ -243,27 +241,25 @@ static int __init watchdog_init(void)
        cause = PNX833X_REG(PNX833X_RESET);
        /*If bit 31 is set then watchdog was cause of reset.*/
        if (cause & 0x80000000) {
-               printk(KERN_INFO PFX "The system was previously reset due to "
-                       "the watchdog firing - please investigate...\n");
+               pr_info("The system was previously reset due to the watchdog firing - please investigate...\n");
        }
 
        ret = register_reboot_notifier(&pnx833x_wdt_notifier);
        if (ret) {
-               printk(KERN_ERR PFX
-                       "cannot register reboot notifier (err=%d)\n", ret);
+               pr_err("cannot register reboot notifier (err=%d)\n", ret);
                return ret;
        }
 
        ret = misc_register(&pnx833x_wdt_miscdev);
        if (ret) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                       WATCHDOG_MINOR, ret);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      WATCHDOG_MINOR, ret);
                unregister_reboot_notifier(&pnx833x_wdt_notifier);
                return ret;
        }
 
-       printk(banner);
+       pr_info("Hardware Watchdog Timer for PNX833x: Version 0.1\n");
+
        if (start_enabled)
                pnx833x_wdt_start();
 
index bf7bc8a..547353a 100644 (file)
@@ -17,6 +17,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>              /* For module specific items */
 #include <linux/moduleparam.h>         /* For new moduleparam's */
 #include <linux/types.h>               /* For standard types (like size_t) */
@@ -33,8 +35,6 @@
 
 #include <asm/mach-rc32434/integ.h>    /* For the Watchdog registers */
 
-#define PFX KBUILD_MODNAME ": "
-
 #define VERSION "1.0"
 
 static struct {
@@ -64,8 +64,8 @@ module_param(timeout, int, 0);
 MODULE_PARM_DESC(timeout, "Watchdog timeout value, in seconds (default="
                __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
        __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
@@ -78,8 +78,7 @@ static int rc32434_wdt_set(int new_timeout)
        int max_to = WTCOMP2SEC((u32)-1);
 
        if (new_timeout < 0 || new_timeout > max_to) {
-               printk(KERN_ERR PFX "timeout value must be between 0 and %d",
-                       max_to);
+               pr_err("timeout value must be between 0 and %d\n", max_to);
                return -EINVAL;
        }
        timeout = new_timeout;
@@ -119,7 +118,7 @@ static void rc32434_wdt_start(void)
        SET_BITS(wdt_reg->wtc, or, nand);
 
        spin_unlock(&rc32434_wdt_device.io_lock);
-       printk(KERN_INFO PFX "Started watchdog timer.\n");
+       pr_info("Started watchdog timer\n");
 }
 
 static void rc32434_wdt_stop(void)
@@ -130,7 +129,7 @@ static void rc32434_wdt_stop(void)
        SET_BITS(wdt_reg->wtc, 0, 1 << RC32434_WTC_EN);
 
        spin_unlock(&rc32434_wdt_device.io_lock);
-       printk(KERN_INFO PFX "Stopped watchdog timer.\n");
+       pr_info("Stopped watchdog timer\n");
 }
 
 static void rc32434_wdt_ping(void)
@@ -160,8 +159,7 @@ static int rc32434_wdt_release(struct inode *inode, struct file *file)
                rc32434_wdt_stop();
                module_put(THIS_MODULE);
        } else {
-               printk(KERN_CRIT PFX
-                       "device closed unexpectedly. WDT will not stop!\n");
+               pr_crit("device closed unexpectedly. WDT will not stop!\n");
                rc32434_wdt_ping();
        }
        clear_bit(0, &rc32434_wdt_device.inuse);
@@ -262,9 +260,6 @@ static struct miscdevice rc32434_wdt_miscdev = {
        .fops   = &rc32434_wdt_fops,
 };
 
-static char banner[] __devinitdata = KERN_INFO PFX
-               "Watchdog Timer version " VERSION ", timer margin: %d sec\n";
-
 static int __devinit rc32434_wdt_probe(struct platform_device *pdev)
 {
        int ret;
@@ -272,13 +267,13 @@ static int __devinit rc32434_wdt_probe(struct platform_device *pdev)
 
        r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rb532_wdt_res");
        if (!r) {
-               printk(KERN_ERR PFX "failed to retrieve resources\n");
+               pr_err("failed to retrieve resources\n");
                return -ENODEV;
        }
 
        wdt_reg = ioremap_nocache(r->start, resource_size(r));
        if (!wdt_reg) {
-               printk(KERN_ERR PFX "failed to remap I/O resources\n");
+               pr_err("failed to remap I/O resources\n");
                return -ENXIO;
        }
 
@@ -291,18 +286,18 @@ static int __devinit rc32434_wdt_probe(struct platform_device *pdev)
         * if not reset to the default */
        if (rc32434_wdt_set(timeout)) {
                rc32434_wdt_set(WATCHDOG_TIMEOUT);
-               printk(KERN_INFO PFX
-                       "timeout value must be between 0 and %d\n",
+               pr_info("timeout value must be between 0 and %d\n",
                        WTCOMP2SEC((u32)-1));
        }
 
        ret = misc_register(&rc32434_wdt_miscdev);
        if (ret < 0) {
-               printk(KERN_ERR PFX "failed to register watchdog device\n");
+               pr_err("failed to register watchdog device\n");
                goto unmap;
        }
 
-       printk(banner, timeout);
+       pr_info("Watchdog Timer version " VERSION ", timer margin: %d sec\n",
+               timeout);
 
        return 0;
 
index c7e17ce..49e1b1c 100644 (file)
@@ -3,6 +3,8 @@
  * Copyright (C) 2001, 2008 David S. Miller (davem@davemloft.net)
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/types.h>
@@ -189,7 +191,7 @@ static int __devinit riowd_probe(struct platform_device *op)
 
        p->regs = of_ioremap(&op->resource[0], 0, 2, DRIVER_NAME);
        if (!p->regs) {
-               printk(KERN_ERR PFX "Cannot map registers.\n");
+               pr_err("Cannot map registers\n");
                goto out_free;
        }
        /* Make miscdev useable right away */
@@ -197,12 +199,12 @@ static int __devinit riowd_probe(struct platform_device *op)
 
        err = misc_register(&riowd_miscdev);
        if (err) {
-               printk(KERN_ERR PFX "Cannot register watchdog misc device.\n");
+               pr_err("Cannot register watchdog misc device\n");
                goto out_iounmap;
        }
 
-       printk(KERN_INFO PFX "Hardware watchdog [%i minutes], "
-              "regs at %p\n", riowd_timeout, p->regs);
+       pr_info("Hardware watchdog [%i minutes], regs at %p\n",
+               riowd_timeout, p->regs);
 
        dev_set_drvdata(&op->dev, p);
        return 0;
index 404172f..04e5a6d 100644 (file)
@@ -23,6 +23,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 
 #include <plat/regs-watchdog.h>
 
-#define PFX "s3c2410-wdt: "
-
 #define CONFIG_S3C2410_WATCHDOG_ATBOOT         (0)
 #define CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME   (15)
 
-static int nowayout    = WATCHDOG_NOWAYOUT;
+static bool nowayout   = WATCHDOG_NOWAYOUT;
 static int tmr_margin  = CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME;
 static int tmr_atboot  = CONFIG_S3C2410_WATCHDOG_ATBOOT;
 static int soft_noboot;
@@ -59,7 +59,7 @@ static int debug;
 
 module_param(tmr_margin,  int, 0);
 module_param(tmr_atboot,  int, 0);
-module_param(nowayout,    int, 0);
+module_param(nowayout,   bool, 0);
 module_param(soft_noboot, int, 0);
 module_param(debug,      int, 0);
 
@@ -84,10 +84,11 @@ static DEFINE_SPINLOCK(wdt_lock);
 
 /* watchdog control routines */
 
-#define DBG(msg...) do { \
-       if (debug) \
-               printk(KERN_INFO msg); \
-       } while (0)
+#define DBG(fmt, ...)                                  \
+do {                                                   \
+       if (debug)                                      \
+               pr_info(fmt, ##__VA_ARGS__);            \
+} while (0)
 
 /* functions */
 
@@ -200,6 +201,8 @@ static int s3c2410wdt_set_heartbeat(struct watchdog_device *wdd, unsigned timeou
        writel(count, wdt_base + S3C2410_WTDAT);
        writel(wtcon, wdt_base + S3C2410_WTCON);
 
+       wdd->timeout = timeout;
+
        return 0;
 }
 
@@ -354,7 +357,7 @@ static int __devinit s3c2410wdt_probe(struct platform_device *pdev)
 
        ret = s3c2410wdt_cpufreq_register();
        if (ret < 0) {
-               printk(KERN_ERR PFX "failed to register cpufreq\n");
+               pr_err("failed to register cpufreq\n");
                goto err_clk;
        }
 
@@ -483,8 +486,8 @@ static int s3c2410wdt_resume(struct platform_device *dev)
        writel(wtdat_save, wdt_base + S3C2410_WTCNT); /* Reset count */
        writel(wtcon_save, wdt_base + S3C2410_WTCON);
 
-       printk(KERN_INFO PFX "watchdog %sabled\n",
-              (wtcon_save & S3C2410_WTCON_ENABLE) ? "en" : "dis");
+       pr_info("watchdog %sabled\n",
+               (wtcon_save & S3C2410_WTCON_ENABLE) ? "en" : "dis");
 
        return 0;
 }
@@ -518,12 +521,10 @@ static struct platform_driver s3c2410wdt_driver = {
 };
 
 
-static char banner[] __initdata =
-       KERN_INFO "S3C2410 Watchdog Timer, (c) 2004 Simtec Electronics\n";
-
 static int __init watchdog_init(void)
 {
-       printk(banner);
+       pr_info("S3C2410 Watchdog Timer, (c) 2004 Simtec Electronics\n");
+
        return platform_driver_register(&s3c2410wdt_driver);
 }
 
index 0162454..d54e04d 100644 (file)
@@ -17,6 +17,9 @@
  *
  *     27/11/2000 Initial release
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
@@ -66,7 +69,7 @@ static int sa1100dog_open(struct inode *inode, struct file *file)
  */
 static int sa1100dog_release(struct inode *inode, struct file *file)
 {
-       printk(KERN_CRIT "WATCHDOG: Device closed - timer will not stop\n");
+       pr_crit("Device closed - timer will not stop\n");
        clear_bit(1, &sa1100wdt_users);
        return 0;
 }
@@ -169,9 +172,8 @@ static int __init sa1100dog_init(void)
 
        ret = misc_register(&sa1100dog_miscdev);
        if (ret == 0)
-               printk(KERN_INFO
-                       "SA1100/PXA2xx Watchdog Timer: timer margin %d sec\n",
-                                               margin);
+               pr_info("SA1100/PXA2xx Watchdog Timer: timer margin %d sec\n",
+                       margin);
        return ret;
 }
 
index b01a30e..25c7a3f 100644 (file)
@@ -43,6 +43,9 @@
  *     version 1 or 2 as published by the Free Software Foundation.
  *
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/io.h>
 #include <linux/uaccess.h>
@@ -125,9 +128,8 @@ static int sbwdog_release(struct inode *inode, struct file *file)
                __raw_writeb(0, user_dog);
                module_put(THIS_MODULE);
        } else {
-               printk(KERN_CRIT
-                       "%s: Unexpected close, not stopping watchdog!\n",
-                                               ident.identity);
+               pr_crit("%s: Unexpected close, not stopping watchdog!\n",
+                       ident.identity);
                sbwdog_pet(user_dog);
        }
        clear_bit(0, &sbwdog_gate);
@@ -269,7 +271,7 @@ irqreturn_t sbwdog_interrupt(int irq, void *addr)
         * if it's the second watchdog timer, it's for those users
         */
        if (wd_cfg_reg == user_dog)
-               printk(KERN_CRIT "%s in danger of initiating system reset "
+               pr_crit("%s in danger of initiating system reset "
                        "in %ld.%01ld seconds\n",
                        ident.identity,
                        wd_init / 1000000, (wd_init / 100000) % 10);
@@ -290,9 +292,8 @@ static int __init sbwdog_init(void)
         */
        ret = register_reboot_notifier(&sbwdog_notifier);
        if (ret) {
-               printk(KERN_ERR
-                       "%s: cannot register reboot notifier (err=%d)\n",
-                                               ident.identity, ret);
+               pr_err("%s: cannot register reboot notifier (err=%d)\n",
+                      ident.identity, ret);
                return ret;
        }
 
@@ -303,16 +304,16 @@ static int __init sbwdog_init(void)
        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",
-                                               ident.identity, ret);
+               pr_err("%s: failed to request irq 1 - %d\n",
+                      ident.identity, ret);
                goto out;
        }
 
        ret = misc_register(&sbwdog_miscdev);
        if (ret == 0) {
-               printk(KERN_INFO "%s: timeout is %ld.%ld secs\n",
-                               ident.identity,
-                               timeout / 1000000, (timeout / 100000) % 10);
+               pr_info("%s: timeout is %ld.%ld secs\n",
+                       ident.identity,
+                       timeout / 1000000, (timeout / 100000) % 10);
                return 0;
        }
        free_irq(1, (void *)user_dog);
@@ -353,8 +354,7 @@ void platform_wd_setup(void)
        ret = request_irq(1, sbwdog_interrupt, IRQF_SHARED,
                "Kernel Watchdog", IOADDR(A_SCD_WDOG_CFG_0));
        if (ret) {
-               printk(KERN_CRIT
-                 "Watchdog IRQ zero(0) failed to be requested - %d\n", ret);
+               pr_crit("Watchdog IRQ zero(0) failed to be requested - %d\n", ret);
        }
 }
 
index 626d0e8..63632ec 100644 (file)
@@ -48,6 +48,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
@@ -63,7 +65,6 @@
 #include <linux/io.h>
 #include <linux/uaccess.h>
 
-#include <asm/system.h>
 
 #define OUR_NAME "sbc60xxwdt"
 #define PFX OUR_NAME ": "
@@ -105,8 +106,8 @@ MODULE_PARM_DESC(timeout,
        "Watchdog timeout in seconds. (1<=timeout<=3600, default="
                                __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
        "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -132,8 +133,7 @@ static void wdt_timer_ping(unsigned long data)
                /* Re-set the timer interval */
                mod_timer(&timer, jiffies + WDT_INTERVAL);
        } else
-               printk(KERN_WARNING PFX
-                       "Heartbeat lost! Will not ping the watchdog\n");
+               pr_warn("Heartbeat lost! Will not ping the watchdog\n");
 }
 
 /*
@@ -146,7 +146,7 @@ static void wdt_startup(void)
 
        /* Start the timer */
        mod_timer(&timer, jiffies + WDT_INTERVAL);
-       printk(KERN_INFO PFX "Watchdog timer is now enabled.\n");
+       pr_info("Watchdog timer is now enabled\n");
 }
 
 static void wdt_turnoff(void)
@@ -154,7 +154,7 @@ static void wdt_turnoff(void)
        /* Stop the timer */
        del_timer(&timer);
        inb_p(wdt_stop);
-       printk(KERN_INFO PFX "Watchdog timer is now disabled...\n");
+       pr_info("Watchdog timer is now disabled...\n");
 }
 
 static void wdt_keepalive(void)
@@ -217,8 +217,7 @@ static int fop_close(struct inode *inode, struct file *file)
                wdt_turnoff();
        else {
                del_timer(&timer);
-               printk(KERN_CRIT PFX
-                 "device file closed unexpectedly. Will not stop the WDT!\n");
+               pr_crit("device file closed unexpectedly. Will not stop the WDT!\n");
        }
        clear_bit(0, &wdt_is_open);
        wdt_expect_close = 0;
@@ -335,14 +334,12 @@ static int __init sbc60xxwdt_init(void)
 
        if (timeout < 1 || timeout > 3600) { /* arbitrary upper limit */
                timeout = WATCHDOG_TIMEOUT;
-               printk(KERN_INFO PFX
-                       "timeout value must be 1 <= x <= 3600, using %d\n",
-                                                               timeout);
+               pr_info("timeout value must be 1 <= x <= 3600, using %d\n",
+                       timeout);
        }
 
        if (!request_region(wdt_start, 1, "SBC 60XX WDT")) {
-               printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
-                       wdt_start);
+               pr_err("I/O address 0x%04x already in use\n", wdt_start);
                rc = -EIO;
                goto err_out;
        }
@@ -350,9 +347,7 @@ static int __init sbc60xxwdt_init(void)
        /* We cannot reserve 0x45 - the kernel already has! */
        if (wdt_stop != 0x45 && wdt_stop != wdt_start) {
                if (!request_region(wdt_stop, 1, "SBC 60XX WDT")) {
-                       printk(KERN_ERR PFX
-                               "I/O address 0x%04x already in use\n",
-                                                       wdt_stop);
+                       pr_err("I/O address 0x%04x already in use\n", wdt_stop);
                        rc = -EIO;
                        goto err_out_region1;
                }
@@ -360,21 +355,18 @@ static int __init sbc60xxwdt_init(void)
 
        rc = register_reboot_notifier(&wdt_notifier);
        if (rc) {
-               printk(KERN_ERR PFX
-                       "cannot register reboot notifier (err=%d)\n", rc);
+               pr_err("cannot register reboot notifier (err=%d)\n", rc);
                goto err_out_region2;
        }
 
        rc = misc_register(&wdt_miscdev);
        if (rc) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                                               wdt_miscdev.minor, rc);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      wdt_miscdev.minor, rc);
                goto err_out_reboot;
        }
-       printk(KERN_INFO PFX
-               "WDT driver for 60XX single board computer initialised. "
-               "timeout=%d sec (nowayout=%d)\n", timeout, nowayout);
+       pr_info("WDT driver for 60XX single board computer initialised. timeout=%d sec (nowayout=%d)\n",
+               timeout, nowayout);
 
        return 0;
 
index 93ac589..719edc8 100644 (file)
@@ -16,6 +16,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/fs.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
@@ -30,9 +32,6 @@
 #include <linux/io.h>
 #include <linux/uaccess.h>
 #include <linux/atomic.h>
-#include <asm/system.h>
-
-#define SBC7240_PREFIX "sbc7240_wdt: "
 
 #define SBC7240_ENABLE_PORT            0x443
 #define SBC7240_DISABLE_PORT           0x043
@@ -47,8 +46,8 @@ MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<="
                 __MODULE_STRING(SBC7240_MAX_TIMEOUT) ", default="
                 __MODULE_STRING(SBC7240_TIMEOUT) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Disable watchdog when closing device file");
 
 #define SBC7240_OPEN_STATUS_BIT                0
@@ -65,8 +64,7 @@ static void wdt_disable(void)
        /* disable the watchdog */
        if (test_and_clear_bit(SBC7240_ENABLED_STATUS_BIT, &wdt_status)) {
                inb_p(SBC7240_DISABLE_PORT);
-               printk(KERN_INFO SBC7240_PREFIX
-                      "Watchdog timer is now disabled.\n");
+               pr_info("Watchdog timer is now disabled\n");
        }
 }
 
@@ -75,23 +73,20 @@ static void wdt_enable(void)
        /* enable the watchdog */
        if (!test_and_set_bit(SBC7240_ENABLED_STATUS_BIT, &wdt_status)) {
                inb_p(SBC7240_ENABLE_PORT);
-               printk(KERN_INFO SBC7240_PREFIX
-                      "Watchdog timer is now enabled.\n");
+               pr_info("Watchdog timer is now enabled\n");
        }
 }
 
 static int wdt_set_timeout(int t)
 {
        if (t < 1 || t > SBC7240_MAX_TIMEOUT) {
-               printk(KERN_ERR SBC7240_PREFIX
-                      "timeout value must be 1<=x<=%d\n",
-                      SBC7240_MAX_TIMEOUT);
+               pr_err("timeout value must be 1<=x<=%d\n", SBC7240_MAX_TIMEOUT);
                return -1;
        }
        /* set the timeout */
        outb_p((unsigned)t, SBC7240_SET_TIMEOUT_PORT);
        timeout = t;
-       printk(KERN_INFO SBC7240_PREFIX "timeout set to %d seconds\n", t);
+       pr_info("timeout set to %d seconds\n", t);
        return 0;
 }
 
@@ -150,8 +145,7 @@ static int fop_close(struct inode *inode, struct file *file)
            || !nowayout) {
                wdt_disable();
        } else {
-               printk(KERN_CRIT SBC7240_PREFIX
-                      "Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
                wdt_keepalive();
        }
 
@@ -252,7 +246,7 @@ static struct notifier_block wdt_notifier = {
 
 static void __exit sbc7240_wdt_unload(void)
 {
-       printk(KERN_INFO SBC7240_PREFIX "Removing watchdog\n");
+       pr_info("Removing watchdog\n");
        misc_deregister(&wdt_miscdev);
 
        unregister_reboot_notifier(&wdt_notifier);
@@ -264,8 +258,7 @@ static int __init sbc7240_wdt_init(void)
        int rc = -EBUSY;
 
        if (!request_region(SBC7240_ENABLE_PORT, 1, "SBC7240 WDT")) {
-               printk(KERN_ERR SBC7240_PREFIX
-                      "I/O address 0x%04x already in use\n",
+               pr_err("I/O address 0x%04x already in use\n",
                       SBC7240_ENABLE_PORT);
                rc = -EIO;
                goto err_out;
@@ -277,31 +270,27 @@ static int __init sbc7240_wdt_init(void)
 
        if (timeout < 1 || timeout > SBC7240_MAX_TIMEOUT) {
                timeout = SBC7240_TIMEOUT;
-               printk(KERN_INFO SBC7240_PREFIX
-                      "timeout value must be 1<=x<=%d, using %d\n",
-                      SBC7240_MAX_TIMEOUT, timeout);
+               pr_info("timeout value must be 1<=x<=%d, using %d\n",
+                       SBC7240_MAX_TIMEOUT, timeout);
        }
        wdt_set_timeout(timeout);
        wdt_disable();
 
        rc = register_reboot_notifier(&wdt_notifier);
        if (rc) {
-               printk(KERN_ERR SBC7240_PREFIX
-                      "cannot register reboot notifier (err=%d)\n", rc);
+               pr_err("cannot register reboot notifier (err=%d)\n", rc);
                goto err_out_region;
        }
 
        rc = misc_register(&wdt_miscdev);
        if (rc) {
-               printk(KERN_ERR SBC7240_PREFIX
-                      "cannot register miscdev on minor=%d (err=%d)\n",
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
                       wdt_miscdev.minor, rc);
                goto err_out_reboot_notifier;
        }
 
-       printk(KERN_INFO SBC7240_PREFIX
-              "Watchdog driver for SBC7240 initialised (nowayout=%d)\n",
-              nowayout);
+       pr_info("Watchdog driver for SBC7240 initialised (nowayout=%d)\n",
+               nowayout);
 
        return 0;
 
index 514ec23..d4781e0 100644 (file)
@@ -36,6 +36,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/miscdevice.h>
 #include <linux/io.h>
 #include <linux/uaccess.h>
 
-#include <asm/system.h>
 
 static unsigned long sbc8360_is_open;
 static char expect_close;
 
-#define PFX "sbc8360: "
-
 /*
  *
  * Watchdog Timer Configuration
@@ -197,11 +196,11 @@ static int wd_times[64][2] = {
 static int timeout = 27;
 static int wd_margin = 0xB;
 static int wd_multiplier = 2;
-static int nowayout = WATCHDOG_NOWAYOUT;
+static bool nowayout = WATCHDOG_NOWAYOUT;
 
 module_param(timeout, int, 0);
 MODULE_PARM_DESC(timeout, "Index into timeout table (0-63) (default=27 (60s))");
-module_param(nowayout, int, 0);
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                 "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -280,8 +279,7 @@ static int sbc8360_close(struct inode *inode, struct file *file)
        if (expect_close == 42)
                sbc8360_stop();
        else
-               printk(KERN_CRIT PFX "SBC8360 device closed unexpectedly.  "
-                                               "SBC8360 will not stop!\n");
+               pr_crit("SBC8360 device closed unexpectedly.  SBC8360 will not stop!\n");
 
        clear_bit(0, &sbc8360_is_open);
        expect_close = 0;
@@ -334,20 +332,19 @@ static int __init sbc8360_init(void)
        unsigned long int mseconds = 60000;
 
        if (timeout < 0 || timeout > 63) {
-               printk(KERN_ERR PFX "Invalid timeout index (must be 0-63).\n");
+               pr_err("Invalid timeout index (must be 0-63)\n");
                res = -EINVAL;
                goto out;
        }
 
        if (!request_region(SBC8360_ENABLE, 1, "SBC8360")) {
-               printk(KERN_ERR PFX "ENABLE method I/O %X is not available.\n",
+               pr_err("ENABLE method I/O %X is not available\n",
                       SBC8360_ENABLE);
                res = -EIO;
                goto out;
        }
        if (!request_region(SBC8360_BASETIME, 1, "SBC8360")) {
-               printk(KERN_ERR PFX
-                      "BASETIME method I/O %X is not available.\n",
+               pr_err("BASETIME method I/O %X is not available\n",
                       SBC8360_BASETIME);
                res = -EIO;
                goto out_nobasetimereg;
@@ -355,13 +352,13 @@ static int __init sbc8360_init(void)
 
        res = register_reboot_notifier(&sbc8360_notifier);
        if (res) {
-               printk(KERN_ERR PFX "Failed to register reboot notifier.\n");
+               pr_err("Failed to register reboot notifier\n");
                goto out_noreboot;
        }
 
        res = misc_register(&sbc8360_miscdev);
        if (res) {
-               printk(KERN_ERR PFX "failed to register misc device\n");
+               pr_err("failed to register misc device\n");
                goto out_nomisc;
        }
 
@@ -378,7 +375,7 @@ static int __init sbc8360_init(void)
                mseconds = (wd_margin + 1) * 100000;
 
        /* My kingdom for the ability to print "0.5 seconds" in the kernel! */
-       printk(KERN_INFO PFX "Timeout set at %ld ms.\n", mseconds);
+       pr_info("Timeout set at %ld ms\n", mseconds);
 
        return 0;
 
index eaca366..0c3e9f6 100644 (file)
@@ -13,6 +13,8 @@
  *     based on softdog.c by Alan Cox <alan@lxorguk.ukuu.org.uk>
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/uaccess.h>
 #include <linux/io.h>
 
-#define PFX "epx_c3: "
 static int epx_c3_alive;
 
 #define WATCHDOG_TIMEOUT 1             /* 1 sec default timeout */
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
                                        __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
@@ -51,7 +52,7 @@ static void epx_c3_stop(void)
 
        outb(0, EPXC3_WATCHDOG_CTL_REG);
 
-       printk(KERN_INFO PFX "Stopped watchdog timer.\n");
+       pr_info("Stopped watchdog timer\n");
 }
 
 static void epx_c3_pet(void)
@@ -75,7 +76,7 @@ static int epx_c3_open(struct inode *inode, struct file *file)
        epx_c3_pet();
 
        epx_c3_alive = 1;
-       printk(KERN_INFO "Started watchdog timer.\n");
+       pr_info("Started watchdog timer\n");
 
        return nonseekable_open(inode, file);
 }
@@ -173,9 +174,6 @@ static struct notifier_block epx_c3_notifier = {
        .notifier_call = epx_c3_notify_sys,
 };
 
-static const char banner[] __initconst = KERN_INFO PFX
-       "Hardware Watchdog Timer for Winsystems EPX-C3 SBC: 0.1\n";
-
 static int __init watchdog_init(void)
 {
        int ret;
@@ -185,20 +183,19 @@ static int __init watchdog_init(void)
 
        ret = register_reboot_notifier(&epx_c3_notifier);
        if (ret) {
-               printk(KERN_ERR PFX "cannot register reboot notifier "
-                       "(err=%d)\n", ret);
+               pr_err("cannot register reboot notifier (err=%d)\n", ret);
                goto out;
        }
 
        ret = misc_register(&epx_c3_miscdev);
        if (ret) {
-               printk(KERN_ERR PFX "cannot register miscdev on minor=%d "
-                       "(err=%d)\n", WATCHDOG_MINOR, ret);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      WATCHDOG_MINOR, ret);
                unregister_reboot_notifier(&epx_c3_notifier);
                goto out;
        }
 
-       printk(banner);
+       pr_info("Hardware Watchdog Timer for Winsystems EPX-C3 SBC: 0.1\n");
 
        return 0;
 
index d5d3994..90d5527 100644 (file)
@@ -25,9 +25,8 @@
 #include <linux/io.h>
 #include <linux/uaccess.h>
 
-#include <asm/system.h>
 
-static int nowayout = WATCHDOG_NOWAYOUT;
+static bool nowayout = WATCHDOG_NOWAYOUT;
 static unsigned int margin = 60;       /* (secs) Default is 1 minute */
 static unsigned long wdt_status;
 static DEFINE_MUTEX(wdt_lock);
@@ -171,8 +170,7 @@ static int fitpc2_wdt_release(struct inode *inode, struct file *file)
                wdt_disable();
                pr_info("Device disabled\n");
        } else {
-               pr_warning("Device closed unexpectedly -"
-                       " timer will not stop\n");
+               pr_warn("Device closed unexpectedly - timer will not stop\n");
                wdt_enable();
        }
 
@@ -222,8 +220,8 @@ static int __init fitpc2_wdt_init(void)
        }
 
        if (margin < 31 || margin > 255) {
-               pr_err("margin must be in range 31 - 255"
-                      " seconds, you tried to set %d\n", margin);
+               pr_err("margin must be in range 31 - 255 seconds, you tried to set %d\n",
+                      margin);
                err = -EINVAL;
                goto err_margin;
        }
@@ -231,7 +229,7 @@ static int __init fitpc2_wdt_init(void)
        err = misc_register(&fitpc2_wdt_miscdev);
        if (err) {
                pr_err("cannot register miscdev on minor=%d (err=%d)\n",
-                                                       WATCHDOG_MINOR, err);
+                      WATCHDOG_MINOR, err);
                goto err_margin;
        }
 
@@ -261,7 +259,7 @@ MODULE_DESCRIPTION("SBC-FITPC2 Watchdog");
 module_param(margin, int, 0);
 MODULE_PARM_DESC(margin, "Watchdog margin in seconds (default 60s)");
 
-module_param(nowayout, int, 0);
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
 
 MODULE_LICENSE("GPL");
index c01daca..3fb83b0 100644 (file)
@@ -31,6 +31,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/miscdevice.h>
@@ -48,7 +50,6 @@
 
 #define SC1200_MODULE_VER      "build 20020303"
 #define SC1200_MODULE_NAME     "sc1200wdt"
-#define PFX                    SC1200_MODULE_NAME ": "
 
 #define        MAX_TIMEOUT     255     /* 255 minutes */
 #define PMIR           (io)    /* Power Management Index Register */
@@ -71,7 +72,6 @@
 #define UART2_IRQ      0x04    /* Serial1 */
 /* 5 -7 are reserved */
 
-static char banner[] __initdata = PFX SC1200_MODULE_VER;
 static int timeout = 1;
 static int io = -1;
 static int io_len = 2;         /* for non plug and play */
@@ -93,8 +93,8 @@ MODULE_PARM_DESC(io, "io port");
 module_param(timeout, int, 0);
 MODULE_PARM_DESC(timeout, "range is 0-255 minutes, default is 1");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
        "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -176,7 +176,7 @@ static int sc1200wdt_open(struct inode *inode, struct file *file)
                timeout = MAX_TIMEOUT;
 
        sc1200wdt_start();
-       printk(KERN_INFO PFX "Watchdog enabled, timeout = %d min(s)", timeout);
+       pr_info("Watchdog enabled, timeout = %d min(s)", timeout);
 
        return nonseekable_open(inode, file);
 }
@@ -254,11 +254,10 @@ static int sc1200wdt_release(struct inode *inode, struct file *file)
 {
        if (expect_close == 42) {
                sc1200wdt_stop();
-               printk(KERN_INFO PFX "Watchdog disabled\n");
+               pr_info("Watchdog disabled\n");
        } else {
                sc1200wdt_write_data(WDTO, timeout);
-               printk(KERN_CRIT PFX
-                       "Unexpected close!, timeout = %d min(s)\n", timeout);
+               pr_crit("Unexpected close!, timeout = %d min(s)\n", timeout);
        }
        clear_bit(0, &open_flag);
        expect_close = 0;
@@ -361,12 +360,11 @@ static int scl200wdt_pnp_probe(struct pnp_dev *dev,
        io_len = pnp_port_len(wdt_dev, 0);
 
        if (!request_region(io, io_len, SC1200_MODULE_NAME)) {
-               printk(KERN_ERR PFX "Unable to register IO port %#x\n", io);
+               pr_err("Unable to register IO port %#x\n", io);
                return -EBUSY;
        }
 
-       printk(KERN_INFO "scl200wdt: PnP device found at io port %#x/%d\n",
-                                                               io, io_len);
+       pr_info("PnP device found at io port %#x/%d\n", io, io_len);
        return 0;
 }
 
@@ -392,7 +390,7 @@ static int __init sc1200wdt_init(void)
 {
        int ret;
 
-       printk(KERN_INFO "%s\n", banner);
+       pr_info("%s\n", SC1200_MODULE_VER);
 
 #if defined CONFIG_PNP
        if (isapnp) {
@@ -403,7 +401,7 @@ static int __init sc1200wdt_init(void)
 #endif
 
        if (io == -1) {
-               printk(KERN_ERR PFX "io parameter must be specified\n");
+               pr_err("io parameter must be specified\n");
                ret = -EINVAL;
                goto out_pnp;
        }
@@ -416,7 +414,7 @@ static int __init sc1200wdt_init(void)
 #endif
 
        if (!request_region(io, io_len, SC1200_MODULE_NAME)) {
-               printk(KERN_ERR PFX "Unable to register IO port %#x\n", io);
+               pr_err("Unable to register IO port %#x\n", io);
                ret = -EBUSY;
                goto out_pnp;
        }
@@ -427,16 +425,14 @@ static int __init sc1200wdt_init(void)
 
        ret = register_reboot_notifier(&sc1200wdt_notifier);
        if (ret) {
-               printk(KERN_ERR PFX
-                       "Unable to register reboot notifier err = %d\n", ret);
+               pr_err("Unable to register reboot notifier err = %d\n", ret);
                goto out_io;
        }
 
        ret = misc_register(&sc1200wdt_miscdev);
        if (ret) {
-               printk(KERN_ERR PFX
-                       "Unable to register miscdev on minor %d\n",
-                                                       WATCHDOG_MINOR);
+               pr_err("Unable to register miscdev on minor %d\n",
+                      WATCHDOG_MINOR);
                goto out_rbt;
        }
 
index b284040..707e027 100644 (file)
@@ -52,6 +52,8 @@
  *  This driver uses memory mapped IO, and spinlock.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/io.h>
 #include <linux/uaccess.h>
 
-#include <asm/system.h>
-
-#define OUR_NAME "sc520_wdt"
-#define PFX OUR_NAME ": "
 
 /*
  * The AMD Elan SC520 timeout value is 492us times a power of 2 (0-7)
@@ -98,8 +96,8 @@ MODULE_PARM_DESC(timeout,
        "Watchdog timeout in seconds. (1 <= timeout <= 3600, default="
                                __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -151,8 +149,7 @@ static void wdt_timer_ping(unsigned long data)
                /* Re-set the timer interval */
                mod_timer(&timer, jiffies + WDT_INTERVAL);
        } else
-               printk(KERN_WARNING PFX
-                       "Heartbeat lost! Will not ping the watchdog\n");
+               pr_warn("Heartbeat lost! Will not ping the watchdog\n");
 }
 
 /*
@@ -187,7 +184,7 @@ static int wdt_startup(void)
        /* Start the watchdog */
        wdt_config(WDT_ENB | WDT_WRST_ENB | WDT_EXP_SEL_04);
 
-       printk(KERN_INFO PFX "Watchdog timer is now enabled.\n");
+       pr_info("Watchdog timer is now enabled\n");
        return 0;
 }
 
@@ -199,7 +196,7 @@ static int wdt_turnoff(void)
        /* Stop the watchdog */
        wdt_config(0);
 
-       printk(KERN_INFO PFX "Watchdog timer is now disabled...\n");
+       pr_info("Watchdog timer is now disabled...\n");
        return 0;
 }
 
@@ -270,8 +267,7 @@ static int fop_close(struct inode *inode, struct file *file)
        if (wdt_expect_close == 42)
                wdt_turnoff();
        else {
-               printk(KERN_CRIT PFX
-                       "Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
                wdt_keepalive();
        }
        clear_bit(0, &wdt_is_open);
@@ -393,36 +389,32 @@ static int __init sc520_wdt_init(void)
           if not reset to the default */
        if (wdt_set_heartbeat(timeout)) {
                wdt_set_heartbeat(WATCHDOG_TIMEOUT);
-               printk(KERN_INFO PFX
-                   "timeout value must be 1 <= timeout <= 3600, using %d\n",
-                                                       WATCHDOG_TIMEOUT);
+               pr_info("timeout value must be 1 <= timeout <= 3600, using %d\n",
+                       WATCHDOG_TIMEOUT);
        }
 
        wdtmrctl = ioremap(MMCR_BASE + OFFS_WDTMRCTL, 2);
        if (!wdtmrctl) {
-               printk(KERN_ERR PFX "Unable to remap memory\n");
+               pr_err("Unable to remap memory\n");
                rc = -ENOMEM;
                goto err_out_region2;
        }
 
        rc = register_reboot_notifier(&wdt_notifier);
        if (rc) {
-               printk(KERN_ERR PFX
-                       "cannot register reboot notifier (err=%d)\n", rc);
+               pr_err("cannot register reboot notifier (err=%d)\n", rc);
                goto err_out_ioremap;
        }
 
        rc = misc_register(&wdt_miscdev);
        if (rc) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                                                       WATCHDOG_MINOR, rc);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      WATCHDOG_MINOR, rc);
                goto err_out_notifier;
        }
 
-       printk(KERN_INFO PFX
-          "WDT driver for SC520 initialised. timeout=%d sec (nowayout=%d)\n",
-                                                       timeout, nowayout);
+       pr_info("WDT driver for SC520 initialised. timeout=%d sec (nowayout=%d)\n",
+               timeout, nowayout);
 
        return 0;
 
index 029467e..bd86f32 100644 (file)
@@ -18,6 +18,8 @@
  *     Includes, defines, variables, module parameters, ...
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 /* Includes */
 #include <linux/module.h>              /* For module specific items */
 #include <linux/moduleparam.h>         /* For new moduleparam's */
@@ -37,7 +39,6 @@
 
 /* Module and version information */
 #define DRV_NAME       "sch311x_wdt"
-#define PFX            DRV_NAME ": "
 
 /* Runtime registers */
 #define RESGEN                 0x1d
@@ -79,8 +80,8 @@ MODULE_PARM_DESC(timeout,
        "Watchdog timeout in seconds. 1<= timeout <=15300, default="
                __MODULE_STRING(WATCHDOG_TIMEOUT) ".");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
        "Watchdog cannot be stopped once started (default="
                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -323,8 +324,7 @@ static int sch311x_wdt_close(struct inode *inode, struct file *file)
        if (sch311x_wdt_expect_close == 42) {
                sch311x_wdt_stop();
        } else {
-               printk(KERN_CRIT PFX
-                               "Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
                sch311x_wdt_keepalive();
        }
        clear_bit(0, &sch311x_wdt_is_open);
@@ -504,20 +504,19 @@ static int __init sch311x_detect(int sio_config_port, unsigned short *addr)
 
        /* Check if Logical Device Register is currently active */
        if ((sch311x_sio_inb(sio_config_port, 0x30) & 0x01) == 0)
-               printk(KERN_INFO PFX "Seems that LDN 0x0a is not active...\n");
+               pr_info("Seems that LDN 0x0a is not active...\n");
 
        /* Get the base address of the runtime registers */
        base_addr = (sch311x_sio_inb(sio_config_port, 0x60) << 8) |
                           sch311x_sio_inb(sio_config_port, 0x61);
        if (!base_addr) {
-               printk(KERN_ERR PFX "Base address not set.\n");
+               pr_err("Base address not set\n");
                err = -ENODEV;
                goto exit;
        }
        *addr = base_addr;
 
-       printk(KERN_INFO PFX "Found an SMSC SCH311%d chip at 0x%04x\n",
-               dev_id, base_addr);
+       pr_info("Found an SMSC SCH311%d chip at 0x%04x\n", dev_id, base_addr);
 
 exit:
        sch311x_sio_exit(sio_config_port);
index e67b76c..8ae7c28 100644 (file)
@@ -17,6 +17,8 @@
    of any nature resulting due to the use of this software. This
    software is provided AS-IS with no warranties. */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
@@ -30,7 +32,7 @@
 #include <linux/uaccess.h>
 #include <linux/io.h>
 
-#define NAME "scx200_wdt"
+#define DEBUG
 
 MODULE_AUTHOR("Christer Weinigel <wingel@nano-system.com>");
 MODULE_DESCRIPTION("NatSemi SCx200 Watchdog Driver");
@@ -41,8 +43,8 @@ static int margin = 60;               /* in seconds */
 module_param(margin, int, 0);
 MODULE_PARM_DESC(margin, "Watchdog margin in seconds");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close");
 
 static u16 wdto_restart;
@@ -66,14 +68,13 @@ static void scx200_wdt_ping(void)
 
 static void scx200_wdt_update_margin(void)
 {
-       printk(KERN_INFO NAME ": timer margin %d seconds\n", margin);
+       pr_info("timer margin %d seconds\n", margin);
        wdto_restart = margin * W_SCALE;
 }
 
 static void scx200_wdt_enable(void)
 {
-       printk(KERN_DEBUG NAME ": enabling watchdog timer, wdto_restart = %d\n",
-              wdto_restart);
+       pr_debug("enabling watchdog timer, wdto_restart = %d\n", wdto_restart);
 
        spin_lock(&scx_lock);
        outw(0, scx200_cb_base + SCx200_WDT_WDTO);
@@ -86,7 +87,7 @@ static void scx200_wdt_enable(void)
 
 static void scx200_wdt_disable(void)
 {
-       printk(KERN_DEBUG NAME ": disabling watchdog timer\n");
+       pr_debug("disabling watchdog timer\n");
 
        spin_lock(&scx_lock);
        outw(0, scx200_cb_base + SCx200_WDT_WDTO);
@@ -108,9 +109,7 @@ static int scx200_wdt_open(struct inode *inode, struct file *file)
 static int scx200_wdt_release(struct inode *inode, struct file *file)
 {
        if (expect_close != 42)
-               printk(KERN_WARNING NAME
-                       ": watchdog device closed unexpectedly, "
-                       "will not disable the watchdog timer\n");
+               pr_warn("watchdog device closed unexpectedly, will not disable the watchdog timer\n");
        else if (!nowayout)
                scx200_wdt_disable();
        expect_close = 0;
@@ -219,7 +218,7 @@ static int __init scx200_wdt_init(void)
 {
        int r;
 
-       printk(KERN_DEBUG NAME ": NatSemi SCx200 Watchdog Driver\n");
+       pr_debug("NatSemi SCx200 Watchdog Driver\n");
 
        /* check that we have found the configuration block */
        if (!scx200_cb_present())
@@ -228,7 +227,7 @@ static int __init scx200_wdt_init(void)
        if (!request_region(scx200_cb_base + SCx200_WDT_OFFSET,
                            SCx200_WDT_SIZE,
                            "NatSemi SCx200 Watchdog")) {
-               printk(KERN_WARNING NAME ": watchdog I/O region busy\n");
+               pr_warn("watchdog I/O region busy\n");
                return -EBUSY;
        }
 
@@ -237,7 +236,7 @@ static int __init scx200_wdt_init(void)
 
        r = register_reboot_notifier(&scx200_wdt_notifier);
        if (r) {
-               printk(KERN_ERR NAME ": unable to register reboot notifier");
+               pr_err("unable to register reboot notifier\n");
                release_region(scx200_cb_base + SCx200_WDT_OFFSET,
                                SCx200_WDT_SIZE);
                return r;
index a267dc0..93958a7 100644 (file)
@@ -17,6 +17,9 @@
  *     Added expect close support, made emulated timeout runtime changeable
  *     general cleanups, add some ioctls
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/platform_device.h>
@@ -72,7 +75,7 @@ static DEFINE_SPINLOCK(shwdt_lock);
 
 #define WATCHDOG_HEARTBEAT 30                  /* 30 sec default heartbeat */
 static int heartbeat = WATCHDOG_HEARTBEAT;     /* in seconds */
-static int nowayout = WATCHDOG_NOWAYOUT;
+static bool nowayout = WATCHDOG_NOWAYOUT;
 static unsigned long next_heartbeat;
 
 struct sh_wdt {
@@ -440,20 +443,20 @@ static int __init sh_wdt_init(void)
                     clock_division_ratio > 0x7)) {
                clock_division_ratio = WTCSR_CKS_4096;
 
-               pr_info("%s: divisor must be 0x5<=x<=0x7, using %d\n",
-                        DRV_NAME, clock_division_ratio);
+               pr_info("divisor must be 0x5<=x<=0x7, using %d\n",
+                       clock_division_ratio);
        }
 
        rc = sh_wdt_set_heartbeat(heartbeat);
        if (unlikely(rc)) {
                heartbeat = WATCHDOG_HEARTBEAT;
 
-               pr_info("%s: heartbeat value must be 1<=x<=3600, using %d\n",
-                       DRV_NAME, heartbeat);
+               pr_info("heartbeat value must be 1<=x<=3600, using %d\n",
+                       heartbeat);
        }
 
-       pr_info("%s: configured with heartbeat=%d sec (nowayout=%d)\n",
-               DRV_NAME, heartbeat, nowayout);
+       pr_info("configured with heartbeat=%d sec (nowayout=%d)\n",
+               heartbeat, nowayout);
 
        return platform_driver_register(&sh_wdt_driver);
 }
@@ -481,7 +484,7 @@ MODULE_PARM_DESC(heartbeat,
        "Watchdog heartbeat in seconds. (1 <= heartbeat <= 3600, default="
                                __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
 
-module_param(nowayout, int, 0);
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
        "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
index 97b8184..6d665f9 100644 (file)
@@ -43,6 +43,8 @@
  *   Documentation/watchdog/wdt.txt
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
@@ -58,7 +60,6 @@
 #include <linux/io.h>
 #include <linux/uaccess.h>
 
-#include <asm/system.h>
 
 /* enable support for minutes as units? */
 /* (does not always work correctly, so disabled by default!) */
@@ -70,7 +71,6 @@
 #define UNIT_SECOND     0
 #define UNIT_MINUTE     1
 
-#define MODNAME                "smsc37b787_wdt: "
 #define VERSION                "1.1"
 
 #define IOPORT         0x3F0
@@ -85,7 +85,7 @@ static char expect_close;       /* is the close expected? */
 
 static DEFINE_SPINLOCK(io_lock);/* to guard the watchdog from io races */
 
-static int nowayout = WATCHDOG_NOWAYOUT;
+static bool nowayout = WATCHDOG_NOWAYOUT;
 
 /* -- Low level function ----------------------------------------*/
 
@@ -363,8 +363,7 @@ static int wb_smsc_wdt_open(struct inode *inode, struct file *file)
        /* Reload and activate timer */
        wb_smsc_wdt_enable();
 
-       printk(KERN_INFO MODNAME
-               "Watchdog enabled. Timeout set to %d %s.\n",
+       pr_info("Watchdog enabled. Timeout set to %d %s\n",
                timeout, (unit == UNIT_SECOND) ? "second(s)" : "minute(s)");
 
        return nonseekable_open(inode, file);
@@ -378,11 +377,9 @@ static int wb_smsc_wdt_release(struct inode *inode, struct file *file)
 
        if (expect_close == 42) {
                wb_smsc_wdt_disable();
-               printk(KERN_INFO MODNAME
-                               "Watchdog disabled, sleeping again...\n");
+               pr_info("Watchdog disabled, sleeping again...\n");
        } else {
-               printk(KERN_CRIT MODNAME
-                               "Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
                wb_smsc_wdt_reset_timer();
        }
 
@@ -534,12 +531,11 @@ static int __init wb_smsc_wdt_init(void)
 {
        int ret;
 
-       printk(KERN_INFO "SMsC 37B787 watchdog component driver "
-                                       VERSION " initialising...\n");
+       pr_info("SMsC 37B787 watchdog component driver "
+               VERSION " initialising...\n");
 
        if (!request_region(IOPORT, IOPORT_SIZE, "SMsC 37B787 watchdog")) {
-               printk(KERN_ERR MODNAME "Unable to register IO port %#x\n",
-                                                               IOPORT);
+               pr_err("Unable to register IO port %#x\n", IOPORT);
                ret = -EBUSY;
                goto out_pnp;
        }
@@ -553,25 +549,22 @@ static int __init wb_smsc_wdt_init(void)
 
        ret = register_reboot_notifier(&wb_smsc_wdt_notifier);
        if (ret) {
-               printk(KERN_ERR MODNAME
-                       "Unable to register reboot notifier err = %d\n", ret);
+               pr_err("Unable to register reboot notifier err = %d\n", ret);
                goto out_io;
        }
 
        ret = misc_register(&wb_smsc_wdt_miscdev);
        if (ret) {
-               printk(KERN_ERR MODNAME
-                       "Unable to register miscdev on minor %d\n",
-                                                       WATCHDOG_MINOR);
+               pr_err("Unable to register miscdev on minor %d\n",
+                      WATCHDOG_MINOR);
                goto out_rbt;
        }
 
        /* output info */
-       printk(KERN_INFO MODNAME "Timeout set to %d %s.\n",
+       pr_info("Timeout set to %d %s\n",
                timeout, (unit == UNIT_SECOND) ? "second(s)" : "minute(s)");
-       printk(KERN_INFO MODNAME
-               "Watchdog initialized and sleeping (nowayout=%d)...\n",
-                                                               nowayout);
+       pr_info("Watchdog initialized and sleeping (nowayout=%d)...\n",
+               nowayout);
 out_clean:
        return ret;
 
@@ -592,14 +585,14 @@ static void __exit wb_smsc_wdt_exit(void)
        /* Stop the timer before we leave */
        if (!nowayout) {
                wb_smsc_wdt_shutdown();
-               printk(KERN_INFO MODNAME "Watchdog disabled.\n");
+               pr_info("Watchdog disabled\n");
        }
 
        misc_deregister(&wb_smsc_wdt_miscdev);
        unregister_reboot_notifier(&wb_smsc_wdt_notifier);
        release_region(IOPORT, IOPORT_SIZE);
 
-       printk(KERN_INFO "SMsC 37B787 watchdog component driver removed.\n");
+       pr_info("SMsC 37B787 watchdog component driver removed\n");
 }
 
 module_init(wb_smsc_wdt_init);
@@ -621,7 +614,7 @@ MODULE_PARM_DESC(unit,
 module_param(timeout, int, 0);
 MODULE_PARM_DESC(timeout, "range is 1-255 units, default is 60");
 
-module_param(nowayout, int, 0);
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
index bf16ffb..fe83beb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *     SoftDog 0.07:   A Software Watchdog Device
+ *     SoftDog:        A Software Watchdog Device
  *
  *     (c) Copyright 1996 Alan Cox <alan@lxorguk.ukuu.org.uk>,
  *                                                     All Rights Reserved.
  *     Added Matt Domsch's nowayout module option.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/timer.h>
 #include <linux/miscdevice.h>
 #include <linux/watchdog.h>
-#include <linux/fs.h>
 #include <linux/notifier.h>
 #include <linux/reboot.h>
 #include <linux/init.h>
 #include <linux/jiffies.h>
-#include <linux/uaccess.h>
 #include <linux/kernel.h>
 
-#define PFX "SoftDog: "
-
 #define TIMER_MARGIN   60              /* Default is 60 seconds */
-static int soft_margin = TIMER_MARGIN; /* in seconds */
-module_param(soft_margin, int, 0);
+static unsigned int soft_margin = TIMER_MARGIN;        /* in seconds */
+module_param(soft_margin, uint, 0);
 MODULE_PARM_DESC(soft_margin,
        "Watchdog soft_margin in seconds. (0 < soft_margin < 65536, default="
                                        __MODULE_STRING(TIMER_MARGIN) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
-#ifdef ONLY_TESTING
-static int soft_noboot = 1;
-#else
 static int soft_noboot = 0;
-#endif  /* ONLY_TESTING */
-
 module_param(soft_noboot, int, 0);
 MODULE_PARM_DESC(soft_noboot,
-       "Softdog action, set to 1 to ignore reboots, 0 to reboot "
-                                       "(default depends on ONLY_TESTING)");
+       "Softdog action, set to 1 to ignore reboots, 0 to reboot (default=0)");
 
 static int soft_panic;
 module_param(soft_panic, int, 0);
@@ -89,9 +81,6 @@ static void watchdog_fire(unsigned long);
 
 static struct timer_list watchdog_ticktock =
                TIMER_INITIALIZER(watchdog_fire, 0, 0);
-static unsigned long driver_open, orphan_timer;
-static char expect_close;
-
 
 /*
  *     If the timer expires..
@@ -99,18 +88,15 @@ static char expect_close;
 
 static void watchdog_fire(unsigned long data)
 {
-       if (test_and_clear_bit(0, &orphan_timer))
-               module_put(THIS_MODULE);
-
        if (soft_noboot)
-               printk(KERN_CRIT PFX "Triggered - Reboot ignored.\n");
+               pr_crit("Triggered - Reboot ignored\n");
        else if (soft_panic) {
-               printk(KERN_CRIT PFX "Initiating panic.\n");
-               panic("Software Watchdog Timer expired.");
+               pr_crit("Initiating panic\n");
+               panic("Software Watchdog Timer expired");
        } else {
-               printk(KERN_CRIT PFX "Initiating system reboot.\n");
+               pr_crit("Initiating system reboot\n");
                emergency_restart();
-               printk(KERN_CRIT PFX "Reboot didn't ?????\n");
+               pr_crit("Reboot didn't ?????\n");
        }
 }
 
@@ -118,127 +104,24 @@ static void watchdog_fire(unsigned long data)
  *     Softdog operations
  */
 
-static int softdog_keepalive(void)
+static int softdog_ping(struct watchdog_device *w)
 {
-       mod_timer(&watchdog_ticktock, jiffies+(soft_margin*HZ));
+       mod_timer(&watchdog_ticktock, jiffies+(w->timeout*HZ));
        return 0;
 }
 
-static int softdog_stop(void)
+static int softdog_stop(struct watchdog_device *w)
 {
        del_timer(&watchdog_ticktock);
        return 0;
 }
 
-static int softdog_set_heartbeat(int t)
-{
-       if ((t < 0x0001) || (t > 0xFFFF))
-               return -EINVAL;
-
-       soft_margin = t;
-       return 0;
-}
-
-/*
- *     /dev/watchdog handling
- */
-
-static int softdog_open(struct inode *inode, struct file *file)
-{
-       if (test_and_set_bit(0, &driver_open))
-               return -EBUSY;
-       if (!test_and_clear_bit(0, &orphan_timer))
-               __module_get(THIS_MODULE);
-       /*
-        *      Activate timer
-        */
-       softdog_keepalive();
-       return nonseekable_open(inode, file);
-}
-
-static int softdog_release(struct inode *inode, struct file *file)
+static int softdog_set_timeout(struct watchdog_device *w, unsigned int t)
 {
-       /*
-        *      Shut off the timer.
-        *      Lock it in if it's a module and we set nowayout
-        */
-       if (expect_close == 42) {
-               softdog_stop();
-               module_put(THIS_MODULE);
-       } else {
-               printk(KERN_CRIT PFX
-                       "Unexpected close, not stopping watchdog!\n");
-               set_bit(0, &orphan_timer);
-               softdog_keepalive();
-       }
-       clear_bit(0, &driver_open);
-       expect_close = 0;
+       w->timeout = t;
        return 0;
 }
 
-static ssize_t softdog_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;
-                       }
-               }
-               softdog_keepalive();
-       }
-       return len;
-}
-
-static long softdog_ioctl(struct file *file, unsigned int cmd,
-                                                       unsigned long arg)
-{
-       void __user *argp = (void __user *)arg;
-       int __user *p = argp;
-       int new_margin;
-       static const struct watchdog_info ident = {
-               .options =              WDIOF_SETTIMEOUT |
-                                       WDIOF_KEEPALIVEPING |
-                                       WDIOF_MAGICCLOSE,
-               .firmware_version =     0,
-               .identity =             "Software Watchdog",
-       };
-       switch (cmd) {
-       case WDIOC_GETSUPPORT:
-               return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
-       case WDIOC_GETSTATUS:
-       case WDIOC_GETBOOTSTATUS:
-               return put_user(0, p);
-       case WDIOC_KEEPALIVE:
-               softdog_keepalive();
-               return 0;
-       case WDIOC_SETTIMEOUT:
-               if (get_user(new_margin, p))
-                       return -EFAULT;
-               if (softdog_set_heartbeat(new_margin))
-                       return -EINVAL;
-               softdog_keepalive();
-               /* Fall */
-       case WDIOC_GETTIMEOUT:
-               return put_user(soft_margin, p);
-       default:
-               return -ENOTTY;
-       }
-}
-
 /*
  *     Notifier for system down
  */
@@ -248,7 +131,7 @@ static int softdog_notify_sys(struct notifier_block *this, unsigned long code,
 {
        if (code == SYS_DOWN || code == SYS_HALT)
                /* Turn the WDT off */
-               softdog_stop();
+               softdog_stop(NULL);
        return NOTIFY_DONE;
 }
 
@@ -256,28 +139,29 @@ static int softdog_notify_sys(struct notifier_block *this, unsigned long code,
  *     Kernel Interfaces
  */
 
-static const struct file_operations softdog_fops = {
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .write          = softdog_write,
-       .unlocked_ioctl = softdog_ioctl,
-       .open           = softdog_open,
-       .release        = softdog_release,
+static struct notifier_block softdog_notifier = {
+       .notifier_call  = softdog_notify_sys,
 };
 
-static struct miscdevice softdog_miscdev = {
-       .minor          = WATCHDOG_MINOR,
-       .name           = "watchdog",
-       .fops           = &softdog_fops,
+static struct watchdog_info softdog_info = {
+       .identity = "Software Watchdog",
+       .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
 };
 
-static struct notifier_block softdog_notifier = {
-       .notifier_call  = softdog_notify_sys,
+static struct watchdog_ops softdog_ops = {
+       .owner = THIS_MODULE,
+       .start = softdog_ping,
+       .stop = softdog_stop,
+       .ping = softdog_ping,
+       .set_timeout = softdog_set_timeout,
 };
 
-static char banner[] __initdata = KERN_INFO "Software Watchdog Timer: 0.07 "
-       "initialized. soft_noboot=%d soft_margin=%d sec soft_panic=%d "
-       "(nowayout= %d)\n";
+static struct watchdog_device softdog_dev = {
+       .info = &softdog_info,
+       .ops = &softdog_ops,
+       .min_timeout = 1,
+       .max_timeout = 0xFFFF
+};
 
 static int __init watchdog_init(void)
 {
@@ -285,37 +169,36 @@ static int __init watchdog_init(void)
 
        /* Check that the soft_margin value is within it's range;
           if not reset to the default */
-       if (softdog_set_heartbeat(soft_margin)) {
-               softdog_set_heartbeat(TIMER_MARGIN);
-               printk(KERN_INFO PFX
-                   "soft_margin must be 0 < soft_margin < 65536, using %d\n",
+       if (soft_margin < 1 || soft_margin > 65535) {
+               pr_info("soft_margin must be 0 < soft_margin < 65536, using %d\n",
                        TIMER_MARGIN);
+               return -EINVAL;
        }
+       softdog_dev.timeout = soft_margin;
+
+       watchdog_set_nowayout(&softdog_dev, nowayout);
 
        ret = register_reboot_notifier(&softdog_notifier);
        if (ret) {
-               printk(KERN_ERR PFX
-                       "cannot register reboot notifier (err=%d)\n", ret);
+               pr_err("cannot register reboot notifier (err=%d)\n", ret);
                return ret;
        }
 
-       ret = misc_register(&softdog_miscdev);
+       ret = watchdog_register_device(&softdog_dev);
        if (ret) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                                               WATCHDOG_MINOR, ret);
                unregister_reboot_notifier(&softdog_notifier);
                return ret;
        }
 
-       printk(banner, soft_noboot, soft_margin, soft_panic, nowayout);
+       pr_info("Software Watchdog Timer: 0.08 initialized. soft_noboot=%d soft_margin=%d sec soft_panic=%d (nowayout=%d)\n",
+               soft_noboot, soft_margin, soft_panic, nowayout);
 
        return 0;
 }
 
 static void __exit watchdog_exit(void)
 {
-       misc_deregister(&softdog_miscdev);
+       watchdog_unregister_device(&softdog_dev);
        unregister_reboot_notifier(&softdog_notifier);
 }
 
index 87e0527..59108e4 100644 (file)
@@ -20,6 +20,8 @@
  *     Includes, defines, variables, module parameters, ...
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
@@ -39,7 +41,6 @@
 #define TCO_VERSION "0.01"
 #define TCO_MODULE_NAME "SP5100 TCO timer"
 #define TCO_DRIVER_NAME   TCO_MODULE_NAME ", v" TCO_VERSION
-#define PFX TCO_MODULE_NAME ": "
 
 /* internal variables */
 static u32 tcobase_phys;
@@ -61,8 +62,8 @@ module_param(heartbeat, int, 0);
 MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (default="
                 __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started"
                " (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
@@ -143,8 +144,7 @@ static int sp5100_tco_release(struct inode *inode, struct file *file)
        if (tco_expect_close == 42) {
                tco_timer_stop();
        } else {
-               printk(KERN_CRIT PFX
-                       "Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
                tco_timer_keepalive();
        }
        clear_bit(0, &timer_alive);
@@ -290,8 +290,7 @@ static unsigned char __devinit sp5100_tco_setupdevice(void)
        /* Request the IO ports used by this driver */
        pm_iobase = SP5100_IO_PM_INDEX_REG;
        if (!request_region(pm_iobase, SP5100_PM_IOPORTS_SIZE, "SP5100 TCO")) {
-               printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
-                       pm_iobase);
+               pr_err("I/O address 0x%04x already in use\n", pm_iobase);
                goto exit;
        }
 
@@ -308,15 +307,14 @@ static unsigned char __devinit sp5100_tco_setupdevice(void)
 
        if (!request_mem_region_exclusive(val, SP5100_WDT_MEM_MAP_SIZE,
                                                                "SP5100 TCO")) {
-               printk(KERN_ERR PFX "mmio address 0x%04x already in use\n",
-                       val);
+               pr_err("mmio address 0x%04x already in use\n", val);
                goto unreg_region;
        }
        tcobase_phys = val;
 
        tcobase = ioremap(val, SP5100_WDT_MEM_MAP_SIZE);
        if (tcobase == 0) {
-               printk(KERN_ERR PFX "failed to get tcobase address\n");
+               pr_err("failed to get tcobase address\n");
                goto unreg_mem_region;
        }
 
@@ -375,9 +373,9 @@ static int __devinit sp5100_tco_init(struct platform_device *dev)
                return -ENODEV;
 
        /* Check to see if last reboot was due to watchdog timeout */
-       printk(KERN_INFO PFX "Watchdog reboot %sdetected.\n",
-              readl(SP5100_WDT_CONTROL(tcobase)) & SP5100_PM_WATCHDOG_FIRED ?
-                     "" : "not ");
+       pr_info("Watchdog reboot %sdetected\n",
+               readl(SP5100_WDT_CONTROL(tcobase)) & SP5100_PM_WATCHDOG_FIRED ?
+               "" : "not ");
 
        /* Clear out the old status */
        val = readl(SP5100_WDT_CONTROL(tcobase));
@@ -395,16 +393,14 @@ static int __devinit sp5100_tco_init(struct platform_device *dev)
 
        ret = misc_register(&sp5100_tco_miscdev);
        if (ret != 0) {
-               printk(KERN_ERR PFX "cannot register miscdev on minor="
-                      "%d (err=%d)\n",
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
                       WATCHDOG_MINOR, ret);
                goto exit;
        }
 
        clear_bit(0, &timer_alive);
 
-       printk(KERN_INFO PFX "initialized (0x%p). heartbeat=%d sec"
-               " (nowayout=%d)\n",
+       pr_info("initialized (0x%p). heartbeat=%d sec (nowayout=%d)\n",
                tcobase, heartbeat, nowayout);
 
        return 0;
@@ -455,8 +451,7 @@ static int __init sp5100_tco_init_module(void)
 {
        int err;
 
-       printk(KERN_INFO PFX "SP5100 TCO WatchDog Timer Driver v%s\n",
-              TCO_VERSION);
+       pr_info("SP5100 TCO WatchDog Timer Driver v%s\n", TCO_VERSION);
 
        err = platform_driver_register(&sp5100_tco_driver);
        if (err)
@@ -480,7 +475,7 @@ static void __exit sp5100_tco_cleanup_module(void)
 {
        platform_device_unregister(sp5100_tco_platform_device);
        platform_driver_unregister(&sp5100_tco_driver);
-       printk(KERN_INFO PFX "SP5100 TCO Watchdog Module Unloaded.\n");
+       pr_info("SP5100 TCO Watchdog Module Unloaded\n");
 }
 
 module_init(sp5100_tco_init_module);
index 3ff9e47..bbb170e 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/miscdevice.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
+#include <linux/pm.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/types.h>
 
 /**
  * struct sp805_wdt: sp805 wdt device structure
- *
- * lock: spin lock protecting dev structure and io access
- * base: base address of wdt
- * clk: clock structure of wdt
- * dev: amba device structure of wdt
- * status: current status of wdt
- * load_val: load value to be set for current timeout
- * timeout: current programmed timeout
+ * @lock: spin lock protecting dev structure and io access
+ * @base: base address of wdt
+ * @clk: clock structure of wdt
+ * @adev: amba device structure of wdt
+ * @status: current status of wdt
+ * @load_val: load value to be set for current timeout
+ * @timeout: current programmed timeout
  */
 struct sp805_wdt {
        spinlock_t                      lock;
@@ -78,7 +78,7 @@ struct sp805_wdt {
 
 /* local variables */
 static struct sp805_wdt *wdt;
-static int nowayout = WATCHDOG_NOWAYOUT;
+static bool nowayout = WATCHDOG_NOWAYOUT;
 
 /* This routine finds load value that will reset system in required timout */
 static void wdt_setload(unsigned int timeout)
@@ -113,10 +113,10 @@ static u32 wdt_timeleft(void)
        rate = clk_get_rate(wdt->clk);
 
        spin_lock(&wdt->lock);
-       load = readl(wdt->base + WDTVALUE);
+       load = readl_relaxed(wdt->base + WDTVALUE);
 
        /*If the interrupt is inactive then time left is WDTValue + WDTLoad. */
-       if (!(readl(wdt->base + WDTRIS) & INT_MASK))
+       if (!(readl_relaxed(wdt->base + WDTRIS) & INT_MASK))
                load += wdt->load_val + 1;
        spin_unlock(&wdt->lock);
 
@@ -128,14 +128,14 @@ static void wdt_enable(void)
 {
        spin_lock(&wdt->lock);
 
-       writel(UNLOCK, wdt->base + WDTLOCK);
-       writel(wdt->load_val, wdt->base + WDTLOAD);
-       writel(INT_MASK, wdt->base + WDTINTCLR);
-       writel(INT_ENABLE | RESET_ENABLE, wdt->base + WDTCONTROL);
-       writel(LOCK, wdt->base + WDTLOCK);
+       writel_relaxed(UNLOCK, wdt->base + WDTLOCK);
+       writel_relaxed(wdt->load_val, wdt->base + WDTLOAD);
+       writel_relaxed(INT_MASK, wdt->base + WDTINTCLR);
+       writel_relaxed(INT_ENABLE | RESET_ENABLE, wdt->base + WDTCONTROL);
+       writel_relaxed(LOCK, wdt->base + WDTLOCK);
 
        /* Flush posted writes. */
-       readl(wdt->base + WDTLOCK);
+       readl_relaxed(wdt->base + WDTLOCK);
        spin_unlock(&wdt->lock);
 }
 
@@ -144,12 +144,12 @@ static void wdt_disable(void)
 {
        spin_lock(&wdt->lock);
 
-       writel(UNLOCK, wdt->base + WDTLOCK);
-       writel(0, wdt->base + WDTCONTROL);
-       writel(LOCK, wdt->base + WDTLOCK);
+       writel_relaxed(UNLOCK, wdt->base + WDTLOCK);
+       writel_relaxed(0, wdt->base + WDTCONTROL);
+       writel_relaxed(LOCK, wdt->base + WDTLOCK);
 
        /* Flush posted writes. */
-       readl(wdt->base + WDTLOCK);
+       readl_relaxed(wdt->base + WDTLOCK);
        spin_unlock(&wdt->lock);
 }
 
@@ -285,32 +285,33 @@ sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id)
 {
        int ret = 0;
 
-       if (!request_mem_region(adev->res.start, resource_size(&adev->res),
-                               "sp805_wdt")) {
+       if (!devm_request_mem_region(&adev->dev, adev->res.start,
+                               resource_size(&adev->res), "sp805_wdt")) {
                dev_warn(&adev->dev, "Failed to get memory region resource\n");
                ret = -ENOENT;
                goto err;
        }
 
-       wdt = kzalloc(sizeof(*wdt), GFP_KERNEL);
+       wdt = devm_kzalloc(&adev->dev, sizeof(*wdt), GFP_KERNEL);
        if (!wdt) {
                dev_warn(&adev->dev, "Kzalloc failed\n");
                ret = -ENOMEM;
-               goto err_kzalloc;
+               goto err;
+       }
+
+       wdt->base = devm_ioremap(&adev->dev, adev->res.start,
+                       resource_size(&adev->res));
+       if (!wdt->base) {
+               ret = -ENOMEM;
+               dev_warn(&adev->dev, "ioremap fail\n");
+               goto err;
        }
 
        wdt->clk = clk_get(&adev->dev, NULL);
        if (IS_ERR(wdt->clk)) {
                dev_warn(&adev->dev, "Clock not found\n");
                ret = PTR_ERR(wdt->clk);
-               goto err_clk_get;
-       }
-
-       wdt->base = ioremap(adev->res.start, resource_size(&adev->res));
-       if (!wdt->base) {
-               ret = -ENOMEM;
-               dev_warn(&adev->dev, "ioremap fail\n");
-               goto err_ioremap;
+               goto err;
        }
 
        wdt->adev = adev;
@@ -327,14 +328,7 @@ sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id)
        return 0;
 
 err_misc_register:
-       iounmap(wdt->base);
-err_ioremap:
        clk_put(wdt->clk);
-err_clk_get:
-       kfree(wdt);
-       wdt = NULL;
-err_kzalloc:
-       release_mem_region(adev->res.start, resource_size(&adev->res));
 err:
        dev_err(&adev->dev, "Probe Failed!!!\n");
        return ret;
@@ -343,14 +337,42 @@ err:
 static int __devexit sp805_wdt_remove(struct amba_device *adev)
 {
        misc_deregister(&sp805_wdt_miscdev);
-       iounmap(wdt->base);
        clk_put(wdt->clk);
-       kfree(wdt);
-       release_mem_region(adev->res.start, resource_size(&adev->res));
 
        return 0;
 }
 
+#ifdef CONFIG_PM
+static int sp805_wdt_suspend(struct device *dev)
+{
+       if (test_bit(WDT_BUSY, &wdt->status)) {
+               wdt_disable();
+               clk_disable(wdt->clk);
+       }
+
+       return 0;
+}
+
+static int sp805_wdt_resume(struct device *dev)
+{
+       int ret = 0;
+
+       if (test_bit(WDT_BUSY, &wdt->status)) {
+               ret = clk_enable(wdt->clk);
+               if (ret) {
+                       dev_err(dev, "clock enable fail");
+                       return ret;
+               }
+               wdt_enable();
+       }
+
+       return ret;
+}
+#endif /* CONFIG_PM */
+
+static SIMPLE_DEV_PM_OPS(sp805_wdt_dev_pm_ops, sp805_wdt_suspend,
+               sp805_wdt_resume);
+
 static struct amba_id sp805_wdt_ids[] = {
        {
                .id     = 0x00141805,
@@ -364,6 +386,7 @@ MODULE_DEVICE_TABLE(amba, sp805_wdt_ids);
 static struct amba_driver sp805_wdt_driver = {
        .drv = {
                .name   = MODULE_NAME,
+               .pm     = &sp805_wdt_dev_pm_ops,
        },
        .id_table       = sp805_wdt_ids,
        .probe          = sp805_wdt_probe,
@@ -372,7 +395,7 @@ static struct amba_driver sp805_wdt_driver = {
 
 module_amba_driver(sp805_wdt_driver);
 
-module_param(nowayout, int, 0);
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                "Set to 1 to keep watchdog running after device release");
 
index e37d811..21d96b9 100644 (file)
@@ -6,6 +6,9 @@
  * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
  * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/fs.h>
@@ -32,7 +35,7 @@
 
 static DEFINE_SPINLOCK(stmp3xxx_wdt_io_lock);
 static unsigned long wdt_status;
-static const int nowayout = WATCHDOG_NOWAYOUT;
+static const bool nowayout = WATCHDOG_NOWAYOUT;
 static int heartbeat = DEFAULT_HEARTBEAT;
 static unsigned long boot_status;
 
@@ -221,8 +224,7 @@ static int __devinit stmp3xxx_wdt_probe(struct platform_device *pdev)
                return ret;
        }
 
-       printk(KERN_INFO "stmp3xxx watchdog: initialized, heartbeat %d sec\n",
-               heartbeat);
+       pr_info("initialized, heartbeat %d sec\n", heartbeat);
 
        return ret;
 }
index 1490293..8df050d 100644 (file)
@@ -34,8 +34,8 @@ MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. "
                          __MODULE_STRING(TS72XX_WDT_DEFAULT_TIMEOUT)
                          ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close");
 
 /**
index 0764c62..249f113 100644 (file)
@@ -42,8 +42,8 @@ struct twl4030_wdt {
        unsigned long           state;
 };
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
        "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
index 9e9ed7b..98e1637 100644 (file)
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/miscdevice.h>
 #include <linux/watchdog.h>
-#include <linux/fs.h>
 #include <linux/init.h>
-#include <linux/uaccess.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/io.h>
 #include <asm/txx9tmr.h>
 
+#define WD_TIMER_CCD   7               /* 1/256 */
+#define WD_TIMER_CLK   (clk_get_rate(txx9_imclk) / (2 << WD_TIMER_CCD))
+#define WD_MAX_TIMEOUT ((0xffffffff >> (32 - TXX9_TIMER_BITS)) / WD_TIMER_CLK)
 #define TIMER_MARGIN   60              /* Default is 60 seconds */
 
-static int timeout = TIMER_MARGIN;     /* in seconds */
-module_param(timeout, int, 0);
+static unsigned int timeout = TIMER_MARGIN;    /* in seconds */
+module_param(timeout, uint, 0);
 MODULE_PARM_DESC(timeout,
        "Watchdog timeout in seconds. "
        "(0<timeout<((2^" __MODULE_STRING(TXX9_TIMER_BITS) ")/(IMCLK/256)), "
        "default=" __MODULE_STRING(TIMER_MARGIN) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
        "Watchdog cannot be stopped once started "
        "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
-#define WD_TIMER_CCD   7       /* 1/256 */
-#define WD_TIMER_CLK   (clk_get_rate(txx9_imclk) / (2 << WD_TIMER_CCD))
-#define WD_MAX_TIMEOUT ((0xffffffff >> (32 - TXX9_TIMER_BITS)) / WD_TIMER_CLK)
-
-static unsigned long txx9wdt_alive;
-static int expect_close;
 static struct txx9_tmr_reg __iomem *txx9wdt_reg;
 static struct clk *txx9_imclk;
 static DEFINE_SPINLOCK(txx9_lock);
 
-static void txx9wdt_ping(void)
+static int txx9wdt_ping(struct watchdog_device *wdt_dev)
 {
        spin_lock(&txx9_lock);
        __raw_writel(TXx9_TMWTMR_TWIE | TXx9_TMWTMR_TWC, &txx9wdt_reg->wtmr);
        spin_unlock(&txx9_lock);
+       return 0;
 }
 
-static void txx9wdt_start(void)
+static int txx9wdt_start(struct watchdog_device *wdt_dev)
 {
        spin_lock(&txx9_lock);
-       __raw_writel(WD_TIMER_CLK * timeout, &txx9wdt_reg->cpra);
+       __raw_writel(WD_TIMER_CLK * wdt_dev->timeout, &txx9wdt_reg->cpra);
        __raw_writel(WD_TIMER_CCD, &txx9wdt_reg->ccdr);
        __raw_writel(0, &txx9wdt_reg->tisr);    /* clear pending interrupt */
        __raw_writel(TXx9_TMTCR_TCE | TXx9_TMTCR_CCDE | TXx9_TMTCR_TMODE_WDOG,
                     &txx9wdt_reg->tcr);
        __raw_writel(TXx9_TMWTMR_TWIE | TXx9_TMWTMR_TWC, &txx9wdt_reg->wtmr);
        spin_unlock(&txx9_lock);
+       return 0;
 }
 
-static void txx9wdt_stop(void)
+static int txx9wdt_stop(struct watchdog_device *wdt_dev)
 {
        spin_lock(&txx9_lock);
        __raw_writel(TXx9_TMWTMR_WDIS, &txx9wdt_reg->wtmr);
        __raw_writel(__raw_readl(&txx9wdt_reg->tcr) & ~TXx9_TMTCR_TCE,
                     &txx9wdt_reg->tcr);
        spin_unlock(&txx9_lock);
-}
-
-static int txx9wdt_open(struct inode *inode, struct file *file)
-{
-       if (test_and_set_bit(0, &txx9wdt_alive))
-               return -EBUSY;
-
-       if (__raw_readl(&txx9wdt_reg->tcr) & TXx9_TMTCR_TCE) {
-               clear_bit(0, &txx9wdt_alive);
-               return -EBUSY;
-       }
-
-       if (nowayout)
-               __module_get(THIS_MODULE);
-
-       txx9wdt_start();
-       return nonseekable_open(inode, file);
-}
-
-static int txx9wdt_release(struct inode *inode, struct file *file)
-{
-       if (expect_close)
-               txx9wdt_stop();
-       else {
-               printk(KERN_CRIT "txx9wdt: "
-                      "Unexpected close, not stopping watchdog!\n");
-               txx9wdt_ping();
-       }
-       clear_bit(0, &txx9wdt_alive);
-       expect_close = 0;
        return 0;
 }
 
-static ssize_t txx9wdt_write(struct file *file, const char __user *data,
-                            size_t len, loff_t *ppos)
+static int txx9wdt_set_timeout(struct watchdog_device *wdt_dev,
+                              unsigned int new_timeout)
 {
-       if (len) {
-               if (!nowayout) {
-                       size_t i;
-
-                       expect_close = 0;
-                       for (i = 0; i != len; i++) {
-                               char c;
-                               if (get_user(c, data + i))
-                                       return -EFAULT;
-                               if (c == 'V')
-                                       expect_close = 1;
-                       }
-               }
-               txx9wdt_ping();
-       }
-       return len;
+       wdt_dev->timeout = new_timeout;
+       txx9wdt_stop(wdt_dev);
+       txx9wdt_start(wdt_dev);
+       return 0;
 }
 
-static long txx9wdt_ioctl(struct file *file, unsigned int cmd,
-                                                       unsigned long arg)
-{
-       void __user *argp = (void __user *)arg;
-       int __user *p = argp;
-       int new_timeout;
-       static const struct watchdog_info ident = {
-               .options =              WDIOF_SETTIMEOUT |
-                                       WDIOF_KEEPALIVEPING |
-                                       WDIOF_MAGICCLOSE,
-               .firmware_version =     0,
-               .identity =             "Hardware Watchdog for TXx9",
-       };
-
-       switch (cmd) {
-       case WDIOC_GETSUPPORT:
-               return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
-       case WDIOC_GETSTATUS:
-       case WDIOC_GETBOOTSTATUS:
-               return put_user(0, p);
-       case WDIOC_KEEPALIVE:
-               txx9wdt_ping();
-               return 0;
-       case WDIOC_SETTIMEOUT:
-               if (get_user(new_timeout, p))
-                       return -EFAULT;
-               if (new_timeout < 1 || new_timeout > WD_MAX_TIMEOUT)
-                       return -EINVAL;
-               timeout = new_timeout;
-               txx9wdt_stop();
-               txx9wdt_start();
-               /* Fall */
-       case WDIOC_GETTIMEOUT:
-               return put_user(timeout, p);
-       default:
-               return -ENOTTY;
-       }
-}
+static const struct watchdog_info txx9wdt_info = {
+       .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
+       .identity = "Hardware Watchdog for TXx9",
+};
 
-static const struct file_operations txx9wdt_fops = {
-       .owner          =       THIS_MODULE,
-       .llseek         =       no_llseek,
-       .write          =       txx9wdt_write,
-       .unlocked_ioctl =       txx9wdt_ioctl,
-       .open           =       txx9wdt_open,
-       .release        =       txx9wdt_release,
+static const struct watchdog_ops txx9wdt_ops = {
+       .owner = THIS_MODULE,
+       .start = txx9wdt_start,
+       .stop = txx9wdt_stop,
+       .ping = txx9wdt_ping,
+       .set_timeout = txx9wdt_set_timeout,
 };
 
-static struct miscdevice txx9wdt_miscdev = {
-       .minor  =       WATCHDOG_MINOR,
-       .name   =       "watchdog",
-       .fops   =       &txx9wdt_fops,
+static struct watchdog_device txx9wdt = {
+       .info = &txx9wdt_info,
+       .ops = &txx9wdt_ops,
 };
 
 static int __init txx9wdt_probe(struct platform_device *dev)
@@ -199,27 +121,27 @@ static int __init txx9wdt_probe(struct platform_device *dev)
        }
 
        res = platform_get_resource(dev, IORESOURCE_MEM, 0);
-       if (!res)
-               goto exit_busy;
-       if (!devm_request_mem_region(&dev->dev, res->start, resource_size(res),
-                                    "txx9wdt"))
-               goto exit_busy;
-       txx9wdt_reg = devm_ioremap(&dev->dev, res->start, resource_size(res));
-       if (!txx9wdt_reg)
-               goto exit_busy;
-
-       ret = misc_register(&txx9wdt_miscdev);
-       if (ret) {
+       txx9wdt_reg = devm_request_and_ioremap(&dev->dev, res);
+       if (!txx9wdt_reg) {
+               ret = -EBUSY;
                goto exit;
        }
 
-       printk(KERN_INFO "Hardware Watchdog Timer for TXx9: "
-              "timeout=%d sec (max %ld) (nowayout= %d)\n",
-              timeout, WD_MAX_TIMEOUT, nowayout);
+       if (timeout < 1 || timeout > WD_MAX_TIMEOUT)
+               timeout = TIMER_MARGIN;
+       txx9wdt.timeout = timeout;
+       txx9wdt.min_timeout = 1;
+       txx9wdt.max_timeout = WD_MAX_TIMEOUT;
+       watchdog_set_nowayout(&txx9wdt, nowayout);
+
+       ret = watchdog_register_device(&txx9wdt);
+       if (ret)
+               goto exit;
+
+       pr_info("Hardware Watchdog Timer: timeout=%d sec (max %ld) (nowayout= %d)\n",
+               timeout, WD_MAX_TIMEOUT, nowayout);
 
        return 0;
-exit_busy:
-       ret = -EBUSY;
 exit:
        if (txx9_imclk) {
                clk_disable(txx9_imclk);
@@ -230,7 +152,7 @@ exit:
 
 static int __exit txx9wdt_remove(struct platform_device *dev)
 {
-       misc_deregister(&txx9wdt_miscdev);
+       watchdog_unregister_device(&txx9wdt);
        clk_disable(txx9_imclk);
        clk_put(txx9_imclk);
        return 0;
@@ -238,7 +160,7 @@ static int __exit txx9wdt_remove(struct platform_device *dev)
 
 static void txx9wdt_shutdown(struct platform_device *dev)
 {
-       txx9wdt_stop();
+       txx9wdt_stop(&txx9wdt);
 }
 
 static struct platform_driver txx9wdt_driver = {
index 8f07dd4..465e082 100644 (file)
@@ -10,6 +10,9 @@
  * Caveat: PnP must be enabled in BIOS to allow full access to watchdog
  * control registers. If not, the watchdog must be configured in BIOS manually.
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/device.h>
 #include <linux/io.h>
 #include <linux/jiffies.h>
@@ -55,8 +58,8 @@ module_param(timeout, int, 0);
 MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds, between 1 and 1023 "
        "(default = " __MODULE_STRING(WDT_TIMEOUT) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
        "(default = " __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
@@ -98,7 +101,7 @@ static void wdt_timer_tick(unsigned long data)
 static int wdt_ping(struct watchdog_device *wdd)
 {
        /* calculate when the next userspace timeout will be */
-       next_heartbeat = jiffies + timeout * HZ;
+       next_heartbeat = jiffies + wdd->timeout * HZ;
        return 0;
 }
 
@@ -106,7 +109,7 @@ static int wdt_start(struct watchdog_device *wdd)
 {
        unsigned int ctl = readl(wdt_mem);
 
-       writel(timeout, wdt_mem + VIA_WDT_COUNT);
+       writel(wdd->timeout, wdt_mem + VIA_WDT_COUNT);
        writel(ctl | VIA_WDT_RUNNING | VIA_WDT_TRIGGER, wdt_mem);
        wdt_ping(wdd);
        mod_timer(&timer, jiffies + WDT_HEARTBEAT);
@@ -125,7 +128,7 @@ static int wdt_set_timeout(struct watchdog_device *wdd,
                           unsigned int new_timeout)
 {
        writel(new_timeout, wdt_mem + VIA_WDT_COUNT);
-       timeout = new_timeout;
+       wdd->timeout = new_timeout;
        return 0;
 }
 
index 576a388..92f1326 100644 (file)
@@ -26,6 +26,8 @@
  *     (c) Copyright 1995    Alan Cox <alan@lxorguk.ukuu.org.uk>
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/io.h>
 #include <linux/uaccess.h>
 
-#include <asm/system.h>
 
 #define WATCHDOG_NAME "w83627hf/thf/hg/dhg WDT"
-#define PFX WATCHDOG_NAME ": "
 #define WATCHDOG_TIMEOUT 60            /* 60 sec default timeout */
 
 static unsigned long wdt_is_open;
@@ -61,8 +61,8 @@ MODULE_PARM_DESC(timeout,
                "Watchdog timeout in seconds. 1 <= timeout <= 255, default="
                                __MODULE_STRING(WATCHDOG_TIMEOUT) ".");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -119,9 +119,8 @@ static void w83627hf_init(void)
        outb_p(0xF6, WDT_EFER); /* Select CRF6 */
        t = inb_p(WDT_EFDR);      /* read CRF6 */
        if (t != 0) {
-               printk(KERN_INFO PFX
-                    "Watchdog already running. Resetting timeout to %d sec\n",
-                                                               timeout);
+               pr_info("Watchdog already running. Resetting timeout to %d sec\n",
+                       timeout);
                outb_p(timeout, WDT_EFDR);    /* Write back to CRF6 */
        }
 
@@ -290,8 +289,7 @@ static int wdt_close(struct inode *inode, struct file *file)
        if (expect_close == 42)
                wdt_disable();
        else {
-               printk(KERN_CRIT PFX
-                       "Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
                wdt_ping();
        }
        expect_close = 0;
@@ -344,18 +342,16 @@ static int __init wdt_init(void)
 {
        int ret;
 
-       printk(KERN_INFO "WDT driver for the Winbond(TM) W83627HF/THF/HG/DHG Super I/O chip initialising.\n");
+       pr_info("WDT driver for the Winbond(TM) W83627HF/THF/HG/DHG Super I/O chip initialising\n");
 
        if (wdt_set_heartbeat(timeout)) {
                wdt_set_heartbeat(WATCHDOG_TIMEOUT);
-               printk(KERN_INFO PFX
-                    "timeout value must be 1 <= timeout <= 255, using %d\n",
-                               WATCHDOG_TIMEOUT);
+               pr_info("timeout value must be 1 <= timeout <= 255, using %d\n",
+                       WATCHDOG_TIMEOUT);
        }
 
        if (!request_region(wdt_io, 1, WATCHDOG_NAME)) {
-               printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
-                       wdt_io);
+               pr_err("I/O address 0x%04x already in use\n", wdt_io);
                ret = -EIO;
                goto out;
        }
@@ -364,22 +360,19 @@ static int __init wdt_init(void)
 
        ret = register_reboot_notifier(&wdt_notifier);
        if (ret != 0) {
-               printk(KERN_ERR PFX
-                       "cannot register reboot notifier (err=%d)\n", ret);
+               pr_err("cannot register reboot notifier (err=%d)\n", ret);
                goto unreg_regions;
        }
 
        ret = misc_register(&wdt_miscdev);
        if (ret != 0) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                                                       WATCHDOG_MINOR, ret);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      WATCHDOG_MINOR, ret);
                goto unreg_reboot;
        }
 
-       printk(KERN_INFO PFX
-                       "initialized. timeout=%d sec (nowayout=%d)\n",
-                                                       timeout, nowayout);
+       pr_info("initialized. timeout=%d sec (nowayout=%d)\n",
+               timeout, nowayout);
 
 out:
        return ret;
index af08972..cd9f3c1 100644 (file)
@@ -25,6 +25,8 @@
  *     "AS-IS" and at no charge.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/io.h>
 #include <linux/uaccess.h>
 
-#include <asm/system.h>
 
 #define WATCHDOG_NAME "w83697hf/hg WDT"
-#define PFX WATCHDOG_NAME ": "
 #define WATCHDOG_TIMEOUT 60            /* 60 sec default timeout */
 #define WATCHDOG_EARLY_DISABLE 1       /* Disable until userland kicks in */
 
@@ -62,8 +62,8 @@ MODULE_PARM_DESC(timeout,
        "Watchdog timeout in seconds. 1<= timeout <=255 (default="
                                __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
        "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -309,8 +309,7 @@ static int wdt_close(struct inode *inode, struct file *file)
        if (expect_close == 42)
                wdt_disable();
        else {
-               printk(KERN_CRIT PFX
-                       "Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
                wdt_ping();
        }
        expect_close = 0;
@@ -362,24 +361,21 @@ static struct notifier_block wdt_notifier = {
 static int w83697hf_check_wdt(void)
 {
        if (!request_region(wdt_io, 2, WATCHDOG_NAME)) {
-               printk(KERN_ERR PFX
-                       "I/O address 0x%x already in use\n", wdt_io);
+               pr_err("I/O address 0x%x already in use\n", wdt_io);
                return -EIO;
        }
 
-       printk(KERN_DEBUG PFX
-                       "Looking for watchdog at address 0x%x\n", wdt_io);
+       pr_debug("Looking for watchdog at address 0x%x\n", wdt_io);
        w83697hf_unlock();
        if (w83697hf_get_reg(0x20) == 0x60) {
-               printk(KERN_INFO PFX
-                       "watchdog found at address 0x%x\n", wdt_io);
+               pr_info("watchdog found at address 0x%x\n", wdt_io);
                w83697hf_lock();
                return 0;
        }
        /* Reprotect in case it was a compatible device */
        w83697hf_lock();
 
-       printk(KERN_INFO PFX "watchdog not found at address 0x%x\n", wdt_io);
+       pr_info("watchdog not found at address 0x%x\n", wdt_io);
        release_region(wdt_io, 2);
        return -EIO;
 }
@@ -390,7 +386,7 @@ static int __init wdt_init(void)
 {
        int ret, i, found = 0;
 
-       printk(KERN_INFO PFX "WDT driver for W83697HF/HG initializing\n");
+       pr_info("WDT driver for W83697HF/HG initializing\n");
 
        if (wdt_io == 0) {
                /* we will autodetect the W83697HF/HG watchdog */
@@ -405,7 +401,7 @@ static int __init wdt_init(void)
        }
 
        if (!found) {
-               printk(KERN_ERR PFX "No W83697HF/HG could be found\n");
+               pr_err("No W83697HF/HG could be found\n");
                ret = -EIO;
                goto out;
        }
@@ -413,34 +409,30 @@ static int __init wdt_init(void)
        w83697hf_init();
        if (early_disable) {
                if (wdt_running())
-                       printk(KERN_WARNING PFX "Stopping previously enabled "
-                                       "watchdog until userland kicks in\n");
+                       pr_warn("Stopping previously enabled watchdog until userland kicks in\n");
                wdt_disable();
        }
 
        if (wdt_set_heartbeat(timeout)) {
                wdt_set_heartbeat(WATCHDOG_TIMEOUT);
-               printk(KERN_INFO PFX
-                    "timeout value must be 1 <= timeout <= 255, using %d\n",
-                                                       WATCHDOG_TIMEOUT);
+               pr_info("timeout value must be 1 <= timeout <= 255, using %d\n",
+                       WATCHDOG_TIMEOUT);
        }
 
        ret = register_reboot_notifier(&wdt_notifier);
        if (ret != 0) {
-               printk(KERN_ERR PFX
-                       "cannot register reboot notifier (err=%d)\n", ret);
+               pr_err("cannot register reboot notifier (err=%d)\n", ret);
                goto unreg_regions;
        }
 
        ret = misc_register(&wdt_miscdev);
        if (ret != 0) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                                               WATCHDOG_MINOR, ret);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      WATCHDOG_MINOR, ret);
                goto unreg_reboot;
        }
 
-       printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n",
+       pr_info("initialized. timeout=%d sec (nowayout=%d)\n",
                timeout, nowayout);
 
 out:
index be9c4d8..274be0b 100644 (file)
@@ -30,6 +30,8 @@
  *     (c) Copyright 1995    Alan Cox <alan@redhat.com>
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/io.h>
 #include <linux/uaccess.h>
 
-#include <asm/system.h>
 
 #define WATCHDOG_NAME "w83697ug/uf WDT"
-#define PFX WATCHDOG_NAME ": "
 #define WATCHDOG_TIMEOUT 60            /* 60 sec default timeout */
 
 static unsigned long wdt_is_open;
@@ -64,8 +64,8 @@ MODULE_PARM_DESC(timeout,
        "Watchdog timeout in seconds. 1<= timeout <=255 (default="
                                __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
        "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -91,8 +91,8 @@ static int w83697ug_select_wd_register(void)
        version = inb(WDT_EFDR);
 
        if (version == 0x68) {  /* W83697UG             */
-               printk(KERN_INFO PFX "Watchdog chip version 0x%02x = "
-                       "W83697UG/UF found at 0x%04x\n", version, wdt_io);
+               pr_info("Watchdog chip version 0x%02x = W83697UG/UF found at 0x%04x\n",
+                       version, wdt_io);
 
                outb_p(0x2b, WDT_EFER);
                c = inb_p(WDT_EFDR);    /* select WDT0 */
@@ -101,7 +101,7 @@ static int w83697ug_select_wd_register(void)
                outb_p(c, WDT_EFDR);    /* set pin118 to WDT0 */
 
        } else {
-               printk(KERN_ERR PFX "No W83697UG/UF could be found\n");
+               pr_err("No W83697UG/UF could be found\n");
                return -ENODEV;
        }
 
@@ -131,8 +131,8 @@ static int w83697ug_init(void)
        outb_p(0xF6, WDT_EFER); /* Select CRF6 */
        t = inb_p(WDT_EFDR);    /* read CRF6 */
        if (t != 0) {
-               printk(KERN_INFO PFX "Watchdog already running."
-                       " Resetting timeout to %d sec\n", timeout);
+               pr_info("Watchdog already running. Resetting timeout to %d sec\n",
+                       timeout);
                outb_p(timeout, WDT_EFDR);    /* Write back to CRF6 */
        }
        outb_p(0xF5, WDT_EFER); /* Select CRF5 */
@@ -286,8 +286,7 @@ static int wdt_close(struct inode *inode, struct file *file)
        if (expect_close == 42)
                wdt_disable();
        else {
-               printk(KERN_CRIT PFX
-                       "Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
                wdt_ping();
        }
        expect_close = 0;
@@ -340,18 +339,16 @@ static int __init wdt_init(void)
 {
        int ret;
 
-       printk(KERN_INFO "WDT driver for the Winbond(TM) W83697UG/UF Super I/O chip initialising.\n");
+       pr_info("WDT driver for the Winbond(TM) W83697UG/UF Super I/O chip initialising\n");
 
        if (wdt_set_heartbeat(timeout)) {
                wdt_set_heartbeat(WATCHDOG_TIMEOUT);
-               printk(KERN_INFO PFX
-                       "timeout value must be 1<=timeout<=255, using %d\n",
+               pr_info("timeout value must be 1<=timeout<=255, using %d\n",
                        WATCHDOG_TIMEOUT);
        }
 
        if (!request_region(wdt_io, 1, WATCHDOG_NAME)) {
-               printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
-                       wdt_io);
+               pr_err("I/O address 0x%04x already in use\n", wdt_io);
                ret = -EIO;
                goto out;
        }
@@ -362,20 +359,18 @@ static int __init wdt_init(void)
 
        ret = register_reboot_notifier(&wdt_notifier);
        if (ret != 0) {
-               printk(KERN_ERR PFX
-                       "cannot register reboot notifier (err=%d)\n", ret);
+               pr_err("cannot register reboot notifier (err=%d)\n", ret);
                goto unreg_regions;
        }
 
        ret = misc_register(&wdt_miscdev);
        if (ret != 0) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                       WATCHDOG_MINOR, ret);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      WATCHDOG_MINOR, ret);
                goto unreg_reboot;
        }
 
-       printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n",
+       pr_info("initialized. timeout=%d sec (nowayout=%d)\n",
                timeout, nowayout);
 
 out:
index 24587d2..7874ae0 100644 (file)
@@ -42,6 +42,8 @@
  *  daemon always getting scheduled within that time frame.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/uaccess.h>
-#include <asm/system.h>
 
 #define OUR_NAME "w83877f_wdt"
-#define PFX OUR_NAME ": "
 
 #define ENABLE_W83877F_PORT 0x3F0
 #define ENABLE_W83877F 0x87
@@ -91,8 +91,8 @@ MODULE_PARM_DESC(timeout,
                                __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
 
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -126,8 +126,7 @@ static void wdt_timer_ping(unsigned long data)
                spin_unlock(&wdt_spinlock);
 
        } else
-               printk(KERN_WARNING PFX
-                       "Heartbeat lost! Will not ping the watchdog\n");
+               pr_warn("Heartbeat lost! Will not ping the watchdog\n");
 }
 
 /*
@@ -165,7 +164,7 @@ static void wdt_startup(void)
 
        wdt_change(WDT_ENABLE);
 
-       printk(KERN_INFO PFX "Watchdog timer is now enabled.\n");
+       pr_info("Watchdog timer is now enabled\n");
 }
 
 static void wdt_turnoff(void)
@@ -175,7 +174,7 @@ static void wdt_turnoff(void)
 
        wdt_change(WDT_DISABLE);
 
-       printk(KERN_INFO PFX "Watchdog timer is now disabled...\n");
+       pr_info("Watchdog timer is now disabled...\n");
 }
 
 static void wdt_keepalive(void)
@@ -234,8 +233,7 @@ static int fop_close(struct inode *inode, struct file *file)
                wdt_turnoff();
        else {
                del_timer(&timer);
-               printk(KERN_CRIT PFX
-                 "device file closed unexpectedly. Will not stop the WDT!\n");
+               pr_crit("device file closed unexpectedly. Will not stop the WDT!\n");
        }
        clear_bit(0, &wdt_is_open);
        wdt_expect_close = 0;
@@ -357,42 +355,37 @@ static int __init w83877f_wdt_init(void)
 
        if (timeout < 1 || timeout > 3600) { /* arbitrary upper limit */
                timeout = WATCHDOG_TIMEOUT;
-               printk(KERN_INFO PFX
-                       "timeout value must be 1 <= x <= 3600, using %d\n",
-                                                       timeout);
+               pr_info("timeout value must be 1 <= x <= 3600, using %d\n",
+                       timeout);
        }
 
        if (!request_region(ENABLE_W83877F_PORT, 2, "W83877F WDT")) {
-               printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
-                       ENABLE_W83877F_PORT);
+               pr_err("I/O address 0x%04x already in use\n",
+                      ENABLE_W83877F_PORT);
                rc = -EIO;
                goto err_out;
        }
 
        if (!request_region(WDT_PING, 1, "W8387FF WDT")) {
-               printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
-                       WDT_PING);
+               pr_err("I/O address 0x%04x already in use\n", WDT_PING);
                rc = -EIO;
                goto err_out_region1;
        }
 
        rc = register_reboot_notifier(&wdt_notifier);
        if (rc) {
-               printk(KERN_ERR PFX
-                       "cannot register reboot notifier (err=%d)\n", rc);
+               pr_err("cannot register reboot notifier (err=%d)\n", rc);
                goto err_out_region2;
        }
 
        rc = misc_register(&wdt_miscdev);
        if (rc) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                                                       wdt_miscdev.minor, rc);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      wdt_miscdev.minor, rc);
                goto err_out_reboot;
        }
 
-       printk(KERN_INFO PFX
-         "WDT driver for W83877F initialised. timeout=%d sec (nowayout=%d)\n",
+       pr_info("WDT driver for W83877F initialised. timeout=%d sec (nowayout=%d)\n",
                timeout, nowayout);
 
        return 0;
index 6e6743d..5d2c902 100644 (file)
@@ -15,6 +15,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/uaccess.h>
 #include <linux/io.h>
 
-#include <asm/system.h>
 
 #define WATCHDOG_VERSION  "1.00"
 #define WATCHDOG_NAME     "W83977F WDT"
-#define PFX WATCHDOG_NAME ": "
-#define DRIVER_VERSION    WATCHDOG_NAME " driver, v" WATCHDOG_VERSION "\n"
 
 #define IO_INDEX_PORT     0x3F0
 #define IO_DATA_PORT      (IO_INDEX_PORT+1)
@@ -59,8 +58,8 @@ MODULE_PARM_DESC(timeout,
 module_param(testmode, int, 0);
 MODULE_PARM_DESC(testmode, "Watchdog testmode (1 = no reboot), default=0");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -131,7 +130,7 @@ static int wdt_start(void)
 
        spin_unlock_irqrestore(&spinlock, flags);
 
-       printk(KERN_INFO PFX "activated.\n");
+       pr_info("activated\n");
 
        return 0;
 }
@@ -185,7 +184,7 @@ static int wdt_stop(void)
 
        spin_unlock_irqrestore(&spinlock, flags);
 
-       printk(KERN_INFO PFX "shutdown.\n");
+       pr_info("shutdown\n");
 
        return 0;
 }
@@ -313,8 +312,7 @@ static int wdt_release(struct inode *inode, struct file *file)
                clear_bit(0, &timer_alive);
        } else {
                wdt_keepalive();
-               printk(KERN_CRIT PFX
-                       "unexpected close, not stopping watchdog!\n");
+               pr_crit("unexpected close, not stopping watchdog!\n");
        }
        expect_close = 0;
        return 0;
@@ -471,7 +469,7 @@ static int __init w83977f_wdt_init(void)
 {
        int rc;
 
-       printk(KERN_INFO PFX DRIVER_VERSION);
+       pr_info("driver v%s\n", WATCHDOG_VERSION);
 
        /*
         * Check that the timeout value is within it's range;
@@ -479,36 +477,31 @@ static int __init w83977f_wdt_init(void)
         */
        if (wdt_set_timeout(timeout)) {
                wdt_set_timeout(DEFAULT_TIMEOUT);
-               printk(KERN_INFO PFX
-                   "timeout value must be 15 <= timeout <= 7635, using %d\n",
-                                                       DEFAULT_TIMEOUT);
+               pr_info("timeout value must be 15 <= timeout <= 7635, using %d\n",
+                       DEFAULT_TIMEOUT);
        }
 
        if (!request_region(IO_INDEX_PORT, 2, WATCHDOG_NAME)) {
-               printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
-                       IO_INDEX_PORT);
+               pr_err("I/O address 0x%04x already in use\n", IO_INDEX_PORT);
                rc = -EIO;
                goto err_out;
        }
 
        rc = register_reboot_notifier(&wdt_notifier);
        if (rc) {
-               printk(KERN_ERR PFX
-                       "cannot register reboot notifier (err=%d)\n", rc);
+               pr_err("cannot register reboot notifier (err=%d)\n", rc);
                goto err_out_region;
        }
 
        rc = misc_register(&wdt_miscdev);
        if (rc) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                                               wdt_miscdev.minor, rc);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      wdt_miscdev.minor, rc);
                goto err_out_reboot;
        }
 
-       printk(KERN_INFO PFX
-               "initialized. timeout=%d sec (nowayout=%d testmode=%d)\n",
-                                       timeout, nowayout, testmode);
+       pr_info("initialized. timeout=%d sec (nowayout=%d testmode=%d)\n",
+               timeout, nowayout, testmode);
 
        return 0;
 
index c3c3188..25aba6e 100644 (file)
@@ -26,6 +26,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/miscdevice.h>
@@ -65,8 +67,8 @@ MODULE_PARM_DESC(timeout,
                "Watchdog timeout in seconds. 1 <= timeout <= 255, default="
                                __MODULE_STRING(WD_TIMO) ".");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -203,8 +205,7 @@ static int wafwdt_close(struct inode *inode, struct file *file)
        if (expect_close == 42)
                wafwdt_stop();
        else {
-               printk(KERN_CRIT PFX
-                   "WDT device closed unexpectedly.  WDT will not stop!\n");
+               pr_crit("WDT device closed unexpectedly.  WDT will not stop!\n");
                wafwdt_ping();
        }
        clear_bit(0, &wafwdt_is_open);
@@ -256,49 +257,42 @@ static int __init wafwdt_init(void)
 {
        int ret;
 
-       printk(KERN_INFO
-         "WDT driver for Wafer 5823 single board computer initialising.\n");
+       pr_info("WDT driver for Wafer 5823 single board computer initialising\n");
 
        if (timeout < 1 || timeout > 255) {
                timeout = WD_TIMO;
-               printk(KERN_INFO PFX
-                       "timeout value must be 1 <= x <= 255, using %d\n",
-                                                               timeout);
+               pr_info("timeout value must be 1 <= x <= 255, using %d\n",
+                       timeout);
        }
 
        if (wdt_stop != wdt_start) {
                if (!request_region(wdt_stop, 1, "Wafer 5823 WDT")) {
-                       printk(KERN_ERR PFX
-                               "I/O address 0x%04x already in use\n",
-                                                               wdt_stop);
+                       pr_err("I/O address 0x%04x already in use\n", wdt_stop);
                        ret = -EIO;
                        goto error;
                }
        }
 
        if (!request_region(wdt_start, 1, "Wafer 5823 WDT")) {
-               printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
-                       wdt_start);
+               pr_err("I/O address 0x%04x already in use\n", wdt_start);
                ret = -EIO;
                goto error2;
        }
 
        ret = register_reboot_notifier(&wafwdt_notifier);
        if (ret != 0) {
-               printk(KERN_ERR PFX
-                       "cannot register reboot notifier (err=%d)\n", ret);
+               pr_err("cannot register reboot notifier (err=%d)\n", ret);
                goto error3;
        }
 
        ret = misc_register(&wafwdt_miscdev);
        if (ret != 0) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                                               WATCHDOG_MINOR, ret);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      WATCHDOG_MINOR, ret);
                goto error4;
        }
 
-       printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n",
+       pr_info("initialized. timeout=%d sec (nowayout=%d)\n",
                timeout, nowayout);
 
        return ret;
index cfa1a15..14d768b 100644 (file)
@@ -77,7 +77,7 @@ int watchdog_register_device(struct watchdog_device *wdd)
        /* We only support 1 watchdog device via the /dev/watchdog interface */
        ret = watchdog_dev_register(wdd);
        if (ret) {
-               pr_err("error registering /dev/watchdog (err=%d).\n", ret);
+               pr_err("error registering /dev/watchdog (err=%d)\n", ret);
                return ret;
        }
 
@@ -101,7 +101,7 @@ void watchdog_unregister_device(struct watchdog_device *wdd)
 
        ret = watchdog_dev_unregister(wdd);
        if (ret)
-               pr_err("error unregistering /dev/watchdog (err=%d).\n", ret);
+               pr_err("error unregistering /dev/watchdog (err=%d)\n", ret);
 }
 EXPORT_SYMBOL_GPL(watchdog_unregister_device);
 
index 1199da0..8558da9 100644 (file)
@@ -226,7 +226,6 @@ static long watchdog_ioctl(struct file *file, unsigned int cmd,
                err = wdd->ops->set_timeout(wdd, val);
                if (err < 0)
                        return err;
-               wdd->timeout = val;
                /* If the watchdog is active then we send a keepalive ping
                 * to make sure that the watchdog keep's running (and if
                 * possible that it takes the new timeout) */
@@ -237,6 +236,11 @@ static long watchdog_ioctl(struct file *file, unsigned int cmd,
                if (wdd->timeout == 0)
                        return -EOPNOTSUPP;
                return put_user(wdd->timeout, p);
+       case WDIOC_GETTIMELEFT:
+               if (!wdd->ops->get_timeleft)
+                       return -EOPNOTSUPP;
+
+               return put_user(wdd->ops->get_timeleft(wdd), p);
        default:
                return -ENOTTY;
        }
@@ -347,7 +351,7 @@ int watchdog_dev_register(struct watchdog_device *watchdog)
 
        /* Only one device can register for /dev/watchdog */
        if (test_and_set_bit(0, &watchdog_dev_busy)) {
-               pr_err("only one watchdog can use /dev/watchdog.\n");
+               pr_err("only one watchdog can use /dev/watchdog\n");
                return -EBUSY;
        }
 
@@ -355,8 +359,8 @@ int watchdog_dev_register(struct watchdog_device *watchdog)
 
        err = misc_register(&watchdog_miscdev);
        if (err != 0) {
-               pr_err("%s: cannot register miscdev on minor=%d (err=%d).\n",
-                       watchdog->info->identity, WATCHDOG_MINOR, err);
+               pr_err("%s: cannot register miscdev on minor=%d (err=%d)\n",
+                      watchdog->info->identity, WATCHDOG_MINOR, err);
                goto out;
        }
 
@@ -383,8 +387,8 @@ int watchdog_dev_unregister(struct watchdog_device *watchdog)
 
        /* We can only unregister the watchdog device that was registered */
        if (watchdog != wdd) {
-               pr_err("%s: watchdog was not registered as /dev/watchdog.\n",
-                       watchdog->info->identity);
+               pr_err("%s: watchdog was not registered as /dev/watchdog\n",
+                      watchdog->info->identity);
                return -ENODEV;
        }
 
index 94ec22b..0a77655 100644 (file)
@@ -26,6 +26,8 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/fs.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -49,7 +51,7 @@ MODULE_LICENSE("GPL");
 MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
 MODULE_ALIAS_MISCDEV(TEMP_MINOR);
 
-static int wdrtas_nowayout = WATCHDOG_NOWAYOUT;
+static bool wdrtas_nowayout = WATCHDOG_NOWAYOUT;
 static atomic_t wdrtas_miscdev_open = ATOMIC_INIT(0);
 static char wdrtas_expect_close;
 
@@ -93,8 +95,8 @@ static int wdrtas_set_interval(int interval)
        result = rtas_call(wdrtas_token_set_indicator, 3, 1, NULL,
                           WDRTAS_SURVEILLANCE_IND, 0, interval);
        if (result < 0 && print_msg) {
-               printk(KERN_ERR "wdrtas: setting the watchdog to %i "
-                      "timeout failed: %li\n", interval, result);
+               pr_err("setting the watchdog to %i timeout failed: %li\n",
+                      interval, result);
                print_msg--;
        }
 
@@ -128,8 +130,8 @@ static int wdrtas_get_interval(int fallback_value)
        spin_unlock(&rtas_data_buf_lock);
 
        if (value[0] != 0 || value[1] != 2 || value[3] != 0 || result < 0) {
-               printk(KERN_WARNING "wdrtas: could not get sp_spi watchdog "
-                      "timeout (%li). Continuing\n", result);
+               pr_warn("could not get sp_spi watchdog timeout (%li). Continuing\n",
+                       result);
                return fallback_value;
        }
 
@@ -170,18 +172,18 @@ static void wdrtas_log_scanned_event(void)
        int i;
 
        for (i = 0; i < WDRTAS_LOGBUFFER_LEN; i += 16)
-               printk(KERN_INFO "wdrtas: dumping event (line %i/%i), data = "
-                      "%02x %02x %02x %02x  %02x %02x %02x %02x   "
-                      "%02x %02x %02x %02x  %02x %02x %02x %02x\n",
-                      (i / 16) + 1, (WDRTAS_LOGBUFFER_LEN / 16),
-                      wdrtas_logbuffer[i + 0], wdrtas_logbuffer[i + 1],
-                      wdrtas_logbuffer[i + 2], wdrtas_logbuffer[i + 3],
-                      wdrtas_logbuffer[i + 4], wdrtas_logbuffer[i + 5],
-                      wdrtas_logbuffer[i + 6], wdrtas_logbuffer[i + 7],
-                      wdrtas_logbuffer[i + 8], wdrtas_logbuffer[i + 9],
-                      wdrtas_logbuffer[i + 10], wdrtas_logbuffer[i + 11],
-                      wdrtas_logbuffer[i + 12], wdrtas_logbuffer[i + 13],
-                      wdrtas_logbuffer[i + 14], wdrtas_logbuffer[i + 15]);
+               pr_info("dumping event (line %i/%i), data = "
+                       "%02x %02x %02x %02x  %02x %02x %02x %02x   "
+                       "%02x %02x %02x %02x  %02x %02x %02x %02x\n",
+                       (i / 16) + 1, (WDRTAS_LOGBUFFER_LEN / 16),
+                       wdrtas_logbuffer[i + 0], wdrtas_logbuffer[i + 1],
+                       wdrtas_logbuffer[i + 2], wdrtas_logbuffer[i + 3],
+                       wdrtas_logbuffer[i + 4], wdrtas_logbuffer[i + 5],
+                       wdrtas_logbuffer[i + 6], wdrtas_logbuffer[i + 7],
+                       wdrtas_logbuffer[i + 8], wdrtas_logbuffer[i + 9],
+                       wdrtas_logbuffer[i + 10], wdrtas_logbuffer[i + 11],
+                       wdrtas_logbuffer[i + 12], wdrtas_logbuffer[i + 13],
+                       wdrtas_logbuffer[i + 14], wdrtas_logbuffer[i + 15]);
 }
 
 /**
@@ -201,8 +203,7 @@ static void wdrtas_timer_keepalive(void)
                                   (void *)__pa(wdrtas_logbuffer),
                                   WDRTAS_LOGBUFFER_LEN);
                if (result < 0)
-                       printk(KERN_ERR "wdrtas: event-scan failed: %li\n",
-                              result);
+                       pr_err("event-scan failed: %li\n", result);
                if (result == 0)
                        wdrtas_log_scanned_event();
        } while (result == 0);
@@ -224,8 +225,7 @@ static int wdrtas_get_temperature(void)
        result = rtas_get_sensor(WDRTAS_THERMAL_SENSOR, 0, &temperature);
 
        if (result < 0)
-               printk(KERN_WARNING "wdrtas: reading the thermal sensor "
-                      "failed: %i\n", result);
+               pr_warn("reading the thermal sensor failed: %i\n", result);
        else
                temperature = ((temperature * 9) / 5) + 32; /* fahrenheit */
 
@@ -419,8 +419,7 @@ static int wdrtas_close(struct inode *inode, struct file *file)
        if (wdrtas_expect_close == WDRTAS_MAGIC_CHAR)
                wdrtas_timer_stop();
        else {
-               printk(KERN_WARNING "wdrtas: got unexpected close. Watchdog "
-                      "not stopped.\n");
+               pr_warn("got unexpected close. Watchdog not stopped.\n");
                wdrtas_timer_keepalive();
        }
 
@@ -552,30 +551,24 @@ static int wdrtas_get_tokens(void)
 {
        wdrtas_token_get_sensor_state = rtas_token("get-sensor-state");
        if (wdrtas_token_get_sensor_state == RTAS_UNKNOWN_SERVICE) {
-               printk(KERN_WARNING "wdrtas: couldn't get token for "
-                      "get-sensor-state. Trying to continue without "
-                      "temperature support.\n");
+               pr_warn("couldn't get token for get-sensor-state. Trying to continue without temperature support.\n");
        }
 
        wdrtas_token_get_sp = rtas_token("ibm,get-system-parameter");
        if (wdrtas_token_get_sp == RTAS_UNKNOWN_SERVICE) {
-               printk(KERN_WARNING "wdrtas: couldn't get token for "
-                      "ibm,get-system-parameter. Trying to continue with "
-                      "a default timeout value of %i seconds.\n",
-                      WDRTAS_DEFAULT_INTERVAL);
+               pr_warn("couldn't get token for ibm,get-system-parameter. Trying to continue with a default timeout value of %i seconds.\n",
+                       WDRTAS_DEFAULT_INTERVAL);
        }
 
        wdrtas_token_set_indicator = rtas_token("set-indicator");
        if (wdrtas_token_set_indicator == RTAS_UNKNOWN_SERVICE) {
-               printk(KERN_ERR "wdrtas: couldn't get token for "
-                      "set-indicator. Terminating watchdog code.\n");
+               pr_err("couldn't get token for set-indicator. Terminating watchdog code.\n");
                return -EIO;
        }
 
        wdrtas_token_event_scan = rtas_token("event-scan");
        if (wdrtas_token_event_scan == RTAS_UNKNOWN_SERVICE) {
-               printk(KERN_ERR "wdrtas: couldn't get token for event-scan. "
-                      "Terminating watchdog code.\n");
+               pr_err("couldn't get token for event-scan. Terminating watchdog code.\n");
                return -EIO;
        }
 
@@ -609,17 +602,14 @@ static int wdrtas_register_devs(void)
 
        result = misc_register(&wdrtas_miscdev);
        if (result) {
-               printk(KERN_ERR "wdrtas: couldn't register watchdog misc "
-                      "device. Terminating watchdog code.\n");
+               pr_err("couldn't register watchdog misc device. Terminating watchdog code.\n");
                return result;
        }
 
        if (wdrtas_token_get_sensor_state != RTAS_UNKNOWN_SERVICE) {
                result = misc_register(&wdrtas_tempdev);
                if (result) {
-                       printk(KERN_WARNING "wdrtas: couldn't register "
-                              "watchdog temperature misc device. Continuing "
-                              "without temperature support.\n");
+                       pr_warn("couldn't register watchdog temperature misc device. Continuing without temperature support.\n");
                        wdrtas_token_get_sensor_state = RTAS_UNKNOWN_SERVICE;
                }
        }
@@ -643,8 +633,7 @@ static int __init wdrtas_init(void)
                return -ENODEV;
 
        if (register_reboot_notifier(&wdrtas_notifier)) {
-               printk(KERN_ERR "wdrtas: could not register reboot notifier. "
-                      "Terminating watchdog code.\n");
+               pr_err("could not register reboot notifier. Terminating watchdog code.\n");
                wdrtas_unregister_devs();
                return -ENODEV;
        }
index d2ef002..ee4333c 100644 (file)
@@ -32,6 +32,8 @@
  *             Matt Domsch     :       Added nowayout module option
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
@@ -46,7 +48,6 @@
 #include <linux/io.h>
 #include <linux/uaccess.h>
 
-#include <asm/system.h>
 #include "wd501p.h"
 
 static unsigned long wdt_is_open;
@@ -65,8 +66,8 @@ MODULE_PARM_DESC(heartbeat,
        "Watchdog heartbeat in seconds. (0 < heartbeat < 65536, default="
                                __MODULE_STRING(WD_TIMO) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
        "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -252,11 +253,11 @@ static int wdt_get_temperature(void)
 static void wdt_decode_501(int status)
 {
        if (!(status & WDC_SR_TGOOD))
-               printk(KERN_CRIT "Overheat alarm.(%d)\n", inb_p(WDT_RT));
+               pr_crit("Overheat alarm (%d)\n", inb_p(WDT_RT));
        if (!(status & WDC_SR_PSUOVER))
-               printk(KERN_CRIT "PSU over voltage.\n");
+               pr_crit("PSU over voltage\n");
        if (!(status & WDC_SR_PSUUNDR))
-               printk(KERN_CRIT "PSU under voltage.\n");
+               pr_crit("PSU under voltage\n");
 }
 
 /**
@@ -280,25 +281,25 @@ static irqreturn_t wdt_interrupt(int irq, void *dev_id)
        spin_lock(&wdt_lock);
        status = inb_p(WDT_SR);
 
-       printk(KERN_CRIT "WDT status %d\n", status);
+       pr_crit("WDT status %d\n", status);
 
        if (type == 501) {
                wdt_decode_501(status);
                if (tachometer) {
                        if (!(status & WDC_SR_FANGOOD))
-                               printk(KERN_CRIT "Possible fan fault.\n");
+                               pr_crit("Possible fan fault\n");
                }
        }
        if (!(status & WDC_SR_WCCR)) {
 #ifdef SOFTWARE_REBOOT
 #ifdef ONLY_TESTING
-               printk(KERN_CRIT "Would Reboot.\n");
+               pr_crit("Would Reboot\n");
 #else
-               printk(KERN_CRIT "Initiating system reboot.\n");
+               pr_crit("Initiating system reboot\n");
                emergency_restart();
 #endif
 #else
-               printk(KERN_CRIT "Reset in 5ms.\n");
+               pr_crit("Reset in 5ms\n");
 #endif
        }
        spin_unlock(&wdt_lock);
@@ -441,8 +442,7 @@ static int wdt_release(struct inode *inode, struct file *file)
                wdt_stop();
                clear_bit(0, &wdt_is_open);
        } else {
-               printk(KERN_CRIT
-                "wdt: WDT device closed unexpectedly.  WDT will not stop!\n");
+               pr_crit("WDT device closed unexpectedly.  WDT will not stop!\n");
                wdt_ping();
        }
        expect_close = 0;
@@ -593,7 +593,7 @@ static int __init wdt_init(void)
        int ret;
 
        if (type != 500 && type != 501) {
-               printk(KERN_ERR "wdt: unknown card type '%d'.\n", type);
+               pr_err("unknown card type '%d'\n", type);
                return -ENODEV;
        }
 
@@ -601,53 +601,49 @@ static int __init wdt_init(void)
           if not reset to the default */
        if (wdt_set_heartbeat(heartbeat)) {
                wdt_set_heartbeat(WD_TIMO);
-               printk(KERN_INFO "wdt: heartbeat value must be "
-                       "0 < heartbeat < 65536, using %d\n", WD_TIMO);
+               pr_info("heartbeat value must be 0 < heartbeat < 65536, using %d\n",
+                       WD_TIMO);
        }
 
        if (!request_region(io, 8, "wdt501p")) {
-               printk(KERN_ERR
-                       "wdt: I/O address 0x%04x already in use\n", io);
+               pr_err("I/O address 0x%04x already in use\n", io);
                ret = -EBUSY;
                goto out;
        }
 
        ret = request_irq(irq, wdt_interrupt, 0, "wdt501p", NULL);
        if (ret) {
-               printk(KERN_ERR "wdt: IRQ %d is not free.\n", irq);
+               pr_err("IRQ %d is not free\n", irq);
                goto outreg;
        }
 
        ret = register_reboot_notifier(&wdt_notifier);
        if (ret) {
-               printk(KERN_ERR
-                     "wdt: cannot register reboot notifier (err=%d)\n", ret);
+               pr_err("cannot register reboot notifier (err=%d)\n", ret);
                goto outirq;
        }
 
        if (type == 501) {
                ret = misc_register(&temp_miscdev);
                if (ret) {
-                       printk(KERN_ERR "wdt: cannot register miscdev "
-                               "on minor=%d (err=%d)\n", TEMP_MINOR, ret);
+                       pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                              TEMP_MINOR, ret);
                        goto outrbt;
                }
        }
 
        ret = misc_register(&wdt_miscdev);
        if (ret) {
-               printk(KERN_ERR
-                       "wdt: cannot register miscdev on minor=%d (err=%d)\n",
-                                                       WATCHDOG_MINOR, ret);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      WATCHDOG_MINOR, ret);
                goto outmisc;
        }
 
-       printk(KERN_INFO "WDT500/501-P driver 0.10 "
-               "at 0x%04x (Interrupt %d). heartbeat=%d sec (nowayout=%d)\n",
+       pr_info("WDT500/501-P driver 0.10 at 0x%04x (Interrupt %d). heartbeat=%d sec (nowayout=%d)\n",
                io, irq, heartbeat, nowayout);
        if (type == 501)
-               printk(KERN_INFO "wdt: Fan Tachometer is %s\n",
-                               (tachometer ? "Enabled" : "Disabled"));
+               pr_info("Fan Tachometer is %s\n",
+                       tachometer ? "Enabled" : "Disabled");
        return 0;
 
 outmisc:
index f551356..5eec740 100644 (file)
@@ -16,6 +16,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
@@ -32,6 +34,7 @@
 #include <mach/hardware.h>
 
 #include <asm/mach-types.h>
+#include <asm/system_info.h>
 #include <asm/hardware/dec21285.h>
 
 /*
@@ -49,7 +52,7 @@ static unsigned long timer_alive;
  */
 static void watchdog_fire(int irq, void *dev_id)
 {
-       printk(KERN_CRIT "Watchdog: Would Reboot.\n");
+       pr_crit("Would Reboot\n");
        *CSR_TIMER4_CNTL = 0;
        *CSR_TIMER4_CLR = 0;
 }
@@ -205,13 +208,11 @@ static int __init footbridge_watchdog_init(void)
        if (retval < 0)
                return retval;
 
-       printk(KERN_INFO
-               "Footbridge Watchdog Timer: 0.01, timer margin: %d sec\n",
-                                                               soft_margin);
+       pr_info("Footbridge Watchdog Timer: 0.01, timer margin: %d sec\n",
+               soft_margin);
 
        if (machine_is_cats())
-               printk(KERN_WARNING
-                 "Warning: Watchdog reset may not work on this machine.\n");
+               pr_warn("Warning: Watchdog reset may not work on this machine\n");
        return 0;
 }
 
index a2f01c9..65a4023 100644 (file)
@@ -23,6 +23,8 @@
  *                                 Netwinders only
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/io.h>
 #include <linux/uaccess.h>
 
-#include <asm/system.h>
 #include <asm/mach-types.h>
 
 #define WATCHDOG_VERSION  "0.04"
 #define WATCHDOG_NAME     "Wdt977"
-#define PFX WATCHDOG_NAME ": "
-#define DRIVER_VERSION    WATCHDOG_NAME " driver, v" WATCHDOG_VERSION "\n"
 
 #define IO_INDEX_PORT  0x370           /* on some systems it can be 0x3F0 */
 #define IO_DATA_PORT   (IO_INDEX_PORT + 1)
@@ -68,8 +67,8 @@ MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (60..15300, default="
 module_param(testmode, int, 0);
 MODULE_PARM_DESC(testmode, "Watchdog testmode (1 = no reboot), default=0");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -119,7 +118,7 @@ static int wdt977_start(void)
        outb_p(LOCK_DATA, IO_INDEX_PORT);
 
        spin_unlock_irqrestore(&spinlock, flags);
-       printk(KERN_INFO PFX "activated.\n");
+       pr_info("activated\n");
 
        return 0;
 }
@@ -164,7 +163,7 @@ static int wdt977_stop(void)
        outb_p(LOCK_DATA, IO_INDEX_PORT);
 
        spin_unlock_irqrestore(&spinlock, flags);
-       printk(KERN_INFO PFX "shutdown.\n");
+       pr_info("shutdown\n");
 
        return 0;
 }
@@ -288,8 +287,7 @@ static int wdt977_release(struct inode *inode, struct file *file)
                clear_bit(0, &timer_alive);
        } else {
                wdt977_keepalive();
-               printk(KERN_CRIT PFX
-                       "Unexpected close, not stopping watchdog!\n");
+               pr_crit("Unexpected close, not stopping watchdog!\n");
        }
        expect_close = 0;
        return 0;
@@ -446,15 +444,14 @@ static int __init wd977_init(void)
 {
        int rc;
 
-       printk(KERN_INFO PFX DRIVER_VERSION);
+       pr_info("driver v%s\n", WATCHDOG_VERSION);
 
        /* Check that the timeout value is within its range;
           if not reset to the default */
        if (wdt977_set_timeout(timeout)) {
                wdt977_set_timeout(DEFAULT_TIMEOUT);
-               printk(KERN_INFO PFX
-                     "timeout value must be 60 < timeout < 15300, using %d\n",
-                                                       DEFAULT_TIMEOUT);
+               pr_info("timeout value must be 60 < timeout < 15300, using %d\n",
+                       DEFAULT_TIMEOUT);
        }
 
        /* on Netwinder the IOports are already reserved by
@@ -462,9 +459,8 @@ static int __init wd977_init(void)
         */
        if (!machine_is_netwinder()) {
                if (!request_region(IO_INDEX_PORT, 2, WATCHDOG_NAME)) {
-                       printk(KERN_ERR PFX
-                               "I/O address 0x%04x already in use\n",
-                                                               IO_INDEX_PORT);
+                       pr_err("I/O address 0x%04x already in use\n",
+                              IO_INDEX_PORT);
                        rc = -EIO;
                        goto err_out;
                }
@@ -472,22 +468,19 @@ static int __init wd977_init(void)
 
        rc = register_reboot_notifier(&wdt977_notifier);
        if (rc) {
-               printk(KERN_ERR PFX
-                       "cannot register reboot notifier (err=%d)\n", rc);
+               pr_err("cannot register reboot notifier (err=%d)\n", rc);
                goto err_out_region;
        }
 
        rc = misc_register(&wdt977_miscdev);
        if (rc) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                                               wdt977_miscdev.minor, rc);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      wdt977_miscdev.minor, rc);
                goto err_out_reboot;
        }
 
-       printk(KERN_INFO PFX
-               "initialized. timeout=%d sec (nowayout=%d, testmode=%i)\n",
-                                               timeout, nowayout, testmode);
+       pr_info("initialized. timeout=%d sec (nowayout=%d, testmode=%i)\n",
+               timeout, nowayout, testmode);
 
        return 0;
 
index e0fc3ba..1c888c7 100644 (file)
@@ -37,6 +37,8 @@
  *             Matt Domsch     :       nowayout module option
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/io.h>
 #include <linux/uaccess.h>
 
-#include <asm/system.h>
 
 #define WDT_IS_PCI
 #include "wd501p.h"
 
-#define PFX "wdt_pci: "
-
 /* We can only use 1 card due to the /dev/watchdog restriction */
 static int dev_count;
 
@@ -80,8 +79,8 @@ MODULE_PARM_DESC(heartbeat,
                "Watchdog heartbeat in seconds. (0<heartbeat<65536, default="
                                __MODULE_STRING(WD_TIMO) ")");
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -312,33 +311,32 @@ static irqreturn_t wdtpci_interrupt(int irq, void *dev_id)
        status = inb(WDT_SR);
        udelay(8);
 
-       printk(KERN_CRIT PFX "status %d\n", status);
+       pr_crit("status %d\n", status);
 
        if (type == 501) {
                if (!(status & WDC_SR_TGOOD)) {
-                       printk(KERN_CRIT PFX "Overheat alarm.(%d)\n",
-                                                               inb(WDT_RT));
+                       pr_crit("Overheat alarm (%d)\n", inb(WDT_RT));
                        udelay(8);
                }
                if (!(status & WDC_SR_PSUOVER))
-                       printk(KERN_CRIT PFX "PSU over voltage.\n");
+                       pr_crit("PSU over voltage\n");
                if (!(status & WDC_SR_PSUUNDR))
-                       printk(KERN_CRIT PFX "PSU under voltage.\n");
+                       pr_crit("PSU under voltage\n");
                if (tachometer) {
                        if (!(status & WDC_SR_FANGOOD))
-                               printk(KERN_CRIT PFX "Possible fan fault.\n");
+                               pr_crit("Possible fan fault\n");
                }
        }
        if (!(status & WDC_SR_WCCR)) {
 #ifdef SOFTWARE_REBOOT
 #ifdef ONLY_TESTING
-               printk(KERN_CRIT PFX "Would Reboot.\n");
+               pr_crit("Would Reboot\n");
 #else
-               printk(KERN_CRIT PFX "Initiating system reboot.\n");
+               pr_crit("Initiating system reboot\n");
                emergency_restart(NULL);
 #endif
 #else
-               printk(KERN_CRIT PFX "Reset in 5ms.\n");
+               pr_crit("Reset in 5ms\n");
 #endif
        }
        spin_unlock(&wdtpci_lock);
@@ -484,7 +482,7 @@ static int wdtpci_release(struct inode *inode, struct file *file)
        if (expect_close == 42) {
                wdtpci_stop();
        } else {
-               printk(KERN_CRIT PFX "Unexpected close, not stopping timer!");
+               pr_crit("Unexpected close, not stopping timer!\n");
                wdtpci_ping();
        }
        expect_close = 0;
@@ -614,29 +612,29 @@ static int __devinit wdtpci_init_one(struct pci_dev *dev,
 
        dev_count++;
        if (dev_count > 1) {
-               printk(KERN_ERR PFX "This driver only supports one device\n");
+               pr_err("This driver only supports one device\n");
                return -ENODEV;
        }
 
        if (type != 500 && type != 501) {
-               printk(KERN_ERR PFX "unknown card type '%d'.\n", type);
+               pr_err("unknown card type '%d'\n", type);
                return -ENODEV;
        }
 
        if (pci_enable_device(dev)) {
-               printk(KERN_ERR PFX "Not possible to enable PCI Device\n");
+               pr_err("Not possible to enable PCI Device\n");
                return -ENODEV;
        }
 
        if (pci_resource_start(dev, 2) == 0x0000) {
-               printk(KERN_ERR PFX "No I/O-Address for card detected\n");
+               pr_err("No I/O-Address for card detected\n");
                ret = -ENODEV;
                goto out_pci;
        }
 
        if (pci_request_region(dev, 2, "wdt_pci")) {
-               printk(KERN_ERR PFX "I/O address 0x%llx already in use\n",
-                       (unsigned long long)pci_resource_start(dev, 2));
+               pr_err("I/O address 0x%llx already in use\n",
+                      (unsigned long long)pci_resource_start(dev, 2));
                goto out_pci;
        }
 
@@ -645,53 +643,48 @@ static int __devinit wdtpci_init_one(struct pci_dev *dev,
 
        if (request_irq(irq, wdtpci_interrupt, IRQF_SHARED,
                         "wdt_pci", &wdtpci_miscdev)) {
-               printk(KERN_ERR PFX "IRQ %d is not free\n", irq);
+               pr_err("IRQ %d is not free\n", irq);
                goto out_reg;
        }
 
-       printk(KERN_INFO
-        "PCI-WDT500/501 (PCI-WDG-CSM) driver 0.10 at 0x%llx (Interrupt %d)\n",
-                                       (unsigned long long)io, irq);
+       pr_info("PCI-WDT500/501 (PCI-WDG-CSM) driver 0.10 at 0x%llx (Interrupt %d)\n",
+               (unsigned long long)io, irq);
 
        /* Check that the heartbeat value is within its range;
           if not reset to the default */
        if (wdtpci_set_heartbeat(heartbeat)) {
                wdtpci_set_heartbeat(WD_TIMO);
-               printk(KERN_INFO PFX
-                 "heartbeat value must be 0 < heartbeat < 65536, using %d\n",
-                                                               WD_TIMO);
+               pr_info("heartbeat value must be 0 < heartbeat < 65536, using %d\n",
+                       WD_TIMO);
        }
 
        ret = register_reboot_notifier(&wdtpci_notifier);
        if (ret) {
-               printk(KERN_ERR PFX
-                       "cannot register reboot notifier (err=%d)\n", ret);
+               pr_err("cannot register reboot notifier (err=%d)\n", ret);
                goto out_irq;
        }
 
        if (type == 501) {
                ret = misc_register(&temp_miscdev);
                if (ret) {
-                       printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                                                       TEMP_MINOR, ret);
+                       pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                              TEMP_MINOR, ret);
                        goto out_rbt;
                }
        }
 
        ret = misc_register(&wdtpci_miscdev);
        if (ret) {
-               printk(KERN_ERR PFX
-                       "cannot register miscdev on minor=%d (err=%d)\n",
-                                               WATCHDOG_MINOR, ret);
+               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
+                      WATCHDOG_MINOR, ret);
                goto out_misc;
        }
 
-       printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n",
+       pr_info("initialized. heartbeat=%d sec (nowayout=%d)\n",
                heartbeat, nowayout);
        if (type == 501)
-               printk(KERN_INFO "wdt: Fan Tachometer is %s\n",
-                               (tachometer ? "Enabled" : "Disabled"));
+               pr_info("Fan Tachometer is %s\n",
+                       tachometer ? "Enabled" : "Disabled");
 
        ret = 0;
 out:
index 263c883..b1815c5 100644 (file)
@@ -22,8 +22,8 @@
 #include <linux/mfd/wm831x/pdata.h>
 #include <linux/mfd/wm831x/watchdog.h>
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                 "Watchdog cannot be stopped once started (default="
                 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
@@ -163,6 +163,8 @@ static int wm831x_wdt_set_timeout(struct watchdog_device *wdt_dev,
                        ret);
        }
 
+       wdt_dev->timeout = timeout;
+
        return ret;
 }
 
index 5d7113c..3c76693 100644 (file)
@@ -8,63 +8,65 @@
  * as published by the Free Software Foundation
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/miscdevice.h>
 #include <linux/platform_device.h>
 #include <linux/watchdog.h>
 #include <linux/uaccess.h>
 #include <linux/mfd/wm8350/core.h>
 
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout,
                 "Watchdog cannot be stopped once started (default="
                 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
-static unsigned long wm8350_wdt_users;
-static struct miscdevice wm8350_wdt_miscdev;
-static int wm8350_wdt_expect_close;
 static DEFINE_MUTEX(wdt_mutex);
 
 static struct {
-       int time;  /* Seconds */
-       u16 val;   /* To be set in WM8350_SYSTEM_CONTROL_2 */
+       unsigned int time;  /* Seconds */
+       u16 val;            /* To be set in WM8350_SYSTEM_CONTROL_2 */
 } wm8350_wdt_cfgs[] = {
        { 1, 0x02 },
        { 2, 0x04 },
        { 4, 0x05 },
 };
 
-static struct wm8350 *get_wm8350(void)
-{
-       return dev_get_drvdata(wm8350_wdt_miscdev.parent);
-}
-
-static int wm8350_wdt_set_timeout(struct wm8350 *wm8350, u16 value)
+static int wm8350_wdt_set_timeout(struct watchdog_device *wdt_dev,
+                                 unsigned int timeout)
 {
-       int ret;
+       struct wm8350 *wm8350 = watchdog_get_drvdata(wdt_dev);
+       int ret, i;
        u16 reg;
 
+       for (i = 0; i < ARRAY_SIZE(wm8350_wdt_cfgs); i++)
+               if (wm8350_wdt_cfgs[i].time == timeout)
+                       break;
+       if (i == ARRAY_SIZE(wm8350_wdt_cfgs))
+               return -EINVAL;
+
        mutex_lock(&wdt_mutex);
        wm8350_reg_unlock(wm8350);
 
        reg = wm8350_reg_read(wm8350, WM8350_SYSTEM_CONTROL_2);
        reg &= ~WM8350_WDOG_TO_MASK;
-       reg |= value;
+       reg |= wm8350_wdt_cfgs[i].val;
        ret = wm8350_reg_write(wm8350, WM8350_SYSTEM_CONTROL_2, reg);
 
        wm8350_reg_lock(wm8350);
        mutex_unlock(&wdt_mutex);
 
+       wdt_dev->timeout = timeout;
        return ret;
 }
 
-static int wm8350_wdt_start(struct wm8350 *wm8350)
+static int wm8350_wdt_start(struct watchdog_device *wdt_dev)
 {
+       struct wm8350 *wm8350 = watchdog_get_drvdata(wdt_dev);
        int ret;
        u16 reg;
 
@@ -82,8 +84,9 @@ static int wm8350_wdt_start(struct wm8350 *wm8350)
        return ret;
 }
 
-static int wm8350_wdt_stop(struct wm8350 *wm8350)
+static int wm8350_wdt_stop(struct watchdog_device *wdt_dev)
 {
+       struct wm8350 *wm8350 = watchdog_get_drvdata(wdt_dev);
        int ret;
        u16 reg;
 
@@ -100,8 +103,9 @@ static int wm8350_wdt_stop(struct wm8350 *wm8350)
        return ret;
 }
 
-static int wm8350_wdt_kick(struct wm8350 *wm8350)
+static int wm8350_wdt_ping(struct watchdog_device *wdt_dev)
 {
+       struct wm8350 *wm8350 = watchdog_get_drvdata(wdt_dev);
        int ret;
        u16 reg;
 
@@ -115,168 +119,25 @@ static int wm8350_wdt_kick(struct wm8350 *wm8350)
        return ret;
 }
 
-static int wm8350_wdt_open(struct inode *inode, struct file *file)
-{
-       struct wm8350 *wm8350 = get_wm8350();
-       int ret;
-
-       if (!wm8350)
-               return -ENODEV;
-
-       if (test_and_set_bit(0, &wm8350_wdt_users))
-               return -EBUSY;
-
-       ret = wm8350_wdt_start(wm8350);
-       if (ret != 0)
-               return ret;
-
-       return nonseekable_open(inode, file);
-}
-
-static int wm8350_wdt_release(struct inode *inode, struct file *file)
-{
-       struct wm8350 *wm8350 = get_wm8350();
-
-       if (wm8350_wdt_expect_close)
-               wm8350_wdt_stop(wm8350);
-       else {
-               dev_warn(wm8350->dev, "Watchdog device closed uncleanly\n");
-               wm8350_wdt_kick(wm8350);
-       }
-
-       clear_bit(0, &wm8350_wdt_users);
-
-       return 0;
-}
-
-static ssize_t wm8350_wdt_write(struct file *file,
-                               const char __user *data, size_t count,
-                               loff_t *ppos)
-{
-       struct wm8350 *wm8350 = get_wm8350();
-       size_t i;
-
-       if (count) {
-               wm8350_wdt_kick(wm8350);
-
-               if (!nowayout) {
-                       /* In case it was set long ago */
-                       wm8350_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')
-                                       wm8350_wdt_expect_close = 42;
-                       }
-               }
-       }
-       return count;
-}
-
-static const struct watchdog_info ident = {
+static const struct watchdog_info wm8350_wdt_info = {
        .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
        .identity = "WM8350 Watchdog",
 };
 
-static long wm8350_wdt_ioctl(struct file *file, unsigned int cmd,
-                            unsigned long arg)
-{
-       struct wm8350 *wm8350 = get_wm8350();
-       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 = wm8350_wdt_stop(wm8350);
-
-               if (options == WDIOS_ENABLECARD)
-                       ret = wm8350_wdt_start(wm8350);
-               break;
-       }
-
-       case WDIOC_KEEPALIVE:
-               ret = wm8350_wdt_kick(wm8350);
-               break;
-
-       case WDIOC_SETTIMEOUT:
-               ret = get_user(time, p);
-               if (ret)
-                       break;
-
-               if (time == 0) {
-                       if (nowayout)
-                               ret = -EINVAL;
-                       else
-                               wm8350_wdt_stop(wm8350);
-                       break;
-               }
-
-               for (i = 0; i < ARRAY_SIZE(wm8350_wdt_cfgs); i++)
-                       if (wm8350_wdt_cfgs[i].time == time)
-                               break;
-               if (i == ARRAY_SIZE(wm8350_wdt_cfgs))
-                       ret = -EINVAL;
-               else
-                       ret = wm8350_wdt_set_timeout(wm8350,
-                                                    wm8350_wdt_cfgs[i].val);
-               break;
-
-       case WDIOC_GETTIMEOUT:
-               reg = wm8350_reg_read(wm8350, WM8350_SYSTEM_CONTROL_2);
-               reg &= WM8350_WDOG_TO_MASK;
-               for (i = 0; i < ARRAY_SIZE(wm8350_wdt_cfgs); i++)
-                       if (wm8350_wdt_cfgs[i].val == reg)
-                               break;
-               if (i == ARRAY_SIZE(wm8350_wdt_cfgs)) {
-                       dev_warn(wm8350->dev,
-                                "Unknown watchdog configuration: %x\n", reg);
-                       ret = -EINVAL;
-               } else
-                       ret = put_user(wm8350_wdt_cfgs[i].time, p);
-
-       }
-
-       return ret;
-}
-
-static const struct file_operations wm8350_wdt_fops = {
+static const struct watchdog_ops wm8350_wdt_ops = {
        .owner = THIS_MODULE,
-       .llseek = no_llseek,
-       .write = wm8350_wdt_write,
-       .unlocked_ioctl = wm8350_wdt_ioctl,
-       .open = wm8350_wdt_open,
-       .release = wm8350_wdt_release,
+       .start = wm8350_wdt_start,
+       .stop = wm8350_wdt_stop,
+       .ping = wm8350_wdt_ping,
+       .set_timeout = wm8350_wdt_set_timeout,
 };
 
-static struct miscdevice wm8350_wdt_miscdev = {
-       .minor = WATCHDOG_MINOR,
-       .name = "watchdog",
-       .fops = &wm8350_wdt_fops,
+static struct watchdog_device wm8350_wdt = {
+       .info = &wm8350_wdt_info,
+       .ops = &wm8350_wdt_ops,
+       .timeout = 4,
+       .min_timeout = 1,
+       .max_timeout = 4,
 };
 
 static int __devinit wm8350_wdt_probe(struct platform_device *pdev)
@@ -288,18 +149,18 @@ static int __devinit wm8350_wdt_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
-       /* Default to 4s timeout */
-       wm8350_wdt_set_timeout(wm8350, 0x05);
+       watchdog_set_nowayout(&wm8350_wdt, nowayout);
+       watchdog_set_drvdata(&wm8350_wdt, wm8350);
 
-       wm8350_wdt_miscdev.parent = &pdev->dev;
+       /* Default to 4s timeout */
+       wm8350_wdt_set_timeout(&wm8350_wdt, 4);
 
-       return misc_register(&wm8350_wdt_miscdev);
+       return watchdog_register_device(&wm8350_wdt);
 }
 
 static int __devexit wm8350_wdt_remove(struct platform_device *pdev)
 {
-       misc_deregister(&wm8350_wdt_miscdev);
-
+       watchdog_unregister_device(&wm8350_wdt);
        return 0;
 }
 
index 49bd9d3..e4a25b5 100644 (file)
@@ -9,9 +9,10 @@
  *     2 of the License, or (at your option) any later version.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define DRV_NAME       "wdt"
 #define DRV_VERSION    "0.01"
-#define PFX            DRV_NAME ": "
 
 #include <linux/bug.h>
 #include <linux/errno.h>
@@ -131,16 +132,17 @@ static int xen_wdt_open(struct inode *inode, struct file *file)
 
 static int xen_wdt_release(struct inode *inode, struct file *file)
 {
+       int err = 0;
+
        if (expect_release)
-               xen_wdt_stop();
+               err = xen_wdt_stop();
        else {
-               printk(KERN_CRIT PFX
-                      "unexpected close, not stopping watchdog!\n");
+               pr_crit("unexpected close, not stopping watchdog!\n");
                xen_wdt_kick();
        }
-       is_active = false;
+       is_active = err;
        expect_release = false;
-       return 0;
+       return err;
 }
 
 static ssize_t xen_wdt_write(struct file *file, const char __user *data,
@@ -251,30 +253,27 @@ static int __devinit xen_wdt_probe(struct platform_device *dev)
        case -EINVAL:
                if (!timeout) {
                        timeout = WATCHDOG_TIMEOUT;
-                       printk(KERN_INFO PFX
-                              "timeout value invalid, using %d\n", timeout);
+                       pr_info("timeout value invalid, using %d\n", timeout);
                }
 
                ret = misc_register(&xen_wdt_miscdev);
                if (ret) {
-                       printk(KERN_ERR PFX
-                              "cannot register miscdev on minor=%d (%d)\n",
+                       pr_err("cannot register miscdev on minor=%d (%d)\n",
                               WATCHDOG_MINOR, ret);
                        break;
                }
 
-               printk(KERN_INFO PFX
-                      "initialized (timeout=%ds, nowayout=%d)\n",
-                      timeout, nowayout);
+               pr_info("initialized (timeout=%ds, nowayout=%d)\n",
+                       timeout, nowayout);
                break;
 
        case -ENOSYS:
-               printk(KERN_INFO PFX "not supported\n");
+               pr_info("not supported\n");
                ret = -ENODEV;
                break;
 
        default:
-               printk(KERN_INFO PFX "bogus return value %d\n", ret);
+               pr_info("bogus return value %d\n", ret);
                break;
        }
 
@@ -299,11 +298,18 @@ static void xen_wdt_shutdown(struct platform_device *dev)
 
 static int xen_wdt_suspend(struct platform_device *dev, pm_message_t state)
 {
-       return xen_wdt_stop();
+       typeof(wdt.id) id = wdt.id;
+       int rc = xen_wdt_stop();
+
+       wdt.id = id;
+       return rc;
 }
 
 static int xen_wdt_resume(struct platform_device *dev)
 {
+       if (!wdt.id)
+               return 0;
+       wdt.id = 0;
        return xen_wdt_start();
 }
 
@@ -326,7 +332,7 @@ static int __init xen_wdt_init_module(void)
        if (!xen_domain())
                return -ENODEV;
 
-       printk(KERN_INFO PFX "Xen WatchDog Timer Driver v%s\n", DRV_VERSION);
+       pr_info("Xen WatchDog Timer Driver v%s\n", DRV_VERSION);
 
        err = platform_driver_register(&xen_wdt_driver);
        if (err)
@@ -346,7 +352,7 @@ static void __exit xen_wdt_cleanup_module(void)
 {
        platform_device_unregister(platform_device);
        platform_driver_unregister(&xen_wdt_driver);
-       printk(KERN_INFO PFX "module unloaded\n");
+       pr_info("module unloaded\n");
 }
 
 module_init(xen_wdt_init_module);
index 4d5e6d2..2eb12f1 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/coredump.h>
 #include <linux/slab.h>
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/cacheflush.h>
 #include <asm/a.out-core.h>
index 504b6ee..7d7ff20 100644 (file)
@@ -35,6 +35,7 @@
 #include <asm/uaccess.h>
 #include <asm/param.h>
 #include <asm/page.h>
+#include <asm/exec.h>
 
 static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs);
 static int load_elf_library(struct file *);
index c64bf5e..9bd5612 100644 (file)
@@ -39,6 +39,7 @@
 #include <asm/uaccess.h>
 #include <asm/param.h>
 #include <asm/pgalloc.h>
+#include <asm/exec.h>
 
 typedef char *elf_caddr_t;
 
index 5979027..024d20e 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/syscalls.h>
 
 #include <asm/byteorder.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/unaligned.h>
 #include <asm/cacheflush.h>
index 05156c1..2870597 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/vfs.h>
 #include <linux/slab.h>
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 
 #include <linux/fs.h>
index 8f616e0..761d5b3 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/mutex.h>
 #include <linux/device.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/poll.h>
 #include <asm/uaccess.h>
 
index 9727e0c..0c68fd3 100644 (file)
@@ -14,7 +14,6 @@
  * improvements to the Coda project. Contact Peter Braam <coda@cs.cmu.edu>.
  */
 
-#include <asm/system.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/types.h>
index 629e9ed..739b098 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/mutex.h>
 #include <linux/anon_inodes.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/mman.h>
 #include <linux/atomic.h>
index 23559c2..c8b63d1 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -59,6 +59,7 @@
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
 #include <asm/tlb.h>
+#include <asm/exec.h>
 
 #include <trace/events/task.h>
 #include "internal.h"
index 17f557f..806525a 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/blkdev.h>
 #include <linux/bitops.h>
 #include <trace/events/jbd2.h>
-#include <asm/system.h>
 
 /*
  * Default IO end handler for temporary BJ_IO buffer_heads.
index 98ed6db..1afb701 100644 (file)
@@ -50,7 +50,6 @@
 
 #include <asm/uaccess.h>
 #include <asm/page.h>
-#include <asm/system.h>
 
 EXPORT_SYMBOL(jbd2_journal_extend);
 EXPORT_SYMBOL(jbd2_journal_stop);
index 64a3264..3ff5fcc 100644 (file)
@@ -7,7 +7,6 @@
  */
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 
 #include <linux/time.h>
 #include <linux/kernel.h>
index 49df0e7..87484fb 100644 (file)
@@ -11,7 +11,6 @@
 
 #include <linux/module.h>
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/byteorder.h>
 
index e5d71b2..be20a7e 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/memcontrol.h>
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 
 #include "ncp_fs.h"
 
index 4a108a0..da7b5e4 100644 (file)
@@ -43,7 +43,6 @@
 #include <linux/nsproxy.h>
 #include <linux/pid_namespace.h>
 
-#include <asm/system.h>
 
 #include "nfs4_fs.h"
 #include "callback.h"
index 9c7f66a..481be7f 100644 (file)
@@ -51,7 +51,6 @@
 #include <linux/nfs_page.h>
 #include <linux/sunrpc/clnt.h>
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <linux/atomic.h>
 
index 4fdaaa6..aa9b709 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/swap.h>
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 
 #include "delegation.h"
 #include "internal.h"
index 801d6d8..4ca6f5c 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/namei.h>
 #include <linux/security.h>
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 
 #include "nfs4_fs.h"
index 7bb4d13..e8bbfa5 100644 (file)
@@ -41,7 +41,6 @@
 #include <linux/freezer.h>
 #include <linux/crc32.h>
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 
 #include "nfs4_fs.h"
index cc1f758..9a0e8ef 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/nfs_page.h>
 #include <linux/module.h>
 
-#include <asm/system.h>
 #include "pnfs.h"
 
 #include "nfs4_fs.h"
index ccc4cdb..37412f7 100644 (file)
@@ -55,7 +55,6 @@
 #include <linux/nsproxy.h>
 #include <linux/rcupdate.h>
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 
 #include "nfs4_fs.h"
index 8461a7b..205c922 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/slab.h>
 #include <linux/mount.h>
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 
 #include "internal.h"
index cf9f4de..b1a0857 100644 (file)
@@ -51,7 +51,6 @@
 #include <linux/uaccess.h>
 #include <linux/slab.h>
 
-#include <asm/system.h>
 
 /* gets a struct reiserfs_journal_list * from a list head */
 #define JOURNAL_LIST_ENTRY(h) (list_entry((h), struct reiserfs_journal_list, \
index 9094e1d..7cdd395 100644 (file)
@@ -26,7 +26,6 @@
  */
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 
 #include <linux/errno.h>
 #include <linux/fs.h>
index f636f6b..ac8e279 100644 (file)
@@ -73,7 +73,6 @@
 #include <stdarg.h>
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 
 #include <linux/errno.h>
 #include <linux/fs.h>
index ce84ffd..0f0df27 100644 (file)
@@ -35,6 +35,7 @@
 #include "xfs_error.h"
 #include "xfs_trace.h"
 
+struct workqueue_struct *xfs_alloc_wq;
 
 #define XFS_ABSDIFF(a,b)       (((a) <= (b)) ? ((b) - (a)) : ((a) - (b)))
 
@@ -68,7 +69,7 @@ xfs_alloc_lookup_eq(
  * Lookup the first record greater than or equal to [bno, len]
  * in the btree given by cur.
  */
-STATIC int                             /* error */
+int                            /* error */
 xfs_alloc_lookup_ge(
        struct xfs_btree_cur    *cur,   /* btree cursor */
        xfs_agblock_t           bno,    /* starting block of extent */
@@ -2207,7 +2208,7 @@ xfs_alloc_read_agf(
  * group or loop over the allocation groups to find the result.
  */
 int                            /* error */
-xfs_alloc_vextent(
+__xfs_alloc_vextent(
        xfs_alloc_arg_t *args)  /* allocation argument structure */
 {
        xfs_agblock_t   agsize; /* allocation group size */
@@ -2417,6 +2418,37 @@ error0:
        return error;
 }
 
+static void
+xfs_alloc_vextent_worker(
+       struct work_struct      *work)
+{
+       struct xfs_alloc_arg    *args = container_of(work,
+                                               struct xfs_alloc_arg, work);
+       unsigned long           pflags;
+
+       /* we are in a transaction context here */
+       current_set_flags_nested(&pflags, PF_FSTRANS);
+
+       args->result = __xfs_alloc_vextent(args);
+       complete(args->done);
+
+       current_restore_flags_nested(&pflags, PF_FSTRANS);
+}
+
+
+int                            /* error */
+xfs_alloc_vextent(
+       xfs_alloc_arg_t *args)  /* allocation argument structure */
+{
+       DECLARE_COMPLETION_ONSTACK(done);
+
+       args->done = &done;
+       INIT_WORK(&args->work, xfs_alloc_vextent_worker);
+       queue_work(xfs_alloc_wq, &args->work);
+       wait_for_completion(&done);
+       return args->result;
+}
+
 /*
  * Free an extent.
  * Just break up the extent address and hand off to xfs_free_ag_extent
index 2f52b92..3a7e7d8 100644 (file)
@@ -25,6 +25,8 @@ struct xfs_perag;
 struct xfs_trans;
 struct xfs_busy_extent;
 
+extern struct workqueue_struct *xfs_alloc_wq;
+
 /*
  * Freespace allocation types.  Argument to xfs_alloc_[v]extent.
  */
@@ -119,6 +121,9 @@ typedef struct xfs_alloc_arg {
        char            isfl;           /* set if is freelist blocks - !acctg */
        char            userdata;       /* set if this is user data */
        xfs_fsblock_t   firstblock;     /* io first block allocated */
+       struct completion *done;
+       struct work_struct work;
+       int             result;
 } xfs_alloc_arg_t;
 
 /*
@@ -243,6 +248,13 @@ xfs_alloc_lookup_le(
        xfs_extlen_t            len,    /* length of extent */
        int                     *stat); /* success/failure */
 
+int                            /* error */
+xfs_alloc_lookup_ge(
+       struct xfs_btree_cur    *cur,   /* btree cursor */
+       xfs_agblock_t           bno,    /* starting block of extent */
+       xfs_extlen_t            len,    /* length of extent */
+       int                     *stat); /* success/failure */
+
 int                                    /* error */
 xfs_alloc_get_rec(
        struct xfs_btree_cur    *cur,   /* btree cursor */
index 08b9ac6..65d61b9 100644 (file)
@@ -853,6 +853,8 @@ xfs_attr_shortform_addname(xfs_da_args_t *args)
 {
        int newsize, forkoff, retval;
 
+       trace_xfs_attr_sf_addname(args);
+
        retval = xfs_attr_shortform_lookup(args);
        if ((args->flags & ATTR_REPLACE) && (retval == ENOATTR)) {
                return(retval);
@@ -896,6 +898,8 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
        xfs_dabuf_t *bp;
        int retval, error, committed, forkoff;
 
+       trace_xfs_attr_leaf_addname(args);
+
        /*
         * Read the (only) block in the attribute list in.
         */
@@ -920,6 +924,9 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
                        xfs_da_brelse(args->trans, bp);
                        return(retval);
                }
+
+               trace_xfs_attr_leaf_replace(args);
+
                args->op_flags |= XFS_DA_OP_RENAME;     /* an atomic rename */
                args->blkno2 = args->blkno;             /* set 2nd entry info*/
                args->index2 = args->index;
@@ -1090,6 +1097,8 @@ xfs_attr_leaf_removename(xfs_da_args_t *args)
        xfs_dabuf_t *bp;
        int error, committed, forkoff;
 
+       trace_xfs_attr_leaf_removename(args);
+
        /*
         * Remove the attribute.
         */
@@ -1223,6 +1232,8 @@ xfs_attr_node_addname(xfs_da_args_t *args)
        xfs_mount_t *mp;
        int committed, retval, error;
 
+       trace_xfs_attr_node_addname(args);
+
        /*
         * Fill in bucket of arguments/results/context to carry around.
         */
@@ -1249,6 +1260,9 @@ restart:
        } else if (retval == EEXIST) {
                if (args->flags & ATTR_CREATE)
                        goto out;
+
+               trace_xfs_attr_node_replace(args);
+
                args->op_flags |= XFS_DA_OP_RENAME;     /* atomic rename op */
                args->blkno2 = args->blkno;             /* set 2nd entry info*/
                args->index2 = args->index;
@@ -1480,6 +1494,8 @@ xfs_attr_node_removename(xfs_da_args_t *args)
        xfs_dabuf_t *bp;
        int retval, error, committed, forkoff;
 
+       trace_xfs_attr_node_removename(args);
+
        /*
         * Tie a string around our finger to remind us where we are.
         */
index d25eafd..76d93dc 100644 (file)
@@ -235,6 +235,8 @@ xfs_attr_shortform_create(xfs_da_args_t *args)
        xfs_inode_t *dp;
        xfs_ifork_t *ifp;
 
+       trace_xfs_attr_sf_create(args);
+
        dp = args->dp;
        ASSERT(dp != NULL);
        ifp = dp->i_afp;
@@ -268,6 +270,8 @@ xfs_attr_shortform_add(xfs_da_args_t *args, int forkoff)
        xfs_inode_t *dp;
        xfs_ifork_t *ifp;
 
+       trace_xfs_attr_sf_add(args);
+
        dp = args->dp;
        mp = dp->i_mount;
        dp->i_d.di_forkoff = forkoff;
@@ -337,6 +341,8 @@ xfs_attr_shortform_remove(xfs_da_args_t *args)
        xfs_mount_t *mp;
        xfs_inode_t *dp;
 
+       trace_xfs_attr_sf_remove(args);
+
        dp = args->dp;
        mp = dp->i_mount;
        base = sizeof(xfs_attr_sf_hdr_t);
@@ -405,6 +411,8 @@ xfs_attr_shortform_lookup(xfs_da_args_t *args)
        int i;
        xfs_ifork_t *ifp;
 
+       trace_xfs_attr_sf_lookup(args);
+
        ifp = args->dp->i_afp;
        ASSERT(ifp->if_flags & XFS_IFINLINE);
        sf = (xfs_attr_shortform_t *)ifp->if_u1.if_data;
@@ -476,6 +484,8 @@ xfs_attr_shortform_to_leaf(xfs_da_args_t *args)
        xfs_dabuf_t *bp;
        xfs_ifork_t *ifp;
 
+       trace_xfs_attr_sf_to_leaf(args);
+
        dp = args->dp;
        ifp = dp->i_afp;
        sf = (xfs_attr_shortform_t *)ifp->if_u1.if_data;
@@ -775,6 +785,8 @@ xfs_attr_leaf_to_shortform(xfs_dabuf_t *bp, xfs_da_args_t *args, int forkoff)
        char *tmpbuffer;
        int error, i;
 
+       trace_xfs_attr_leaf_to_sf(args);
+
        dp = args->dp;
        tmpbuffer = kmem_alloc(XFS_LBSIZE(dp->i_mount), KM_SLEEP);
        ASSERT(tmpbuffer != NULL);
@@ -848,6 +860,8 @@ xfs_attr_leaf_to_node(xfs_da_args_t *args)
        xfs_dablk_t blkno;
        int error;
 
+       trace_xfs_attr_leaf_to_node(args);
+
        dp = args->dp;
        bp1 = bp2 = NULL;
        error = xfs_da_grow_inode(args, &blkno);
@@ -911,6 +925,8 @@ xfs_attr_leaf_create(xfs_da_args_t *args, xfs_dablk_t blkno, xfs_dabuf_t **bpp)
        xfs_dabuf_t *bp;
        int error;
 
+       trace_xfs_attr_leaf_create(args);
+
        dp = args->dp;
        ASSERT(dp != NULL);
        error = xfs_da_get_buf(args->trans, args->dp, blkno, -1, &bp,
@@ -948,6 +964,8 @@ xfs_attr_leaf_split(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk,
        xfs_dablk_t blkno;
        int error;
 
+       trace_xfs_attr_leaf_split(state->args);
+
        /*
         * Allocate space for a new leaf node.
         */
@@ -977,10 +995,13 @@ xfs_attr_leaf_split(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk,
         *
         * Insert the "new" entry in the correct block.
         */
-       if (state->inleaf)
+       if (state->inleaf) {
+               trace_xfs_attr_leaf_add_old(state->args);
                error = xfs_attr_leaf_add(oldblk->bp, state->args);
-       else
+       } else {
+               trace_xfs_attr_leaf_add_new(state->args);
                error = xfs_attr_leaf_add(newblk->bp, state->args);
+       }
 
        /*
         * Update last hashval in each block since we added the name.
@@ -1001,6 +1022,8 @@ xfs_attr_leaf_add(xfs_dabuf_t *bp, xfs_da_args_t *args)
        xfs_attr_leaf_map_t *map;
        int tablesize, entsize, sum, tmp, i;
 
+       trace_xfs_attr_leaf_add(args);
+
        leaf = bp->data;
        ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
        ASSERT((args->index >= 0)
@@ -1128,8 +1151,6 @@ xfs_attr_leaf_add_work(xfs_dabuf_t *bp, xfs_da_args_t *args, int mapindex)
               (be32_to_cpu(entry->hashval) <= be32_to_cpu((entry+1)->hashval)));
 
        /*
-        * Copy the attribute name and value into the new space.
-        *
         * For "remote" attribute values, simply note that we need to
         * allocate space for the "remote" value.  We can't actually
         * allocate the extents in this transaction, and we can't decide
@@ -1265,6 +1286,8 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,
        ASSERT(leaf2->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
        args = state->args;
 
+       trace_xfs_attr_leaf_rebalance(args);
+
        /*
         * Check ordering of blocks, reverse if it makes things simpler.
         *
@@ -1810,6 +1833,8 @@ xfs_attr_leaf_unbalance(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk,
        xfs_mount_t *mp;
        char *tmpbuffer;
 
+       trace_xfs_attr_leaf_unbalance(state->args);
+
        /*
         * Set up environment.
         */
@@ -1919,6 +1944,8 @@ xfs_attr_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args)
        int probe, span;
        xfs_dahash_t hashval;
 
+       trace_xfs_attr_leaf_lookup(args);
+
        leaf = bp->data;
        ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
        ASSERT(be16_to_cpu(leaf->hdr.count)
@@ -2445,6 +2472,7 @@ xfs_attr_leaf_clearflag(xfs_da_args_t *args)
        char *name;
 #endif /* DEBUG */
 
+       trace_xfs_attr_leaf_clearflag(args);
        /*
         * Set up the operation.
         */
@@ -2509,6 +2537,8 @@ xfs_attr_leaf_setflag(xfs_da_args_t *args)
        xfs_dabuf_t *bp;
        int error;
 
+       trace_xfs_attr_leaf_setflag(args);
+
        /*
         * Set up the operation.
         */
@@ -2565,6 +2595,8 @@ xfs_attr_leaf_flipflags(xfs_da_args_t *args)
        char *name1, *name2;
 #endif /* DEBUG */
 
+       trace_xfs_attr_leaf_flipflags(args);
+
        /*
         * Read the block containing the "old" attr
         */
index 3548c6f..85e7e32 100644 (file)
@@ -5124,6 +5124,15 @@ xfs_bunmapi(
                cur->bc_private.b.flags = 0;
        } else
                cur = NULL;
+
+       if (isrt) {
+               /*
+                * Synchronize by locking the bitmap inode.
+                */
+               xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL);
+               xfs_trans_ijoin(tp, mp->m_rbmip, XFS_ILOCK_EXCL);
+       }
+
        extno = 0;
        while (bno != (xfs_fileoff_t)-1 && bno >= start && lastx >= 0 &&
               (nexts == 0 || extno < nexts)) {
index df7ffb0..5bf3be4 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/list.h>
 #include <linux/types.h>
 #include <linux/spinlock.h>
-#include <asm/system.h>
 #include <linux/mm.h>
 #include <linux/fs.h>
 #include <linux/buffer_head.h>
index 77c7425..7f1a6f5 100644 (file)
@@ -108,6 +108,8 @@ xfs_da_node_create(xfs_da_args_t *args, xfs_dablk_t blkno, int level,
        int error;
        xfs_trans_t *tp;
 
+       trace_xfs_da_node_create(args);
+
        tp = args->trans;
        error = xfs_da_get_buf(tp, args->dp, blkno, -1, &bp, whichfork);
        if (error)
@@ -140,6 +142,8 @@ xfs_da_split(xfs_da_state_t *state)
        xfs_dabuf_t *bp;
        int max, action, error, i;
 
+       trace_xfs_da_split(state->args);
+
        /*
         * Walk back up the tree splitting/inserting/adjusting as necessary.
         * If we need to insert and there isn't room, split the node, then
@@ -178,10 +182,12 @@ xfs_da_split(xfs_da_state_t *state)
                        state->extravalid = 1;
                        if (state->inleaf) {
                                state->extraafter = 0;  /* before newblk */
+                               trace_xfs_attr_leaf_split_before(state->args);
                                error = xfs_attr_leaf_split(state, oldblk,
                                                            &state->extrablk);
                        } else {
                                state->extraafter = 1;  /* after newblk */
+                               trace_xfs_attr_leaf_split_after(state->args);
                                error = xfs_attr_leaf_split(state, newblk,
                                                            &state->extrablk);
                        }
@@ -300,6 +306,8 @@ xfs_da_root_split(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,
        xfs_mount_t *mp;
        xfs_dir2_leaf_t *leaf;
 
+       trace_xfs_da_root_split(state->args);
+
        /*
         * Copy the existing (incorrect) block from the root node position
         * to a free space somewhere.
@@ -380,6 +388,8 @@ xfs_da_node_split(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk,
        int newcount, error;
        int useextra;
 
+       trace_xfs_da_node_split(state->args);
+
        node = oldblk->bp->data;
        ASSERT(node->hdr.info.magic == cpu_to_be16(XFS_DA_NODE_MAGIC));
 
@@ -466,6 +476,8 @@ xfs_da_node_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,
        int count, tmp;
        xfs_trans_t *tp;
 
+       trace_xfs_da_node_rebalance(state->args);
+
        node1 = blk1->bp->data;
        node2 = blk2->bp->data;
        /*
@@ -574,6 +586,8 @@ xfs_da_node_add(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk,
        xfs_da_node_entry_t *btree;
        int tmp;
 
+       trace_xfs_da_node_add(state->args);
+
        node = oldblk->bp->data;
        ASSERT(node->hdr.info.magic == cpu_to_be16(XFS_DA_NODE_MAGIC));
        ASSERT((oldblk->index >= 0) && (oldblk->index <= be16_to_cpu(node->hdr.count)));
@@ -619,6 +633,8 @@ xfs_da_join(xfs_da_state_t *state)
        xfs_da_state_blk_t *drop_blk, *save_blk;
        int action, error;
 
+       trace_xfs_da_join(state->args);
+
        action = 0;
        drop_blk = &state->path.blk[ state->path.active-1 ];
        save_blk = &state->altpath.blk[ state->path.active-1 ];
@@ -723,6 +739,8 @@ xfs_da_root_join(xfs_da_state_t *state, xfs_da_state_blk_t *root_blk)
        xfs_dabuf_t *bp;
        int error;
 
+       trace_xfs_da_root_join(state->args);
+
        args = state->args;
        ASSERT(args != NULL);
        ASSERT(root_blk->magic == XFS_DA_NODE_MAGIC);
@@ -941,6 +959,8 @@ xfs_da_node_remove(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk)
        xfs_da_node_entry_t *btree;
        int tmp;
 
+       trace_xfs_da_node_remove(state->args);
+
        node = drop_blk->bp->data;
        ASSERT(drop_blk->index < be16_to_cpu(node->hdr.count));
        ASSERT(drop_blk->index >= 0);
@@ -984,6 +1004,8 @@ xfs_da_node_unbalance(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk,
        int tmp;
        xfs_trans_t *tp;
 
+       trace_xfs_da_node_unbalance(state->args);
+
        drop_node = drop_blk->bp->data;
        save_node = save_blk->bp->data;
        ASSERT(drop_node->hdr.info.magic == cpu_to_be16(XFS_DA_NODE_MAGIC));
@@ -1230,6 +1252,7 @@ xfs_da_blk_link(xfs_da_state_t *state, xfs_da_state_blk_t *old_blk,
                /*
                 * Link new block in before existing block.
                 */
+               trace_xfs_da_link_before(args);
                new_info->forw = cpu_to_be32(old_blk->blkno);
                new_info->back = old_info->back;
                if (old_info->back) {
@@ -1251,6 +1274,7 @@ xfs_da_blk_link(xfs_da_state_t *state, xfs_da_state_blk_t *old_blk,
                /*
                 * Link new block in after existing block.
                 */
+               trace_xfs_da_link_after(args);
                new_info->forw = old_info->forw;
                new_info->back = cpu_to_be32(old_blk->blkno);
                if (old_info->forw) {
@@ -1348,6 +1372,7 @@ xfs_da_blk_unlink(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk,
         * Unlink the leaf block from the doubly linked chain of leaves.
         */
        if (be32_to_cpu(save_info->back) == drop_blk->blkno) {
+               trace_xfs_da_unlink_back(args);
                save_info->back = drop_info->back;
                if (drop_info->back) {
                        error = xfs_da_read_buf(args->trans, args->dp,
@@ -1365,6 +1390,7 @@ xfs_da_blk_unlink(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk,
                        xfs_da_buf_done(bp);
                }
        } else {
+               trace_xfs_da_unlink_forward(args);
                save_info->forw = drop_info->forw;
                if (drop_info->forw) {
                        error = xfs_da_read_buf(args->trans, args->dp,
@@ -1652,6 +1678,8 @@ xfs_da_grow_inode(
        int                     count;
        int                     error;
 
+       trace_xfs_da_grow_inode(args);
+
        if (args->whichfork == XFS_DATA_FORK) {
                bno = args->dp->i_mount->m_dirleafblk;
                count = args->dp->i_mount->m_dirblkfsbs;
@@ -1690,6 +1718,8 @@ xfs_da_swap_lastblock(xfs_da_args_t *args, xfs_dablk_t *dead_blknop,
        xfs_dir2_leaf_t *dead_leaf2;
        xfs_dahash_t dead_hash;
 
+       trace_xfs_da_swap_lastblock(args);
+
        dead_buf = *dead_bufp;
        dead_blkno = *dead_blknop;
        tp = args->trans;
@@ -1878,6 +1908,8 @@ xfs_da_shrink_inode(xfs_da_args_t *args, xfs_dablk_t dead_blkno,
        xfs_trans_t *tp;
        xfs_mount_t *mp;
 
+       trace_xfs_da_shrink_inode(args);
+
        dp = args->dp;
        w = args->whichfork;
        tp = args->trans;
index 286a051..1ad3a4b 100644 (file)
@@ -37,9 +37,9 @@ STATIC int
 xfs_trim_extents(
        struct xfs_mount        *mp,
        xfs_agnumber_t          agno,
-       xfs_fsblock_t           start,
-       xfs_fsblock_t           end,
-       xfs_fsblock_t           minlen,
+       xfs_daddr_t             start,
+       xfs_daddr_t             end,
+       xfs_daddr_t             minlen,
        __uint64_t              *blocks_trimmed)
 {
        struct block_device     *bdev = mp->m_ddev_targp->bt_bdev;
@@ -67,7 +67,7 @@ xfs_trim_extents(
        /*
         * Look up the longest btree in the AGF and start with it.
         */
-       error = xfs_alloc_lookup_le(cur, 0,
+       error = xfs_alloc_lookup_ge(cur, 0,
                            be32_to_cpu(XFS_BUF_TO_AGF(agbp)->agf_longest), &i);
        if (error)
                goto out_del_cursor;
@@ -77,8 +77,10 @@ xfs_trim_extents(
         * enough to be worth discarding.
         */
        while (i) {
-               xfs_agblock_t fbno;
-               xfs_extlen_t flen;
+               xfs_agblock_t   fbno;
+               xfs_extlen_t    flen;
+               xfs_daddr_t     dbno;
+               xfs_extlen_t    dlen;
 
                error = xfs_alloc_get_rec(cur, &fbno, &flen, &i);
                if (error)
@@ -87,9 +89,17 @@ xfs_trim_extents(
                ASSERT(flen <= be32_to_cpu(XFS_BUF_TO_AGF(agbp)->agf_longest));
 
                /*
+                * use daddr format for all range/len calculations as that is
+                * the format the range/len variables are supplied in by
+                * userspace.
+                */
+               dbno = XFS_AGB_TO_DADDR(mp, agno, fbno);
+               dlen = XFS_FSB_TO_BB(mp, flen);
+
+               /*
                 * Too small?  Give up.
                 */
-               if (flen < minlen) {
+               if (dlen < minlen) {
                        trace_xfs_discard_toosmall(mp, agno, fbno, flen);
                        goto out_del_cursor;
                }
@@ -99,8 +109,7 @@ xfs_trim_extents(
                 * supposed to discard skip it.  Do not bother to trim
                 * down partially overlapping ranges for now.
                 */
-               if (XFS_AGB_TO_FSB(mp, agno, fbno) + flen < start ||
-                   XFS_AGB_TO_FSB(mp, agno, fbno) > end) {
+               if (dbno + dlen < start || dbno > end) {
                        trace_xfs_discard_exclude(mp, agno, fbno, flen);
                        goto next_extent;
                }
@@ -115,10 +124,7 @@ xfs_trim_extents(
                }
 
                trace_xfs_discard_extent(mp, agno, fbno, flen);
-               error = -blkdev_issue_discard(bdev,
-                               XFS_AGB_TO_DADDR(mp, agno, fbno),
-                               XFS_FSB_TO_BB(mp, flen),
-                               GFP_NOFS, 0);
+               error = -blkdev_issue_discard(bdev, dbno, dlen, GFP_NOFS, 0);
                if (error)
                        goto out_del_cursor;
                *blocks_trimmed += flen;
@@ -137,6 +143,15 @@ out_put_perag:
        return error;
 }
 
+/*
+ * trim a range of the filesystem.
+ *
+ * Note: the parameters passed from userspace are byte ranges into the
+ * filesystem which does not match to the format we use for filesystem block
+ * addressing. FSB addressing is sparse (AGNO|AGBNO), while the incoming format
+ * is a linear address range. Hence we need to use DADDR based conversions and
+ * comparisons for determining the correct offset and regions to trim.
+ */
 int
 xfs_ioc_trim(
        struct xfs_mount                *mp,
@@ -145,7 +160,7 @@ xfs_ioc_trim(
        struct request_queue    *q = mp->m_ddev_targp->bt_bdev->bd_disk->queue;
        unsigned int            granularity = q->limits.discard_granularity;
        struct fstrim_range     range;
-       xfs_fsblock_t           start, end, minlen;
+       xfs_daddr_t             start, end, minlen;
        xfs_agnumber_t          start_agno, end_agno, agno;
        __uint64_t              blocks_trimmed = 0;
        int                     error, last_error = 0;
@@ -159,22 +174,22 @@ xfs_ioc_trim(
 
        /*
         * Truncating down the len isn't actually quite correct, but using
-        * XFS_B_TO_FSB would mean we trivially get overflows for values
+        * BBTOB would mean we trivially get overflows for values
         * of ULLONG_MAX or slightly lower.  And ULLONG_MAX is the default
         * used by the fstrim application.  In the end it really doesn't
         * matter as trimming blocks is an advisory interface.
         */
-       start = XFS_B_TO_FSBT(mp, range.start);
-       end = start + XFS_B_TO_FSBT(mp, range.len) - 1;
-       minlen = XFS_B_TO_FSB(mp, max_t(u64, granularity, range.minlen));
+       start = BTOBB(range.start);
+       end = start + BTOBBT(range.len) - 1;
+       minlen = BTOBB(max_t(u64, granularity, range.minlen));
 
-       if (start >= mp->m_sb.sb_dblocks)
+       if (XFS_BB_TO_FSB(mp, start) >= mp->m_sb.sb_dblocks)
                return -XFS_ERROR(EINVAL);
-       if (end > mp->m_sb.sb_dblocks - 1)
-               end = mp->m_sb.sb_dblocks - 1;
+       if (end > XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks) - 1)
+               end = XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks)- 1;
 
-       start_agno = XFS_FSB_TO_AGNO(mp, start);
-       end_agno = XFS_FSB_TO_AGNO(mp, end);
+       start_agno = xfs_daddr_to_agno(mp, start);
+       end_agno = xfs_daddr_to_agno(mp, end);
 
        for (agno = start_agno; agno <= end_agno; agno++) {
                error = -xfs_trim_extents(mp, agno, start, end, minlen,
index 4be16a0..1155208 100644 (file)
@@ -1065,7 +1065,7 @@ out:
        return -ENOMEM;
 }
 
-void __exit
+void
 xfs_qm_exit(void)
 {
        kmem_zone_destroy(xfs_qm_dqtrxzone);
index a98cb45..bcc6c24 100644 (file)
@@ -289,7 +289,7 @@ xfs_iget_cache_hit(
        if (lock_flags != 0)
                xfs_ilock(ip, lock_flags);
 
-       xfs_iflags_clear(ip, XFS_ISTALE);
+       xfs_iflags_clear(ip, XFS_ISTALE | XFS_IDONTCACHE);
        XFS_STATS_INC(xs_ig_found);
 
        return 0;
@@ -314,6 +314,7 @@ xfs_iget_cache_miss(
        struct xfs_inode        *ip;
        int                     error;
        xfs_agino_t             agino = XFS_INO_TO_AGINO(mp, ino);
+       int                     iflags;
 
        ip = xfs_inode_alloc(mp, ino);
        if (!ip)
@@ -358,8 +359,11 @@ xfs_iget_cache_miss(
         * memory barrier that ensures this detection works correctly at lookup
         * time.
         */
+       iflags = XFS_INEW;
+       if (flags & XFS_IGET_DONTCACHE)
+               iflags |= XFS_IDONTCACHE;
        ip->i_udquot = ip->i_gdquot = NULL;
-       xfs_iflags_set(ip, XFS_INEW);
+       xfs_iflags_set(ip, iflags);
 
        /* insert the new inode */
        spin_lock(&pag->pag_ici_lock);
index f123dbe..7fee338 100644 (file)
@@ -387,10 +387,11 @@ xfs_set_projid(struct xfs_inode *ip,
 #define XFS_IFLOCK             (1 << __XFS_IFLOCK_BIT)
 #define __XFS_IPINNED_BIT      8        /* wakeup key for zero pin count */
 #define XFS_IPINNED            (1 << __XFS_IPINNED_BIT)
+#define XFS_IDONTCACHE         (1 << 9) /* don't cache the inode long term */
 
 /*
  * Per-lifetime flags need to be reset when re-using a reclaimable inode during
- * inode lookup. Thi prevents unintended behaviour on the new inode from
+ * inode lookup. This prevents unintended behaviour on the new inode from
  * ocurring.
  */
 #define XFS_IRECLAIM_RESET_FLAGS       \
@@ -553,6 +554,7 @@ do { \
  */
 #define XFS_IGET_CREATE                0x1
 #define XFS_IGET_UNTRUSTED     0x2
+#define XFS_IGET_DONTCACHE     0x4
 
 int            xfs_inotobp(struct xfs_mount *, struct xfs_trans *,
                            xfs_ino_t, struct xfs_dinode **,
index f588320..91f8ff5 100644 (file)
@@ -209,6 +209,7 @@ xfs_open_by_handle(
        struct file             *filp;
        struct inode            *inode;
        struct dentry           *dentry;
+       fmode_t                 fmode;
 
        if (!capable(CAP_SYS_ADMIN))
                return -XFS_ERROR(EPERM);
@@ -228,26 +229,21 @@ xfs_open_by_handle(
        hreq->oflags |= O_LARGEFILE;
 #endif
 
-       /* Put open permission in namei format. */
        permflag = hreq->oflags;
-       if ((permflag+1) & O_ACCMODE)
-               permflag++;
-       if (permflag & O_TRUNC)
-               permflag |= 2;
-
+       fmode = OPEN_FMODE(permflag);
        if ((!(permflag & O_APPEND) || (permflag & O_TRUNC)) &&
-           (permflag & FMODE_WRITE) && IS_APPEND(inode)) {
+           (fmode & FMODE_WRITE) && IS_APPEND(inode)) {
                error = -XFS_ERROR(EPERM);
                goto out_dput;
        }
 
-       if ((permflag & FMODE_WRITE) && IS_IMMUTABLE(inode)) {
+       if ((fmode & FMODE_WRITE) && IS_IMMUTABLE(inode)) {
                error = -XFS_ERROR(EACCES);
                goto out_dput;
        }
 
        /* Can't write directories. */
-       if (S_ISDIR(inode->i_mode) && (permflag & FMODE_WRITE)) {
+       if (S_ISDIR(inode->i_mode) && (fmode & FMODE_WRITE)) {
                error = -XFS_ERROR(EISDIR);
                goto out_dput;
        }
index 9720c54..acc2bf2 100644 (file)
@@ -75,7 +75,8 @@ xfs_bulkstat_one_int(
                return XFS_ERROR(ENOMEM);
 
        error = xfs_iget(mp, NULL, ino,
-                        XFS_IGET_UNTRUSTED, XFS_ILOCK_SHARED, &ip);
+                        (XFS_IGET_DONTCACHE | XFS_IGET_UNTRUSTED),
+                        XFS_ILOCK_SHARED, &ip);
        if (error) {
                *stat = BULKSTAT_RV_NOTHING;
                goto out_free;
index 98a9cb5..6db1fef 100644 (file)
@@ -726,8 +726,9 @@ xfs_log_unmount_write(xfs_mount_t *mp)
                                .lv_iovecp = &reg,
                        };
 
-                       /* remove inited flag */
+                       /* remove inited flag, and account for space used */
                        tic->t_flags = 0;
+                       tic->t_curr_res -= sizeof(magic);
                        error = xlog_write(log, &vec, tic, &lsn,
                                           NULL, XLOG_UNMOUNT_TRANS);
                        /*
index 7c75c73..8ecad5b 100644 (file)
@@ -3161,37 +3161,26 @@ xlog_recover_process_iunlinks(
                         */
                        continue;
                }
+               /*
+                * Unlock the buffer so that it can be acquired in the normal
+                * course of the transaction to truncate and free each inode.
+                * Because we are not racing with anyone else here for the AGI
+                * buffer, we don't even need to hold it locked to read the
+                * initial unlinked bucket entries out of the buffer. We keep
+                * buffer reference though, so that it stays pinned in memory
+                * while we need the buffer.
+                */
                agi = XFS_BUF_TO_AGI(agibp);
+               xfs_buf_unlock(agibp);
 
                for (bucket = 0; bucket < XFS_AGI_UNLINKED_BUCKETS; bucket++) {
                        agino = be32_to_cpu(agi->agi_unlinked[bucket]);
                        while (agino != NULLAGINO) {
-                               /*
-                                * Release the agi buffer so that it can
-                                * be acquired in the normal course of the
-                                * transaction to truncate and free the inode.
-                                */
-                               xfs_buf_relse(agibp);
-
                                agino = xlog_recover_process_one_iunlink(mp,
                                                        agno, agino, bucket);
-
-                               /*
-                                * Reacquire the agibuffer and continue around
-                                * the loop. This should never fail as we know
-                                * the buffer was good earlier on.
-                                */
-                               error = xfs_read_agi(mp, NULL, agno, &agibp);
-                               ASSERT(error == 0);
-                               agi = XFS_BUF_TO_AGI(agibp);
                        }
                }
-
-               /*
-                * Release the buffer for the current agi so we can
-                * go on to the next one.
-                */
-               xfs_buf_relse(agibp);
+               xfs_buf_rele(agibp);
        }
 
        mp->m_dmevmask = mp_dmevmask;
index 87323f1..ca4f315 100644 (file)
@@ -183,6 +183,7 @@ error_cancel:
                oblocks = map.br_startoff + map.br_blockcount;
        }
        return 0;
+
 error:
        return error;
 }
@@ -2139,11 +2140,9 @@ xfs_rtfree_extent(
        xfs_buf_t       *sumbp;         /* summary file block buffer */
 
        mp = tp->t_mountp;
-       /*
-        * Synchronize by locking the bitmap inode.
-        */
-       xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL);
-       xfs_trans_ijoin(tp, mp->m_rbmip, XFS_ILOCK_EXCL);
+
+       ASSERT(mp->m_rbmip->i_itemp != NULL);
+       ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL));
 
 #if defined(__KERNEL__) && defined(DEBUG)
        /*
index 912442c..dab9a5f 100644 (file)
@@ -950,6 +950,22 @@ xfs_fs_evict_inode(
        xfs_inactive(ip);
 }
 
+/*
+ * We do an unlocked check for XFS_IDONTCACHE here because we are already
+ * serialised against cache hits here via the inode->i_lock and igrab() in
+ * xfs_iget_cache_hit(). Hence a lookup that might clear this flag will not be
+ * racing with us, and it avoids needing to grab a spinlock here for every inode
+ * we drop the final reference on.
+ */
+STATIC int
+xfs_fs_drop_inode(
+       struct inode            *inode)
+{
+       struct xfs_inode        *ip = XFS_I(inode);
+
+       return generic_drop_inode(inode) || (ip->i_flags & XFS_IDONTCACHE);
+}
+
 STATIC void
 xfs_free_fsname(
        struct xfs_mount        *mp)
@@ -1433,6 +1449,7 @@ static const struct super_operations xfs_super_operations = {
        .destroy_inode          = xfs_fs_destroy_inode,
        .dirty_inode            = xfs_fs_dirty_inode,
        .evict_inode            = xfs_fs_evict_inode,
+       .drop_inode             = xfs_fs_drop_inode,
        .put_super              = xfs_fs_put_super,
        .sync_fs                = xfs_fs_sync_fs,
        .freeze_fs              = xfs_fs_freeze,
@@ -1606,12 +1623,28 @@ xfs_init_workqueues(void)
        xfs_syncd_wq = alloc_workqueue("xfssyncd", WQ_NON_REENTRANT, 0);
        if (!xfs_syncd_wq)
                return -ENOMEM;
+
+       /*
+        * The allocation workqueue can be used in memory reclaim situations
+        * (writepage path), and parallelism is only limited by the number of
+        * AGs in all the filesystems mounted. Hence use the default large
+        * max_active value for this workqueue.
+        */
+       xfs_alloc_wq = alloc_workqueue("xfsalloc", WQ_MEM_RECLAIM, 0);
+       if (!xfs_alloc_wq)
+               goto out_destroy_syncd;
+
        return 0;
+
+out_destroy_syncd:
+       destroy_workqueue(xfs_syncd_wq);
+       return -ENOMEM;
 }
 
 STATIC void
 xfs_destroy_workqueues(void)
 {
+       destroy_workqueue(xfs_alloc_wq);
        destroy_workqueue(xfs_syncd_wq);
 }
 
index 75eb54a..06838c4 100644 (file)
@@ -627,16 +627,19 @@ DECLARE_EVENT_CLASS(xfs_namespace_class,
        TP_STRUCT__entry(
                __field(dev_t, dev)
                __field(xfs_ino_t, dp_ino)
+               __field(int, namelen)
                __dynamic_array(char, name, name->len)
        ),
        TP_fast_assign(
                __entry->dev = VFS_I(dp)->i_sb->s_dev;
                __entry->dp_ino = dp->i_ino;
+               __entry->namelen = name->len;
                memcpy(__get_str(name), name->name, name->len);
        ),
-       TP_printk("dev %d:%d dp ino 0x%llx name %s",
+       TP_printk("dev %d:%d dp ino 0x%llx name %.*s",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  __entry->dp_ino,
+                 __entry->namelen,
                  __get_str(name))
 )
 
@@ -658,6 +661,8 @@ TRACE_EVENT(xfs_rename,
                __field(dev_t, dev)
                __field(xfs_ino_t, src_dp_ino)
                __field(xfs_ino_t, target_dp_ino)
+               __field(int, src_namelen)
+               __field(int, target_namelen)
                __dynamic_array(char, src_name, src_name->len)
                __dynamic_array(char, target_name, target_name->len)
        ),
@@ -665,15 +670,20 @@ TRACE_EVENT(xfs_rename,
                __entry->dev = VFS_I(src_dp)->i_sb->s_dev;
                __entry->src_dp_ino = src_dp->i_ino;
                __entry->target_dp_ino = target_dp->i_ino;
+               __entry->src_namelen = src_name->len;
+               __entry->target_namelen = target_name->len;
                memcpy(__get_str(src_name), src_name->name, src_name->len);
-               memcpy(__get_str(target_name), target_name->name, target_name->len);
+               memcpy(__get_str(target_name), target_name->name,
+                       target_name->len);
        ),
        TP_printk("dev %d:%d src dp ino 0x%llx target dp ino 0x%llx"
-                 " src name %s target name %s",
+                 " src name %.*s target name %.*s",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  __entry->src_dp_ino,
                  __entry->target_dp_ino,
+                 __entry->src_namelen,
                  __get_str(src_name),
+                 __entry->target_namelen,
                  __get_str(target_name))
 )
 
@@ -1408,7 +1418,7 @@ DEFINE_ALLOC_EVENT(xfs_alloc_vextent_noagbp);
 DEFINE_ALLOC_EVENT(xfs_alloc_vextent_loopfailed);
 DEFINE_ALLOC_EVENT(xfs_alloc_vextent_allfailed);
 
-DECLARE_EVENT_CLASS(xfs_dir2_class,
+DECLARE_EVENT_CLASS(xfs_da_class,
        TP_PROTO(struct xfs_da_args *args),
        TP_ARGS(args),
        TP_STRUCT__entry(
@@ -1443,7 +1453,7 @@ DECLARE_EVENT_CLASS(xfs_dir2_class,
 )
 
 #define DEFINE_DIR2_EVENT(name) \
-DEFINE_EVENT(xfs_dir2_class, name, \
+DEFINE_EVENT(xfs_da_class, name, \
        TP_PROTO(struct xfs_da_args *args), \
        TP_ARGS(args))
 DEFINE_DIR2_EVENT(xfs_dir2_sf_addname);
@@ -1472,6 +1482,64 @@ DEFINE_DIR2_EVENT(xfs_dir2_node_replace);
 DEFINE_DIR2_EVENT(xfs_dir2_node_removename);
 DEFINE_DIR2_EVENT(xfs_dir2_node_to_leaf);
 
+#define DEFINE_ATTR_EVENT(name) \
+DEFINE_EVENT(xfs_da_class, name, \
+       TP_PROTO(struct xfs_da_args *args), \
+       TP_ARGS(args))
+DEFINE_ATTR_EVENT(xfs_attr_sf_add);
+DEFINE_ATTR_EVENT(xfs_attr_sf_addname);
+DEFINE_ATTR_EVENT(xfs_attr_sf_create);
+DEFINE_ATTR_EVENT(xfs_attr_sf_lookup);
+DEFINE_ATTR_EVENT(xfs_attr_sf_remove);
+DEFINE_ATTR_EVENT(xfs_attr_sf_removename);
+DEFINE_ATTR_EVENT(xfs_attr_sf_to_leaf);
+
+DEFINE_ATTR_EVENT(xfs_attr_leaf_add);
+DEFINE_ATTR_EVENT(xfs_attr_leaf_add_old);
+DEFINE_ATTR_EVENT(xfs_attr_leaf_add_new);
+DEFINE_ATTR_EVENT(xfs_attr_leaf_addname);
+DEFINE_ATTR_EVENT(xfs_attr_leaf_create);
+DEFINE_ATTR_EVENT(xfs_attr_leaf_lookup);
+DEFINE_ATTR_EVENT(xfs_attr_leaf_replace);
+DEFINE_ATTR_EVENT(xfs_attr_leaf_removename);
+DEFINE_ATTR_EVENT(xfs_attr_leaf_split);
+DEFINE_ATTR_EVENT(xfs_attr_leaf_split_before);
+DEFINE_ATTR_EVENT(xfs_attr_leaf_split_after);
+DEFINE_ATTR_EVENT(xfs_attr_leaf_clearflag);
+DEFINE_ATTR_EVENT(xfs_attr_leaf_setflag);
+DEFINE_ATTR_EVENT(xfs_attr_leaf_flipflags);
+DEFINE_ATTR_EVENT(xfs_attr_leaf_to_sf);
+DEFINE_ATTR_EVENT(xfs_attr_leaf_to_node);
+DEFINE_ATTR_EVENT(xfs_attr_leaf_rebalance);
+DEFINE_ATTR_EVENT(xfs_attr_leaf_unbalance);
+
+DEFINE_ATTR_EVENT(xfs_attr_node_addname);
+DEFINE_ATTR_EVENT(xfs_attr_node_lookup);
+DEFINE_ATTR_EVENT(xfs_attr_node_replace);
+DEFINE_ATTR_EVENT(xfs_attr_node_removename);
+
+#define DEFINE_DA_EVENT(name) \
+DEFINE_EVENT(xfs_da_class, name, \
+       TP_PROTO(struct xfs_da_args *args), \
+       TP_ARGS(args))
+DEFINE_DA_EVENT(xfs_da_split);
+DEFINE_DA_EVENT(xfs_da_join);
+DEFINE_DA_EVENT(xfs_da_link_before);
+DEFINE_DA_EVENT(xfs_da_link_after);
+DEFINE_DA_EVENT(xfs_da_unlink_back);
+DEFINE_DA_EVENT(xfs_da_unlink_forward);
+DEFINE_DA_EVENT(xfs_da_root_split);
+DEFINE_DA_EVENT(xfs_da_root_join);
+DEFINE_DA_EVENT(xfs_da_node_add);
+DEFINE_DA_EVENT(xfs_da_node_create);
+DEFINE_DA_EVENT(xfs_da_node_split);
+DEFINE_DA_EVENT(xfs_da_node_remove);
+DEFINE_DA_EVENT(xfs_da_node_rebalance);
+DEFINE_DA_EVENT(xfs_da_node_unbalance);
+DEFINE_DA_EVENT(xfs_da_swap_lastblock);
+DEFINE_DA_EVENT(xfs_da_grow_inode);
+DEFINE_DA_EVENT(xfs_da_shrink_inode);
+
 DECLARE_EVENT_CLASS(xfs_dir2_space_class,
        TP_PROTO(struct xfs_da_args *args, int idx),
        TP_ARGS(args, idx),
index f4b2eff..6fbc4ca 100644 (file)
@@ -57,7 +57,6 @@
 #include <linux/kernel.h>
 #include <linux/ctype.h>
 #include <linux/sched.h>
-#include <asm/system.h>
 #include <linux/atomic.h>
 #include <asm/div64.h>
 #include <asm/acpi.h>
index e37963c..1ced641 100644 (file)
@@ -15,6 +15,8 @@
 #ifndef __ASM_GENERIC_ATOMIC_H
 #define __ASM_GENERIC_ATOMIC_H
 
+#include <asm/cmpxchg.h>
+
 #ifdef CONFIG_SMP
 /* Force people to define core atomics */
 # if !defined(atomic_add_return) || !defined(atomic_sub_return) || \
@@ -52,7 +54,6 @@
 #define atomic_set(v, i) (((v)->counter) = (i))
 
 #include <linux/irqflags.h>
-#include <asm/system.h>
 
 /**
  * atomic_add_return - add integer to atomic variable
diff --git a/include/asm-generic/barrier.h b/include/asm-generic/barrier.h
new file mode 100644 (file)
index 0000000..639d7a4
--- /dev/null
@@ -0,0 +1,50 @@
+/* Generic barrier definitions, based on MN10300 definitions.
+ *
+ * It should be possible to use these on really simple architectures,
+ * but it serves more as a starting point for new ports.
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef __ASM_GENERIC_BARRIER_H
+#define __ASM_GENERIC_BARRIER_H
+
+#ifndef __ASSEMBLY__
+
+#define nop() asm volatile ("nop")
+
+/*
+ * Force strict CPU ordering.
+ * And yes, this is required on UP too when we're talking
+ * to devices.
+ *
+ * This implementation only contains a compiler barrier.
+ */
+
+#define mb()   asm volatile ("": : :"memory")
+#define rmb()  mb()
+#define wmb()  asm volatile ("": : :"memory")
+
+#ifdef CONFIG_SMP
+#define smp_mb()       mb()
+#define smp_rmb()      rmb()
+#define smp_wmb()      wmb()
+#else
+#define smp_mb()       barrier()
+#define smp_rmb()      barrier()
+#define smp_wmb()      barrier()
+#endif
+
+#define set_mb(var, value)  do { var = value;  mb(); } while (0)
+#define set_wmb(var, value) do { var = value; wmb(); } while (0)
+
+#define read_barrier_depends()         do {} while (0)
+#define smp_read_barrier_depends()     do {} while (0)
+
+#endif /* !__ASSEMBLY__ */
+#endif /* __ASM_GENERIC_BARRIER_H */
index ecc44a8..9ae6c34 100644 (file)
@@ -2,7 +2,7 @@
 #define _ASM_GENERIC_BITOPS_ATOMIC_H_
 
 #include <asm/types.h>
-#include <asm/system.h>
+#include <linux/irqflags.h>
 
 #ifdef CONFIG_SMP
 #include <asm/spinlock.h>
index 213ac6e..8a36183 100644 (file)
@@ -1,22 +1,97 @@
+/*
+ * Generic UP xchg and cmpxchg using interrupt disablement.  Does not
+ * support SMP.
+ */
+
 #ifndef __ASM_GENERIC_CMPXCHG_H
 #define __ASM_GENERIC_CMPXCHG_H
 
-/*
- * Generic cmpxchg
- *
- * Uses the local cmpxchg. Does not support SMP.
- */
 #ifdef CONFIG_SMP
 #error "Cannot use generic cmpxchg on SMP"
 #endif
 
+#include <linux/irqflags.h>
+
+#ifndef xchg
+
+/*
+ * This function doesn't exist, so you'll get a linker error if
+ * something tries to do an invalidly-sized xchg().
+ */
+extern void __xchg_called_with_bad_pointer(void);
+
+static inline
+unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
+{
+       unsigned long ret, flags;
+
+       switch (size) {
+       case 1:
+#ifdef __xchg_u8
+               return __xchg_u8(x, ptr);
+#else
+               local_irq_save(flags);
+               ret = *(volatile u8 *)ptr;
+               *(volatile u8 *)ptr = x;
+               local_irq_restore(flags);
+               return ret;
+#endif /* __xchg_u8 */
+
+       case 2:
+#ifdef __xchg_u16
+               return __xchg_u16(x, ptr);
+#else
+               local_irq_save(flags);
+               ret = *(volatile u16 *)ptr;
+               *(volatile u16 *)ptr = x;
+               local_irq_restore(flags);
+               return ret;
+#endif /* __xchg_u16 */
+
+       case 4:
+#ifdef __xchg_u32
+               return __xchg_u32(x, ptr);
+#else
+               local_irq_save(flags);
+               ret = *(volatile u32 *)ptr;
+               *(volatile u32 *)ptr = x;
+               local_irq_restore(flags);
+               return ret;
+#endif /* __xchg_u32 */
+
+#ifdef CONFIG_64BIT
+       case 8:
+#ifdef __xchg_u64
+               return __xchg_u64(x, ptr);
+#else
+               local_irq_save(flags);
+               ret = *(volatile u64 *)ptr;
+               *(volatile u64 *)ptr = x;
+               local_irq_restore(flags);
+               return ret;
+#endif /* __xchg_u64 */
+#endif /* CONFIG_64BIT */
+
+       default:
+               __xchg_called_with_bad_pointer();
+               return x;
+       }
+}
+
+#define xchg(ptr, x) \
+       ((__typeof__(*(ptr))) __xchg((unsigned long)(x), (ptr), sizeof(*(ptr))))
+
+#endif /* xchg */
+
 /*
  * Atomic compare and exchange.
  *
  * Do not define __HAVE_ARCH_CMPXCHG because we want to use it to check whether
  * a cmpxchg primitive faster than repeated local irq save/restore exists.
  */
+#include <asm-generic/cmpxchg-local.h>
+
 #define cmpxchg(ptr, o, n)     cmpxchg_local((ptr), (o), (n))
 #define cmpxchg64(ptr, o, n)   cmpxchg64_local((ptr), (o), (n))
 
-#endif
+#endif /* __ASM_GENERIC_CMPXCHG_H */
diff --git a/include/asm-generic/exec.h b/include/asm-generic/exec.h
new file mode 100644 (file)
index 0000000..567766b
--- /dev/null
@@ -0,0 +1,19 @@
+/* Generic process execution definitions, based on MN10300 definitions.
+ *
+ * It should be possible to use these on really simple architectures,
+ * but it serves more as a starting point for new ports.
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef __ASM_GENERIC_EXEC_H
+#define __ASM_GENERIC_EXEC_H
+
+#define arch_align_stack(x) (x)
+
+#endif /* __ASM_GENERIC_EXEC_H */
index 1ff4e22..5f52690 100644 (file)
@@ -142,9 +142,9 @@ extern int __must_check gpiochip_reserve(int start, int ngpio);
 /* add/remove chips */
 extern int gpiochip_add(struct gpio_chip *chip);
 extern int __must_check gpiochip_remove(struct gpio_chip *chip);
-extern struct gpio_chip *gpiochip_find(void *data,
+extern struct gpio_chip *gpiochip_find(const void *data,
                                        int (*match)(struct gpio_chip *chip,
-                                                    void *data));
+                                                    const void *data));
 
 
 /* Always use the library code for GPIO management calls,
diff --git a/include/asm-generic/switch_to.h b/include/asm-generic/switch_to.h
new file mode 100644 (file)
index 0000000..052c4ac
--- /dev/null
@@ -0,0 +1,30 @@
+/* Generic task switch macro wrapper, based on MN10300 definitions.
+ *
+ * It should be possible to use these on really simple architectures,
+ * but it serves more as a starting point for new ports.
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef __ASM_GENERIC_SWITCH_TO_H
+#define __ASM_GENERIC_SWITCH_TO_H
+
+#include <linux/thread_info.h>
+
+/*
+ * Context switching is now performed out-of-line in switch_to.S
+ */
+extern struct task_struct *__switch_to(struct task_struct *,
+                                      struct task_struct *);
+
+#define switch_to(prev, next, last)                                    \
+       do {                                                            \
+               ((last) = __switch_to((prev), (next)));                 \
+       } while (0)
+
+#endif /* __ASM_GENERIC_SWITCH_TO_H */
diff --git a/include/asm-generic/system.h b/include/asm-generic/system.h
deleted file mode 100644 (file)
index 215efa7..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-/* Generic system definitions, based on MN10300 definitions.
- *
- * It should be possible to use these on really simple architectures,
- * but it serves more as a starting point for new ports.
- *
- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public Licence
- * as published by the Free Software Foundation; either version
- * 2 of the Licence, or (at your option) any later version.
- */
-#ifndef __ASM_GENERIC_SYSTEM_H
-#define __ASM_GENERIC_SYSTEM_H
-
-#ifndef __ASSEMBLY__
-
-#include <linux/types.h>
-#include <linux/irqflags.h>
-
-#include <asm/cmpxchg-local.h>
-#include <asm/cmpxchg.h>
-
-struct task_struct;
-
-/* context switching is now performed out-of-line in switch_to.S */
-extern struct task_struct *__switch_to(struct task_struct *,
-               struct task_struct *);
-#define switch_to(prev, next, last)                                    \
-       do {                                                            \
-               ((last) = __switch_to((prev), (next)));                 \
-       } while (0)
-
-#define arch_align_stack(x) (x)
-
-#define nop() asm volatile ("nop")
-
-#endif /* !__ASSEMBLY__ */
-
-/*
- * Force strict CPU ordering.
- * And yes, this is required on UP too when we're talking
- * to devices.
- *
- * This implementation only contains a compiler barrier.
- */
-
-#define mb()   asm volatile ("": : :"memory")
-#define rmb()  mb()
-#define wmb()  asm volatile ("": : :"memory")
-
-#ifdef CONFIG_SMP
-#define smp_mb()       mb()
-#define smp_rmb()      rmb()
-#define smp_wmb()      wmb()
-#else
-#define smp_mb()       barrier()
-#define smp_rmb()      barrier()
-#define smp_wmb()      barrier()
-#endif
-
-#define set_mb(var, value)  do { var = value;  mb(); } while (0)
-#define set_wmb(var, value) do { var = value; wmb(); } while (0)
-
-#define read_barrier_depends()         do {} while (0)
-#define smp_read_barrier_depends()     do {} while (0)
-
-/*
- * we make sure local_irq_enable() doesn't cause priority inversion
- */
-#ifndef __ASSEMBLY__
-
-/* This function doesn't exist, so you'll get a linker error
- *    if something tries to do an invalid xchg().  */
-extern void __xchg_called_with_bad_pointer(void);
-
-static inline
-unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
-{
-       unsigned long ret, flags;
-
-       switch (size) {
-       case 1:
-#ifdef __xchg_u8
-               return __xchg_u8(x, ptr);
-#else
-               local_irq_save(flags);
-               ret = *(volatile u8 *)ptr;
-               *(volatile u8 *)ptr = x;
-               local_irq_restore(flags);
-               return ret;
-#endif /* __xchg_u8 */
-
-       case 2:
-#ifdef __xchg_u16
-               return __xchg_u16(x, ptr);
-#else
-               local_irq_save(flags);
-               ret = *(volatile u16 *)ptr;
-               *(volatile u16 *)ptr = x;
-               local_irq_restore(flags);
-               return ret;
-#endif /* __xchg_u16 */
-
-       case 4:
-#ifdef __xchg_u32
-               return __xchg_u32(x, ptr);
-#else
-               local_irq_save(flags);
-               ret = *(volatile u32 *)ptr;
-               *(volatile u32 *)ptr = x;
-               local_irq_restore(flags);
-               return ret;
-#endif /* __xchg_u32 */
-
-#ifdef CONFIG_64BIT
-       case 8:
-#ifdef __xchg_u64
-               return __xchg_u64(x, ptr);
-#else
-               local_irq_save(flags);
-               ret = *(volatile u64 *)ptr;
-               *(volatile u64 *)ptr = x;
-               local_irq_restore(flags);
-               return ret;
-#endif /* __xchg_u64 */
-#endif /* CONFIG_64BIT */
-
-       default:
-               __xchg_called_with_bad_pointer();
-               return x;
-       }
-}
-
-#define xchg(ptr, x) \
-       ((__typeof__(*(ptr))) __xchg((unsigned long)(x), (ptr), sizeof(*(ptr))))
-
-#endif /* !__ASSEMBLY__ */
-
-#endif /* __ASM_GENERIC_SYSTEM_H */
index 798603e..8aeadf6 100644 (file)
                *(.init.setup)                                          \
                VMLINUX_SYMBOL(__setup_end) = .;
 
-#define INITCALLS                                                      \
-       *(.initcallearly.init)                                          \
-       VMLINUX_SYMBOL(__early_initcall_end) = .;                       \
-       *(.initcall0.init)                                              \
-       *(.initcall0s.init)                                             \
-       *(.initcall1.init)                                              \
-       *(.initcall1s.init)                                             \
-       *(.initcall2.init)                                              \
-       *(.initcall2s.init)                                             \
-       *(.initcall3.init)                                              \
-       *(.initcall3s.init)                                             \
-       *(.initcall4.init)                                              \
-       *(.initcall4s.init)                                             \
-       *(.initcall5.init)                                              \
-       *(.initcall5s.init)                                             \
-       *(.initcallrootfs.init)                                         \
-       *(.initcall6.init)                                              \
-       *(.initcall6s.init)                                             \
-       *(.initcall7.init)                                              \
-       *(.initcall7s.init)
+#define INIT_CALLS_LEVEL(level)                                                \
+               VMLINUX_SYMBOL(__initcall##level##_start) = .;          \
+               *(.initcall##level##.init)                              \
+               *(.initcall##level##s.init)                             \
 
 #define INIT_CALLS                                                     \
                VMLINUX_SYMBOL(__initcall_start) = .;                   \
-               INITCALLS                                               \
+               *(.initcallearly.init)                                  \
+               INIT_CALLS_LEVEL(0)                                     \
+               INIT_CALLS_LEVEL(1)                                     \
+               INIT_CALLS_LEVEL(2)                                     \
+               INIT_CALLS_LEVEL(3)                                     \
+               INIT_CALLS_LEVEL(4)                                     \
+               INIT_CALLS_LEVEL(5)                                     \
+               INIT_CALLS_LEVEL(rootfs)                                \
+               INIT_CALLS_LEVEL(6)                                     \
+               INIT_CALLS_LEVEL(7)                                     \
                VMLINUX_SYMBOL(__initcall_end) = .;
 
 #define CON_INITCALL                                                   \
index 3f96866..f53fea6 100644 (file)
@@ -151,6 +151,7 @@ extern int ec_write(u8 addr, u8 val);
 extern int ec_transaction(u8 command,
                           const u8 *wdata, unsigned wdata_len,
                           u8 *rdata, unsigned rdata_len);
+extern acpi_handle ec_get_handle(void);
 
 #if defined(CONFIG_ACPI_WMI) || defined(CONFIG_ACPI_WMI_MODULE)
 
diff --git a/include/linux/apple_bl.h b/include/linux/apple_bl.h
new file mode 100644 (file)
index 0000000..47bedc0
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * apple_bl exported symbols
+ */
+
+#ifndef _LINUX_APPLE_BL_H
+#define _LINUX_APPLE_BL_H
+
+#ifdef CONFIG_BACKLIGHT_APPLE
+
+extern int apple_bl_register(void);
+extern void apple_bl_unregister(void);
+
+#else /* !CONFIG_BACKLIGHT_APPLE */
+
+static inline int apple_bl_register(void)
+{
+       return 0;
+}
+
+static inline void apple_bl_unregister(void)
+{
+}
+
+#endif /* !CONFIG_BACKLIGHT_APPLE */
+
+#endif /* _LINUX_APPLE_BL_H */
diff --git a/include/linux/clk-private.h b/include/linux/clk-private.h
new file mode 100644 (file)
index 0000000..5e4312b
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ *  linux/include/linux/clk-private.h
+ *
+ *  Copyright (c) 2010-2011 Jeremy Kerr <jeremy.kerr@canonical.com>
+ *  Copyright (C) 2011-2012 Linaro Ltd <mturquette@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __LINUX_CLK_PRIVATE_H
+#define __LINUX_CLK_PRIVATE_H
+
+#include <linux/clk-provider.h>
+#include <linux/list.h>
+
+/*
+ * WARNING: Do not include clk-private.h from any file that implements struct
+ * clk_ops.  Doing so is a layering violation!
+ *
+ * This header exists only to allow for statically initialized clock data.  Any
+ * static clock data must be defined in a separate file from the logic that
+ * implements the clock operations for that same data.
+ */
+
+#ifdef CONFIG_COMMON_CLK
+
+struct clk {
+       const char              *name;
+       const struct clk_ops    *ops;
+       struct clk_hw           *hw;
+       struct clk              *parent;
+       char                    **parent_names;
+       struct clk              **parents;
+       u8                      num_parents;
+       unsigned long           rate;
+       unsigned long           new_rate;
+       unsigned long           flags;
+       unsigned int            enable_count;
+       unsigned int            prepare_count;
+       struct hlist_head       children;
+       struct hlist_node       child_node;
+       unsigned int            notifier_count;
+#ifdef CONFIG_COMMON_CLK_DEBUG
+       struct dentry           *dentry;
+#endif
+};
+
+/*
+ * DOC: Basic clock implementations common to many platforms
+ *
+ * Each basic clock hardware type is comprised of a structure describing the
+ * clock hardware, implementations of the relevant callbacks in struct clk_ops,
+ * unique flags for that hardware type, a registration function and an
+ * alternative macro for static initialization
+ */
+
+extern struct clk_ops clk_fixed_rate_ops;
+
+#define DEFINE_CLK_FIXED_RATE(_name, _flags, _rate,            \
+                               _fixed_rate_flags)              \
+       static struct clk _name;                                \
+       static char *_name##_parent_names[] = {};               \
+       static struct clk_fixed_rate _name##_hw = {             \
+               .hw = {                                         \
+                       .clk = &_name,                          \
+               },                                              \
+               .fixed_rate = _rate,                            \
+               .flags = _fixed_rate_flags,                     \
+       };                                                      \
+       static struct clk _name = {                             \
+               .name = #_name,                                 \
+               .ops = &clk_fixed_rate_ops,                     \
+               .hw = &_name##_hw.hw,                           \
+               .parent_names = _name##_parent_names,           \
+               .num_parents =                                  \
+                       ARRAY_SIZE(_name##_parent_names),       \
+               .flags = _flags,                                \
+       };
+
+extern struct clk_ops clk_gate_ops;
+
+#define DEFINE_CLK_GATE(_name, _parent_name, _parent_ptr,      \
+                               _flags, _reg, _bit_idx,         \
+                               _gate_flags, _lock)             \
+       static struct clk _name;                                \
+       static char *_name##_parent_names[] = {                 \
+               _parent_name,                                   \
+       };                                                      \
+       static struct clk *_name##_parents[] = {                \
+               _parent_ptr,                                    \
+       };                                                      \
+       static struct clk_gate _name##_hw = {                   \
+               .hw = {                                         \
+                       .clk = &_name,                          \
+               },                                              \
+               .reg = _reg,                                    \
+               .bit_idx = _bit_idx,                            \
+               .flags = _gate_flags,                           \
+               .lock = _lock,                                  \
+       };                                                      \
+       static struct clk _name = {                             \
+               .name = #_name,                                 \
+               .ops = &clk_gate_ops,                           \
+               .hw = &_name##_hw.hw,                           \
+               .parent_names = _name##_parent_names,           \
+               .num_parents =                                  \
+                       ARRAY_SIZE(_name##_parent_names),       \
+               .parents = _name##_parents,                     \
+               .flags = _flags,                                \
+       };
+
+extern struct clk_ops clk_divider_ops;
+
+#define DEFINE_CLK_DIVIDER(_name, _parent_name, _parent_ptr,   \
+                               _flags, _reg, _shift, _width,   \
+                               _divider_flags, _lock)          \
+       static struct clk _name;                                \
+       static char *_name##_parent_names[] = {                 \
+               _parent_name,                                   \
+       };                                                      \
+       static struct clk *_name##_parents[] = {                \
+               _parent_ptr,                                    \
+       };                                                      \
+       static struct clk_divider _name##_hw = {                \
+               .hw = {                                         \
+                       .clk = &_name,                          \
+               },                                              \
+               .reg = _reg,                                    \
+               .shift = _shift,                                \
+               .width = _width,                                \
+               .flags = _divider_flags,                        \
+               .lock = _lock,                                  \
+       };                                                      \
+       static struct clk _name = {                             \
+               .name = #_name,                                 \
+               .ops = &clk_divider_ops,                        \
+               .hw = &_name##_hw.hw,                           \
+               .parent_names = _name##_parent_names,           \
+               .num_parents =                                  \
+                       ARRAY_SIZE(_name##_parent_names),       \
+               .parents = _name##_parents,                     \
+               .flags = _flags,                                \
+       };
+
+extern struct clk_ops clk_mux_ops;
+
+#define DEFINE_CLK_MUX(_name, _parent_names, _parents, _flags, \
+                               _reg, _shift, _width,           \
+                               _mux_flags, _lock)              \
+       static struct clk _name;                                \
+       static struct clk_mux _name##_hw = {                    \
+               .hw = {                                         \
+                       .clk = &_name,                          \
+               },                                              \
+               .reg = _reg,                                    \
+               .shift = _shift,                                \
+               .width = _width,                                \
+               .flags = _mux_flags,                            \
+               .lock = _lock,                                  \
+       };                                                      \
+       static struct clk _name = {                             \
+               .name = #_name,                                 \
+               .ops = &clk_mux_ops,                            \
+               .hw = &_name##_hw.hw,                           \
+               .parent_names = _parent_names,                  \
+               .num_parents =                                  \
+                       ARRAY_SIZE(_parent_names),              \
+               .parents = _parents,                            \
+               .flags = _flags,                                \
+       };
+
+/**
+ * __clk_init - initialize the data structures in a struct clk
+ * @dev:       device initializing this clk, placeholder for now
+ * @clk:       clk being initialized
+ *
+ * Initializes the lists in struct clk, queries the hardware for the
+ * parent and rate and sets them both.
+ *
+ * Any struct clk passed into __clk_init must have the following members
+ * populated:
+ *     .name
+ *     .ops
+ *     .hw
+ *     .parent_names
+ *     .num_parents
+ *     .flags
+ *
+ * It is not necessary to call clk_register if __clk_init is used directly with
+ * statically initialized clock data.
+ */
+void __clk_init(struct device *dev, struct clk *clk);
+
+#endif /* CONFIG_COMMON_CLK */
+#endif /* CLK_PRIVATE_H */
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
new file mode 100644 (file)
index 0000000..5508897
--- /dev/null
@@ -0,0 +1,300 @@
+/*
+ *  linux/include/linux/clk-provider.h
+ *
+ *  Copyright (c) 2010-2011 Jeremy Kerr <jeremy.kerr@canonical.com>
+ *  Copyright (C) 2011-2012 Linaro Ltd <mturquette@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __LINUX_CLK_PROVIDER_H
+#define __LINUX_CLK_PROVIDER_H
+
+#include <linux/clk.h>
+
+#ifdef CONFIG_COMMON_CLK
+
+/**
+ * struct clk_hw - handle for traversing from a struct clk to its corresponding
+ * hardware-specific structure.  struct clk_hw should be declared within struct
+ * clk_foo and then referenced by the struct clk instance that uses struct
+ * clk_foo's clk_ops
+ *
+ * clk: pointer to the struct clk instance that points back to this struct
+ * clk_hw instance
+ */
+struct clk_hw {
+       struct clk *clk;
+};
+
+/*
+ * flags used across common struct clk.  these flags should only affect the
+ * top-level framework.  custom flags for dealing with hardware specifics
+ * belong in struct clk_foo
+ */
+#define CLK_SET_RATE_GATE      BIT(0) /* must be gated across rate change */
+#define CLK_SET_PARENT_GATE    BIT(1) /* must be gated across re-parent */
+#define CLK_SET_RATE_PARENT    BIT(2) /* propagate rate change up one level */
+#define CLK_IGNORE_UNUSED      BIT(3) /* do not gate even if unused */
+#define CLK_IS_ROOT            BIT(4) /* root clk, has no parent */
+
+/**
+ * struct clk_ops -  Callback operations for hardware clocks; these are to
+ * be provided by the clock implementation, and will be called by drivers
+ * through the clk_* api.
+ *
+ * @prepare:   Prepare the clock for enabling. This must not return until
+ *             the clock is fully prepared, and it's safe to call clk_enable.
+ *             This callback is intended to allow clock implementations to
+ *             do any initialisation that may sleep. Called with
+ *             prepare_lock held.
+ *
+ * @unprepare: Release the clock from its prepared state. This will typically
+ *             undo any work done in the @prepare callback. Called with
+ *             prepare_lock held.
+ *
+ * @enable:    Enable the clock atomically. This must not return until the
+ *             clock is generating a valid clock signal, usable by consumer
+ *             devices. Called with enable_lock held. This function must not
+ *             sleep.
+ *
+ * @disable:   Disable the clock atomically. Called with enable_lock held.
+ *             This function must not sleep.
+ *
+ * @recalc_rate        Recalculate the rate of this clock, by quering hardware.  The
+ *             parent rate is an input parameter.  It is up to the caller to
+ *             insure that the prepare_mutex is held across this call.
+ *             Returns the calculated rate.  Optional, but recommended - if
+ *             this op is not set then clock rate will be initialized to 0.
+ *
+ * @round_rate:        Given a target rate as input, returns the closest rate actually
+ *             supported by the clock.
+ *
+ * @get_parent:        Queries the hardware to determine the parent of a clock.  The
+ *             return value is a u8 which specifies the index corresponding to
+ *             the parent clock.  This index can be applied to either the
+ *             .parent_names or .parents arrays.  In short, this function
+ *             translates the parent value read from hardware into an array
+ *             index.  Currently only called when the clock is initialized by
+ *             __clk_init.  This callback is mandatory for clocks with
+ *             multiple parents.  It is optional (and unnecessary) for clocks
+ *             with 0 or 1 parents.
+ *
+ * @set_parent:        Change the input source of this clock; for clocks with multiple
+ *             possible parents specify a new parent by passing in the index
+ *             as a u8 corresponding to the parent in either the .parent_names
+ *             or .parents arrays.  This function in affect translates an
+ *             array index into the value programmed into the hardware.
+ *             Returns 0 on success, -EERROR otherwise.
+ *
+ * @set_rate:  Change the rate of this clock. If this callback returns
+ *             CLK_SET_RATE_PARENT, the rate change will be propagated to the
+ *             parent clock (which may propagate again if the parent clock
+ *             also sets this flag). The requested rate of the parent is
+ *             passed back from the callback in the second 'unsigned long *'
+ *             argument.  Note that it is up to the hardware clock's set_rate
+ *             implementation to insure that clocks do not run out of spec
+ *             when propgating the call to set_rate up to the parent.  One way
+ *             to do this is to gate the clock (via clk_disable and/or
+ *             clk_unprepare) before calling clk_set_rate, then ungating it
+ *             afterward.  If your clock also has the CLK_GATE_SET_RATE flag
+ *             set then this will insure safety.  Returns 0 on success,
+ *             -EERROR otherwise.
+ *
+ * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
+ * implementations to split any work between atomic (enable) and sleepable
+ * (prepare) contexts.  If enabling a clock requires code that might sleep,
+ * this must be done in clk_prepare.  Clock enable code that will never be
+ * called in a sleepable context may be implement in clk_enable.
+ *
+ * Typically, drivers will call clk_prepare when a clock may be needed later
+ * (eg. when a device is opened), and clk_enable when the clock is actually
+ * required (eg. from an interrupt). Note that clk_prepare MUST have been
+ * called before clk_enable.
+ */
+struct clk_ops {
+       int             (*prepare)(struct clk_hw *hw);
+       void            (*unprepare)(struct clk_hw *hw);
+       int             (*enable)(struct clk_hw *hw);
+       void            (*disable)(struct clk_hw *hw);
+       int             (*is_enabled)(struct clk_hw *hw);
+       unsigned long   (*recalc_rate)(struct clk_hw *hw,
+                                       unsigned long parent_rate);
+       long            (*round_rate)(struct clk_hw *hw, unsigned long,
+                                       unsigned long *);
+       int             (*set_parent)(struct clk_hw *hw, u8 index);
+       u8              (*get_parent)(struct clk_hw *hw);
+       int             (*set_rate)(struct clk_hw *hw, unsigned long);
+       void            (*init)(struct clk_hw *hw);
+};
+
+/*
+ * DOC: Basic clock implementations common to many platforms
+ *
+ * Each basic clock hardware type is comprised of a structure describing the
+ * clock hardware, implementations of the relevant callbacks in struct clk_ops,
+ * unique flags for that hardware type, a registration function and an
+ * alternative macro for static initialization
+ */
+
+/**
+ * struct clk_fixed_rate - fixed-rate clock
+ * @hw:                handle between common and hardware-specific interfaces
+ * @fixed_rate:        constant frequency of clock
+ */
+struct clk_fixed_rate {
+       struct          clk_hw hw;
+       unsigned long   fixed_rate;
+       u8              flags;
+};
+
+struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
+               const char *parent_name, unsigned long flags,
+               unsigned long fixed_rate);
+
+/**
+ * struct clk_gate - gating clock
+ *
+ * @hw:                handle between common and hardware-specific interfaces
+ * @reg:       register controlling gate
+ * @bit_idx:   single bit controlling gate
+ * @flags:     hardware-specific flags
+ * @lock:      register lock
+ *
+ * Clock which can gate its output.  Implements .enable & .disable
+ *
+ * Flags:
+ * CLK_GATE_SET_DISABLE - by default this clock sets the bit at bit_idx to
+ *     enable the clock.  Setting this flag does the opposite: setting the bit
+ *     disable the clock and clearing it enables the clock
+ */
+struct clk_gate {
+       struct clk_hw hw;
+       void __iomem    *reg;
+       u8              bit_idx;
+       u8              flags;
+       spinlock_t      *lock;
+       char            *parent[1];
+};
+
+#define CLK_GATE_SET_TO_DISABLE                BIT(0)
+
+struct clk *clk_register_gate(struct device *dev, const char *name,
+               const char *parent_name, unsigned long flags,
+               void __iomem *reg, u8 bit_idx,
+               u8 clk_gate_flags, spinlock_t *lock);
+
+/**
+ * struct clk_divider - adjustable divider clock
+ *
+ * @hw:                handle between common and hardware-specific interfaces
+ * @reg:       register containing the divider
+ * @shift:     shift to the divider bit field
+ * @width:     width of the divider bit field
+ * @lock:      register lock
+ *
+ * Clock with an adjustable divider affecting its output frequency.  Implements
+ * .recalc_rate, .set_rate and .round_rate
+ *
+ * Flags:
+ * CLK_DIVIDER_ONE_BASED - by default the divisor is the value read from the
+ *     register plus one.  If CLK_DIVIDER_ONE_BASED is set then the divider is
+ *     the raw value read from the register, with the value of zero considered
+ *     invalid
+ * CLK_DIVIDER_POWER_OF_TWO - clock divisor is 2 raised to the value read from
+ *     the hardware register
+ */
+struct clk_divider {
+       struct clk_hw   hw;
+       void __iomem    *reg;
+       u8              shift;
+       u8              width;
+       u8              flags;
+       spinlock_t      *lock;
+       char            *parent[1];
+};
+
+#define CLK_DIVIDER_ONE_BASED          BIT(0)
+#define CLK_DIVIDER_POWER_OF_TWO       BIT(1)
+
+struct clk *clk_register_divider(struct device *dev, const char *name,
+               const char *parent_name, unsigned long flags,
+               void __iomem *reg, u8 shift, u8 width,
+               u8 clk_divider_flags, spinlock_t *lock);
+
+/**
+ * struct clk_mux - multiplexer clock
+ *
+ * @hw:                handle between common and hardware-specific interfaces
+ * @reg:       register controlling multiplexer
+ * @shift:     shift to multiplexer bit field
+ * @width:     width of mutliplexer bit field
+ * @num_clks:  number of parent clocks
+ * @lock:      register lock
+ *
+ * Clock with multiple selectable parents.  Implements .get_parent, .set_parent
+ * and .recalc_rate
+ *
+ * Flags:
+ * CLK_MUX_INDEX_ONE - register index starts at 1, not 0
+ * CLK_MUX_INDEX_BITWISE - register index is a single bit (power of two)
+ */
+struct clk_mux {
+       struct clk_hw   hw;
+       void __iomem    *reg;
+       u8              shift;
+       u8              width;
+       u8              flags;
+       spinlock_t      *lock;
+};
+
+#define CLK_MUX_INDEX_ONE              BIT(0)
+#define CLK_MUX_INDEX_BIT              BIT(1)
+
+struct clk *clk_register_mux(struct device *dev, const char *name,
+               char **parent_names, u8 num_parents, unsigned long flags,
+               void __iomem *reg, u8 shift, u8 width,
+               u8 clk_mux_flags, spinlock_t *lock);
+
+/**
+ * clk_register - allocate a new clock, register it and return an opaque cookie
+ * @dev: device that is registering this clock
+ * @name: clock name
+ * @ops: operations this clock supports
+ * @hw: link to hardware-specific clock data
+ * @parent_names: array of string names for all possible parents
+ * @num_parents: number of possible parents
+ * @flags: framework-level hints and quirks
+ *
+ * clk_register is the primary interface for populating the clock tree with new
+ * clock nodes.  It returns a pointer to the newly allocated struct clk which
+ * cannot be dereferenced by driver code but may be used in conjuction with the
+ * rest of the clock API.
+ */
+struct clk *clk_register(struct device *dev, const char *name,
+               const struct clk_ops *ops, struct clk_hw *hw,
+               char **parent_names, u8 num_parents, unsigned long flags);
+
+/* helper functions */
+const char *__clk_get_name(struct clk *clk);
+struct clk_hw *__clk_get_hw(struct clk *clk);
+u8 __clk_get_num_parents(struct clk *clk);
+struct clk *__clk_get_parent(struct clk *clk);
+inline int __clk_get_enable_count(struct clk *clk);
+inline int __clk_get_prepare_count(struct clk *clk);
+unsigned long __clk_get_rate(struct clk *clk);
+unsigned long __clk_get_flags(struct clk *clk);
+int __clk_is_enabled(struct clk *clk);
+struct clk *__clk_lookup(const char *name);
+
+/*
+ * FIXME clock api without lock protection
+ */
+int __clk_prepare(struct clk *clk);
+void __clk_unprepare(struct clk *clk);
+void __clk_reparent(struct clk *clk, struct clk *new_parent);
+unsigned long __clk_round_rate(struct clk *clk, unsigned long rate);
+
+#endif /* CONFIG_COMMON_CLK */
+#endif /* CLK_PROVIDER_H */
index b9d46fa..b025272 100644 (file)
@@ -3,6 +3,7 @@
  *
  *  Copyright (C) 2004 ARM Limited.
  *  Written by Deep Blue Solutions Limited.
+ *  Copyright (C) 2011-2012 Linaro Ltd <mturquette@linaro.org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
 #define __LINUX_CLK_H
 
 #include <linux/kernel.h>
+#include <linux/notifier.h>
 
 struct device;
 
-/*
- * The base API.
+struct clk;
+
+#ifdef CONFIG_COMMON_CLK
+
+/**
+ * DOC: clk notifier callback types
+ *
+ * PRE_RATE_CHANGE - called immediately before the clk rate is changed,
+ *     to indicate that the rate change will proceed.  Drivers must
+ *     immediately terminate any operations that will be affected by the
+ *     rate change.  Callbacks may either return NOTIFY_DONE or
+ *     NOTIFY_STOP.
+ *
+ * ABORT_RATE_CHANGE: called if the rate change failed for some reason
+ *     after PRE_RATE_CHANGE.  In this case, all registered notifiers on
+ *     the clk will be called with ABORT_RATE_CHANGE. Callbacks must
+ *     always return NOTIFY_DONE.
+ *
+ * POST_RATE_CHANGE - called after the clk rate change has successfully
+ *     completed.  Callbacks must always return NOTIFY_DONE.
+ *
  */
+#define PRE_RATE_CHANGE                        BIT(0)
+#define POST_RATE_CHANGE               BIT(1)
+#define ABORT_RATE_CHANGE              BIT(2)
 
+/**
+ * struct clk_notifier - associate a clk with a notifier
+ * @clk: struct clk * to associate the notifier with
+ * @notifier_head: a blocking_notifier_head for this clk
+ * @node: linked list pointers
+ *
+ * A list of struct clk_notifier is maintained by the notifier code.
+ * An entry is created whenever code registers the first notifier on a
+ * particular @clk.  Future notifiers on that @clk are added to the
+ * @notifier_head.
+ */
+struct clk_notifier {
+       struct clk                      *clk;
+       struct srcu_notifier_head       notifier_head;
+       struct list_head                node;
+};
 
-/*
- * struct clk - an machine class defined object / cookie.
+/**
+ * struct clk_notifier_data - rate data to pass to the notifier callback
+ * @clk: struct clk * being changed
+ * @old_rate: previous rate of this clk
+ * @new_rate: new rate of this clk
+ *
+ * For a pre-notifier, old_rate is the clk's rate before this rate
+ * change, and new_rate is what the rate will be in the future.  For a
+ * post-notifier, old_rate and new_rate are both set to the clk's
+ * current rate (this was done to optimize the implementation).
  */
-struct clk;
+struct clk_notifier_data {
+       struct clk              *clk;
+       unsigned long           old_rate;
+       unsigned long           new_rate;
+};
+
+int clk_notifier_register(struct clk *clk, struct notifier_block *nb);
+
+int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb);
+
+#endif /* !CONFIG_COMMON_CLK */
 
 /**
  * clk_get - lookup and obtain a reference to a clock producer.
index e3d8bf2..aa629bc 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/compiler.h>
 #include <linux/types.h>
 #include <asm/byteorder.h>
-#include <asm/system.h>
 
 /* this is used only to give gcc a clue about good code generation */
 union cnt32_to_63 {
index 94f20c1..3bd46f7 100644 (file)
@@ -4,7 +4,6 @@
 #include <linux/kernel.h>
 #include <linux/atomic.h>
 #include <linux/bug.h>
-#include <asm/system.h>
 
 struct task_struct;
 
index 887dcd4..3efbfc2 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/scatterlist.h>
 #include <linux/list.h>
 #include <linux/dma-mapping.h>
+#include <linux/fs.h>
 
 struct device;
 struct dma_buf;
@@ -49,6 +50,17 @@ struct dma_buf_attachment;
  * @unmap_dma_buf: decreases usecount of buffer, might deallocate scatter
  *                pages.
  * @release: release this buffer; to be called after the last dma_buf_put.
+ * @begin_cpu_access: [optional] called before cpu access to invalidate cpu
+ *                   caches and allocate backing storage (if not yet done)
+ *                   respectively pin the objet into memory.
+ * @end_cpu_access: [optional] called after cpu access to flush cashes.
+ * @kmap_atomic: maps a page from the buffer into kernel address
+ *              space, users may not block until the subsequent unmap call.
+ *              This callback must not sleep.
+ * @kunmap_atomic: [optional] unmaps a atomically mapped page from the buffer.
+ *                This Callback must not sleep.
+ * @kmap: maps a page from the buffer into kernel address space.
+ * @kunmap: [optional] unmaps a page from the buffer.
  */
 struct dma_buf_ops {
        int (*attach)(struct dma_buf *, struct device *,
@@ -63,7 +75,8 @@ struct dma_buf_ops {
        struct sg_table * (*map_dma_buf)(struct dma_buf_attachment *,
                                                enum dma_data_direction);
        void (*unmap_dma_buf)(struct dma_buf_attachment *,
-                                               struct sg_table *);
+                                               struct sg_table *,
+                                               enum dma_data_direction);
        /* TODO: Add try_map_dma_buf version, to return immed with -EBUSY
         * if the call would block.
         */
@@ -71,6 +84,14 @@ struct dma_buf_ops {
        /* after final dma_buf_put() */
        void (*release)(struct dma_buf *);
 
+       int (*begin_cpu_access)(struct dma_buf *, size_t, size_t,
+                               enum dma_data_direction);
+       void (*end_cpu_access)(struct dma_buf *, size_t, size_t,
+                              enum dma_data_direction);
+       void *(*kmap_atomic)(struct dma_buf *, unsigned long);
+       void (*kunmap_atomic)(struct dma_buf *, unsigned long, void *);
+       void *(*kmap)(struct dma_buf *, unsigned long);
+       void (*kunmap)(struct dma_buf *, unsigned long, void *);
 };
 
 /**
@@ -86,7 +107,7 @@ struct dma_buf {
        struct file *file;
        struct list_head attachments;
        const struct dma_buf_ops *ops;
-       /* mutex to serialize list manipulation and other ops */
+       /* mutex to serialize list manipulation and attach/detach */
        struct mutex lock;
        void *priv;
 };
@@ -109,20 +130,43 @@ struct dma_buf_attachment {
        void *priv;
 };
 
+/**
+ * get_dma_buf - convenience wrapper for get_file.
+ * @dmabuf:    [in]    pointer to dma_buf
+ *
+ * Increments the reference count on the dma-buf, needed in case of drivers
+ * that either need to create additional references to the dmabuf on the
+ * kernel side.  For example, an exporter that needs to keep a dmabuf ptr
+ * so that subsequent exports don't create a new dmabuf.
+ */
+static inline void get_dma_buf(struct dma_buf *dmabuf)
+{
+       get_file(dmabuf->file);
+}
+
 #ifdef CONFIG_DMA_SHARED_BUFFER
 struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
                                                        struct device *dev);
 void dma_buf_detach(struct dma_buf *dmabuf,
                                struct dma_buf_attachment *dmabuf_attach);
-struct dma_buf *dma_buf_export(void *priv, struct dma_buf_ops *ops,
-                       size_t size, int flags);
-int dma_buf_fd(struct dma_buf *dmabuf);
+struct dma_buf *dma_buf_export(void *priv, const struct dma_buf_ops *ops,
+                              size_t size, int flags);
+int dma_buf_fd(struct dma_buf *dmabuf, int flags);
 struct dma_buf *dma_buf_get(int fd);
 void dma_buf_put(struct dma_buf *dmabuf);
 
 struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *,
                                        enum dma_data_direction);
-void dma_buf_unmap_attachment(struct dma_buf_attachment *, struct sg_table *);
+void dma_buf_unmap_attachment(struct dma_buf_attachment *, struct sg_table *,
+                               enum dma_data_direction);
+int dma_buf_begin_cpu_access(struct dma_buf *dma_buf, size_t start, size_t len,
+                            enum dma_data_direction dir);
+void dma_buf_end_cpu_access(struct dma_buf *dma_buf, size_t start, size_t len,
+                           enum dma_data_direction dir);
+void *dma_buf_kmap_atomic(struct dma_buf *, unsigned long);
+void dma_buf_kunmap_atomic(struct dma_buf *, unsigned long, void *);
+void *dma_buf_kmap(struct dma_buf *, unsigned long);
+void dma_buf_kunmap(struct dma_buf *, unsigned long, void *);
 #else
 
 static inline struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
@@ -138,13 +182,13 @@ static inline void dma_buf_detach(struct dma_buf *dmabuf,
 }
 
 static inline struct dma_buf *dma_buf_export(void *priv,
-                                               struct dma_buf_ops *ops,
-                                               size_t size, int flags)
+                                            const struct dma_buf_ops *ops,
+                                            size_t size, int flags)
 {
        return ERR_PTR(-ENODEV);
 }
 
-static inline int dma_buf_fd(struct dma_buf *dmabuf)
+static inline int dma_buf_fd(struct dma_buf *dmabuf, int flags)
 {
        return -ENODEV;
 }
@@ -166,11 +210,44 @@ static inline struct sg_table *dma_buf_map_attachment(
 }
 
 static inline void dma_buf_unmap_attachment(struct dma_buf_attachment *attach,
-                                               struct sg_table *sg)
+                       struct sg_table *sg, enum dma_data_direction dir)
 {
        return;
 }
 
+static inline int dma_buf_begin_cpu_access(struct dma_buf *dmabuf,
+                                          size_t start, size_t len,
+                                          enum dma_data_direction dir)
+{
+       return -ENODEV;
+}
+
+static inline void dma_buf_end_cpu_access(struct dma_buf *dmabuf,
+                                         size_t start, size_t len,
+                                         enum dma_data_direction dir)
+{
+}
+
+static inline void *dma_buf_kmap_atomic(struct dma_buf *dmabuf,
+                                       unsigned long pnum)
+{
+       return NULL;
+}
+
+static inline void dma_buf_kunmap_atomic(struct dma_buf *dmabuf,
+                                        unsigned long pnum, void *vaddr)
+{
+}
+
+static inline void *dma_buf_kmap(struct dma_buf *dmabuf, unsigned long pnum)
+{
+       return NULL;
+}
+
+static inline void dma_buf_kunmap(struct dma_buf *dmabuf,
+                                 unsigned long pnum, void *vaddr)
+{
+}
 #endif /* CONFIG_DMA_SHARED_BUFFER */
 
 #endif /* __DMA_BUF_H__ */
index ba317e2..c621d76 100644 (file)
@@ -70,25 +70,64 @@ enum dev_type {
 #define DEV_FLAG_X32           BIT(DEV_X32)
 #define DEV_FLAG_X64           BIT(DEV_X64)
 
-/* memory types */
+/**
+ * enum mem_type - memory types. For a more detailed reference, please see
+ *                     http://en.wikipedia.org/wiki/DRAM
+ *
+ * @MEM_EMPTY          Empty csrow
+ * @MEM_RESERVED:      Reserved csrow type
+ * @MEM_UNKNOWN:       Unknown csrow type
+ * @MEM_FPM:           FPM - Fast Page Mode, used on systems up to 1995.
+ * @MEM_EDO:           EDO - Extended data out, used on systems up to 1998.
+ * @MEM_BEDO:          BEDO - Burst Extended data out, an EDO variant.
+ * @MEM_SDR:           SDR - Single data rate SDRAM
+ *                     http://en.wikipedia.org/wiki/Synchronous_dynamic_random-access_memory
+ *                     They use 3 pins for chip select: Pins 0 and 2 are
+ *                     for rank 0; pins 1 and 3 are for rank 1, if the memory
+ *                     is dual-rank.
+ * @MEM_RDR:           Registered SDR SDRAM
+ * @MEM_DDR:           Double data rate SDRAM
+ *                     http://en.wikipedia.org/wiki/DDR_SDRAM
+ * @MEM_RDDR:          Registered Double data rate SDRAM
+ *                     This is a variant of the DDR memories.
+ *                     A registered memory has a buffer inside it, hiding
+ *                     part of the memory details to the memory controller.
+ * @MEM_RMBS:          Rambus DRAM, used on a few Pentium III/IV controllers.
+ * @MEM_DDR2:          DDR2 RAM, as described at JEDEC JESD79-2F.
+ *                     Those memories are labed as "PC2-" instead of "PC" to
+ *                     differenciate from DDR.
+ * @MEM_FB_DDR2:       Fully-Buffered DDR2, as described at JEDEC Std No. 205
+ *                     and JESD206.
+ *                     Those memories are accessed per DIMM slot, and not by
+ *                     a chip select signal.
+ * @MEM_RDDR2:         Registered DDR2 RAM
+ *                     This is a variant of the DDR2 memories.
+ * @MEM_XDR:           Rambus XDR
+ *                     It is an evolution of the original RAMBUS memories,
+ *                     created to compete with DDR2. Weren't used on any
+ *                     x86 arch, but cell_edac PPC memory controller uses it.
+ * @MEM_DDR3:          DDR3 RAM
+ * @MEM_RDDR3:         Registered DDR3 RAM
+ *                     This is a variant of the DDR3 memories.
+ */
 enum mem_type {
-       MEM_EMPTY = 0,          /* Empty csrow */
-       MEM_RESERVED,           /* Reserved csrow type */
-       MEM_UNKNOWN,            /* Unknown csrow type */
-       MEM_FPM,                /* Fast page mode */
-       MEM_EDO,                /* Extended data out */
-       MEM_BEDO,               /* Burst Extended data out */
-       MEM_SDR,                /* Single data rate SDRAM */
-       MEM_RDR,                /* Registered single data rate SDRAM */
-       MEM_DDR,                /* Double data rate SDRAM */
-       MEM_RDDR,               /* Registered Double data rate SDRAM */
-       MEM_RMBS,               /* Rambus DRAM */
-       MEM_DDR2,               /* DDR2 RAM */
-       MEM_FB_DDR2,            /* fully buffered DDR2 */
-       MEM_RDDR2,              /* Registered DDR2 RAM */
-       MEM_XDR,                /* Rambus XDR */
-       MEM_DDR3,               /* DDR3 RAM */
-       MEM_RDDR3,              /* Registered DDR3 RAM */
+       MEM_EMPTY = 0,
+       MEM_RESERVED,
+       MEM_UNKNOWN,
+       MEM_FPM,
+       MEM_EDO,
+       MEM_BEDO,
+       MEM_SDR,
+       MEM_RDR,
+       MEM_DDR,
+       MEM_RDDR,
+       MEM_RMBS,
+       MEM_DDR2,
+       MEM_FB_DDR2,
+       MEM_RDDR2,
+       MEM_XDR,
+       MEM_DDR3,
+       MEM_RDDR3,
 };
 
 #define MEM_FLAG_EMPTY         BIT(MEM_EMPTY)
@@ -166,8 +205,9 @@ enum scrub_type {
 #define OP_OFFLINE             0x300
 
 /*
- * There are several things to be aware of that aren't at all obvious:
+ * Concepts used at the EDAC subsystem
  *
+ * There are several things to be aware of that aren't at all obvious:
  *
  * SOCKETS, SOCKET SETS, BANKS, ROWS, CHIP-SELECT ROWS, CHANNELS, etc..
  *
@@ -176,36 +216,61 @@ enum scrub_type {
  * creating a common ground for discussion, terms and their definitions
  * will be established.
  *
- * Memory devices:     The individual chip on a memory stick.  These devices
- *                     commonly output 4 and 8 bits each.  Grouping several
- *                     of these in parallel provides 64 bits which is common
- *                     for a memory stick.
+ * Memory devices:     The individual DRAM chips on a memory stick.  These
+ *                     devices commonly output 4 and 8 bits each (x4, x8).
+ *                     Grouping several of these in parallel provides the
+ *                     number of bits that the memory controller expects:
+ *                     typically 72 bits, in order to provide 64 bits +
+ *                     8 bits of ECC data.
  *
  * Memory Stick:       A printed circuit board that aggregates multiple
- *                     memory devices in parallel.  This is the atomic
- *                     memory component that is purchaseable by Joe consumer
- *                     and loaded into a memory socket.
+ *                     memory devices in parallel.  In general, this is the
+ *                     Field Replaceable Unit (FRU) which gets replaced, in
+ *                     the case of excessive errors. Most often it is also
+ *                     called DIMM (Dual Inline Memory Module).
+ *
+ * Memory Socket:      A physical connector on the motherboard that accepts
+ *                     a single memory stick. Also called as "slot" on several
+ *                     datasheets.
  *
- * Socket:             A physical connector on the motherboard that accepts
- *                     a single memory stick.
+ * Channel:            A memory controller channel, responsible to communicate
+ *                     with a group of DIMMs. Each channel has its own
+ *                     independent control (command) and data bus, and can
+ *                     be used independently or grouped with other channels.
  *
- * Channel:            Set of memory devices on a memory stick that must be
- *                     grouped in parallel with one or more additional
- *                     channels from other memory sticks.  This parallel
- *                     grouping of the output from multiple channels are
- *                     necessary for the smallest granularity of memory access.
- *                     Some memory controllers are capable of single channel -
- *                     which means that memory sticks can be loaded
- *                     individually.  Other memory controllers are only
- *                     capable of dual channel - which means that memory
- *                     sticks must be loaded as pairs (see "socket set").
+ * Branch:             It is typically the highest hierarchy on a
+ *                     Fully-Buffered DIMM memory controller.
+ *                     Typically, it contains two channels.
+ *                     Two channels at the same branch can be used in single
+ *                     mode or in lockstep mode.
+ *                     When lockstep is enabled, the cacheline is doubled,
+ *                     but it generally brings some performance penalty.
+ *                     Also, it is generally not possible to point to just one
+ *                     memory stick when an error occurs, as the error
+ *                     correction code is calculated using two DIMMs instead
+ *                     of one. Due to that, it is capable of correcting more
+ *                     errors than on single mode.
  *
- * Chip-select row:    All of the memory devices that are selected together.
- *                     for a single, minimum grain of memory access.
- *                     This selects all of the parallel memory devices across
- *                     all of the parallel channels.  Common chip-select rows
- *                     for single channel are 64 bits, for dual channel 128
- *                     bits.
+ * Single-channel:     The data accessed by the memory controller is contained
+ *                     into one dimm only. E. g. if the data is 64 bits-wide,
+ *                     the data flows to the CPU using one 64 bits parallel
+ *                     access.
+ *                     Typically used with SDR, DDR, DDR2 and DDR3 memories.
+ *                     FB-DIMM and RAMBUS use a different concept for channel,
+ *                     so this concept doesn't apply there.
+ *
+ * Double-channel:     The data size accessed by the memory controller is
+ *                     interlaced into two dimms, accessed at the same time.
+ *                     E. g. if the DIMM is 64 bits-wide (72 bits with ECC),
+ *                     the data flows to the CPU using a 128 bits parallel
+ *                     access.
+ *
+ * Chip-select row:    This is the name of the DRAM signal used to select the
+ *                     DRAM ranks to be accessed. Common chip-select rows for
+ *                     single channel are 64 bits, for dual channel 128 bits.
+ *                     It may not be visible by the memory controller, as some
+ *                     DIMM types have a memory buffer that can hide direct
+ *                     access to it from the Memory Controller.
  *
  * Single-Ranked stick:        A Single-ranked stick has 1 chip-select row of memory.
  *                     Motherboards commonly drive two chip-select pins to
@@ -218,8 +283,8 @@ enum scrub_type {
  *
  * Double-sided stick: DEPRECATED TERM, see Double-Ranked stick.
  *                     A double-sided stick has two chip-select rows which
- *                     access different sets of memory devices.  The two
- *                     rows cannot be accessed concurrently.  "Double-sided"
+ *                     access different sets of memory devices. The two
+ *                     rows cannot be accessed concurrently. "Double-sided"
  *                     is irrespective of the memory devices being mounted
  *                     on both sides of the memory stick.
  *
@@ -247,10 +312,22 @@ enum scrub_type {
  * PS - I enjoyed writing all that about as much as you enjoyed reading it.
  */
 
-struct channel_info {
-       int chan_idx;           /* channel index */
-       u32 ce_count;           /* Correctable Errors for this CHANNEL */
-       char label[EDAC_MC_LABEL_LEN + 1];      /* DIMM label on motherboard */
+/**
+ * struct rank_info - contains the information for one DIMM rank
+ *
+ * @chan_idx:  channel number where the rank is (typically, 0 or 1)
+ * @ce_count:  number of correctable errors for this rank
+ * @label:     DIMM label. Different ranks for the same DIMM should be
+ *             filled, on userspace, with the same label.
+ *             FIXME: The core currently won't enforce it.
+ * @csrow:     A pointer to the chip select row structure (the parent
+ *             structure). The location of the rank is given by
+ *             the (csrow->csrow_idx, chan_idx) vector.
+ */
+struct rank_info {
+       int chan_idx;
+       u32 ce_count;
+       char label[EDAC_MC_LABEL_LEN + 1];
        struct csrow_info *csrow;       /* the parent */
 };
 
@@ -274,7 +351,7 @@ struct csrow_info {
 
        /* channel information for this csrow */
        u32 nr_channels;
-       struct channel_info *channels;
+       struct rank_info *channels;
 };
 
 struct mcidev_sysfs_group {
index 47fbf6b..88ec806 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/pstore.h>
 
 #include <asm/page.h>
-#include <asm/system.h>
 
 #define EFI_SUCCESS            0
 #define EFI_LOAD_ERROR          ( 1 | (1UL << (BITS_PER_LONG-1)))
index ed5a467..6155ecf 100644 (file)
 #define GPIOF_OUT_INIT_LOW     (GPIOF_DIR_OUT | GPIOF_INIT_LOW)
 #define GPIOF_OUT_INIT_HIGH    (GPIOF_DIR_OUT | GPIOF_INIT_HIGH)
 
+/* Gpio pin is open drain */
+#define GPIOF_OPEN_DRAIN       (1 << 2)
+
+/* Gpio pin is open source */
+#define GPIOF_OPEN_SOURCE      (1 << 3)
+
 /**
  * struct gpio - a structure describing a GPIO with configuration
  * @gpio:      the GPIO number
index 584ffa0..63904ba 100644 (file)
@@ -15,7 +15,8 @@
 
     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.                */
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+    MA 02110-1301 USA.                                                      */
 /* ------------------------------------------------------------------------- */
 
 /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
index 0f91a95..538e8f4 100644 (file)
@@ -16,7 +16,8 @@
 
     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.                */
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+    MA 02110-1301 USA.                                                      */
 /* ------------------------------------------------------------------------- */
 
 /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
index fd53bfd..8a7406b 100644 (file)
@@ -16,7 +16,8 @@
 
     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.
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+    MA 02110-1301 USA.
 */
 
 #ifndef _LINUX_I2C_DEV_H
index 34536ef..747f0cd 100644 (file)
@@ -18,7 +18,8 @@
  *
  * 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.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA.
  */
 
 #ifndef _LINUX_I2C_MUX_H
index 63f57a8..017fb40 100644 (file)
@@ -15,7 +15,8 @@
  *
  * 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.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA.
  */
 
 #ifndef _LINUX_I2C_SMBUS_H
index 8e25a91..195d8b3 100644 (file)
@@ -17,7 +17,8 @@
 
     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.               */
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+    MA 02110-1301 USA.                                                      */
 /* ------------------------------------------------------------------------- */
 
 /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and
index 7fcab23..2463b61 100644 (file)
@@ -761,7 +761,7 @@ struct twl_regulator_driver_data {
 
 /*----------------------------------------------------------------------*/
 
-int twl4030_sih_setup(int module);
+int twl4030_sih_setup(struct device *dev, int module, int irq_base);
 
 /* Offsets to Power Registers */
 #define TWL4030_VDAC_DEV_GRP           0x3B
index 7afe15f..b179749 100644 (file)
@@ -22,7 +22,6 @@
 #include <acpi/acpi.h>
 #endif
 #include <asm/byteorder.h>
-#include <asm/system.h>
 #include <asm/io.h>
 
 /* for request_sense */
index 3f830e0..2aea5d2 100644 (file)
@@ -19,7 +19,6 @@
 
 #include <linux/atomic.h>
 #include <asm/ptrace.h>
-#include <asm/system.h>
 
 /*
  * These correspond to the IORESOURCE_IRQ_* defines in
index 68e67e5..6c322a9 100644 (file)
@@ -162,6 +162,7 @@ struct kvm_pit_config {
 #define KVM_EXIT_INTERNAL_ERROR   17
 #define KVM_EXIT_OSI              18
 #define KVM_EXIT_PAPR_HCALL      19
+#define KVM_EXIT_S390_UCONTROL   20
 
 /* For KVM_EXIT_INTERNAL_ERROR */
 #define KVM_INTERNAL_ERROR_EMULATION 1
@@ -249,6 +250,11 @@ struct kvm_run {
 #define KVM_S390_RESET_CPU_INIT  8
 #define KVM_S390_RESET_IPL       16
                __u64 s390_reset_flags;
+               /* KVM_EXIT_S390_UCONTROL */
+               struct {
+                       __u64 trans_exc_code;
+                       __u32 pgm_code;
+               } s390_ucontrol;
                /* KVM_EXIT_DCR */
                struct {
                        __u32 dcrn;
@@ -273,6 +279,20 @@ struct kvm_run {
                /* Fix the size of the union. */
                char padding[256];
        };
+
+       /*
+        * shared registers between kvm and userspace.
+        * kvm_valid_regs specifies the register classes set by the host
+        * kvm_dirty_regs specified the register classes dirtied by userspace
+        * struct kvm_sync_regs is architecture specific, as well as the
+        * bits for kvm_valid_regs and kvm_dirty_regs
+        */
+       __u64 kvm_valid_regs;
+       __u64 kvm_dirty_regs;
+       union {
+               struct kvm_sync_regs regs;
+               char padding[1024];
+       } s;
 };
 
 /* for KVM_REGISTER_COALESCED_MMIO / KVM_UNREGISTER_COALESCED_MMIO */
@@ -431,6 +451,11 @@ struct kvm_ppc_pvinfo {
 
 #define KVMIO 0xAE
 
+/* machine type bits, to be used as argument to KVM_CREATE_VM */
+#define KVM_VM_S390_UCONTROL   1
+
+#define KVM_S390_SIE_PAGE_OFFSET 1
+
 /*
  * ioctls for /dev/kvm fds:
  */
@@ -555,9 +580,15 @@ struct kvm_ppc_pvinfo {
 #define KVM_CAP_PPC_SMT 64
 #define KVM_CAP_PPC_RMA        65
 #define KVM_CAP_MAX_VCPUS 66       /* returns max vcpus per vm */
+#define KVM_CAP_PPC_HIOR 67
 #define KVM_CAP_PPC_PAPR 68
+#define KVM_CAP_SW_TLB 69
+#define KVM_CAP_ONE_REG 70
 #define KVM_CAP_S390_GMAP 71
 #define KVM_CAP_TSC_DEADLINE_TIMER 72
+#define KVM_CAP_S390_UCONTROL 73
+#define KVM_CAP_SYNC_REGS 74
+#define KVM_CAP_PCI_2_3 75
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -637,6 +668,52 @@ struct kvm_clock_data {
        __u32 pad[9];
 };
 
+#define KVM_MMU_FSL_BOOKE_NOHV         0
+#define KVM_MMU_FSL_BOOKE_HV           1
+
+struct kvm_config_tlb {
+       __u64 params;
+       __u64 array;
+       __u32 mmu_type;
+       __u32 array_len;
+};
+
+struct kvm_dirty_tlb {
+       __u64 bitmap;
+       __u32 num_dirty;
+};
+
+/* Available with KVM_CAP_ONE_REG */
+
+#define KVM_REG_ARCH_MASK      0xff00000000000000ULL
+#define KVM_REG_GENERIC                0x0000000000000000ULL
+
+/*
+ * Architecture specific registers are to be defined in arch headers and
+ * ORed with the arch identifier.
+ */
+#define KVM_REG_PPC            0x1000000000000000ULL
+#define KVM_REG_X86            0x2000000000000000ULL
+#define KVM_REG_IA64           0x3000000000000000ULL
+#define KVM_REG_ARM            0x4000000000000000ULL
+#define KVM_REG_S390           0x5000000000000000ULL
+
+#define KVM_REG_SIZE_SHIFT     52
+#define KVM_REG_SIZE_MASK      0x00f0000000000000ULL
+#define KVM_REG_SIZE_U8                0x0000000000000000ULL
+#define KVM_REG_SIZE_U16       0x0010000000000000ULL
+#define KVM_REG_SIZE_U32       0x0020000000000000ULL
+#define KVM_REG_SIZE_U64       0x0030000000000000ULL
+#define KVM_REG_SIZE_U128      0x0040000000000000ULL
+#define KVM_REG_SIZE_U256      0x0050000000000000ULL
+#define KVM_REG_SIZE_U512      0x0060000000000000ULL
+#define KVM_REG_SIZE_U1024     0x0070000000000000ULL
+
+struct kvm_one_reg {
+       __u64 id;
+       __u64 addr;
+};
+
 /*
  * ioctls for VM fds
  */
@@ -655,6 +732,17 @@ struct kvm_clock_data {
                                        struct kvm_userspace_memory_region)
 #define KVM_SET_TSS_ADDR          _IO(KVMIO,   0x47)
 #define KVM_SET_IDENTITY_MAP_ADDR _IOW(KVMIO,  0x48, __u64)
+
+/* enable ucontrol for s390 */
+struct kvm_s390_ucas_mapping {
+       __u64 user_addr;
+       __u64 vcpu_addr;
+       __u64 length;
+};
+#define KVM_S390_UCAS_MAP        _IOW(KVMIO, 0x50, struct kvm_s390_ucas_mapping)
+#define KVM_S390_UCAS_UNMAP      _IOW(KVMIO, 0x51, struct kvm_s390_ucas_mapping)
+#define KVM_S390_VCPU_FAULT     _IOW(KVMIO, 0x52, unsigned long)
+
 /* Device model IOC */
 #define KVM_CREATE_IRQCHIP        _IO(KVMIO,   0x60)
 #define KVM_IRQ_LINE              _IOW(KVMIO,  0x61, struct kvm_irq_level)
@@ -697,6 +785,9 @@ struct kvm_clock_data {
 /* Available with KVM_CAP_TSC_CONTROL */
 #define KVM_SET_TSC_KHZ           _IO(KVMIO,  0xa2)
 #define KVM_GET_TSC_KHZ           _IO(KVMIO,  0xa3)
+/* Available with KVM_CAP_PCI_2_3 */
+#define KVM_ASSIGN_SET_INTX_MASK  _IOW(KVMIO,  0xa4, \
+                                      struct kvm_assigned_pci_dev)
 
 /*
  * ioctls for vcpu fds
@@ -763,8 +854,15 @@ struct kvm_clock_data {
 #define KVM_CREATE_SPAPR_TCE     _IOW(KVMIO,  0xa8, struct kvm_create_spapr_tce)
 /* Available with KVM_CAP_RMA */
 #define KVM_ALLOCATE_RMA         _IOR(KVMIO,  0xa9, struct kvm_allocate_rma)
+/* Available with KVM_CAP_SW_TLB */
+#define KVM_DIRTY_TLB            _IOW(KVMIO,  0xaa, struct kvm_dirty_tlb)
+/* Available with KVM_CAP_ONE_REG */
+#define KVM_GET_ONE_REG                  _IOW(KVMIO,  0xab, struct kvm_one_reg)
+#define KVM_SET_ONE_REG                  _IOW(KVMIO,  0xac, struct kvm_one_reg)
 
 #define KVM_DEV_ASSIGN_ENABLE_IOMMU    (1 << 0)
+#define KVM_DEV_ASSIGN_PCI_2_3         (1 << 1)
+#define KVM_DEV_ASSIGN_MASK_INTX       (1 << 2)
 
 struct kvm_assigned_pci_dev {
        __u32 assigned_dev_id;
index ca1b153..665a260 100644 (file)
@@ -172,11 +172,6 @@ static inline int kvm_vcpu_exiting_guest_mode(struct kvm_vcpu *vcpu)
  */
 #define KVM_MEM_MAX_NR_PAGES ((1UL << 31) - 1)
 
-struct kvm_lpage_info {
-       unsigned long rmap_pde;
-       int write_count;
-};
-
 struct kvm_memory_slot {
        gfn_t base_gfn;
        unsigned long npages;
@@ -185,7 +180,7 @@ struct kvm_memory_slot {
        unsigned long *dirty_bitmap;
        unsigned long *dirty_bitmap_head;
        unsigned long nr_dirty_pages;
-       struct kvm_lpage_info *lpage_info[KVM_NR_PAGE_SIZES - 1];
+       struct kvm_arch_memory_slot arch;
        unsigned long userspace_addr;
        int user_alloc;
        int id;
@@ -377,6 +372,9 @@ int kvm_set_memory_region(struct kvm *kvm,
 int __kvm_set_memory_region(struct kvm *kvm,
                            struct kvm_userspace_memory_region *mem,
                            int user_alloc);
+void kvm_arch_free_memslot(struct kvm_memory_slot *free,
+                          struct kvm_memory_slot *dont);
+int kvm_arch_create_memslot(struct kvm_memory_slot *slot, unsigned long npages);
 int kvm_arch_prepare_memory_region(struct kvm *kvm,
                                struct kvm_memory_slot *memslot,
                                struct kvm_memory_slot old,
@@ -386,6 +384,7 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
                                struct kvm_userspace_memory_region *mem,
                                struct kvm_memory_slot old,
                                int user_alloc);
+bool kvm_largepages_enabled(void);
 void kvm_disable_largepages(void);
 void kvm_arch_flush_shadow(struct kvm *kvm);
 
@@ -451,6 +450,7 @@ long kvm_arch_dev_ioctl(struct file *filp,
                        unsigned int ioctl, unsigned long arg);
 long kvm_arch_vcpu_ioctl(struct file *filp,
                         unsigned int ioctl, unsigned long arg);
+int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf);
 
 int kvm_dev_ioctl_check_extension(long ext);
 
@@ -521,7 +521,7 @@ static inline void kvm_arch_free_vm(struct kvm *kvm)
 }
 #endif
 
-int kvm_arch_init_vm(struct kvm *kvm);
+int kvm_arch_init_vm(struct kvm *kvm, unsigned long type);
 void kvm_arch_destroy_vm(struct kvm *kvm);
 void kvm_free_all_assigned_devices(struct kvm *kvm);
 void kvm_arch_sync_events(struct kvm *kvm);
@@ -547,6 +547,7 @@ struct kvm_assigned_dev_kernel {
        unsigned int entries_nr;
        int host_irq;
        bool host_irq_disabled;
+       bool pci_2_3;
        struct msix_entry *host_msix_entries;
        int guest_irq;
        struct msix_entry *guest_msix_entries;
@@ -556,6 +557,7 @@ struct kvm_assigned_dev_kernel {
        struct pci_dev *dev;
        struct kvm *kvm;
        spinlock_t intx_lock;
+       spinlock_t intx_mask_lock;
        char irq_name[32];
        struct pci_saved_state *pci_saved_state;
 };
@@ -651,11 +653,43 @@ static inline void kvm_guest_exit(void)
        current->flags &= ~PF_VCPU;
 }
 
+/*
+ * search_memslots() and __gfn_to_memslot() are here because they are
+ * used in non-modular code in arch/powerpc/kvm/book3s_hv_rm_mmu.c.
+ * gfn_to_memslot() itself isn't here as an inline because that would
+ * bloat other code too much.
+ */
+static inline struct kvm_memory_slot *
+search_memslots(struct kvm_memslots *slots, gfn_t gfn)
+{
+       struct kvm_memory_slot *memslot;
+
+       kvm_for_each_memslot(memslot, slots)
+               if (gfn >= memslot->base_gfn &&
+                     gfn < memslot->base_gfn + memslot->npages)
+                       return memslot;
+
+       return NULL;
+}
+
+static inline struct kvm_memory_slot *
+__gfn_to_memslot(struct kvm_memslots *slots, gfn_t gfn)
+{
+       return search_memslots(slots, gfn);
+}
+
 static inline int memslot_id(struct kvm *kvm, gfn_t gfn)
 {
        return gfn_to_memslot(kvm, gfn)->id;
 }
 
+static inline gfn_t gfn_to_index(gfn_t gfn, gfn_t base_gfn, int level)
+{
+       /* KVM_HPAGE_GFN_SHIFT(PT_PAGE_TABLE_LEVEL) must be 0. */
+       return (gfn >> KVM_HPAGE_GFN_SHIFT(level)) -
+               (base_gfn >> KVM_HPAGE_GFN_SHIFT(level));
+}
+
 static inline unsigned long gfn_to_hva_memslot(struct kvm_memory_slot *slot,
                                               gfn_t gfn)
 {
@@ -702,12 +736,16 @@ static inline int mmu_notifier_retry(struct kvm_vcpu *vcpu, unsigned long mmu_se
        if (unlikely(vcpu->kvm->mmu_notifier_count))
                return 1;
        /*
-        * Both reads happen under the mmu_lock and both values are
-        * modified under mmu_lock, so there's no need of smb_rmb()
-        * here in between, otherwise mmu_notifier_count should be
-        * read before mmu_notifier_seq, see
-        * mmu_notifier_invalidate_range_end write side.
+        * Ensure the read of mmu_notifier_count happens before the read
+        * of mmu_notifier_seq.  This interacts with the smp_wmb() in
+        * mmu_notifier_invalidate_range_end to make sure that the caller
+        * either sees the old (non-zero) value of mmu_notifier_count or
+        * the new (incremented) value of mmu_notifier_seq.
+        * PowerPC Book3s HV KVM calls this under a per-page lock
+        * rather than under kvm->mmu_lock, for scalability, so
+        * can't rely on kvm->mmu_lock to keep things ordered.
         */
+       smp_rmb();
        if (vcpu->kvm->mmu_notifier_seq != mmu_seq)
                return 1;
        return 0;
@@ -770,6 +808,13 @@ static inline bool kvm_vcpu_is_bsp(struct kvm_vcpu *vcpu)
 {
        return vcpu->kvm->bsp_vcpu_id == vcpu->vcpu_id;
 }
+
+bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu);
+
+#else
+
+static inline bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu) { return true; }
+
 #endif
 
 #ifdef __KVM_HAVE_DEVICE_ASSIGNMENT
index 801b44b..a5199f6 100644 (file)
@@ -56,8 +56,7 @@
  */
 
 #include <linux/kernel.h>
-#include <asm/system.h>
-#include <asm/processor.h>
+#include <asm/cmpxchg.h>
 
 struct llist_head {
        struct llist_node *first;
index 88e78de..eab507f 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/path.h>
 #include <linux/key.h>
 #include <linux/skbuff.h>
-#include <asm/system.h>
 
 
 /* Auxiliary data to use in generating the audit record. */
index 92be347..84d071a 100644 (file)
@@ -263,6 +263,22 @@ enum {
 #define PM8607_PD_PREBIAS_MASK         (0x1F << 0)
 #define PM8607_PD_PRECHG_MASK          (7 << 5)
 
+#define PM8606_REF_GP_OSC_OFF         0
+#define PM8606_REF_GP_OSC_ON          1
+#define PM8606_REF_GP_OSC_UNKNOWN     2
+
+/* Clients of reference group and 8MHz oscillator in 88PM8606 */
+enum pm8606_ref_gp_and_osc_clients {
+       REF_GP_NO_CLIENTS       = 0,
+       WLED1_DUTY              = (1<<0), /*PF 0x02.7:0*/
+       WLED2_DUTY              = (1<<1), /*PF 0x04.7:0*/
+       WLED3_DUTY              = (1<<2), /*PF 0x06.7:0*/
+       RGB1_ENABLE             = (1<<3), /*PF 0x07.1*/
+       RGB2_ENABLE             = (1<<4), /*PF 0x07.2*/
+       LDO_VBR_EN              = (1<<5), /*PF 0x12.0*/
+       REF_GP_MAX_CLIENT       = 0xFFFF
+};
+
 /* Interrupt Number in 88PM8607 */
 enum {
        PM8607_IRQ_ONKEY,
@@ -298,6 +314,7 @@ enum {
 struct pm860x_chip {
        struct device           *dev;
        struct mutex            irq_lock;
+       struct mutex            osc_lock;
        struct i2c_client       *client;
        struct i2c_client       *companion;     /* companion chip client */
        struct regmap           *regmap;
@@ -305,12 +322,15 @@ struct pm860x_chip {
 
        int                     buck3_double;   /* DVC ramp slope double */
        unsigned short          companion_addr;
+       unsigned short          osc_vote;
        int                     id;
        int                     irq_mode;
        int                     irq_base;
        int                     core_irq;
        unsigned char           chip_version;
+       unsigned char           osc_status;
 
+       unsigned int            wakeup_flag;
 };
 
 enum {
@@ -369,6 +389,9 @@ struct pm860x_platform_data {
        int             num_regulators;
 };
 
+extern int pm8606_osc_enable(struct pm860x_chip *, unsigned short);
+extern int pm8606_osc_disable(struct pm860x_chip *, unsigned short);
+
 extern int pm860x_reg_read(struct i2c_client *, int);
 extern int pm860x_reg_write(struct i2c_client *, int, unsigned char);
 extern int pm860x_bulk_read(struct i2c_client *, int, int, unsigned char *);
index e20dd6e..5fa6974 100644 (file)
@@ -34,13 +34,6 @@ struct device;
 #define AB5500_1_1     0x21
 #define AB5500_2_0     0x24
 
-/* AB8500 CIDs*/
-#define AB8500_CUT1P0  0x10
-#define AB8500_CUT1P1  0x11
-#define AB8500_CUT2P0  0x20
-#define AB8500_CUT3P0  0x30
-#define AB8500_CUT3P3  0x33
-
 /*
  * AB3100, EVENTA1, A2 and A3 event register flags
  * these are catenated into a single 32-bit flag in the code
index 488a8c9..2387c20 100644 (file)
 
 /*
  * Platform data to register a block: only the initial gpio/irq number.
+ * Array sizes are large enough to contain all AB8500 and AB9540 GPIO
+ * registers.
  */
 
 struct ab8500_gpio_platform_data {
        int gpio_base;
        u32 irq_base;
-       u8  config_reg[7];
+       u8  config_reg[8];
 };
 
 #endif /* _AB8500_GPIO_H */
index 10da029..10eb509 100644 (file)
@@ -71,6 +71,13 @@ static inline int ab8500_sysctrl_clear(u16 reg, u8 bits)
 #define AB8500_SWATCTRL                        0x230
 #define AB8500_HIQCLKCTRL              0x232
 #define AB8500_VSIMSYSCLKCTRL          0x233
+#define AB9540_SYSCLK12BUFCTRL         0x234
+#define AB9540_SYSCLK12CONFCTRL                0x235
+#define AB9540_SYSCLK12BUFCTRL2                0x236
+#define AB9540_SYSCLK12BUF1VALID       0x237
+#define AB9540_SYSCLK12BUF2VALID       0x238
+#define AB9540_SYSCLK12BUF3VALID       0x239
+#define AB9540_SYSCLK12BUF4VALID       0x23A
 
 /* Bits */
 #define AB8500_TURNONSTATUS_PORNVBAT BIT(0)
@@ -251,4 +258,40 @@ static inline int ab8500_sysctrl_clear(u16 reg, u8 bits)
 #define AB8500_VSIMSYSCLKCTRL_VSIMSYSCLKREQ7VALID BIT(6)
 #define AB8500_VSIMSYSCLKCTRL_VSIMSYSCLKREQ8VALID BIT(7)
 
+#define AB9540_SYSCLK12BUFCTRL_SYSCLK12BUF1ENA BIT(0)
+#define AB9540_SYSCLK12BUFCTRL_SYSCLK12BUF2ENA BIT(1)
+#define AB9540_SYSCLK12BUFCTRL_SYSCLK12BUF3ENA BIT(2)
+#define AB9540_SYSCLK12BUFCTRL_SYSCLK12BUF4ENA BIT(3)
+#define AB9540_SYSCLK12BUFCTRL_SYSCLK12BUFENA_MASK 0x0F
+#define AB9540_SYSCLK12BUFCTRL_SYSCLK12BUF1STRE BIT(4)
+#define AB9540_SYSCLK12BUFCTRL_SYSCLK12BUF2STRE BIT(5)
+#define AB9540_SYSCLK12BUFCTRL_SYSCLK12BUF3STRE BIT(6)
+#define AB9540_SYSCLK12BUFCTRL_SYSCLK12BUF4STRE BIT(7)
+#define AB9540_SYSCLK12BUFCTRL_SYSCLK12BUFSTRE_MASK 0xF0
+
+#define AB9540_SYSCLK12CONFCTRL_PLL26TO38ENA BIT(0)
+#define AB9540_SYSCLK12CONFCTRL_SYSCLK12USBMUXSEL BIT(1)
+#define AB9540_SYSCLK12CONFCTRL_INT384MHZMUXSEL_MASK 0x0C
+#define AB9540_SYSCLK12CONFCTRL_INT384MHZMUXSEL_SHIFT 2
+#define AB9540_SYSCLK12CONFCTRL_SYSCLK12BUFMUX BIT(4)
+#define AB9540_SYSCLK12CONFCTRL_SYSCLK12PLLMUX BIT(5)
+#define AB9540_SYSCLK12CONFCTRL_SYSCLK2MUXVALID BIT(6)
+
+#define AB9540_SYSCLK12BUFCTRL2_SYSCLK12BUF1PDENA BIT(0)
+#define AB9540_SYSCLK12BUFCTRL2_SYSCLK12BUF2PDENA BIT(1)
+#define AB9540_SYSCLK12BUFCTRL2_SYSCLK12BUF3PDENA BIT(2)
+#define AB9540_SYSCLK12BUFCTRL2_SYSCLK12BUF4PDENA BIT(3)
+
+#define AB9540_SYSCLK12BUF1VALID_SYSCLK12BUF1VALID_MASK 0xFF
+#define AB9540_SYSCLK12BUF1VALID_SYSCLK12BUF1VALID_SHIFT 0
+
+#define AB9540_SYSCLK12BUF2VALID_SYSCLK12BUF2VALID_MASK 0xFF
+#define AB9540_SYSCLK12BUF2VALID_SYSCLK12BUF2VALID_SHIFT 0
+
+#define AB9540_SYSCLK12BUF3VALID_SYSCLK12BUF3VALID_MASK 0xFF
+#define AB9540_SYSCLK12BUF3VALID_SYSCLK12BUF3VALID_SHIFT 0
+
+#define AB9540_SYSCLK12BUF4VALID_SYSCLK12BUF4VALID_MASK 0xFF
+#define AB9540_SYSCLK12BUF4VALID_SYSCLK12BUF4VALID_SHIFT 0
+
 #endif /* __AB8500_SYSCTRL_H */
index dca9439..fccc300 100644 (file)
 struct device;
 
 /*
+ * AB IC versions
+ *
+ * AB8500_VERSION_AB8500 should be 0xFF but will never be read as need a
+ * non-supported multi-byte I2C access via PRCMU. Set to 0x00 to ease the
+ * print of version string.
+ */
+enum ab8500_version {
+       AB8500_VERSION_AB8500 = 0x0,
+       AB8500_VERSION_AB8505 = 0x1,
+       AB8500_VERSION_AB9540 = 0x2,
+       AB8500_VERSION_AB8540 = 0x3,
+       AB8500_VERSION_UNDEFINED,
+};
+
+/* AB8500 CIDs*/
+#define AB8500_CUTEARLY        0x00
+#define AB8500_CUT1P0  0x10
+#define AB8500_CUT1P1  0x11
+#define AB8500_CUT2P0  0x20
+#define AB8500_CUT3P0  0x30
+#define AB8500_CUT3P3  0x33
+
+/*
  * AB8500 bank addresses
  */
 #define AB8500_SYS_CTRL1_BLOCK 0x1
@@ -37,30 +60,34 @@ struct device;
 
 /*
  * Interrupts
+ * Values used to index into array ab8500_irq_regoffset[] defined in
+ * drivers/mdf/ab8500-core.c
  */
-
-#define AB8500_INT_MAIN_EXT_CH_NOT_OK  0
-#define AB8500_INT_UN_PLUG_TV_DET      1
-#define AB8500_INT_PLUG_TV_DET         2
+/* Definitions for AB8500 and AB9540 */
+/* ab8500_irq_regoffset[0] -> IT[Source|Latch|Mask]1 */
+#define AB8500_INT_MAIN_EXT_CH_NOT_OK  0 /* not 8505/9540 */
+#define AB8500_INT_UN_PLUG_TV_DET      1 /* not 8505/9540 */
+#define AB8500_INT_PLUG_TV_DET         2 /* not 8505/9540 */
 #define AB8500_INT_TEMP_WARM           3
 #define AB8500_INT_PON_KEY2DB_F                4
 #define AB8500_INT_PON_KEY2DB_R                5
 #define AB8500_INT_PON_KEY1DB_F                6
 #define AB8500_INT_PON_KEY1DB_R                7
+/* ab8500_irq_regoffset[1] -> IT[Source|Latch|Mask]2 */
 #define AB8500_INT_BATT_OVV            8
-#define AB8500_INT_MAIN_CH_UNPLUG_DET  10
-#define AB8500_INT_MAIN_CH_PLUG_DET    11
-#define AB8500_INT_USB_ID_DET_F                12
-#define AB8500_INT_USB_ID_DET_R                13
+#define AB8500_INT_MAIN_CH_UNPLUG_DET  10 /* not 8505 */
+#define AB8500_INT_MAIN_CH_PLUG_DET    11 /* not 8505 */
 #define AB8500_INT_VBUS_DET_F          14
 #define AB8500_INT_VBUS_DET_R          15
+/* ab8500_irq_regoffset[2] -> IT[Source|Latch|Mask]3 */
 #define AB8500_INT_VBUS_CH_DROP_END    16
 #define AB8500_INT_RTC_60S             17
 #define AB8500_INT_RTC_ALARM           18
 #define AB8500_INT_BAT_CTRL_INDB       20
 #define AB8500_INT_CH_WD_EXP           21
 #define AB8500_INT_VBUS_OVV            22
-#define AB8500_INT_MAIN_CH_DROP_END    23
+#define AB8500_INT_MAIN_CH_DROP_END    23 /* not 8505/9540 */
+/* ab8500_irq_regoffset[3] -> IT[Source|Latch|Mask]4 */
 #define AB8500_INT_CCN_CONV_ACC                24
 #define AB8500_INT_INT_AUD             25
 #define AB8500_INT_CCEOC               26
@@ -69,7 +96,8 @@ struct device;
 #define AB8500_INT_LOW_BAT_R           29
 #define AB8500_INT_BUP_CHG_NOT_OK      30
 #define AB8500_INT_BUP_CHG_OK          31
-#define AB8500_INT_GP_HW_ADC_CONV_END  32
+/* ab8500_irq_regoffset[4] -> IT[Source|Latch|Mask]5 */
+#define AB8500_INT_GP_HW_ADC_CONV_END  32 /* not 8505 */
 #define AB8500_INT_ACC_DETECT_1DB_F    33
 #define AB8500_INT_ACC_DETECT_1DB_R    34
 #define AB8500_INT_ACC_DETECT_22DB_F   35
@@ -77,38 +105,43 @@ struct device;
 #define AB8500_INT_ACC_DETECT_21DB_F   37
 #define AB8500_INT_ACC_DETECT_21DB_R   38
 #define AB8500_INT_GP_SW_ADC_CONV_END  39
-#define AB8500_INT_GPIO6R              40
-#define AB8500_INT_GPIO7R              41
-#define AB8500_INT_GPIO8R              42
-#define AB8500_INT_GPIO9R              43
+/* ab8500_irq_regoffset[5] -> IT[Source|Latch|Mask]7 */
+#define AB8500_INT_GPIO6R              40 /* not 8505/9540 */
+#define AB8500_INT_GPIO7R              41 /* not 8505/9540 */
+#define AB8500_INT_GPIO8R              42 /* not 8505/9540 */
+#define AB8500_INT_GPIO9R              43 /* not 8505/9540 */
 #define AB8500_INT_GPIO10R             44
 #define AB8500_INT_GPIO11R             45
-#define AB8500_INT_GPIO12R             46
+#define AB8500_INT_GPIO12R             46 /* not 8505 */
 #define AB8500_INT_GPIO13R             47
-#define AB8500_INT_GPIO24R             48
-#define AB8500_INT_GPIO25R             49
-#define AB8500_INT_GPIO36R             50
-#define AB8500_INT_GPIO37R             51
-#define AB8500_INT_GPIO38R             52
-#define AB8500_INT_GPIO39R             53
+/* ab8500_irq_regoffset[6] -> IT[Source|Latch|Mask]8 */
+#define AB8500_INT_GPIO24R             48 /* not 8505 */
+#define AB8500_INT_GPIO25R             49 /* not 8505 */
+#define AB8500_INT_GPIO36R             50 /* not 8505/9540 */
+#define AB8500_INT_GPIO37R             51 /* not 8505/9540 */
+#define AB8500_INT_GPIO38R             52 /* not 8505/9540 */
+#define AB8500_INT_GPIO39R             53 /* not 8505/9540 */
 #define AB8500_INT_GPIO40R             54
 #define AB8500_INT_GPIO41R             55
-#define AB8500_INT_GPIO6F              56
-#define AB8500_INT_GPIO7F              57
-#define AB8500_INT_GPIO8F              58
-#define AB8500_INT_GPIO9F              59
+/* ab8500_irq_regoffset[7] -> IT[Source|Latch|Mask]9 */
+#define AB8500_INT_GPIO6F              56 /* not 8505/9540 */
+#define AB8500_INT_GPIO7F              57 /* not 8505/9540 */
+#define AB8500_INT_GPIO8F              58 /* not 8505/9540 */
+#define AB8500_INT_GPIO9F              59 /* not 8505/9540 */
 #define AB8500_INT_GPIO10F             60
 #define AB8500_INT_GPIO11F             61
-#define AB8500_INT_GPIO12F             62
+#define AB8500_INT_GPIO12F             62 /* not 8505 */
 #define AB8500_INT_GPIO13F             63
-#define AB8500_INT_GPIO24F             64
-#define AB8500_INT_GPIO25F             65
-#define AB8500_INT_GPIO36F             66
-#define AB8500_INT_GPIO37F             67
-#define AB8500_INT_GPIO38F             68
-#define AB8500_INT_GPIO39F             69
+/* ab8500_irq_regoffset[8] -> IT[Source|Latch|Mask]10 */
+#define AB8500_INT_GPIO24F             64 /* not 8505 */
+#define AB8500_INT_GPIO25F             65 /* not 8505 */
+#define AB8500_INT_GPIO36F             66 /* not 8505/9540 */
+#define AB8500_INT_GPIO37F             67 /* not 8505/9540 */
+#define AB8500_INT_GPIO38F             68 /* not 8505/9540 */
+#define AB8500_INT_GPIO39F             69 /* not 8505/9540 */
 #define AB8500_INT_GPIO40F             70
 #define AB8500_INT_GPIO41F             71
+/* ab8500_irq_regoffset[9] -> IT[Source|Latch|Mask]12 */
 #define AB8500_INT_ADP_SOURCE_ERROR    72
 #define AB8500_INT_ADP_SINK_ERROR      73
 #define AB8500_INT_ADP_PROBE_PLUG      74
@@ -116,30 +149,67 @@ struct device;
 #define AB8500_INT_ADP_SENSE_OFF       76
 #define AB8500_INT_USB_PHY_POWER_ERR   78
 #define AB8500_INT_USB_LINK_STATUS     79
+/* ab8500_irq_regoffset[10] -> IT[Source|Latch|Mask]19 */
 #define AB8500_INT_BTEMP_LOW           80
 #define AB8500_INT_BTEMP_LOW_MEDIUM    81
 #define AB8500_INT_BTEMP_MEDIUM_HIGH   82
 #define AB8500_INT_BTEMP_HIGH          83
-#define AB8500_INT_USB_CHARGER_NOT_OK  89
+/* ab8500_irq_regoffset[11] -> IT[Source|Latch|Mask]20 */
+#define AB8500_INT_SRP_DETECT          88
+#define AB8500_INT_USB_CHARGER_NOT_OKR 89
 #define AB8500_INT_ID_WAKEUP_R         90
 #define AB8500_INT_ID_DET_R1R          92
 #define AB8500_INT_ID_DET_R2R          93
 #define AB8500_INT_ID_DET_R3R          94
 #define AB8500_INT_ID_DET_R4R          95
+/* ab8500_irq_regoffset[12] -> IT[Source|Latch|Mask]21 */
 #define AB8500_INT_ID_WAKEUP_F         96
 #define AB8500_INT_ID_DET_R1F          98
 #define AB8500_INT_ID_DET_R2F          99
 #define AB8500_INT_ID_DET_R3F          100
 #define AB8500_INT_ID_DET_R4F          101
-#define AB8500_INT_USB_CHG_DET_DONE    102
+#define AB8500_INT_CHAUTORESTARTAFTSEC  102
+#define AB8500_INT_CHSTOPBYSEC         103
+/* ab8500_irq_regoffset[13] -> IT[Source|Latch|Mask]22 */
 #define AB8500_INT_USB_CH_TH_PROT_F    104
 #define AB8500_INT_USB_CH_TH_PROT_R    105
-#define AB8500_INT_MAIN_CH_TH_PROT_F   106
-#define AB8500_INT_MAIN_CH_TH_PROT_R   107
-#define AB8500_INT_USB_CHARGER_NOT_OKF 111
+#define AB8500_INT_MAIN_CH_TH_PROT_F   106 /* not 8505/9540 */
+#define AB8500_INT_MAIN_CH_TH_PROT_R   107 /* not 8505/9540 */
+#define AB8500_INT_CHCURLIMNOHSCHIRP   109
+#define AB8500_INT_CHCURLIMHSCHIRP     110
+#define AB8500_INT_XTAL32K_KO          111
+
+/* Definitions for AB9540 */
+/* ab8500_irq_regoffset[14] -> IT[Source|Latch|Mask]13 */
+#define AB9540_INT_GPIO50R             113
+#define AB9540_INT_GPIO51R             114 /* not 8505 */
+#define AB9540_INT_GPIO52R             115
+#define AB9540_INT_GPIO53R             116
+#define AB9540_INT_GPIO54R             117 /* not 8505 */
+#define AB9540_INT_IEXT_CH_RF_BFN_R    118
+#define AB9540_INT_IEXT_CH_RF_BFN_F    119
+/* ab8500_irq_regoffset[15] -> IT[Source|Latch|Mask]14 */
+#define AB9540_INT_GPIO50F             121
+#define AB9540_INT_GPIO51F             122 /* not 8505 */
+#define AB9540_INT_GPIO52F             123
+#define AB9540_INT_GPIO53F             124
+#define AB9540_INT_GPIO54F             125 /* not 8505 */
 
+/*
+ * AB8500_AB9540_NR_IRQS is used when configuring the IRQ numbers for the
+ * entire platform. This is a "compile time" constant so this must be set to
+ * the largest possible value that may be encountered with different AB SOCs.
+ * Of the currently supported AB devices, AB8500 and AB9540, it is the AB9540
+ * which is larger.
+ */
 #define AB8500_NR_IRQS                 112
+#define AB8505_NR_IRQS                 128
+#define AB9540_NR_IRQS                 128
+/* This is set to the roof of any AB8500 chip variant IRQ counts */
+#define AB8500_MAX_NR_IRQS             AB9540_NR_IRQS
+
 #define AB8500_NUM_IRQ_REGS            14
+#define AB9540_NUM_IRQ_REGS            17
 
 /**
  * struct ab8500 - ab8500 internal structure
@@ -147,13 +217,18 @@ struct device;
  * @lock: read/write operations lock
  * @irq_lock: genirq bus lock
  * @irq: irq line
+ * @version: chip version id (e.g. ab8500 or ab9540)
  * @chip_id: chip revision id
  * @write: register write
+ * @write_masked: masked register write
  * @read: register read
  * @rx_buf: rx buf for SPI
  * @tx_buf: tx buf for SPI
  * @mask: cache of IRQ regs for bus lock
  * @oldmask: cache of previous IRQ regs for bus lock
+ * @mask_size: Actual number of valid entries in mask[], oldmask[] and
+ * irq_reg_offset
+ * @irq_reg_offset: Array of offsets into IRQ registers
  */
 struct ab8500 {
        struct device   *dev;
@@ -162,16 +237,20 @@ struct ab8500 {
 
        int             irq_base;
        int             irq;
+       enum ab8500_version version;
        u8              chip_id;
 
-       int (*write) (struct ab8500 *a8500, u16 addr, u8 data);
-       int (*read) (struct ab8500 *a8500, u16 addr);
+       int (*write)(struct ab8500 *ab8500, u16 addr, u8 data);
+       int (*write_masked)(struct ab8500 *ab8500, u16 addr, u8 mask, u8 data);
+       int (*read)(struct ab8500 *ab8500, u16 addr);
 
        unsigned long   tx_buf[4];
        unsigned long   rx_buf[4];
 
-       u8 mask[AB8500_NUM_IRQ_REGS];
-       u8 oldmask[AB8500_NUM_IRQ_REGS];
+       u8 *mask;
+       u8 *oldmask;
+       int mask_size;
+       const int *irq_reg_offset;
 };
 
 struct regulator_reg_init;
@@ -197,7 +276,52 @@ struct ab8500_platform_data {
        struct ab8500_gpio_platform_data *gpio;
 };
 
-extern int __devinit ab8500_init(struct ab8500 *ab8500);
+extern int __devinit ab8500_init(struct ab8500 *ab8500,
+                                enum ab8500_version version);
 extern int __devexit ab8500_exit(struct ab8500 *ab8500);
 
+static inline int is_ab8500(struct ab8500 *ab)
+{
+       return ab->version == AB8500_VERSION_AB8500;
+}
+
+static inline int is_ab8505(struct ab8500 *ab)
+{
+       return ab->version == AB8500_VERSION_AB8505;
+}
+
+static inline int is_ab9540(struct ab8500 *ab)
+{
+       return ab->version == AB8500_VERSION_AB9540;
+}
+
+static inline int is_ab8540(struct ab8500 *ab)
+{
+       return ab->version == AB8500_VERSION_AB8540;
+}
+
+/* exclude also ab8505, ab9540... */
+static inline int is_ab8500_1p0_or_earlier(struct ab8500 *ab)
+{
+       return (is_ab8500(ab) && (ab->chip_id <= AB8500_CUT1P0));
+}
+
+/* exclude also ab8505, ab9540... */
+static inline int is_ab8500_1p1_or_earlier(struct ab8500 *ab)
+{
+       return (is_ab8500(ab) && (ab->chip_id <= AB8500_CUT1P1));
+}
+
+/* exclude also ab8505, ab9540... */
+static inline int is_ab8500_2p0_or_earlier(struct ab8500 *ab)
+{
+       return (is_ab8500(ab) && (ab->chip_id <= AB8500_CUT2P0));
+}
+
+/* exclude also ab8505, ab9540... */
+static inline int is_ab8500_2p0(struct ab8500 *ab)
+{
+       return (is_ab8500(ab) && (ab->chip_id == AB8500_CUT2P0));
+}
+
 #endif /* MFD_AB8500_H */
diff --git a/include/linux/mfd/anatop.h b/include/linux/mfd/anatop.h
new file mode 100644 (file)
index 0000000..22c1007
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * anatop.h - Anatop MFD driver
+ *
+ *  Copyright (C) 2012 Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
+ *  Copyright (C) 2012 Linaro
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __LINUX_MFD_ANATOP_H
+#define __LINUX_MFD_ANATOP_H
+
+#include <linux/spinlock.h>
+
+/**
+ * anatop - MFD data
+ * @ioreg: ioremap register
+ * @reglock: spinlock for register read/write
+ */
+struct anatop {
+       void *ioreg;
+       spinlock_t reglock;
+};
+
+extern u32 anatop_get_bits(struct anatop *, u32, int, int);
+extern void anatop_set_bits(struct anatop *, u32, int, int, u32);
+
+#endif /*  __LINUX_MFD_ANATOP_H */
index 5702d1b..7ffbd6e 100644 (file)
@@ -76,8 +76,6 @@ enum da9052_chip_id {
 struct da9052_pdata;
 
 struct da9052 {
-       struct mutex io_lock;
-
        struct device *dev;
        struct regmap *regmap;
 
index 60d27f7..b3a43b1 100644 (file)
 #define __MFD_DB8500_PRCMU_H
 
 #include <linux/interrupt.h>
+#include <linux/bitops.h>
+
+/*
+ * Registers
+ */
+#define DB8500_PRCM_GPIOCR 0x138
+#define DB8500_PRCM_GPIOCR_DBG_UARTMOD_CMD0    BIT(0)
+#define DB8500_PRCM_GPIOCR_DBG_STM_APE_CMD     BIT(9)
+#define DB8500_PRCM_GPIOCR_DBG_STM_MOD_CMD1    BIT(11)
+#define DB8500_PRCM_GPIOCR_SPI2_SELECT         BIT(23)
+
+#define DB8500_PRCM_LINE_VALUE 0x170
+#define DB8500_PRCM_LINE_VALUE_HSI_CAWAKE0     BIT(3)
+
+#define DB8500_PRCM_DSI_SW_RESET 0x324
+#define DB8500_PRCM_DSI_SW_RESET_DSI0_SW_RESETN BIT(0)
+#define DB8500_PRCM_DSI_SW_RESET_DSI1_SW_RESETN BIT(1)
+#define DB8500_PRCM_DSI_SW_RESET_DSI2_SW_RESETN BIT(2)
 
 /* This portion previously known as <mach/prcmu-fw-defs_v1.h> */
 
@@ -421,40 +439,22 @@ enum auto_enable {
 /* End of file previously known as prcmu-fw-defs_v1.h */
 
 /**
- * enum hw_acc_dev - enum for hw accelerators
- * @HW_ACC_SVAMMDSP: for SVAMMDSP
- * @HW_ACC_SVAPIPE:  for SVAPIPE
- * @HW_ACC_SIAMMDSP: for SIAMMDSP
- * @HW_ACC_SIAPIPE: for SIAPIPE
- * @HW_ACC_SGA: for SGA
- * @HW_ACC_B2R2: for B2R2
- * @HW_ACC_MCDE: for MCDE
- * @HW_ACC_ESRAM1: for ESRAM1
- * @HW_ACC_ESRAM2: for ESRAM2
- * @HW_ACC_ESRAM3: for ESRAM3
- * @HW_ACC_ESRAM4: for ESRAM4
- * @NUM_HW_ACC: number of hardware accelerators
- *
- * Different hw accelerators which can be turned ON/
- * OFF or put into retention (MMDSPs and ESRAMs).
- * Used with EPOD API.
+ * enum prcmu_power_status - results from set_power_state
+ * @PRCMU_SLEEP_OK: Sleep went ok
+ * @PRCMU_DEEP_SLEEP_OK: DeepSleep went ok
+ * @PRCMU_IDLE_OK: Idle went ok
+ * @PRCMU_DEEPIDLE_OK: DeepIdle went ok
+ * @PRCMU_PRCMU2ARMPENDINGIT_ER: Pending interrupt detected
+ * @PRCMU_ARMPENDINGIT_ER: Pending interrupt detected
  *
- * NOTE! Deprecated, to be removed when all users switched over to use the
- * regulator API.
  */
-enum hw_acc_dev {
-       HW_ACC_SVAMMDSP,
-       HW_ACC_SVAPIPE,
-       HW_ACC_SIAMMDSP,
-       HW_ACC_SIAPIPE,
-       HW_ACC_SGA,
-       HW_ACC_B2R2,
-       HW_ACC_MCDE,
-       HW_ACC_ESRAM1,
-       HW_ACC_ESRAM2,
-       HW_ACC_ESRAM3,
-       HW_ACC_ESRAM4,
-       NUM_HW_ACC
+enum prcmu_power_status {
+       PRCMU_SLEEP_OK                  = 0xf3,
+       PRCMU_DEEP_SLEEP_OK             = 0xf6,
+       PRCMU_IDLE_OK                   = 0xf0,
+       PRCMU_DEEPIDLE_OK               = 0xe3,
+       PRCMU_PRCMU2ARMPENDINGIT_ER     = 0x91,
+       PRCMU_ARMPENDINGIT_ER           = 0x93,
 };
 
 /*
@@ -493,6 +493,20 @@ struct prcmu_auto_pm_config {
        u8 sva_policy;
 };
 
+#define PRCMU_FW_PROJECT_U8500         2
+#define PRCMU_FW_PROJECT_U9500         4
+#define PRCMU_FW_PROJECT_U8500_C2      7
+#define PRCMU_FW_PROJECT_U9500_C2      11
+#define PRCMU_FW_PROJECT_U8520         13
+#define PRCMU_FW_PROJECT_U8420         14
+
+struct prcmu_fw_version {
+       u8 project;
+       u8 api_version;
+       u8 func_version;
+       u8 errata;
+};
+
 #ifdef CONFIG_MFD_DB8500_PRCMU
 
 void db8500_prcmu_early_init(void);
@@ -500,42 +514,41 @@ int prcmu_set_rc_a2p(enum romcode_write);
 enum romcode_read prcmu_get_rc_p2a(void);
 enum ap_pwrst prcmu_get_xp70_current_state(void);
 bool prcmu_has_arm_maxopp(void);
-bool prcmu_is_u8400(void);
-int prcmu_set_ape_opp(u8 opp);
-int prcmu_get_ape_opp(void);
+struct prcmu_fw_version *prcmu_get_fw_version(void);
 int prcmu_request_ape_opp_100_voltage(bool enable);
 int prcmu_release_usb_wakeup_state(void);
-int prcmu_set_ddr_opp(u8 opp);
-int prcmu_get_ddr_opp(void);
-/* NOTE! Use regulator framework instead */
-int prcmu_set_hwacc(u16 hw_acc_dev, u8 state);
 void prcmu_configure_auto_pm(struct prcmu_auto_pm_config *sleep,
        struct prcmu_auto_pm_config *idle);
 bool prcmu_is_auto_pm_enabled(void);
 
 int prcmu_config_clkout(u8 clkout, u8 source, u8 div);
 int prcmu_set_clock_divider(u8 clock, u8 divider);
-int prcmu_config_hotdog(u8 threshold);
-int prcmu_config_hotmon(u8 low, u8 high);
-int prcmu_start_temp_sense(u16 cycles32k);
-int prcmu_stop_temp_sense(void);
+int db8500_prcmu_config_hotdog(u8 threshold);
+int db8500_prcmu_config_hotmon(u8 low, u8 high);
+int db8500_prcmu_start_temp_sense(u16 cycles32k);
+int db8500_prcmu_stop_temp_sense(void);
 int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size);
 int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size);
 
 void prcmu_ac_wake_req(void);
 void prcmu_ac_sleep_req(void);
-void prcmu_modem_reset(void);
-void prcmu_enable_spi2(void);
-void prcmu_disable_spi2(void);
+void db8500_prcmu_modem_reset(void);
 
-int prcmu_config_a9wdog(u8 num, bool sleep_auto_off);
-int prcmu_enable_a9wdog(u8 id);
-int prcmu_disable_a9wdog(u8 id);
-int prcmu_kick_a9wdog(u8 id);
-int prcmu_load_a9wdog(u8 id, u32 val);
+int db8500_prcmu_config_a9wdog(u8 num, bool sleep_auto_off);
+int db8500_prcmu_enable_a9wdog(u8 id);
+int db8500_prcmu_disable_a9wdog(u8 id);
+int db8500_prcmu_kick_a9wdog(u8 id);
+int db8500_prcmu_load_a9wdog(u8 id, u32 val);
 
 void db8500_prcmu_system_reset(u16 reset_code);
 int db8500_prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll);
+u8 db8500_prcmu_get_power_state_result(void);
+int db8500_prcmu_gic_decouple(void);
+int db8500_prcmu_gic_recouple(void);
+int db8500_prcmu_copy_gic_settings(void);
+bool db8500_prcmu_gic_pending_irq(void);
+bool db8500_prcmu_pending_irq(void);
+bool db8500_prcmu_is_cpu_in_wfi(int cpu);
 void db8500_prcmu_enable_wakeups(u32 wakeups);
 int db8500_prcmu_set_epod(u16 epod_id, u8 epod_state);
 int db8500_prcmu_request_clock(u8 clock, bool enable);
@@ -549,6 +562,14 @@ u16 db8500_prcmu_get_reset_code(void);
 bool db8500_prcmu_is_ac_wake_requested(void);
 int db8500_prcmu_set_arm_opp(u8 opp);
 int db8500_prcmu_get_arm_opp(void);
+int db8500_prcmu_set_ape_opp(u8 opp);
+int db8500_prcmu_get_ape_opp(void);
+int db8500_prcmu_set_ddr_opp(u8 opp);
+int db8500_prcmu_get_ddr_opp(void);
+
+u32 db8500_prcmu_read(unsigned int reg);
+void db8500_prcmu_write(unsigned int reg, u32 value);
+void db8500_prcmu_write_masked(unsigned int reg, u32 mask, u32 value);
 
 #else /* !CONFIG_MFD_DB8500_PRCMU */
 
@@ -574,17 +595,17 @@ static inline bool prcmu_has_arm_maxopp(void)
        return false;
 }
 
-static inline bool prcmu_is_u8400(void)
+static inline struct prcmu_fw_version *prcmu_get_fw_version(void)
 {
-       return false;
+       return NULL;
 }
 
-static inline int prcmu_set_ape_opp(u8 opp)
+static inline int db8500_prcmu_set_ape_opp(u8 opp)
 {
        return 0;
 }
 
-static inline int prcmu_get_ape_opp(void)
+static inline int db8500_prcmu_get_ape_opp(void)
 {
        return APE_100_OPP;
 }
@@ -599,21 +620,16 @@ static inline int prcmu_release_usb_wakeup_state(void)
        return 0;
 }
 
-static inline int prcmu_set_ddr_opp(u8 opp)
+static inline int db8500_prcmu_set_ddr_opp(u8 opp)
 {
        return 0;
 }
 
-static inline int prcmu_get_ddr_opp(void)
+static inline int db8500_prcmu_get_ddr_opp(void)
 {
        return DDR_100_OPP;
 }
 
-static inline int prcmu_set_hwacc(u16 hw_acc_dev, u8 state)
-{
-       return 0;
-}
-
 static inline void prcmu_configure_auto_pm(struct prcmu_auto_pm_config *sleep,
        struct prcmu_auto_pm_config *idle)
 {
@@ -634,22 +650,22 @@ static inline int prcmu_set_clock_divider(u8 clock, u8 divider)
        return 0;
 }
 
-static inline int prcmu_config_hotdog(u8 threshold)
+static inline int db8500_prcmu_config_hotdog(u8 threshold)
 {
        return 0;
 }
 
-static inline int prcmu_config_hotmon(u8 low, u8 high)
+static inline int db8500_prcmu_config_hotmon(u8 low, u8 high)
 {
        return 0;
 }
 
-static inline int prcmu_start_temp_sense(u16 cycles32k)
+static inline int db8500_prcmu_start_temp_sense(u16 cycles32k)
 {
        return 0;
 }
 
-static inline int prcmu_stop_temp_sense(void)
+static inline int db8500_prcmu_stop_temp_sense(void)
 {
        return 0;
 }
@@ -668,22 +684,17 @@ static inline void prcmu_ac_wake_req(void) {}
 
 static inline void prcmu_ac_sleep_req(void) {}
 
-static inline void prcmu_modem_reset(void) {}
+static inline void db8500_prcmu_modem_reset(void) {}
 
-static inline int prcmu_enable_spi2(void)
-{
-       return 0;
-}
+static inline void db8500_prcmu_system_reset(u16 reset_code) {}
 
-static inline int prcmu_disable_spi2(void)
+static inline int db8500_prcmu_set_power_state(u8 state, bool keep_ulp_clk,
+       bool keep_ap_pll)
 {
        return 0;
 }
 
-static inline void db8500_prcmu_system_reset(u16 reset_code) {}
-
-static inline int db8500_prcmu_set_power_state(u8 state, bool keep_ulp_clk,
-       bool keep_ap_pll)
+static inline u8 db8500_prcmu_get_power_state_result(void)
 {
        return 0;
 }
@@ -729,27 +740,27 @@ static inline u16 db8500_prcmu_get_reset_code(void)
        return 0;
 }
 
-static inline int prcmu_config_a9wdog(u8 num, bool sleep_auto_off)
+static inline int db8500_prcmu_config_a9wdog(u8 num, bool sleep_auto_off)
 {
        return 0;
 }
 
-static inline int prcmu_enable_a9wdog(u8 id)
+static inline int db8500_prcmu_enable_a9wdog(u8 id)
 {
        return 0;
 }
 
-static inline int prcmu_disable_a9wdog(u8 id)
+static inline int db8500_prcmu_disable_a9wdog(u8 id)
 {
        return 0;
 }
 
-static inline int prcmu_kick_a9wdog(u8 id)
+static inline int db8500_prcmu_kick_a9wdog(u8 id)
 {
        return 0;
 }
 
-static inline int prcmu_load_a9wdog(u8 id, u32 val)
+static inline int db8500_prcmu_load_a9wdog(u8 id, u32 val)
 {
        return 0;
 }
@@ -769,6 +780,16 @@ static inline int db8500_prcmu_get_arm_opp(void)
        return 0;
 }
 
+static inline u32 db8500_prcmu_read(unsigned int reg)
+{
+       return 0;
+}
+
+static inline void db8500_prcmu_write(unsigned int reg, u32 value) {}
+
+static inline void db8500_prcmu_write_masked(unsigned int reg, u32 mask,
+       u32 value) {}
+
 #endif /* !CONFIG_MFD_DB8500_PRCMU */
 
 #endif /* __MFD_DB8500_PRCMU_H */
index bac942f..d7674eb 100644 (file)
@@ -10,7 +10,7 @@
 
 #include <linux/interrupt.h>
 #include <linux/notifier.h>
-#include <asm/mach-types.h>
+#include <linux/err.h>
 
 /* PRCMU Wakeup defines */
 enum prcmu_wakeup_index {
@@ -80,6 +80,29 @@ enum prcmu_wakeup_index {
 #define EPOD_STATE_ON_CLK_OFF  0x03
 #define EPOD_STATE_ON          0x04
 
+/* DB5500 CLKOUT IDs */
+enum {
+       DB5500_CLKOUT0 = 0,
+       DB5500_CLKOUT1,
+};
+
+/* DB5500 CLKOUTx sources */
+enum {
+       DB5500_CLKOUT_REF_CLK_SEL0,
+       DB5500_CLKOUT_RTC_CLK0_SEL0,
+       DB5500_CLKOUT_ULP_CLK_SEL0,
+       DB5500_CLKOUT_STATIC0,
+       DB5500_CLKOUT_REFCLK,
+       DB5500_CLKOUT_ULPCLK,
+       DB5500_CLKOUT_ARMCLK,
+       DB5500_CLKOUT_SYSACC0CLK,
+       DB5500_CLKOUT_SOC0PLLCLK,
+       DB5500_CLKOUT_SOC1PLLCLK,
+       DB5500_CLKOUT_DDRPLLCLK,
+       DB5500_CLKOUT_TVCLK,
+       DB5500_CLKOUT_IRDACLK,
+};
+
 /*
  * CLKOUT sources
  */
@@ -111,6 +134,7 @@ enum prcmu_clock {
        PRCMU_MSP1CLK,
        PRCMU_I2CCLK,
        PRCMU_SDMMCCLK,
+       PRCMU_SPARE1CLK,
        PRCMU_SLIMCLK,
        PRCMU_PER1CLK,
        PRCMU_PER2CLK,
@@ -139,12 +163,20 @@ enum prcmu_clock {
        PRCMU_IRRCCLK,
        PRCMU_SIACLK,
        PRCMU_SVACLK,
+       PRCMU_ACLK,
        PRCMU_NUM_REG_CLOCKS,
        PRCMU_SYSCLK = PRCMU_NUM_REG_CLOCKS,
+       PRCMU_CDCLK,
        PRCMU_TIMCLK,
        PRCMU_PLLSOC0,
        PRCMU_PLLSOC1,
        PRCMU_PLLDDR,
+       PRCMU_PLLDSI,
+       PRCMU_DSI0CLK,
+       PRCMU_DSI1CLK,
+       PRCMU_DSI0ESCCLK,
+       PRCMU_DSI1ESCCLK,
+       PRCMU_DSI2ESCCLK,
 };
 
 /**
@@ -153,12 +185,14 @@ enum prcmu_clock {
  * @APE_NO_CHANGE: The APE operating point is unchanged
  * @APE_100_OPP: The new APE operating point is ape100opp
  * @APE_50_OPP: 50%
+ * @APE_50_PARTLY_25_OPP: 50%, except some clocks at 25%.
  */
 enum ape_opp {
        APE_OPP_INIT = 0x00,
        APE_NO_CHANGE = 0x01,
        APE_100_OPP = 0x02,
-       APE_50_OPP = 0x03
+       APE_50_OPP = 0x03,
+       APE_50_PARTLY_25_OPP = 0xFF,
 };
 
 /**
@@ -218,9 +252,11 @@ enum ddr_pwrst {
 
 #if defined(CONFIG_UX500_SOC_DB8500) || defined(CONFIG_UX500_SOC_DB5500)
 
+#include <mach/id.h>
+
 static inline void __init prcmu_early_init(void)
 {
-       if (machine_is_u5500())
+       if (cpu_is_u5500())
                return db5500_prcmu_early_init();
        else
                return db8500_prcmu_early_init();
@@ -229,7 +265,7 @@ static inline void __init prcmu_early_init(void)
 static inline int prcmu_set_power_state(u8 state, bool keep_ulp_clk,
                bool keep_ap_pll)
 {
-       if (machine_is_u5500())
+       if (cpu_is_u5500())
                return db5500_prcmu_set_power_state(state, keep_ulp_clk,
                        keep_ap_pll);
        else
@@ -237,9 +273,65 @@ static inline int prcmu_set_power_state(u8 state, bool keep_ulp_clk,
                        keep_ap_pll);
 }
 
+static inline u8 prcmu_get_power_state_result(void)
+{
+       if (cpu_is_u5500())
+               return -EINVAL;
+       else
+               return db8500_prcmu_get_power_state_result();
+}
+
+static inline int prcmu_gic_decouple(void)
+{
+       if (cpu_is_u5500())
+               return -EINVAL;
+       else
+               return db8500_prcmu_gic_decouple();
+}
+
+static inline int prcmu_gic_recouple(void)
+{
+       if (cpu_is_u5500())
+               return -EINVAL;
+       else
+               return db8500_prcmu_gic_recouple();
+}
+
+static inline bool prcmu_gic_pending_irq(void)
+{
+       if (cpu_is_u5500())
+               return -EINVAL;
+       else
+               return db8500_prcmu_gic_pending_irq();
+}
+
+static inline bool prcmu_is_cpu_in_wfi(int cpu)
+{
+       if (cpu_is_u5500())
+               return -EINVAL;
+       else
+               return db8500_prcmu_is_cpu_in_wfi(cpu);
+}
+
+static inline int prcmu_copy_gic_settings(void)
+{
+       if (cpu_is_u5500())
+               return -EINVAL;
+       else
+               return db8500_prcmu_copy_gic_settings();
+}
+
+static inline bool prcmu_pending_irq(void)
+{
+        if (cpu_is_u5500())
+                return -EINVAL;
+        else
+                return db8500_prcmu_pending_irq();
+}
+
 static inline int prcmu_set_epod(u16 epod_id, u8 epod_state)
 {
-       if (machine_is_u5500())
+       if (cpu_is_u5500())
                return -EINVAL;
        else
                return db8500_prcmu_set_epod(epod_id, epod_state);
@@ -247,7 +339,7 @@ static inline int prcmu_set_epod(u16 epod_id, u8 epod_state)
 
 static inline void prcmu_enable_wakeups(u32 wakeups)
 {
-       if (machine_is_u5500())
+       if (cpu_is_u5500())
                db5500_prcmu_enable_wakeups(wakeups);
        else
                db8500_prcmu_enable_wakeups(wakeups);
@@ -260,7 +352,7 @@ static inline void prcmu_disable_wakeups(void)
 
 static inline void prcmu_config_abb_event_readout(u32 abb_events)
 {
-       if (machine_is_u5500())
+       if (cpu_is_u5500())
                db5500_prcmu_config_abb_event_readout(abb_events);
        else
                db8500_prcmu_config_abb_event_readout(abb_events);
@@ -268,7 +360,7 @@ static inline void prcmu_config_abb_event_readout(u32 abb_events)
 
 static inline void prcmu_get_abb_event_buffer(void __iomem **buf)
 {
-       if (machine_is_u5500())
+       if (cpu_is_u5500())
                db5500_prcmu_get_abb_event_buffer(buf);
        else
                db8500_prcmu_get_abb_event_buffer(buf);
@@ -276,25 +368,40 @@ static inline void prcmu_get_abb_event_buffer(void __iomem **buf)
 
 int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size);
 int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size);
+int prcmu_abb_write_masked(u8 slave, u8 reg, u8 *value, u8 *mask, u8 size);
 
 int prcmu_config_clkout(u8 clkout, u8 source, u8 div);
 
 static inline int prcmu_request_clock(u8 clock, bool enable)
 {
-       if (machine_is_u5500())
+       if (cpu_is_u5500())
                return db5500_prcmu_request_clock(clock, enable);
        else
                return db8500_prcmu_request_clock(clock, enable);
 }
 
-int prcmu_set_ape_opp(u8 opp);
-int prcmu_get_ape_opp(void);
-int prcmu_set_ddr_opp(u8 opp);
-int prcmu_get_ddr_opp(void);
+unsigned long prcmu_clock_rate(u8 clock);
+long prcmu_round_clock_rate(u8 clock, unsigned long rate);
+int prcmu_set_clock_rate(u8 clock, unsigned long rate);
+
+static inline int prcmu_set_ddr_opp(u8 opp)
+{
+       if (cpu_is_u5500())
+               return -EINVAL;
+       else
+               return db8500_prcmu_set_ddr_opp(opp);
+}
+static inline int prcmu_get_ddr_opp(void)
+{
+       if (cpu_is_u5500())
+               return -EINVAL;
+       else
+               return db8500_prcmu_get_ddr_opp();
+}
 
 static inline int prcmu_set_arm_opp(u8 opp)
 {
-       if (machine_is_u5500())
+       if (cpu_is_u5500())
                return -EINVAL;
        else
                return db8500_prcmu_set_arm_opp(opp);
@@ -302,15 +409,31 @@ static inline int prcmu_set_arm_opp(u8 opp)
 
 static inline int prcmu_get_arm_opp(void)
 {
-       if (machine_is_u5500())
+       if (cpu_is_u5500())
                return -EINVAL;
        else
                return db8500_prcmu_get_arm_opp();
 }
 
+static inline int prcmu_set_ape_opp(u8 opp)
+{
+       if (cpu_is_u5500())
+               return -EINVAL;
+       else
+               return db8500_prcmu_set_ape_opp(opp);
+}
+
+static inline int prcmu_get_ape_opp(void)
+{
+       if (cpu_is_u5500())
+               return -EINVAL;
+       else
+               return db8500_prcmu_get_ape_opp();
+}
+
 static inline void prcmu_system_reset(u16 reset_code)
 {
-       if (machine_is_u5500())
+       if (cpu_is_u5500())
                return db5500_prcmu_system_reset(reset_code);
        else
                return db8500_prcmu_system_reset(reset_code);
@@ -318,7 +441,7 @@ static inline void prcmu_system_reset(u16 reset_code)
 
 static inline u16 prcmu_get_reset_code(void)
 {
-       if (machine_is_u5500())
+       if (cpu_is_u5500())
                return db5500_prcmu_get_reset_code();
        else
                return db8500_prcmu_get_reset_code();
@@ -326,10 +449,17 @@ static inline u16 prcmu_get_reset_code(void)
 
 void prcmu_ac_wake_req(void);
 void prcmu_ac_sleep_req(void);
-void prcmu_modem_reset(void);
+static inline void prcmu_modem_reset(void)
+{
+       if (cpu_is_u5500())
+               return;
+       else
+               return db8500_prcmu_modem_reset();
+}
+
 static inline bool prcmu_is_ac_wake_requested(void)
 {
-       if (machine_is_u5500())
+       if (cpu_is_u5500())
                return db5500_prcmu_is_ac_wake_requested();
        else
                return db8500_prcmu_is_ac_wake_requested();
@@ -337,7 +467,7 @@ static inline bool prcmu_is_ac_wake_requested(void)
 
 static inline int prcmu_set_display_clocks(void)
 {
-       if (machine_is_u5500())
+       if (cpu_is_u5500())
                return db5500_prcmu_set_display_clocks();
        else
                return db8500_prcmu_set_display_clocks();
@@ -345,7 +475,7 @@ static inline int prcmu_set_display_clocks(void)
 
 static inline int prcmu_disable_dsipll(void)
 {
-       if (machine_is_u5500())
+       if (cpu_is_u5500())
                return db5500_prcmu_disable_dsipll();
        else
                return db8500_prcmu_disable_dsipll();
@@ -353,7 +483,7 @@ static inline int prcmu_disable_dsipll(void)
 
 static inline int prcmu_enable_dsipll(void)
 {
-       if (machine_is_u5500())
+       if (cpu_is_u5500())
                return db5500_prcmu_enable_dsipll();
        else
                return db8500_prcmu_enable_dsipll();
@@ -361,11 +491,107 @@ static inline int prcmu_enable_dsipll(void)
 
 static inline int prcmu_config_esram0_deep_sleep(u8 state)
 {
-       if (machine_is_u5500())
+       if (cpu_is_u5500())
                return -EINVAL;
        else
                return db8500_prcmu_config_esram0_deep_sleep(state);
 }
+
+static inline int prcmu_config_hotdog(u8 threshold)
+{
+       if (cpu_is_u5500())
+               return -EINVAL;
+       else
+               return db8500_prcmu_config_hotdog(threshold);
+}
+
+static inline int prcmu_config_hotmon(u8 low, u8 high)
+{
+       if (cpu_is_u5500())
+               return -EINVAL;
+       else
+               return db8500_prcmu_config_hotmon(low, high);
+}
+
+static inline int prcmu_start_temp_sense(u16 cycles32k)
+{
+       if (cpu_is_u5500())
+               return  -EINVAL;
+       else
+               return  db8500_prcmu_start_temp_sense(cycles32k);
+}
+
+static inline int prcmu_stop_temp_sense(void)
+{
+       if (cpu_is_u5500())
+               return  -EINVAL;
+       else
+               return  db8500_prcmu_stop_temp_sense();
+}
+
+static inline u32 prcmu_read(unsigned int reg)
+{
+       if (cpu_is_u5500())
+               return -EINVAL;
+       else
+               return db8500_prcmu_read(reg);
+}
+
+static inline void prcmu_write(unsigned int reg, u32 value)
+{
+       if (cpu_is_u5500())
+               return;
+       else
+               db8500_prcmu_write(reg, value);
+}
+
+static inline void prcmu_write_masked(unsigned int reg, u32 mask, u32 value)
+{
+       if (cpu_is_u5500())
+               return;
+       else
+               db8500_prcmu_write_masked(reg, mask, value);
+}
+
+static inline int prcmu_enable_a9wdog(u8 id)
+{
+       if (cpu_is_u5500())
+               return -EINVAL;
+       else
+               return db8500_prcmu_enable_a9wdog(id);
+}
+
+static inline int prcmu_disable_a9wdog(u8 id)
+{
+       if (cpu_is_u5500())
+               return -EINVAL;
+       else
+               return db8500_prcmu_disable_a9wdog(id);
+}
+
+static inline int prcmu_kick_a9wdog(u8 id)
+{
+       if (cpu_is_u5500())
+               return -EINVAL;
+       else
+               return db8500_prcmu_kick_a9wdog(id);
+}
+
+static inline int prcmu_load_a9wdog(u8 id, u32 timeout)
+{
+       if (cpu_is_u5500())
+               return -EINVAL;
+       else
+               return db8500_prcmu_load_a9wdog(id, timeout);
+}
+
+static inline int prcmu_config_a9wdog(u8 num, bool sleep_auto_off)
+{
+       if (cpu_is_u5500())
+               return -EINVAL;
+       else
+               return db8500_prcmu_config_a9wdog(num, sleep_auto_off);
+}
 #else
 
 static inline void __init prcmu_early_init(void) {}
@@ -395,6 +621,12 @@ static inline int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
        return -ENOSYS;
 }
 
+static inline int prcmu_abb_write_masked(u8 slave, u8 reg, u8 *value, u8 *mask,
+       u8 size)
+{
+       return -ENOSYS;
+}
+
 static inline int prcmu_config_clkout(u8 clkout, u8 source, u8 div)
 {
        return 0;
@@ -405,6 +637,21 @@ static inline int prcmu_request_clock(u8 clock, bool enable)
        return 0;
 }
 
+static inline long prcmu_round_clock_rate(u8 clock, unsigned long rate)
+{
+       return 0;
+}
+
+static inline int prcmu_set_clock_rate(u8 clock, unsigned long rate)
+{
+       return 0;
+}
+
+static inline unsigned long prcmu_clock_rate(u8 clock)
+{
+       return 0;
+}
+
 static inline int prcmu_set_ape_opp(u8 opp)
 {
        return 0;
@@ -480,14 +727,133 @@ static inline void prcmu_get_abb_event_buffer(void __iomem **buf)
        *buf = NULL;
 }
 
+static inline int prcmu_config_hotdog(u8 threshold)
+{
+       return 0;
+}
+
+static inline int prcmu_config_hotmon(u8 low, u8 high)
+{
+       return 0;
+}
+
+static inline int prcmu_start_temp_sense(u16 cycles32k)
+{
+       return 0;
+}
+
+static inline int prcmu_stop_temp_sense(void)
+{
+       return 0;
+}
+
+static inline u32 prcmu_read(unsigned int reg)
+{
+       return 0;
+}
+
+static inline void prcmu_write(unsigned int reg, u32 value) {}
+
+static inline void prcmu_write_masked(unsigned int reg, u32 mask, u32 value) {}
+
+#endif
+
+static inline void prcmu_set(unsigned int reg, u32 bits)
+{
+       prcmu_write_masked(reg, bits, bits);
+}
+
+static inline void prcmu_clear(unsigned int reg, u32 bits)
+{
+       prcmu_write_masked(reg, bits, 0);
+}
+
+#if defined(CONFIG_UX500_SOC_DB8500) || defined(CONFIG_UX500_SOC_DB5500)
+
+/**
+ * prcmu_enable_spi2 - Enables pin muxing for SPI2 on OtherAlternateC1.
+ */
+static inline void prcmu_enable_spi2(void)
+{
+       if (cpu_is_u8500())
+               prcmu_set(DB8500_PRCM_GPIOCR, DB8500_PRCM_GPIOCR_SPI2_SELECT);
+}
+
+/**
+ * prcmu_disable_spi2 - Disables pin muxing for SPI2 on OtherAlternateC1.
+ */
+static inline void prcmu_disable_spi2(void)
+{
+       if (cpu_is_u8500())
+               prcmu_clear(DB8500_PRCM_GPIOCR, DB8500_PRCM_GPIOCR_SPI2_SELECT);
+}
+
+/**
+ * prcmu_enable_stm_mod_uart - Enables pin muxing for STMMOD
+ * and UARTMOD on OtherAlternateC3.
+ */
+static inline void prcmu_enable_stm_mod_uart(void)
+{
+       if (cpu_is_u8500()) {
+               prcmu_set(DB8500_PRCM_GPIOCR,
+                       (DB8500_PRCM_GPIOCR_DBG_STM_MOD_CMD1 |
+                        DB8500_PRCM_GPIOCR_DBG_UARTMOD_CMD0));
+       }
+}
+
+/**
+ * prcmu_disable_stm_mod_uart - Disables pin muxing for STMMOD
+ * and UARTMOD on OtherAlternateC3.
+ */
+static inline void prcmu_disable_stm_mod_uart(void)
+{
+       if (cpu_is_u8500()) {
+               prcmu_clear(DB8500_PRCM_GPIOCR,
+                       (DB8500_PRCM_GPIOCR_DBG_STM_MOD_CMD1 |
+                        DB8500_PRCM_GPIOCR_DBG_UARTMOD_CMD0));
+       }
+}
+
+/**
+ * prcmu_enable_stm_ape - Enables pin muxing for STM APE on OtherAlternateC1.
+ */
+static inline void prcmu_enable_stm_ape(void)
+{
+       if (cpu_is_u8500()) {
+               prcmu_set(DB8500_PRCM_GPIOCR,
+                       DB8500_PRCM_GPIOCR_DBG_STM_APE_CMD);
+       }
+}
+
+/**
+ * prcmu_disable_stm_ape - Disables pin muxing for STM APE on OtherAlternateC1.
+ */
+static inline void prcmu_disable_stm_ape(void)
+{
+       if (cpu_is_u8500()) {
+               prcmu_clear(DB8500_PRCM_GPIOCR,
+                       DB8500_PRCM_GPIOCR_DBG_STM_APE_CMD);
+       }
+}
+
+#else
+
+static inline void prcmu_enable_spi2(void) {}
+static inline void prcmu_disable_spi2(void) {}
+static inline void prcmu_enable_stm_mod_uart(void) {}
+static inline void prcmu_disable_stm_mod_uart(void) {}
+static inline void prcmu_enable_stm_ape(void) {}
+static inline void prcmu_disable_stm_ape(void) {}
+
 #endif
 
 /* PRCMU QoS APE OPP class */
 #define PRCMU_QOS_APE_OPP 1
 #define PRCMU_QOS_DDR_OPP 2
+#define PRCMU_QOS_ARM_OPP 3
 #define PRCMU_QOS_DEFAULT_VALUE -1
 
-#ifdef CONFIG_UX500_PRCMU_QOS_POWER
+#ifdef CONFIG_DBX500_PRCMU_QOS_POWER
 
 unsigned long prcmu_qos_get_cpufreq_opp_delay(void);
 void prcmu_qos_set_cpufreq_opp_delay(unsigned long);
index b86ee45..10e038b 100644 (file)
@@ -38,7 +38,8 @@ int mc13xxx_irq_ack(struct mc13xxx *mc13xxx, int irq);
 int mc13xxx_get_flags(struct mc13xxx *mc13xxx);
 
 int mc13xxx_adc_do_conversion(struct mc13xxx *mc13xxx,
-               unsigned int mode, unsigned int channel, unsigned int *sample);
+               unsigned int mode, unsigned int channel,
+               u8 ato, bool atox, unsigned int *sample);
 
 #define MC13XXX_IRQ_ADCDONE    0
 #define MC13XXX_IRQ_ADCBISDONE 1
@@ -157,6 +158,18 @@ struct mc13xxx_buttons_platform_data {
        unsigned short b3on_key;
 };
 
+struct mc13xxx_ts_platform_data {
+       /* Delay between Touchscreen polarization and ADC Conversion.
+        * Given in clock ticks of a 32 kHz clock which gives a granularity of
+        * about 30.5ms */
+       u8 ato;
+
+#define MC13783_TS_ATO_FIRST false
+#define MC13783_TS_ATO_EACH  true
+       /* Use the ATO delay only for the first conversion or for each one */
+       bool atox;
+};
+
 struct mc13xxx_platform_data {
 #define MC13XXX_USE_TOUCHSCREEN (1 << 0)
 #define MC13XXX_USE_CODEC      (1 << 1)
@@ -167,6 +180,7 @@ struct mc13xxx_platform_data {
        struct mc13xxx_regulator_platform_data regulators;
        struct mc13xxx_leds_platform_data *leds;
        struct mc13xxx_buttons_platform_data *buttons;
+       struct mc13xxx_ts_platform_data touch;
 };
 
 #define MC13XXX_ADC_MODE_TS            1
diff --git a/include/linux/mfd/rc5t583.h b/include/linux/mfd/rc5t583.h
new file mode 100644 (file)
index 0000000..a2c6160
--- /dev/null
@@ -0,0 +1,295 @@
+/*
+ * Core driver interface to access RICOH_RC5T583 power management chip.
+ *
+ * Copyright (c) 2011-2012, NVIDIA CORPORATION.  All rights reserved.
+ * Author: Laxman dewangan <ldewangan@nvidia.com>
+ *
+ * Based on code
+ *      Copyright (C) 2011 RICOH COMPANY,LTD
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef __LINUX_MFD_RC5T583_H
+#define __LINUX_MFD_RC5T583_H
+
+#include <linux/mutex.h>
+#include <linux/types.h>
+
+#define RC5T583_MAX_REGS               0xF8
+
+/* Maximum number of main interrupts */
+#define MAX_MAIN_INTERRUPT             5
+#define RC5T583_MAX_GPEDGE_REG         2
+#define RC5T583_MAX_INTERRUPT_MASK_REGS        9
+
+/* Interrupt enable register */
+#define RC5T583_INT_EN_SYS1    0x19
+#define RC5T583_INT_EN_SYS2    0x1D
+#define RC5T583_INT_EN_DCDC    0x41
+#define RC5T583_INT_EN_RTC     0xED
+#define RC5T583_INT_EN_ADC1    0x90
+#define RC5T583_INT_EN_ADC2    0x91
+#define RC5T583_INT_EN_ADC3    0x92
+
+/* Interrupt status registers (monitor regs in Ricoh)*/
+#define RC5T583_INTC_INTPOL    0xAD
+#define RC5T583_INTC_INTEN     0xAE
+#define RC5T583_INTC_INTMON    0xAF
+
+#define RC5T583_INT_MON_GRP    0xAF
+#define RC5T583_INT_MON_SYS1   0x1B
+#define RC5T583_INT_MON_SYS2   0x1F
+#define RC5T583_INT_MON_DCDC   0x43
+#define RC5T583_INT_MON_RTC    0xEE
+
+/* Interrupt clearing registers */
+#define RC5T583_INT_IR_SYS1    0x1A
+#define RC5T583_INT_IR_SYS2    0x1E
+#define RC5T583_INT_IR_DCDC    0x42
+#define RC5T583_INT_IR_RTC     0xEE
+#define RC5T583_INT_IR_ADCL    0x94
+#define RC5T583_INT_IR_ADCH    0x95
+#define RC5T583_INT_IR_ADCEND  0x96
+#define RC5T583_INT_IR_GPIOR   0xA9
+#define RC5T583_INT_IR_GPIOF   0xAA
+
+/* Sleep sequence registers */
+#define RC5T583_SLPSEQ1                0x21
+#define RC5T583_SLPSEQ2                0x22
+#define RC5T583_SLPSEQ3                0x23
+#define RC5T583_SLPSEQ4                0x24
+#define RC5T583_SLPSEQ5                0x25
+#define RC5T583_SLPSEQ6                0x26
+#define RC5T583_SLPSEQ7                0x27
+#define RC5T583_SLPSEQ8                0x28
+#define RC5T583_SLPSEQ9                0x29
+#define RC5T583_SLPSEQ10       0x2A
+#define RC5T583_SLPSEQ11       0x2B
+
+/* Regulator registers */
+#define RC5T583_REG_DC0CTL     0x30
+#define RC5T583_REG_DC0DAC     0x31
+#define RC5T583_REG_DC0LATCTL  0x32
+#define RC5T583_REG_SR0CTL     0x33
+
+#define RC5T583_REG_DC1CTL     0x34
+#define RC5T583_REG_DC1DAC     0x35
+#define RC5T583_REG_DC1LATCTL  0x36
+#define RC5T583_REG_SR1CTL     0x37
+
+#define RC5T583_REG_DC2CTL     0x38
+#define RC5T583_REG_DC2DAC     0x39
+#define RC5T583_REG_DC2LATCTL  0x3A
+#define RC5T583_REG_SR2CTL     0x3B
+
+#define RC5T583_REG_DC3CTL     0x3C
+#define RC5T583_REG_DC3DAC     0x3D
+#define RC5T583_REG_DC3LATCTL  0x3E
+#define RC5T583_REG_SR3CTL     0x3F
+
+
+#define RC5T583_REG_LDOEN1     0x50
+#define RC5T583_REG_LDOEN2     0x51
+#define RC5T583_REG_LDODIS1    0x52
+#define RC5T583_REG_LDODIS2    0x53
+
+#define RC5T583_REG_LDO0DAC    0x54
+#define RC5T583_REG_LDO1DAC    0x55
+#define RC5T583_REG_LDO2DAC    0x56
+#define RC5T583_REG_LDO3DAC    0x57
+#define RC5T583_REG_LDO4DAC    0x58
+#define RC5T583_REG_LDO5DAC    0x59
+#define RC5T583_REG_LDO6DAC    0x5A
+#define RC5T583_REG_LDO7DAC    0x5B
+#define RC5T583_REG_LDO8DAC    0x5C
+#define RC5T583_REG_LDO9DAC    0x5D
+
+#define RC5T583_REG_DC0DAC_DS  0x60
+#define RC5T583_REG_DC1DAC_DS  0x61
+#define RC5T583_REG_DC2DAC_DS  0x62
+#define RC5T583_REG_DC3DAC_DS  0x63
+
+#define RC5T583_REG_LDO0DAC_DS 0x64
+#define RC5T583_REG_LDO1DAC_DS 0x65
+#define RC5T583_REG_LDO2DAC_DS 0x66
+#define RC5T583_REG_LDO3DAC_DS 0x67
+#define RC5T583_REG_LDO4DAC_DS 0x68
+#define RC5T583_REG_LDO5DAC_DS 0x69
+#define RC5T583_REG_LDO6DAC_DS 0x6A
+#define RC5T583_REG_LDO7DAC_DS 0x6B
+#define RC5T583_REG_LDO8DAC_DS 0x6C
+#define RC5T583_REG_LDO9DAC_DS 0x6D
+
+/* GPIO register base address */
+#define RC5T583_GPIO_IOSEL     0xA0
+#define RC5T583_GPIO_PDEN      0xA1
+#define RC5T583_GPIO_IOOUT     0xA2
+#define RC5T583_GPIO_PGSEL     0xA3
+#define RC5T583_GPIO_GPINV     0xA4
+#define RC5T583_GPIO_GPDEB     0xA5
+#define RC5T583_GPIO_GPEDGE1   0xA6
+#define RC5T583_GPIO_GPEDGE2   0xA7
+#define RC5T583_GPIO_EN_INT    0xA8
+#define RC5T583_GPIO_MON_IOIN  0xAB
+#define RC5T583_GPIO_GPOFUNC   0xAC
+
+/* RICOH_RC5T583 IRQ definitions */
+enum {
+       RC5T583_IRQ_ONKEY,
+       RC5T583_IRQ_ACOK,
+       RC5T583_IRQ_LIDOPEN,
+       RC5T583_IRQ_PREOT,
+       RC5T583_IRQ_CLKSTP,
+       RC5T583_IRQ_ONKEY_OFF,
+       RC5T583_IRQ_WD,
+       RC5T583_IRQ_EN_PWRREQ1,
+       RC5T583_IRQ_EN_PWRREQ2,
+       RC5T583_IRQ_PRE_VINDET,
+
+       RC5T583_IRQ_DC0LIM,
+       RC5T583_IRQ_DC1LIM,
+       RC5T583_IRQ_DC2LIM,
+       RC5T583_IRQ_DC3LIM,
+
+       RC5T583_IRQ_CTC,
+       RC5T583_IRQ_YALE,
+       RC5T583_IRQ_DALE,
+       RC5T583_IRQ_WALE,
+
+       RC5T583_IRQ_AIN1L,
+       RC5T583_IRQ_AIN2L,
+       RC5T583_IRQ_AIN3L,
+       RC5T583_IRQ_VBATL,
+       RC5T583_IRQ_VIN3L,
+       RC5T583_IRQ_VIN8L,
+       RC5T583_IRQ_AIN1H,
+       RC5T583_IRQ_AIN2H,
+       RC5T583_IRQ_AIN3H,
+       RC5T583_IRQ_VBATH,
+       RC5T583_IRQ_VIN3H,
+       RC5T583_IRQ_VIN8H,
+       RC5T583_IRQ_ADCEND,
+
+       RC5T583_IRQ_GPIO0,
+       RC5T583_IRQ_GPIO1,
+       RC5T583_IRQ_GPIO2,
+       RC5T583_IRQ_GPIO3,
+       RC5T583_IRQ_GPIO4,
+       RC5T583_IRQ_GPIO5,
+       RC5T583_IRQ_GPIO6,
+       RC5T583_IRQ_GPIO7,
+
+       /* Should be last entry */
+       RC5T583_MAX_IRQS,
+};
+
+/* Ricoh583 gpio definitions */
+enum {
+       RC5T583_GPIO0,
+       RC5T583_GPIO1,
+       RC5T583_GPIO2,
+       RC5T583_GPIO3,
+       RC5T583_GPIO4,
+       RC5T583_GPIO5,
+       RC5T583_GPIO6,
+       RC5T583_GPIO7,
+
+       /* Should be last entry */
+       RC5T583_MAX_GPIO,
+};
+
+enum {
+       RC5T583_DS_NONE,
+       RC5T583_DS_DC0,
+       RC5T583_DS_DC1,
+       RC5T583_DS_DC2,
+       RC5T583_DS_DC3,
+       RC5T583_DS_LDO0,
+       RC5T583_DS_LDO1,
+       RC5T583_DS_LDO2,
+       RC5T583_DS_LDO3,
+       RC5T583_DS_LDO4,
+       RC5T583_DS_LDO5,
+       RC5T583_DS_LDO6,
+       RC5T583_DS_LDO7,
+       RC5T583_DS_LDO8,
+       RC5T583_DS_LDO9,
+       RC5T583_DS_PSO0,
+       RC5T583_DS_PSO1,
+       RC5T583_DS_PSO2,
+       RC5T583_DS_PSO3,
+       RC5T583_DS_PSO4,
+       RC5T583_DS_PSO5,
+       RC5T583_DS_PSO6,
+       RC5T583_DS_PSO7,
+
+       /* Should be last entry */
+       RC5T583_DS_MAX,
+};
+
+/*
+ * Ricoh pmic RC5T583 supports sleep through two external controls.
+ * The output of gpios and regulator can be enable/disable through
+ * this external signals.
+ */
+enum {
+       RC5T583_EXT_PWRREQ1_CONTROL = 0x1,
+       RC5T583_EXT_PWRREQ2_CONTROL = 0x2,
+};
+
+struct rc5t583 {
+       struct device   *dev;
+       struct regmap   *regmap;
+       int             chip_irq;
+       int             irq_base;
+       struct mutex    irq_lock;
+       unsigned long   group_irq_en[MAX_MAIN_INTERRUPT];
+
+       /* For main interrupt bits in INTC */
+       uint8_t         intc_inten_reg;
+
+       /* For group interrupt bits and address */
+       uint8_t         irq_en_reg[RC5T583_MAX_INTERRUPT_MASK_REGS];
+
+       /* For gpio edge */
+       uint8_t         gpedge_reg[RC5T583_MAX_GPEDGE_REG];
+};
+
+/*
+ * rc5t583_platform_data: Platform data for ricoh rc5t583 pmu.
+ * The board specific data is provided through this structure.
+ * @irq_base: Irq base number on which this device registers their interrupts.
+ * @enable_shutdown: Enable shutdown through the input pin "shutdown".
+ */
+
+struct rc5t583_platform_data {
+       int             irq_base;
+       bool            enable_shutdown;
+};
+
+int rc5t583_write(struct device *dev, u8 reg, uint8_t val);
+int rc5t583_read(struct device *dev, uint8_t reg, uint8_t *val);
+int rc5t583_set_bits(struct device *dev, unsigned int reg,
+               unsigned int bit_mask);
+int rc5t583_clear_bits(struct device *dev, unsigned int reg,
+               unsigned int bit_mask);
+int rc5t583_update(struct device *dev, unsigned int reg,
+               unsigned int val, unsigned int mask);
+int rc5t583_ext_power_req_config(struct device *dev, int deepsleep_id,
+       int ext_pwr_req, int deepsleep_slot_nr);
+int rc5t583_irq_init(struct rc5t583 *rc5t583, int irq, int irq_base);
+int rc5t583_irq_exit(struct rc5t583 *rc5t583);
+
+#endif
index 8c54de6..8516fd1 100644 (file)
@@ -28,6 +28,7 @@ enum stmpe_partnum {
        STMPE1601,
        STMPE2401,
        STMPE2403,
+       STMPE_NBR_PARTS
 };
 
 /*
diff --git a/include/linux/mfd/tps65090.h b/include/linux/mfd/tps65090.h
new file mode 100644 (file)
index 0000000..38e31c5
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Core driver interface for TI TPS65090 PMIC family
+ *
+ * Copyright (C) 2012 NVIDIA Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ */
+
+#ifndef __LINUX_MFD_TPS65090_H
+#define __LINUX_MFD_TPS65090_H
+
+struct tps65090_subdev_info {
+       int             id;
+       const char      *name;
+       void            *platform_data;
+};
+
+struct tps65090_platform_data {
+       int irq_base;
+       int num_subdevs;
+       struct tps65090_subdev_info *subdevs;
+};
+
+/*
+ * NOTE: the functions below are not intended for use outside
+ * of the TPS65090 sub-device drivers
+ */
+extern int tps65090_write(struct device *dev, int reg, uint8_t val);
+extern int tps65090_read(struct device *dev, int reg, uint8_t *val);
+extern int tps65090_set_bits(struct device *dev, int reg, uint8_t bit_num);
+extern int tps65090_clr_bits(struct device *dev, int reg, uint8_t bit_num);
+
+#endif /*__LINUX_MFD_TPS65090_H */
diff --git a/include/linux/mfd/tps65217.h b/include/linux/mfd/tps65217.h
new file mode 100644 (file)
index 0000000..e030ef9
--- /dev/null
@@ -0,0 +1,283 @@
+/*
+ * linux/mfd/tps65217.h
+ *
+ * Functions to access TPS65217 power management chip.
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __LINUX_MFD_TPS65217_H
+#define __LINUX_MFD_TPS65217_H
+
+#include <linux/i2c.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+
+/* I2C ID for TPS65217 part */
+#define TPS65217_I2C_ID                        0x24
+
+/* All register addresses */
+#define TPS65217_REG_CHIPID            0X00
+#define TPS65217_REG_PPATH             0X01
+#define TPS65217_REG_INT               0X02
+#define TPS65217_REG_CHGCONFIG0                0X03
+#define TPS65217_REG_CHGCONFIG1                0X04
+#define TPS65217_REG_CHGCONFIG2                0X05
+#define TPS65217_REG_CHGCONFIG3                0X06
+#define TPS65217_REG_WLEDCTRL1         0X07
+#define TPS65217_REG_WLEDCTRL2         0X08
+#define TPS65217_REG_MUXCTRL           0X09
+#define TPS65217_REG_STATUS            0X0A
+#define TPS65217_REG_PASSWORD          0X0B
+#define TPS65217_REG_PGOOD             0X0C
+#define TPS65217_REG_DEFPG             0X0D
+#define TPS65217_REG_DEFDCDC1          0X0E
+#define TPS65217_REG_DEFDCDC2          0X0F
+#define TPS65217_REG_DEFDCDC3          0X10
+#define TPS65217_REG_DEFSLEW           0X11
+#define TPS65217_REG_DEFLDO1           0X12
+#define TPS65217_REG_DEFLDO2           0X13
+#define TPS65217_REG_DEFLS1            0X14
+#define TPS65217_REG_DEFLS2            0X15
+#define TPS65217_REG_ENABLE            0X16
+#define TPS65217_REG_DEFUVLO           0X18
+#define TPS65217_REG_SEQ1              0X19
+#define TPS65217_REG_SEQ2              0X1A
+#define TPS65217_REG_SEQ3              0X1B
+#define TPS65217_REG_SEQ4              0X1C
+#define TPS65217_REG_SEQ5              0X1D
+#define TPS65217_REG_SEQ6              0X1E
+
+/* Register field definitions */
+#define TPS65217_CHIPID_CHIP_MASK      0xF0
+#define TPS65217_CHIPID_REV_MASK       0x0F
+
+#define TPS65217_PPATH_ACSINK_ENABLE   BIT(7)
+#define TPS65217_PPATH_USBSINK_ENABLE  BIT(6)
+#define TPS65217_PPATH_AC_PW_ENABLE    BIT(5)
+#define TPS65217_PPATH_USB_PW_ENABLE   BIT(4)
+#define TPS65217_PPATH_AC_CURRENT_MASK 0x0C
+#define TPS65217_PPATH_USB_CURRENT_MASK        0x03
+
+#define TPS65217_INT_PBM               BIT(6)
+#define TPS65217_INT_ACM               BIT(5)
+#define TPS65217_INT_USBM              BIT(4)
+#define TPS65217_INT_PBI               BIT(2)
+#define TPS65217_INT_ACI               BIT(1)
+#define TPS65217_INT_USBI              BIT(0)
+
+#define TPS65217_CHGCONFIG0_TREG       BIT(7)
+#define TPS65217_CHGCONFIG0_DPPM       BIT(6)
+#define TPS65217_CHGCONFIG0_TSUSP      BIT(5)
+#define TPS65217_CHGCONFIG0_TERMI      BIT(4)
+#define TPS65217_CHGCONFIG0_ACTIVE     BIT(3)
+#define TPS65217_CHGCONFIG0_CHGTOUT    BIT(2)
+#define TPS65217_CHGCONFIG0_PCHGTOUT   BIT(1)
+#define TPS65217_CHGCONFIG0_BATTEMP    BIT(0)
+
+#define TPS65217_CHGCONFIG1_TMR_MASK   0xC0
+#define TPS65217_CHGCONFIG1_TMR_ENABLE BIT(5)
+#define TPS65217_CHGCONFIG1_NTC_TYPE   BIT(4)
+#define TPS65217_CHGCONFIG1_RESET      BIT(3)
+#define TPS65217_CHGCONFIG1_TERM       BIT(2)
+#define TPS65217_CHGCONFIG1_SUSP       BIT(1)
+#define TPS65217_CHGCONFIG1_CHG_EN     BIT(0)
+
+#define TPS65217_CHGCONFIG2_DYNTMR     BIT(7)
+#define TPS65217_CHGCONFIG2_VPREGHG    BIT(6)
+#define TPS65217_CHGCONFIG2_VOREG_MASK 0x30
+
+#define TPS65217_CHGCONFIG3_ICHRG_MASK 0xC0
+#define TPS65217_CHGCONFIG3_DPPMTH_MASK        0x30
+#define TPS65217_CHGCONFIG2_PCHRGT     BIT(3)
+#define TPS65217_CHGCONFIG2_TERMIF     0x06
+#define TPS65217_CHGCONFIG2_TRANGE     BIT(0)
+
+#define TPS65217_WLEDCTRL1_ISINK_ENABLE        BIT(3)
+#define TPS65217_WLEDCTRL1_ISEL                BIT(2)
+#define TPS65217_WLEDCTRL1_FDIM_MASK   0x03
+
+#define TPS65217_WLEDCTRL2_DUTY_MASK   0x7F
+
+#define TPS65217_MUXCTRL_MUX_MASK      0x07
+
+#define TPS65217_STATUS_OFF            BIT(7)
+#define TPS65217_STATUS_ACPWR          BIT(3)
+#define TPS65217_STATUS_USBPWR         BIT(2)
+#define TPS65217_STATUS_PB             BIT(0)
+
+#define TPS65217_PASSWORD_REGS_UNLOCK  0x7D
+
+#define TPS65217_PGOOD_LDO3_PG         BIT(6)
+#define TPS65217_PGOOD_LDO4_PG         BIT(5)
+#define TPS65217_PGOOD_DC1_PG          BIT(4)
+#define TPS65217_PGOOD_DC2_PG          BIT(3)
+#define TPS65217_PGOOD_DC3_PG          BIT(2)
+#define TPS65217_PGOOD_LDO1_PG         BIT(1)
+#define TPS65217_PGOOD_LDO2_PG         BIT(0)
+
+#define TPS65217_DEFPG_LDO1PGM         BIT(3)
+#define TPS65217_DEFPG_LDO2PGM         BIT(2)
+#define TPS65217_DEFPG_PGDLY_MASK      0x03
+
+#define TPS65217_DEFDCDCX_XADJX                BIT(7)
+#define TPS65217_DEFDCDCX_DCDC_MASK    0x3F
+
+#define TPS65217_DEFSLEW_GO            BIT(7)
+#define TPS65217_DEFSLEW_GODSBL                BIT(6)
+#define TPS65217_DEFSLEW_PFM_EN1       BIT(5)
+#define TPS65217_DEFSLEW_PFM_EN2       BIT(4)
+#define TPS65217_DEFSLEW_PFM_EN3       BIT(3)
+#define TPS65217_DEFSLEW_SLEW_MASK     0x07
+
+#define TPS65217_DEFLDO1_LDO1_MASK     0x0F
+
+#define TPS65217_DEFLDO2_TRACK         BIT(6)
+#define TPS65217_DEFLDO2_LDO2_MASK     0x3F
+
+#define TPS65217_DEFLDO3_LDO3_EN       BIT(5)
+#define TPS65217_DEFLDO3_LDO3_MASK     0x1F
+
+#define TPS65217_DEFLDO4_LDO4_EN       BIT(5)
+#define TPS65217_DEFLDO4_LDO4_MASK     0x1F
+
+#define TPS65217_ENABLE_LS1_EN         BIT(6)
+#define TPS65217_ENABLE_LS2_EN         BIT(5)
+#define TPS65217_ENABLE_DC1_EN         BIT(4)
+#define TPS65217_ENABLE_DC2_EN         BIT(3)
+#define TPS65217_ENABLE_DC3_EN         BIT(2)
+#define TPS65217_ENABLE_LDO1_EN                BIT(1)
+#define TPS65217_ENABLE_LDO2_EN                BIT(0)
+
+#define TPS65217_DEFUVLO_UVLOHYS       BIT(2)
+#define TPS65217_DEFUVLO_UVLO_MASK     0x03
+
+#define TPS65217_SEQ1_DC1_SEQ_MASK     0xF0
+#define TPS65217_SEQ1_DC2_SEQ_MASK     0x0F
+
+#define TPS65217_SEQ2_DC3_SEQ_MASK     0xF0
+#define TPS65217_SEQ2_LDO1_SEQ_MASK    0x0F
+
+#define TPS65217_SEQ3_LDO2_SEQ_MASK    0xF0
+#define TPS65217_SEQ3_LDO3_SEQ_MASK    0x0F
+
+#define TPS65217_SEQ4_LDO4_SEQ_MASK    0xF0
+
+#define TPS65217_SEQ5_DLY1_MASK                0xC0
+#define TPS65217_SEQ5_DLY2_MASK                0x30
+#define TPS65217_SEQ5_DLY3_MASK                0x0C
+#define TPS65217_SEQ5_DLY4_MASK                0x03
+
+#define TPS65217_SEQ6_DLY5_MASK                0xC0
+#define TPS65217_SEQ6_DLY6_MASK                0x30
+#define TPS65217_SEQ6_SEQUP            BIT(2)
+#define TPS65217_SEQ6_SEQDWN           BIT(1)
+#define TPS65217_SEQ6_INSTDWN          BIT(0)
+
+#define TPS65217_MAX_REGISTER          0x1E
+#define TPS65217_PROTECT_NONE          0
+#define TPS65217_PROTECT_L1            1
+#define TPS65217_PROTECT_L2            2
+
+
+enum tps65217_regulator_id {
+       /* DCDC's */
+       TPS65217_DCDC_1,
+       TPS65217_DCDC_2,
+       TPS65217_DCDC_3,
+       /* LDOs */
+       TPS65217_LDO_1,
+       TPS65217_LDO_2,
+       TPS65217_LDO_3,
+       TPS65217_LDO_4,
+};
+
+#define TPS65217_MAX_REG_ID            TPS65217_LDO_4
+
+/* Number of step-down converters available */
+#define TPS65217_NUM_DCDC              3
+/* Number of LDO voltage regulators available */
+#define TPS65217_NUM_LDO               4
+/* Number of total regulators available */
+#define TPS65217_NUM_REGULATOR         (TPS65217_NUM_DCDC + TPS65217_NUM_LDO)
+
+/**
+ * struct tps65217_board - packages regulator init data
+ * @tps65217_regulator_data: regulator initialization values
+ *
+ * Board data may be used to initialize regulator.
+ */
+struct tps65217_board {
+       struct regulator_init_data *tps65217_init_data;
+};
+
+/**
+ * struct tps_info - packages regulator constraints
+ * @name:              Voltage regulator name
+ * @min_uV:            minimum micro volts
+ * @max_uV:            minimum micro volts
+ * @vsel_to_uv:                Function pointer to get voltage from selector
+ * @uv_to_vsel:                Function pointer to get selector from voltage
+ * @table:             Table for non-uniform voltage step-size
+ * @table_len:         Length of the voltage table
+ * @enable_mask:       Regulator enable mask bits
+ * @set_vout_reg:      Regulator output voltage set register
+ * @set_vout_mask:     Regulator output voltage set mask
+ *
+ * This data is used to check the regualtor voltage limits while setting.
+ */
+struct tps_info {
+       const char *name;
+       int min_uV;
+       int max_uV;
+       int (*vsel_to_uv)(unsigned int vsel);
+       int (*uv_to_vsel)(int uV, unsigned int *vsel);
+       const int *table;
+       unsigned int table_len;
+       unsigned int enable_mask;
+       unsigned int set_vout_reg;
+       unsigned int set_vout_mask;
+};
+
+/**
+ * struct tps65217 - tps65217 sub-driver chip access routines
+ *
+ * Device data may be used to access the TPS65217 chip
+ */
+
+struct tps65217 {
+       struct device *dev;
+       struct tps65217_board *pdata;
+       struct regulator_desc desc[TPS65217_NUM_REGULATOR];
+       struct regulator_dev *rdev[TPS65217_NUM_REGULATOR];
+       struct tps_info *info[TPS65217_NUM_REGULATOR];
+       struct regmap *regmap;
+
+       /* Client devices */
+       struct platform_device *regulator_pdev[TPS65217_NUM_REGULATOR];
+};
+
+static inline struct tps65217 *dev_to_tps65217(struct device *dev)
+{
+       return dev_get_drvdata(dev);
+}
+
+int tps65217_reg_read(struct tps65217 *tps, unsigned int reg,
+                                       unsigned int *val);
+int tps65217_reg_write(struct tps65217 *tps, unsigned int reg,
+                       unsigned int val, unsigned int level);
+int tps65217_set_bits(struct tps65217 *tps, unsigned int reg,
+               unsigned int mask, unsigned int val, unsigned int level);
+int tps65217_clear_bits(struct tps65217 *tps, unsigned int reg,
+               unsigned int mask, unsigned int level);
+
+#endif /*  __LINUX_MFD_TPS65217_H */
index 76700b5..1c6c286 100644 (file)
@@ -17,6 +17,8 @@
 #ifndef __LINUX_MFD_TPS65910_H
 #define __LINUX_MFD_TPS65910_H
 
+#include <linux/gpio.h>
+
 /* TPS chip id list */
 #define TPS65910                       0
 #define TPS65911                       1
 
 
 /*Register GPIO  (0x80) register.RegisterDescription */
+#define GPIO_SLEEP_MASK                         0x80
+#define GPIO_SLEEP_SHIFT                        7
 #define GPIO_DEB_MASK                           0x10
 #define GPIO_DEB_SHIFT                          4
 #define GPIO_PUEN_MASK                          0x08
 #define TPS65910_GPIO_STS                              BIT(1)
 #define TPS65910_GPIO_SET                              BIT(0)
 
+/* Max number of TPS65910/11 GPIOs */
+#define TPS65910_NUM_GPIO                              6
+#define TPS65911_NUM_GPIO                              9
+#define TPS6591X_MAX_NUM_GPIO                          9
+
 /* Regulator Index Definitions */
 #define TPS65910_REG_VRTC                              0
 #define TPS65910_REG_VIO                               1
@@ -785,6 +794,7 @@ struct tps65910_board {
        int irq_base;
        int vmbch_threshold;
        int vmbch2_threshold;
+       bool en_gpio_sleep[TPS6591X_MAX_NUM_GPIO];
        unsigned long regulator_ext_sleep_control[TPS65910_NUM_REGS];
        struct regulator_init_data *tps65910_pmic_init_data[TPS65910_NUM_REGS];
 };
@@ -796,6 +806,7 @@ struct tps65910_board {
 struct tps65910 {
        struct device *dev;
        struct i2c_client *i2c_client;
+       struct regmap *regmap;
        struct mutex io_mutex;
        unsigned int id;
        int (*read)(struct tps65910 *tps65910, u8 reg, int size, void *dest);
index dc3e050..893267b 100644 (file)
@@ -22,7 +22,6 @@ struct wm8994_ldo_pdata {
        /** GPIOs to enable regulator, 0 or less if not available */
        int enable;
 
-       const char *supply;
        const struct regulator_init_data *init_data;
 };
 
index 6300681..d8738a4 100644 (file)
@@ -1258,6 +1258,8 @@ static inline void pgtable_page_dtor(struct page *page)
 extern void free_area_init(unsigned long * zones_size);
 extern void free_area_init_node(int nid, unsigned long * zones_size,
                unsigned long zone_start_pfn, unsigned long *zholes_size);
+extern void free_initmem(void);
+
 #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
 /*
  * With CONFIG_HAVE_MEMBLOCK_NODE_MAP set, an architecture may initialise its
index 4598bf0..fbcafe2 100644 (file)
@@ -21,8 +21,6 @@
 #include <linux/percpu.h>
 #include <asm/module.h>
 
-#include <trace/events/module.h>
-
 /* Not Yet Implemented */
 #define MODULE_SUPPORTED_DEVICE(name)
 
@@ -452,33 +450,11 @@ void symbol_put_addr(void *addr);
 
 /* Sometimes we know we already have a refcount, and it's easier not
    to handle the error case (which only happens with rmmod --wait). */
-static inline void __module_get(struct module *module)
-{
-       if (module) {
-               preempt_disable();
-               __this_cpu_inc(module->refptr->incs);
-               trace_module_get(module, _THIS_IP_);
-               preempt_enable();
-       }
-}
-
-static inline int try_module_get(struct module *module)
-{
-       int ret = 1;
-
-       if (module) {
-               preempt_disable();
+extern void __module_get(struct module *module);
 
-               if (likely(module_is_live(module))) {
-                       __this_cpu_inc(module->refptr->incs);
-                       trace_module_get(module, _THIS_IP_);
-               } else
-                       ret = 0;
-
-               preempt_enable();
-       }
-       return ret;
-}
+/* This is the Right Way to get a module: if it fails, it's being removed,
+ * so pretend it's not there. */
+extern bool try_module_get(struct module *module);
 
 extern void module_put(struct module *module);
 
index c47f4d6..ea36486 100644 (file)
@@ -47,14 +47,11 @@ struct kernel_param_ops {
        void (*free)(void *arg);
 };
 
-/* Flag bits for kernel_param.flags */
-#define KPARAM_ISBOOL          2
-
 struct kernel_param {
        const char *name;
        const struct kernel_param_ops *ops;
        u16 perm;
-       u16 flags;
+       s16 level;
        union {
                void *arg;
                const struct kparam_string *str;
@@ -131,8 +128,40 @@ struct kparam_array
  * The ops can have NULL set or get functions.
  */
 #define module_param_cb(name, ops, arg, perm)                                \
-       __module_param_call(MODULE_PARAM_PREFIX,                              \
-                           name, ops, arg, __same_type((arg), bool *), perm)
+       __module_param_call(MODULE_PARAM_PREFIX, name, ops, arg, perm, 0)
+
+/**
+ * <level>_param_cb - general callback for a module/cmdline parameter
+ *                    to be evaluated before certain initcall level
+ * @name: a valid C identifier which is the parameter name.
+ * @ops: the set & get operations for this parameter.
+ * @perm: visibility in sysfs.
+ *
+ * The ops can have NULL set or get functions.
+ */
+#define __level_param_cb(name, ops, arg, perm, level)                  \
+       __module_param_call(MODULE_PARAM_PREFIX, name, ops, arg, perm, level)
+
+#define core_param_cb(name, ops, arg, perm)            \
+       __level_param_cb(name, ops, arg, perm, 1)
+
+#define postcore_param_cb(name, ops, arg, perm)                \
+       __level_param_cb(name, ops, arg, perm, 2)
+
+#define arch_param_cb(name, ops, arg, perm)            \
+       __level_param_cb(name, ops, arg, perm, 3)
+
+#define subsys_param_cb(name, ops, arg, perm)          \
+       __level_param_cb(name, ops, arg, perm, 4)
+
+#define fs_param_cb(name, ops, arg, perm)              \
+       __level_param_cb(name, ops, arg, perm, 5)
+
+#define device_param_cb(name, ops, arg, perm)          \
+       __level_param_cb(name, ops, arg, perm, 6)
+
+#define late_param_cb(name, ops, arg, perm)            \
+       __level_param_cb(name, ops, arg, perm, 7)
 
 /* On alpha, ia64 and ppc64 relocations to global data cannot go into
    read-only sections (which is part of respective UNIX ABI on these
@@ -146,7 +175,7 @@ struct kparam_array
 
 /* This is the fundamental function for registering boot/module
    parameters. */
-#define __module_param_call(prefix, name, ops, arg, isbool, perm)      \
+#define __module_param_call(prefix, name, ops, arg, perm, level)       \
        /* Default value instead of permissions? */                     \
        static int __param_perm_check_##name __attribute__((unused)) =  \
        BUILD_BUG_ON_ZERO((perm) < 0 || (perm) > 0777 || ((perm) & 2))  \
@@ -155,8 +184,7 @@ struct kparam_array
        static struct kernel_param __moduleparam_const __param_##name   \
        __used                                                          \
     __attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) \
-       = { __param_str_##name, ops, perm, isbool ? KPARAM_ISBOOL : 0,  \
-           { arg } }
+       = { __param_str_##name, ops, perm, level, { arg } }
 
 /* Obsolete - use module_param_cb() */
 #define module_param_call(name, set, get, arg, perm)                   \
@@ -164,8 +192,7 @@ struct kparam_array
                 { (void *)set, (void *)get };                          \
        __module_param_call(MODULE_PARAM_PREFIX,                        \
                            name, &__param_ops_##name, arg,             \
-                           __same_type(arg, bool *),                   \
-                           (perm) + sizeof(__check_old_set_param(set))*0)
+                           (perm) + sizeof(__check_old_set_param(set))*0, 0)
 
 /* We don't get oldget: it's often a new-style param_get_uint, etc. */
 static inline int
@@ -245,8 +272,7 @@ static inline void __kernel_param_unlock(void)
  */
 #define core_param(name, var, type, perm)                              \
        param_check_##type(name, &(var));                               \
-       __module_param_call("", name, &param_ops_##type,                \
-                           &var, __same_type(var, bool), perm)
+       __module_param_call("", name, &param_ops_##type, &var, perm, 0)
 #endif /* !MODULE */
 
 /**
@@ -264,7 +290,7 @@ static inline void __kernel_param_unlock(void)
                = { len, string };                                      \
        __module_param_call(MODULE_PARAM_PREFIX, name,                  \
                            &param_ops_string,                          \
-                           .str = &__param_string_##name, 0, perm);    \
+                           .str = &__param_string_##name, perm, 0);    \
        __MODULE_PARM_TYPE(name, "string")
 
 /**
@@ -292,6 +318,8 @@ extern int parse_args(const char *name,
                      char *args,
                      const struct kernel_param *params,
                      unsigned num,
+                     s16 level_min,
+                     s16 level_max,
                      int (*unknown)(char *param, char *val));
 
 /* Called by module remove. */
@@ -403,7 +431,7 @@ extern int param_set_bint(const char *val, const struct kernel_param *kp);
        __module_param_call(MODULE_PARAM_PREFIX, name,                  \
                            &param_array_ops,                           \
                            .arr = &__param_arr_##name,                 \
-                           __same_type(array[0], bool), perm);         \
+                           perm, 0);                                   \
        __MODULE_PARM_TYPE(name, "array of " #type)
 
 extern struct kernel_param_ops param_array_ops;
index 94e924e..3595a02 100644 (file)
@@ -29,8 +29,8 @@
 #include <linux/kernel.h>
 
 #include <asm/unaligned.h>
-#include <asm/system.h>
 #include <asm/io.h>
+#include <asm/barrier.h>
 
 #ifdef CONFIG_MTD_MAP_BANK_WIDTH_1
 #define map_bankwidth(map) 1
index d46a18f..fa7fb1d 100644 (file)
@@ -58,9 +58,6 @@ struct device_node {
        struct  kref kref;
        unsigned long _flags;
        void    *data;
-#if defined(CONFIG_EEH)
-       struct eeh_dev *edev;
-#endif
 #if defined(CONFIG_SPARC)
        char    *path_component_name;
        unsigned int unique_id;
@@ -75,13 +72,6 @@ struct of_phandle_args {
        uint32_t args[MAX_PHANDLE_ARGS];
 };
 
-#if defined(CONFIG_EEH)
-static inline struct eeh_dev *of_node_to_eeh_dev(struct device_node *dn)
-{
-       return dn->edev;
-}
-#endif
-
 #ifdef CONFIG_OF_DYNAMIC
 extern struct device_node *of_node_get(struct device_node *node);
 extern void of_node_put(struct device_node *node);
@@ -361,6 +351,22 @@ static inline int of_machine_is_compatible(const char *compat)
 #define of_match_node(_matches, _node) NULL
 #endif /* CONFIG_OF */
 
+/**
+ * of_property_read_bool - Findfrom a property
+ * @np:                device node from which the property value is to be read.
+ * @propname:  name of the property to be searched.
+ *
+ * Search for a property in a device node.
+ * Returns true if the property exist false otherwise.
+ */
+static inline bool of_property_read_bool(const struct device_node *np,
+                                        const char *propname)
+{
+       struct property *prop = of_find_property(np, propname, NULL);
+
+       return prop ? true : false;
+}
+
 static inline int of_property_read_u32(const struct device_node *np,
                                       const char *propname,
                                       u32 *out_value)
index b254052..81733d1 100644 (file)
@@ -50,7 +50,8 @@ static inline struct of_mm_gpio_chip *to_of_mm_gpio_chip(struct gpio_chip *gc)
 extern int of_get_named_gpio_flags(struct device_node *np,
                const char *list_name, int index, enum of_gpio_flags *flags);
 
-extern unsigned int of_gpio_count(struct device_node *np);
+extern unsigned int of_gpio_named_count(struct device_node *np,
+                                       const char* propname);
 
 extern int of_mm_gpiochip_add(struct device_node *np,
                              struct of_mm_gpio_chip *mm_gc);
@@ -71,7 +72,8 @@ static inline int of_get_named_gpio_flags(struct device_node *np,
        return -ENOSYS;
 }
 
-static inline unsigned int of_gpio_count(struct device_node *np)
+static inline unsigned int of_gpio_named_count(struct device_node *np,
+                                       const char* propname)
 {
        return 0;
 }
@@ -89,6 +91,27 @@ static inline void of_gpiochip_remove(struct gpio_chip *gc) { }
 #endif /* CONFIG_OF_GPIO */
 
 /**
+ * of_gpio_count - Count GPIOs for a device
+ * @np:                device node to count GPIOs for
+ *
+ * The function returns the count of GPIOs specified for a node.
+ *
+ * Note that the empty GPIO specifiers counts too. For example,
+ *
+ * gpios = <0
+ *          &pio1 1 2
+ *          0
+ *          &pio2 3 4>;
+ *
+ * defines four GPIOs (so this function will return 4), two of which
+ * are not specified.
+ */
+static inline unsigned int of_gpio_count(struct device_node *np)
+{
+       return of_gpio_named_count(np, "gpios");
+}
+
+/**
  * of_get_gpio_flags() - Get a GPIO number and flags to use with GPIO API
  * @np:                device node to get GPIO from
  * @index:     index of the GPIO
diff --git a/include/linux/of_mtd.h b/include/linux/of_mtd.h
new file mode 100644 (file)
index 0000000..bae1b60
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * OF helpers for mtd.
+ *
+ * This file is released under the GPLv2
+ */
+
+#ifndef __LINUX_OF_MTD_H
+#define __LINUX_OF_NET_H
+
+#ifdef CONFIG_OF_MTD
+#include <linux/of.h>
+extern const int of_get_nand_ecc_mode(struct device_node *np);
+int of_get_nand_bus_width(struct device_node *np);
+bool of_get_nand_on_flash_bbt(struct device_node *np);
+#endif
+
+#endif /* __LINUX_OF_MTD_H */
index 38a423e..106c2ca 100644 (file)
@@ -100,7 +100,6 @@ typedef enum {
 #include <linux/wait.h>
 #include <linux/irqreturn.h>
 #include <linux/semaphore.h>
-#include <asm/system.h>
 #include <asm/ptrace.h>
 
 /* Define this later. */
diff --git a/include/linux/platform_data/atmel.h b/include/linux/platform_data/atmel.h
new file mode 100644 (file)
index 0000000..d056263
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * atmel platform data
+ *
+ * GPL v2 Only
+ */
+
+#ifndef __ATMEL_NAND_H__
+#define __ATMEL_NAND_H__
+
+#include <linux/mtd/nand.h>
+
+ /* NAND / SmartMedia */
+struct atmel_nand_data {
+       int             enable_pin;             /* chip enable */
+       int             det_pin;                /* card detect */
+       int             rdy_pin;                /* ready/busy */
+       u8              rdy_pin_active_low;     /* rdy_pin value is inverted */
+       u8              ale;                    /* address line number connected to ALE */
+       u8              cle;                    /* address line number connected to CLE */
+       u8              bus_width_16;           /* buswidth is 16 bit */
+       u8              ecc_mode;               /* ecc mode */
+       u8              on_flash_bbt;           /* bbt on flash */
+       struct mtd_partition *parts;
+       unsigned int    num_parts;
+};
+
+#endif /* __ATMEL_NAND_H__ */
index 76579f9..7bd73bb 100644 (file)
@@ -26,7 +26,26 @@ enum ab8500_regulator_id {
        AB8500_NUM_REGULATORS,
 };
 
-/* AB8500 register initialization */
+/* AB9450 regulators */
+enum ab9540_regulator_id {
+       AB9540_LDO_AUX1,
+       AB9540_LDO_AUX2,
+       AB9540_LDO_AUX3,
+       AB9540_LDO_AUX4,
+       AB9540_LDO_INTCORE,
+       AB9540_LDO_TVOUT,
+       AB9540_LDO_USB,
+       AB9540_LDO_AUDIO,
+       AB9540_LDO_ANAMIC1,
+       AB9540_LDO_ANAMIC2,
+       AB9540_LDO_DMIC,
+       AB9540_LDO_ANA,
+       AB9540_SYSCLKREQ_2,
+       AB9540_SYSCLKREQ_4,
+       AB9540_NUM_REGULATORS,
+};
+
+/* AB8500 and AB9540 register initialization */
 struct ab8500_regulator_reg_init {
        int id;
        u8 value;
@@ -71,4 +90,53 @@ enum ab8500_regulator_reg {
        AB8500_NUM_REGULATOR_REGISTERS,
 };
 
+
+/* AB9540 registers */
+enum ab9540_regulator_reg {
+       AB9540_REGUREQUESTCTRL1,
+       AB9540_REGUREQUESTCTRL2,
+       AB9540_REGUREQUESTCTRL3,
+       AB9540_REGUREQUESTCTRL4,
+       AB9540_REGUSYSCLKREQ1HPVALID1,
+       AB9540_REGUSYSCLKREQ1HPVALID2,
+       AB9540_REGUHWHPREQ1VALID1,
+       AB9540_REGUHWHPREQ1VALID2,
+       AB9540_REGUHWHPREQ2VALID1,
+       AB9540_REGUHWHPREQ2VALID2,
+       AB9540_REGUSWHPREQVALID1,
+       AB9540_REGUSWHPREQVALID2,
+       AB9540_REGUSYSCLKREQVALID1,
+       AB9540_REGUSYSCLKREQVALID2,
+       AB9540_REGUVAUX4REQVALID,
+       AB9540_REGUMISC1,
+       AB9540_VAUDIOSUPPLY,
+       AB9540_REGUCTRL1VAMIC,
+       AB9540_VSMPS1REGU,
+       AB9540_VSMPS2REGU,
+       AB9540_VSMPS3REGU, /* NOTE! PRCMU register */
+       AB9540_VPLLVANAREGU,
+       AB9540_EXTSUPPLYREGU,
+       AB9540_VAUX12REGU,
+       AB9540_VRF1VAUX3REGU,
+       AB9540_VSMPS1SEL1,
+       AB9540_VSMPS1SEL2,
+       AB9540_VSMPS1SEL3,
+       AB9540_VSMPS2SEL1,
+       AB9540_VSMPS2SEL2,
+       AB9540_VSMPS2SEL3,
+       AB9540_VSMPS3SEL1, /* NOTE! PRCMU register */
+       AB9540_VSMPS3SEL2, /* NOTE! PRCMU register */
+       AB9540_VAUX1SEL,
+       AB9540_VAUX2SEL,
+       AB9540_VRF1VAUX3SEL,
+       AB9540_REGUCTRL2SPARE,
+       AB9540_VAUX4REQCTRL,
+       AB9540_VAUX4REGU,
+       AB9540_VAUX4SEL,
+       AB9540_REGUCTRLDISCH,
+       AB9540_REGUCTRLDISCH2,
+       AB9540_REGUCTRLDISCH3,
+       AB9540_NUM_REGULATOR_REGISTERS,
+};
+
 #endif
index 63d4065..54bd7cd 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/list.h>
 #include <linux/spinlock.h>
 
-#include <asm/system.h>
 #include <linux/atomic.h>
 
 struct rw_semaphore;
index 0c3854b..81a173c 100644 (file)
@@ -63,7 +63,6 @@ struct sched_param {
 #include <linux/nodemask.h>
 #include <linux/mm_types.h>
 
-#include <asm/system.h>
 #include <asm/page.h>
 #include <asm/ptrace.h>
 #include <asm/cputime.h>
index 192250b..3337027 100644 (file)
@@ -501,7 +501,6 @@ struct sk_buff {
  */
 #include <linux/slab.h>
 
-#include <asm/system.h>
 
 /*
  * skb might have a dst pointer attached, refcounted or not.
index 573c809..a595dce 100644 (file)
@@ -190,7 +190,7 @@ size_t ksize(const void *);
 #endif
 
 /**
- * kcalloc - allocate memory for an array. The memory is set to zero.
+ * kmalloc_array - allocate memory for an array.
  * @n: number of elements.
  * @size: element size.
  * @flags: the type of memory to allocate.
@@ -240,11 +240,22 @@ size_t ksize(const void *);
  * for general use, and so are not documented here. For a full list of
  * potential flags, always refer to linux/gfp.h.
  */
-static inline void *kcalloc(size_t n, size_t size, gfp_t flags)
+static inline void *kmalloc_array(size_t n, size_t size, gfp_t flags)
 {
        if (size != 0 && n > ULONG_MAX / size)
                return NULL;
-       return __kmalloc(n * size, flags | __GFP_ZERO);
+       return __kmalloc(n * size, flags);
+}
+
+/**
+ * kcalloc - allocate memory for an array. The memory is set to zero.
+ * @n: number of elements.
+ * @size: element size.
+ * @flags: the type of memory to allocate (see kmalloc).
+ */
+static inline void *kcalloc(size_t n, size_t size, gfp_t flags)
+{
+       return kmalloc_array(n, size, flags | __GFP_ZERO);
 }
 
 #if !defined(CONFIG_NUMA) && !defined(CONFIG_SLOB)
index ca122b3..c2f8c8b 100644 (file)
@@ -22,7 +22,7 @@ enum stat_item {
        FREE_FROZEN,            /* Freeing to frozen slab */
        FREE_ADD_PARTIAL,       /* Freeing moves slab to partial list */
        FREE_REMOVE_PARTIAL,    /* Freeing removes last object */
-       ALLOC_FROM_PARTIAL,     /* Cpu slab acquired from partial list */
+       ALLOC_FROM_PARTIAL,     /* Cpu slab acquired from node partial list */
        ALLOC_SLAB,             /* Cpu slab acquired from page allocator */
        ALLOC_REFILL,           /* Refill cpu slab from slab freelist */
        ALLOC_NODE_MISMATCH,    /* Switching cpu slab */
@@ -38,7 +38,9 @@ enum stat_item {
        CMPXCHG_DOUBLE_CPU_FAIL,/* Failure of this_cpu_cmpxchg_double */
        CMPXCHG_DOUBLE_FAIL,    /* Number of times that cmpxchg double did not match */
        CPU_PARTIAL_ALLOC,      /* Used cpu partial on alloc */
-       CPU_PARTIAL_FREE,       /* USed cpu partial on free */
+       CPU_PARTIAL_FREE,       /* Refill cpu partial on free */
+       CPU_PARTIAL_NODE,       /* Refill cpu partial from node partial */
+       CPU_PARTIAL_DRAIN,      /* Drain cpu partial to node partial */
        NR_SLUB_STAT_ITEMS };
 
 struct kmem_cache_cpu {
index decf6d8..b4d9fa6 100644 (file)
@@ -11,7 +11,6 @@
 
 struct orion_spi_info {
        u32     tclk;           /* no <linux/clk.h> support yet */
-       u32     enable_clock_fix;
 };
 
 
index 3632390..7d537ce 100644 (file)
@@ -55,8 +55,8 @@
 #include <linux/kernel.h>
 #include <linux/stringify.h>
 #include <linux/bottom_half.h>
+#include <asm/barrier.h>
 
-#include <asm/system.h>
 
 /*
  * Must define these before including other files, inline functions need them
index c170edc..3b5e910 100644 (file)
@@ -5,7 +5,6 @@
 #include <linux/cpumask.h>
 #include <linux/smp.h>
 #include <linux/list.h>
-#include <asm/system.h>
 
 /*
  * stop_cpu[s]() is simplistic per-cpu maximum priority cpu
index a91ff40..9f47ab5 100644 (file)
@@ -44,7 +44,6 @@
 #include <linux/tty_ldisc.h>
 #include <linux/mutex.h>
 
-#include <asm/system.h>
 
 
 /*
index 7d9a9e9..1dee81c 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/list.h>
 #include <linux/stddef.h>
 #include <linux/spinlock.h>
-#include <asm/system.h>
 #include <asm/current.h>
 
 typedef struct __wait_queue wait_queue_t;
index 43ba5b3..ac40716 100644 (file)
@@ -66,6 +66,7 @@ struct watchdog_device;
  * @ping:      The routine that sends a keepalive ping to the watchdog device.
  * @status:    The routine that shows the status of the watchdog device.
  * @set_timeout:The routine for setting the watchdog devices timeout value.
+ * @get_timeleft:The routine that get's the time that's left before a reset.
  * @ioctl:     The routines that handles extra ioctl calls.
  *
  * The watchdog_ops structure contains a list of low-level operations
@@ -82,6 +83,7 @@ struct watchdog_ops {
        int (*ping)(struct watchdog_device *);
        unsigned int (*status)(struct watchdog_device *);
        int (*set_timeout)(struct watchdog_device *, unsigned int);
+       unsigned int (*get_timeleft)(struct watchdog_device *);
        long (*ioctl)(struct watchdog_device *, unsigned int, unsigned long);
 };
 
@@ -127,7 +129,7 @@ struct watchdog_device {
 #endif
 
 /* Use the following function to set the nowayout feature */
-static inline void watchdog_set_nowayout(struct watchdog_device *wdd, int nowayout)
+static inline void watchdog_set_nowayout(struct watchdog_device *wdd, bool nowayout)
 {
        if (nowayout)
                set_bit(WDOG_NO_WAY_OUT, &wdd->status);
index 03c85d7..6a198e4 100644 (file)
@@ -23,6 +23,7 @@ int xen_create_contiguous_region(unsigned long vstart, unsigned int order,
 
 void xen_destroy_contiguous_region(unsigned long vstart, unsigned int order);
 
+struct vm_area_struct;
 int xen_remap_domain_mfn_range(struct vm_area_struct *vma,
                               unsigned long addr,
                               unsigned long mfn, int nr,
index c24805c..9d454f0 100644 (file)
@@ -87,7 +87,6 @@ extern void mca_init(void);
 extern void sbus_init(void);
 extern void prio_tree_init(void);
 extern void radix_tree_init(void);
-extern void free_initmem(void);
 #ifndef CONFIG_DEBUG_RODATA
 static inline void mark_rodata_ro(void) { }
 #endif
@@ -400,7 +399,7 @@ static int __init do_early_param(char *param, char *val)
 
 void __init parse_early_options(char *cmdline)
 {
-       parse_args("early options", cmdline, NULL, 0, do_early_param);
+       parse_args("early options", cmdline, NULL, 0, 0, 0, do_early_param);
 }
 
 /* Arch code calls this early on, or if not, just before other parsing. */
@@ -503,7 +502,7 @@ asmlinkage void __init start_kernel(void)
        parse_early_param();
        parse_args("Booting kernel", static_command_line, __start___param,
                   __stop___param - __start___param,
-                  &unknown_bootoption);
+                  0, 0, &unknown_bootoption);
 
        jump_label_init();
 
@@ -699,16 +698,69 @@ int __init_or_module do_one_initcall(initcall_t fn)
 }
 
 
-extern initcall_t __initcall_start[], __initcall_end[], __early_initcall_end[];
+extern initcall_t __initcall_start[];
+extern initcall_t __initcall0_start[];
+extern initcall_t __initcall1_start[];
+extern initcall_t __initcall2_start[];
+extern initcall_t __initcall3_start[];
+extern initcall_t __initcall4_start[];
+extern initcall_t __initcall5_start[];
+extern initcall_t __initcall6_start[];
+extern initcall_t __initcall7_start[];
+extern initcall_t __initcall_end[];
+
+static initcall_t *initcall_levels[] __initdata = {
+       __initcall0_start,
+       __initcall1_start,
+       __initcall2_start,
+       __initcall3_start,
+       __initcall4_start,
+       __initcall5_start,
+       __initcall6_start,
+       __initcall7_start,
+       __initcall_end,
+};
+
+static char *initcall_level_names[] __initdata = {
+       "early parameters",
+       "core parameters",
+       "postcore parameters",
+       "arch parameters",
+       "subsys parameters",
+       "fs parameters",
+       "device parameters",
+       "late parameters",
+};
+
+static int __init ignore_unknown_bootoption(char *param, char *val)
+{
+       return 0;
+}
 
-static void __init do_initcalls(void)
+static void __init do_initcall_level(int level)
 {
+       extern const struct kernel_param __start___param[], __stop___param[];
        initcall_t *fn;
 
-       for (fn = __early_initcall_end; fn < __initcall_end; fn++)
+       strcpy(static_command_line, saved_command_line);
+       parse_args(initcall_level_names[level],
+                  static_command_line, __start___param,
+                  __stop___param - __start___param,
+                  level, level,
+                  ignore_unknown_bootoption);
+
+       for (fn = initcall_levels[level]; fn < initcall_levels[level+1]; fn++)
                do_one_initcall(*fn);
 }
 
+static void __init do_initcalls(void)
+{
+       int level;
+
+       for (level = 0; level < ARRAY_SIZE(initcall_levels) - 1; level++)
+               do_initcall_level(level);
+}
+
 /*
  * Ok, the machine is now initialized. None of the devices
  * have been touched yet, but the CPU subsystem is up and
@@ -732,7 +784,7 @@ static void __init do_pre_smp_initcalls(void)
 {
        initcall_t *fn;
 
-       for (fn = __initcall_start; fn < __early_initcall_end; fn++)
+       for (fn = __initcall_start; fn < __initcall0_start; fn++)
                do_one_initcall(*fn);
 }
 
index 3f88a45..1dc53ba 100644 (file)
@@ -53,7 +53,6 @@
 #include <asm/cacheflush.h>
 #include <asm/byteorder.h>
 #include <linux/atomic.h>
-#include <asm/system.h>
 
 #include "debug_core.h"
 
index 7179eac..07c9bbb 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/sched.h>
 #include <linux/kdb.h>
 #include <linux/nmi.h>
-#include <asm/system.h>
 #include "kdb_private.h"
 
 
index 68a2306..6c6262f 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/proc_fs.h>
 #include <linux/init.h>
 #include <asm/dma.h>
-#include <asm/system.h>
 
 
 
index 3288c9b..4e2e472 100644 (file)
@@ -37,7 +37,6 @@
 #include <asm/page.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
-#include <asm/system.h>
 #include <asm/sections.h>
 
 /* Per cpu memory for storing cpu states in case of system crash. */
index 2c93276..78ac6ec 100644 (file)
@@ -105,6 +105,7 @@ struct list_head *kdb_modules = &modules; /* kdb needs the list of modules */
 
 /* Block module loading/unloading? */
 int modules_disabled = 0;
+core_param(nomodule, modules_disabled, bint, 0);
 
 /* Waiting for a module to finish initializing? */
 static DECLARE_WAIT_QUEUE_HEAD(module_wq);
@@ -903,6 +904,36 @@ static ssize_t show_refcnt(struct module_attribute *mattr,
 static struct module_attribute modinfo_refcnt =
        __ATTR(refcnt, 0444, show_refcnt, NULL);
 
+void __module_get(struct module *module)
+{
+       if (module) {
+               preempt_disable();
+               __this_cpu_inc(module->refptr->incs);
+               trace_module_get(module, _RET_IP_);
+               preempt_enable();
+       }
+}
+EXPORT_SYMBOL(__module_get);
+
+bool try_module_get(struct module *module)
+{
+       bool ret = true;
+
+       if (module) {
+               preempt_disable();
+
+               if (likely(module_is_live(module))) {
+                       __this_cpu_inc(module->refptr->incs);
+                       trace_module_get(module, _RET_IP_);
+               } else
+                       ret = false;
+
+               preempt_enable();
+       }
+       return ret;
+}
+EXPORT_SYMBOL(try_module_get);
+
 void module_put(struct module *module)
 {
        if (module) {
@@ -2380,8 +2411,7 @@ static int copy_and_check(struct load_info *info,
                return -ENOEXEC;
 
        /* Suck in entire file: we'll want most of it. */
-       /* vmalloc barfs on "unusual" numbers.  Check here */
-       if (len > 64 * 1024 * 1024 || (hdr = vmalloc(len)) == NULL)
+       if ((hdr = vmalloc(len)) == NULL)
                return -ENOMEM;
 
        if (copy_from_user(hdr, umod, len) != 0) {
@@ -2922,7 +2952,8 @@ static struct module *load_module(void __user *umod,
        mutex_unlock(&module_mutex);
 
        /* Module is ready to execute: parsing args may do that. */
-       err = parse_args(mod->name, mod->args, mod->kp, mod->num_kp, NULL);
+       err = parse_args(mod->name, mod->args, mod->kp, mod->num_kp,
+                        -32768, 32767, NULL);
        if (err < 0)
                goto unlink;
 
index 47f5bf1..f37d826 100644 (file)
@@ -87,6 +87,8 @@ static int parse_one(char *param,
                     char *val,
                     const struct kernel_param *params,
                     unsigned num_params,
+                    s16 min_level,
+                    s16 max_level,
                     int (*handle_unknown)(char *param, char *val))
 {
        unsigned int i;
@@ -95,6 +97,9 @@ static int parse_one(char *param,
        /* Find parameter */
        for (i = 0; i < num_params; i++) {
                if (parameq(param, params[i].name)) {
+                       if (params[i].level < min_level
+                           || params[i].level > max_level)
+                               return 0;
                        /* No one handled NULL, so do it here. */
                        if (!val && params[i].ops->set != param_set_bool
                            && params[i].ops->set != param_set_bint)
@@ -174,6 +179,8 @@ int parse_args(const char *name,
               char *args,
               const struct kernel_param *params,
               unsigned num,
+              s16 min_level,
+              s16 max_level,
               int (*unknown)(char *param, char *val))
 {
        char *param, *val;
@@ -189,7 +196,8 @@ int parse_args(const char *name,
 
                args = next_arg(args, &param, &val);
                irq_was_disabled = irqs_disabled();
-               ret = parse_one(param, val, params, num, unknown);
+               ret = parse_one(param, val, params, num,
+                               min_level, max_level, unknown);
                if (irq_was_disabled && !irqs_disabled()) {
                        printk(KERN_WARNING "parse_args(): option '%s' enabled "
                                        "irq's!\n", param);
@@ -297,35 +305,18 @@ EXPORT_SYMBOL(param_ops_charp);
 /* Actually could be a bool or an int, for historical reasons. */
 int param_set_bool(const char *val, const struct kernel_param *kp)
 {
-       bool v;
-       int ret;
-
        /* No equals means "set"... */
        if (!val) val = "1";
 
        /* One of =[yYnN01] */
-       ret = strtobool(val, &v);
-       if (ret)
-               return ret;
-
-       if (kp->flags & KPARAM_ISBOOL)
-               *(bool *)kp->arg = v;
-       else
-               *(int *)kp->arg = v;
-       return 0;
+       return strtobool(val, kp->arg);
 }
 EXPORT_SYMBOL(param_set_bool);
 
 int param_get_bool(char *buffer, const struct kernel_param *kp)
 {
-       bool val;
-       if (kp->flags & KPARAM_ISBOOL)
-               val = *(bool *)kp->arg;
-       else
-               val = *(int *)kp->arg;
-
        /* Y and N chosen as being relatively non-coder friendly */
-       return sprintf(buffer, "%c", val ? 'Y' : 'N');
+       return sprintf(buffer, "%c", *(bool *)kp->arg ? 'Y' : 'N');
 }
 EXPORT_SYMBOL(param_get_bool);
 
@@ -343,7 +334,6 @@ int param_set_invbool(const char *val, const struct kernel_param *kp)
        struct kernel_param dummy;
 
        dummy.arg = &boolval;
-       dummy.flags = KPARAM_ISBOOL;
        ret = param_set_bool(val, &dummy);
        if (ret == 0)
                *(bool *)kp->arg = !boolval;
@@ -372,7 +362,6 @@ int param_set_bint(const char *val, const struct kernel_param *kp)
        /* Match bool exactly, by re-using it. */
        boolkp = *kp;
        boolkp.arg = &v;
-       boolkp.flags |= KPARAM_ISBOOL;
 
        ret = param_set_bool(val, &boolkp);
        if (ret == 0)
@@ -393,7 +382,7 @@ static int param_array(const char *name,
                       unsigned int min, unsigned int max,
                       void *elem, int elemsize,
                       int (*set)(const char *, const struct kernel_param *kp),
-                      u16 flags,
+                      s16 level,
                       unsigned int *num)
 {
        int ret;
@@ -403,7 +392,7 @@ static int param_array(const char *name,
        /* Get the name right for errors. */
        kp.name = name;
        kp.arg = elem;
-       kp.flags = flags;
+       kp.level = level;
 
        *num = 0;
        /* We expect a comma-separated list of values. */
@@ -444,7 +433,7 @@ static int param_array_set(const char *val, const struct kernel_param *kp)
        unsigned int temp_num;
 
        return param_array(kp->name, val, 1, arr->max, arr->elem,
-                          arr->elemsize, arr->ops->set, kp->flags,
+                          arr->elemsize, arr->ops->set, kp->level,
                           arr->num ?: &temp_num);
 }
 
index b152f74..6850f53 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/export.h>
 #include <linux/rwsem.h>
 
-#include <asm/system.h>
 #include <linux/atomic.h>
 
 /*
index 503d642..157fb9b 100644 (file)
@@ -73,6 +73,7 @@
 #include <linux/init_task.h>
 #include <linux/binfmts.h>
 
+#include <asm/switch_to.h>
 #include <asm/tlb.h>
 #include <asm/irq_regs.h>
 #include <asm/mutex.h>
index d523da0..17afcaf 100644 (file)
@@ -36,6 +36,7 @@
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
 #include <asm/siginfo.h>
+#include <asm/cacheflush.h>
 #include "audit.h"     /* audit_signal_info() */
 
 /*
index dbd70bd..52b3a06 100644 (file)
@@ -69,6 +69,9 @@
 #include <asm/stacktrace.h>
 #include <asm/io.h>
 #endif
+#ifdef CONFIG_SPARC
+#include <asm/setup.h>
+#endif
 #ifdef CONFIG_BSD_PROCESS_ACCT
 #include <linux/acct.h>
 #endif
@@ -143,7 +146,6 @@ static const int cap_last_cap = CAP_LAST_CAP;
 #include <linux/inotify.h>
 #endif
 #ifdef CONFIG_SPARC
-#include <asm/system.h>
 #endif
 
 #ifdef CONFIG_SPARC64
index 8221b3d..4a15115 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/interrupt.h>
 #include <linux/llist.h>
 
-#include <asm/system.h>
 
 /**
  * llist_add_batch - add several linked entries in batch
index 2654d5c..b71012b 100644 (file)
@@ -28,8 +28,8 @@
 
 #include <altivec.h>
 #ifdef __KERNEL__
-# include <asm/system.h>
 # include <asm/cputable.h>
+# include <asm/switch_to.h>
 #endif
 
 /*
index 29c8716..e901a36 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -1731,6 +1731,52 @@ static int __init cpucache_init(void)
 }
 __initcall(cpucache_init);
 
+static noinline void
+slab_out_of_memory(struct kmem_cache *cachep, gfp_t gfpflags, int nodeid)
+{
+       struct kmem_list3 *l3;
+       struct slab *slabp;
+       unsigned long flags;
+       int node;
+
+       printk(KERN_WARNING
+               "SLAB: Unable to allocate memory on node %d (gfp=0x%x)\n",
+               nodeid, gfpflags);
+       printk(KERN_WARNING "  cache: %s, object size: %d, order: %d\n",
+               cachep->name, cachep->buffer_size, cachep->gfporder);
+
+       for_each_online_node(node) {
+               unsigned long active_objs = 0, num_objs = 0, free_objects = 0;
+               unsigned long active_slabs = 0, num_slabs = 0;
+
+               l3 = cachep->nodelists[node];
+               if (!l3)
+                       continue;
+
+               spin_lock_irqsave(&l3->list_lock, flags);
+               list_for_each_entry(slabp, &l3->slabs_full, list) {
+                       active_objs += cachep->num;
+                       active_slabs++;
+               }
+               list_for_each_entry(slabp, &l3->slabs_partial, list) {
+                       active_objs += slabp->inuse;
+                       active_slabs++;
+               }
+               list_for_each_entry(slabp, &l3->slabs_free, list)
+                       num_slabs++;
+
+               free_objects += l3->free_objects;
+               spin_unlock_irqrestore(&l3->list_lock, flags);
+
+               num_slabs += active_slabs;
+               num_objs = num_slabs * cachep->num;
+               printk(KERN_WARNING
+                       "  node %d: slabs: %ld/%ld, objs: %ld/%ld, free: %ld\n",
+                       node, active_slabs, num_slabs, active_objs, num_objs,
+                       free_objects);
+       }
+}
+
 /*
  * Interface to system's page allocator. No need to hold the cache-lock.
  *
@@ -1757,8 +1803,11 @@ static void *kmem_getpages(struct kmem_cache *cachep, gfp_t flags, int nodeid)
                flags |= __GFP_RECLAIMABLE;
 
        page = alloc_pages_exact_node(nodeid, flags | __GFP_NOTRACK, cachep->gfporder);
-       if (!page)
+       if (!page) {
+               if (!(flags & __GFP_NOWARN) && printk_ratelimit())
+                       slab_out_of_memory(cachep, flags, nodeid);
                return NULL;
+       }
 
        nr_pages = (1 << cachep->gfporder);
        if (cachep->flags & SLAB_RECLAIM_ACCOUNT)
@@ -3696,13 +3745,12 @@ static inline void __cache_free(struct kmem_cache *cachep, void *objp,
 
        if (likely(ac->avail < ac->limit)) {
                STATS_INC_FREEHIT(cachep);
-               ac->entry[ac->avail++] = objp;
-               return;
        } else {
                STATS_INC_FREEMISS(cachep);
                cache_flusharray(cachep, ac);
-               ac->entry[ac->avail++] = objp;
        }
+
+       ac->entry[ac->avail++] = objp;
 }
 
 /**
index dcbb192..ffe13fd 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -29,6 +29,7 @@
 #include <linux/math64.h>
 #include <linux/fault-inject.h>
 #include <linux/stacktrace.h>
+#include <linux/prefetch.h>
 
 #include <trace/events/kmem.h>
 
@@ -269,6 +270,11 @@ static inline void *get_freepointer(struct kmem_cache *s, void *object)
        return *(void **)(object + s->offset);
 }
 
+static void prefetch_freepointer(const struct kmem_cache *s, void *object)
+{
+       prefetch(object + s->offset);
+}
+
 static inline void *get_freepointer_safe(struct kmem_cache *s, void *object)
 {
        void *p;
@@ -1560,6 +1566,7 @@ static void *get_partial_node(struct kmem_cache *s,
                } else {
                        page->freelist = t;
                        available = put_cpu_partial(s, page, 0);
+                       stat(s, CPU_PARTIAL_NODE);
                }
                if (kmem_cache_debug(s) || available > s->cpu_partial / 2)
                        break;
@@ -1983,6 +1990,7 @@ int put_cpu_partial(struct kmem_cache *s, struct page *page, int drain)
                                local_irq_restore(flags);
                                pobjects = 0;
                                pages = 0;
+                               stat(s, CPU_PARTIAL_DRAIN);
                        }
                }
 
@@ -1994,7 +2002,6 @@ int put_cpu_partial(struct kmem_cache *s, struct page *page, int drain)
                page->next = oldpage;
 
        } while (this_cpu_cmpxchg(s->cpu_slab->partial, oldpage, page) != oldpage);
-       stat(s, CPU_PARTIAL_FREE);
        return pobjects;
 }
 
@@ -2327,6 +2334,8 @@ redo:
                object = __slab_alloc(s, gfpflags, node, addr, c);
 
        else {
+               void *next_object = get_freepointer_safe(s, object);
+
                /*
                 * The cmpxchg will only match if there was no additional
                 * operation and if we are on the right processor.
@@ -2342,11 +2351,12 @@ redo:
                if (unlikely(!this_cpu_cmpxchg_double(
                                s->cpu_slab->freelist, s->cpu_slab->tid,
                                object, tid,
-                               get_freepointer_safe(s, object), next_tid(tid)))) {
+                               next_object, next_tid(tid)))) {
 
                        note_cmpxchg_failure("slab_alloc", s, tid);
                        goto redo;
                }
+               prefetch_freepointer(s, next_object);
                stat(s, ALLOC_FASTPATH);
        }
 
@@ -2483,9 +2493,10 @@ static void __slab_free(struct kmem_cache *s, struct page *page,
                 * If we just froze the page then put it onto the
                 * per cpu partial list.
                 */
-               if (new.frozen && !was_frozen)
+               if (new.frozen && !was_frozen) {
                        put_cpu_partial(s, page, 1);
-
+                       stat(s, CPU_PARTIAL_FREE);
+               }
                /*
                 * The list lock was not taken therefore no list
                 * activity can be necessary.
@@ -3947,13 +3958,14 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size,
                if (kmem_cache_open(s, n,
                                size, align, flags, ctor)) {
                        list_add(&s->list, &slab_caches);
+                       up_write(&slub_lock);
                        if (sysfs_slab_add(s)) {
+                               down_write(&slub_lock);
                                list_del(&s->list);
                                kfree(n);
                                kfree(s);
                                goto err;
                        }
-                       up_write(&slub_lock);
                        return s;
                }
                kfree(n);
@@ -5077,6 +5089,8 @@ STAT_ATTR(CMPXCHG_DOUBLE_CPU_FAIL, cmpxchg_double_cpu_fail);
 STAT_ATTR(CMPXCHG_DOUBLE_FAIL, cmpxchg_double_fail);
 STAT_ATTR(CPU_PARTIAL_ALLOC, cpu_partial_alloc);
 STAT_ATTR(CPU_PARTIAL_FREE, cpu_partial_free);
+STAT_ATTR(CPU_PARTIAL_NODE, cpu_partial_node);
+STAT_ATTR(CPU_PARTIAL_DRAIN, cpu_partial_drain);
 #endif
 
 static struct attribute *slab_attrs[] = {
@@ -5142,6 +5156,8 @@ static struct attribute *slab_attrs[] = {
        &cmpxchg_double_cpu_fail_attr.attr,
        &cpu_partial_alloc_attr.attr,
        &cpu_partial_free_attr.attr,
+       &cpu_partial_node_attr.attr,
+       &cpu_partial_drain_attr.attr,
 #endif
 #ifdef CONFIG_FAILSLAB
        &failslab_attr.attr,
index bd345f3..b324e31 100644 (file)
@@ -11,7 +11,6 @@
  */
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
index 94b3ad0..5ab25cd 100644 (file)
@@ -27,7 +27,6 @@
  */
 
 #include <linux/module.h>
-#include <asm/system.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
index 91aca87..056794e 100644 (file)
@@ -35,7 +35,6 @@
 #include <net/arp.h>
 #include <net/sock.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 
 /*
  * Create the HIPPI MAC header for an arbitrary protocol layer
index 5e20cf8..b9a3a14 100644 (file)
@@ -16,7 +16,6 @@
  */
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
index 5de42ea..8ae3a78 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/param.h> /* for HZ */
 #include <linux/uaccess.h>
 #include <asm/byteorder.h> /* for htons etc. */
-#include <asm/system.h> /* save/restore_flags */
 #include <linux/atomic.h>
 
 #include "common.h"
index 3cd0a0d..0906c19 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/termios.h>     /* For TIOCINQ/OUTQ */
 #include <linux/mm.h>
index 7e7964d..9162409 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index c1cb982..d0de30e 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index 8273b12..9bd31e8 100644 (file)
@@ -23,7 +23,6 @@
 #include <net/sock.h>
 #include <net/tcp_states.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index 85816e6..5ea7fd3 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index c7d8143..993c439 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index 60b545e..7d5f24b 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index 9bb7765..96f4cab 100644 (file)
@@ -27,7 +27,6 @@
 #include <net/sock.h>
 #include <net/tcp_states.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index cf0c47a..846ae4e 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/termios.h>     /* For TIOCINQ/OUTQ */
 #include <linux/mm.h>
index 37507d8..be8a25e 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/netfilter.h>
 #include <net/sock.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index 87fddab..a655880 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/spinlock.h>
 #include <net/sock.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index a8eef88..3fbf8f7 100644 (file)
@@ -30,7 +30,6 @@
 #include <net/sock.h>
 #include <net/tcp_states.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index 277f81b..8b66a41 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index 96e4b92..004467c 100644 (file)
@@ -25,7 +25,6 @@
 #include <net/sock.h>
 #include <net/tcp_states.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index c6715ee..1997538 100644 (file)
@@ -26,7 +26,6 @@
 #include <net/sock.h>
 #include <net/tcp_states.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index db29ea7..c3cffa7 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index 4c83137..e3c579b 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index 9f9c8dc..180bfc4 100644 (file)
@@ -42,7 +42,6 @@
 #include <linux/uaccess.h>
 #include <net/sock.h>
 
-#include <asm/system.h>
 
 #include "bnep.h"
 
index 1230faa..311668d 100644 (file)
@@ -39,7 +39,6 @@
 
 #include <linux/isdn/capilli.h>
 
-#include <asm/system.h>
 
 #include "cmtp.h"
 
index 947172b..5238b6b 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/interrupt.h>
 #include <net/sock.h>
 
-#include <asm/system.h>
 #include <linux/uaccess.h>
 #include <asm/unaligned.h>
 
index 59ec99e..e33af63 100644 (file)
@@ -45,7 +45,6 @@
 #include <linux/crypto.h>
 #include <net/sock.h>
 
-#include <asm/system.h>
 #include <linux/uaccess.h>
 #include <asm/unaligned.h>
 
index badb785..b375310 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/interrupt.h>
 #include <net/sock.h>
 
-#include <asm/system.h>
 #include <linux/uaccess.h>
 #include <asm/unaligned.h>
 
index 63afd23..4914261 100644 (file)
@@ -42,7 +42,6 @@
 #include <linux/ioctl.h>
 #include <net/sock.h>
 
-#include <asm/system.h>
 #include <linux/uaccess.h>
 #include <asm/unaligned.h>
 
index 3e450f4..b8e17e4 100644 (file)
@@ -49,7 +49,6 @@
 #include <linux/crc16.h>
 #include <net/sock.h>
 
-#include <asm/system.h>
 #include <asm/unaligned.h>
 
 #include <net/bluetooth/bluetooth.h>
index 22169c3..a55a43e 100644 (file)
@@ -45,7 +45,6 @@
 #include <linux/security.h>
 #include <net/sock.h>
 
-#include <asm/system.h>
 #include <linux/uaccess.h>
 
 #include <net/bluetooth/bluetooth.h>
index 8bf26d1..f6ab129 100644 (file)
@@ -44,7 +44,6 @@
 #include <linux/security.h>
 #include <net/sock.h>
 
-#include <asm/system.h>
 #include <linux/uaccess.h>
 
 #include <net/bluetooth/bluetooth.h>
index d3cf12f..e4fbfd6 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
 #include <linux/errno.h>
index 452db70..5d59155 100644 (file)
@@ -73,7 +73,6 @@
  */
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/bitops.h>
 #include <linux/capability.h>
 #include <linux/cpu.h>
index 5dea452..cf4989a 100644 (file)
@@ -33,7 +33,6 @@
 #include <net/sock.h>
 #include <linux/errno.h>
 #include <linux/timer.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/unaligned.h>
 #include <linux/filter.h>
index 43b03dd..d9d198a 100644 (file)
@@ -14,7 +14,6 @@
  */
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/bitops.h>
 #include <linux/module.h>
 #include <linux/types.h>
index 1a63c6e..90430b7 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/pci.h>
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 
 #include <linux/inet.h>
 #include <linux/netdevice.h>
index ff52ad0..611c5ef 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/nsproxy.h>
 #include <linux/slab.h>
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 
 #include <net/protocol.h>
index a690cae..f223cdc 100644 (file)
@@ -66,7 +66,6 @@
 #include <net/xfrm.h>
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <trace/events/skb.h>
 
 #include "kmap_skb.h"
index 9be6d0d..b2e14c0 100644 (file)
 #include <linux/memcontrol.h>
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 
 #include <linux/netdevice.h>
 #include <net/protocol.h>
index 386e263..dc3c3fa 100644 (file)
@@ -30,7 +30,6 @@
 #include <net/net_ratelimit.h>
 
 #include <asm/byteorder.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 
 int net_msg_warn __read_mostly = 1;
index 19acd00..4136987 100644 (file)
@@ -119,7 +119,6 @@ Version 0.0.6    2.1.110   07-aug-98   Eduardo Marcelo Serrat
 #include <net/sock.h>
 #include <net/tcp_states.h>
 #include <net/flow.h>
-#include <asm/system.h>
 #include <asm/ioctls.h>
 #include <linux/capability.h>
 #include <linux/mm.h>
index 74d321a..c00e307 100644 (file)
@@ -42,7 +42,6 @@
 #include <linux/notifier.h>
 #include <linux/slab.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <net/net_namespace.h>
 #include <net/neighbour.h>
 #include <net/dst.h>
index 73fa268..f6544b2 100644 (file)
@@ -60,7 +60,6 @@
 #include <linux/slab.h>
 #include <net/sock.h>
 #include <net/tcp_states.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/termios.h>
index bd78836..e446e85 100644 (file)
@@ -52,7 +52,6 @@
 #include <linux/route.h>
 #include <linux/slab.h>
 #include <net/sock.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/termios.h>
index 7e717cb..71b5edc 100644 (file)
@@ -47,7 +47,6 @@
 #include <linux/mutex.h>
 
 #include <linux/uaccess.h>
-#include <asm/system.h>
 
 static const struct proto_ops econet_ops;
 static struct hlist_head econet_sklist;
index a93af86..bf10a31 100644 (file)
@@ -59,7 +59,6 @@
 #include <net/ip.h>
 #include <net/dsa.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 
 __setup("ether=", netdev_boot_setup);
 
index fdf49fd..10e3751 100644 (file)
@@ -91,7 +91,6 @@
 #include <linux/slab.h>
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 
 #include <linux/inet.h>
 #include <linux/igmp.h>
index 73f46d6..18d9b81 100644 (file)
 #include <net/ax25.h>
 #include <net/netrom.h>
 
-#include <asm/system.h>
 #include <linux/uaccess.h>
 
 #include <linux/netfilter_arp.h>
index d4fad5c..6e447ff 100644 (file)
@@ -27,7 +27,6 @@
 
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/bitops.h>
 #include <linux/capability.h>
 #include <linux/module.h>
index 76e72ba..cbe3a68 100644 (file)
@@ -15,7 +15,6 @@
 
 #include <linux/module.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/bitops.h>
 #include <linux/capability.h>
 #include <linux/types.h>
index a8c5c1d..5063fa3 100644 (file)
@@ -14,7 +14,6 @@
  */
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
index da9b9cb..bce36f1 100644 (file)
@@ -51,7 +51,6 @@
 #define VERSION "0.409"
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
index 9664d35..2cb2bf8 100644 (file)
@@ -91,7 +91,6 @@
 #include <linux/errno.h>
 #include <linux/timer.h>
 #include <linux/init.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <net/checksum.h>
 #include <net/xfrm.h>
index 450e5d2..5dfecfd 100644 (file)
@@ -73,7 +73,6 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/jiffies.h>
index f3f1108..26eccc5 100644 (file)
 
 #define pr_fmt(fmt) "IPv4: " fmt
 
-#include <asm/system.h>
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
index ff302bd..4910176 100644 (file)
@@ -43,7 +43,6 @@
  */
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
index 0518a4f..960fbfc 100644 (file)
@@ -26,7 +26,6 @@
  *
  */
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <linux/types.h>
 #include <linux/capability.h>
index ab6b36e..50009c7 100644 (file)
@@ -20,7 +20,6 @@
  *
  */
 
-#include <asm/system.h>
 #include <linux/uaccess.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
index 12ccf88..4dc1c10 100644 (file)
@@ -66,7 +66,6 @@
 
 #include <linux/module.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
index d6f5fee..fe14105 100644 (file)
@@ -79,7 +79,6 @@
 
 #define pr_fmt(fmt) "UDP: " fmt
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/ioctls.h>
 #include <linux/bootmem.h>
index 5605f9d..8ed1b93 100644 (file)
@@ -60,7 +60,6 @@
 #endif
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/mroute6.h>
 
 MODULE_AUTHOR("Cast of dozens");
index af88934..27ac95a 100644 (file)
@@ -66,7 +66,6 @@
 #include <net/inet_common.h>
 
 #include <asm/uaccess.h>
-#include <asm/system.h>
 
 /*
  *     The ICMP socket(s). This is the most convenient way to flow control
index 5aa3981..8110362 100644 (file)
@@ -16,7 +16,6 @@
  *
  */
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <linux/types.h>
 #include <linux/sched.h>
index ba1a3fc..42cf139 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/bitops.h>
 #include <net/arp.h>
 
-#include <asm/system.h>
 #include <asm/byteorder.h>
 
 #include <net/irda/irda.h>
index 579617c..7ac4d1b 100644 (file)
@@ -40,7 +40,6 @@
 #include <linux/moduleparam.h>
 #include <linux/bitops.h>
 
-#include <asm/system.h>
 #include <asm/byteorder.h>
 
 #include <net/irda/irda.h>
index 8b61cf0..32dcaac 100644 (file)
@@ -36,7 +36,6 @@
 #include <linux/bitops.h>
 #include <linux/slab.h>
 
-#include <asm/system.h>
 #include <asm/byteorder.h>
 
 #include <net/irda/irda.h>
index f418cb2..1d552b3 100644 (file)
@@ -24,7 +24,6 @@
  *
  ********************************************************************/
 
-#include <asm/system.h>
 #include <linux/delay.h>
 
 #include <net/irda/timer.h>
index 8d0324b..ab3d35f 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/slab.h>
 #include <net/sock.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index 2ec1af5..f4e3c1a 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/slab.h>
 #include <net/sock.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index c75a795..baab276 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/slab.h>
 #include <net/sock.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index 43a2a7f..066225b 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/slab.h>
 #include <net/sock.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index af6d14b..f8cd641 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index fe6cb43..5285617 100644 (file)
@@ -31,7 +31,6 @@
 #include <net/net_namespace.h>
 #include <net/protocol.h>
 #include <net/tcp.h>
-#include <asm/system.h>
 #include <linux/stat.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
index 8531293..f843a88 100644 (file)
@@ -25,7 +25,6 @@
 #include <net/protocol.h>
 #include <net/tcp.h>
 #include <net/udp.h>
-#include <asm/system.h>
 #include <linux/stat.h>
 #include <linux/proc_fs.h>
 
index 4d70785..e6ddde1 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/net.h>
 #include <linux/skbuff.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <net/sock.h>
 #include <net/netlink.h>
 #include <linux/init.h>
index 7dab229..06592d8 100644 (file)
@@ -31,7 +31,6 @@
 #include <net/net_namespace.h>
 #include <net/sock.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/termios.h>     /* For TIOCINQ/OUTQ */
 #include <linux/mm.h>
index 64e6dde..1c51d7a 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/if_ether.h>    /* For the statistics structure. */
 #include <linux/slab.h>
 
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
index 6d4ef6d..c3073a2 100644 (file)
@@ -24,7 +24,6 @@
 #include <net/sock.h>
 #include <net/tcp_states.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index 607fddb..0b4bcb2 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index 2cf3301..70ffff7 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/termios.h>     /* For TIOCINQ/OUTQ */
 #include <linux/mm.h>
index 6a947ae..ca40e22 100644 (file)
@@ -23,7 +23,6 @@
 #include <net/sock.h>
 #include <net/tcp_states.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index 1cb98e8..ff2c1b1 100644 (file)
@@ -24,7 +24,6 @@
 #include <net/sock.h>
 #include <net/tcp_states.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index 2c03050..e44e631 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/udp.h>
 #include <linux/ethtool.h>
 #include <linux/wait.h>
-#include <asm/system.h>
 #include <asm/div64.h>
 #include <linux/highmem.h>
 #include <linux/netfilter_bridge.h>
index ae2d484..4f2c0df 100644 (file)
@@ -73,7 +73,6 @@
 #include <net/sock.h>
 #include <linux/errno.h>
 #include <linux/timer.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/ioctls.h>
 #include <asm/page.h>
index f9ea925..c4719ce 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/if_arp.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <linux/fcntl.h>
 #include <linux/termios.h>
index 178ff4f..1ab8689 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/if_ether.h>
 #include <linux/slab.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 
 #include <linux/inet.h>
index 7f7fcb4..79c4abc 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <net/tcp_states.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index 7a02bd1..bc55142 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index 4ebf33a..9ad98b5 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index cd9b7ee..4014893 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <net/tcp_states.h>
-#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <linux/fcntl.h>
 #include <linux/termios.h>     /* For TIOCINQ/OUTQ */
index f6c71ca..47f1fdb 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <net/tcp_states.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index b6c8f38..bc5469d 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <net/tcp_states.h>
-#include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index 7a4cb5f..6797246 100644 (file)
@@ -17,7 +17,6 @@
  *  Copyright (C) 1995,1996 Olaf Kirch <okir@monad.swb.de>
  */
 
-#include <asm/system.h>
 
 #include <linux/module.h>
 #include <linux/types.h>
index 7c69599..6327685 100644 (file)
@@ -410,7 +410,8 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
                 * exec\0change_profile
                 */
                state = aa_dfa_null_transition(profile->file.dfa, state);
-               cp = change_profile_perms(profile, cxt->onexec->ns, name,
+               cp = change_profile_perms(profile, cxt->onexec->ns,
+                                         cxt->onexec->base.name,
                                          AA_MAY_ONEXEC, state);
 
                if (!(cp.allow & AA_MAY_ONEXEC))
index 3022c0f..5d176f2 100644 (file)
@@ -215,6 +215,8 @@ static struct file_perms compute_perms(struct aa_dfa *dfa, unsigned int state,
        /* change_profile wasn't determined by ownership in old mapping */
        if (ACCEPT_TABLE(dfa)[state] & 0x80000000)
                perms.allow |= AA_MAY_CHANGE_PROFILE;
+       if (ACCEPT_TABLE(dfa)[state] & 0x40000000)
+               perms.allow |= AA_MAY_ONEXEC;
 
        return perms;
 }
index 47fda96..005a91b 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/audit.h>
 #include <linux/lsm_audit.h>
 #include <linux/in6.h>
-#include <asm/system.h>
 #include "flask.h"
 #include "av_permissions.h"
 #include "security.h"
index b43813c..c220f31 100644 (file)
@@ -7,6 +7,8 @@
 #ifndef _SELINUX_XFRM_H_
 #define _SELINUX_XFRM_H_
 
+#include <net/flow.h>
+
 int selinux_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp,
                              struct xfrm_user_sec_ctx *sec_ctx);
 int selinux_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx,
index a1a962d..75ad0cd 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/slab.h>
 #include <linux/ioport.h>
 #include <asm/page.h>
-#include <asm/system.h>
 #include <linux/vmalloc.h>
 #include <asm/uaccess.h>
 #include <linux/poll.h>
index 12ba28e..92ca5be 100644 (file)
@@ -28,7 +28,6 @@
 #include <asm/io.h>
 #include <asm/hardware/iomd.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 
 #include "sound_config.h"
 #include "vidc.h"
index 5246874..24c430f 100644 (file)
@@ -42,7 +42,6 @@
 #include <linux/spinlock.h>
 #include <linux/bitops.h>
 
-#include <asm/system.h>
 
 #include "sound_config.h"
 #include "waveartist.h"
index c5cef11..d3fbd0d 100644 (file)
@@ -30,7 +30,6 @@ HPI Operating System Specific macros for Linux Kernel driver
 #define HPI_BUILD_KERNEL_MODE
 
 #include <linux/io.h>
-#include <asm/system.h>
 #include <linux/ioctl.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
index 8afd8b5..4439636 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/pci.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <sound/core.h>
 #include <sound/initval.h>
index 758e3b3..01f572c 100644 (file)
@@ -49,31 +49,73 @@ static int find_index_from_host_irq(struct kvm_assigned_dev_kernel
                        index = i;
                        break;
                }
-       if (index < 0) {
+       if (index < 0)
                printk(KERN_WARNING "Fail to find correlated MSI-X entry!\n");
-               return 0;
-       }
 
        return index;
 }
 
-static irqreturn_t kvm_assigned_dev_thread(int irq, void *dev_id)
+static irqreturn_t kvm_assigned_dev_intx(int irq, void *dev_id)
 {
        struct kvm_assigned_dev_kernel *assigned_dev = dev_id;
+       int ret;
+
+       spin_lock(&assigned_dev->intx_lock);
+       if (pci_check_and_mask_intx(assigned_dev->dev)) {
+               assigned_dev->host_irq_disabled = true;
+               ret = IRQ_WAKE_THREAD;
+       } else
+               ret = IRQ_NONE;
+       spin_unlock(&assigned_dev->intx_lock);
+
+       return ret;
+}
 
-       if (assigned_dev->irq_requested_type & KVM_DEV_IRQ_HOST_INTX) {
-               spin_lock(&assigned_dev->intx_lock);
+static void
+kvm_assigned_dev_raise_guest_irq(struct kvm_assigned_dev_kernel *assigned_dev,
+                                int vector)
+{
+       if (unlikely(assigned_dev->irq_requested_type &
+                    KVM_DEV_IRQ_GUEST_INTX)) {
+               spin_lock(&assigned_dev->intx_mask_lock);
+               if (!(assigned_dev->flags & KVM_DEV_ASSIGN_MASK_INTX))
+                       kvm_set_irq(assigned_dev->kvm,
+                                   assigned_dev->irq_source_id, vector, 1);
+               spin_unlock(&assigned_dev->intx_mask_lock);
+       } else
+               kvm_set_irq(assigned_dev->kvm, assigned_dev->irq_source_id,
+                           vector, 1);
+}
+
+static irqreturn_t kvm_assigned_dev_thread_intx(int irq, void *dev_id)
+{
+       struct kvm_assigned_dev_kernel *assigned_dev = dev_id;
+
+       if (!(assigned_dev->flags & KVM_DEV_ASSIGN_PCI_2_3)) {
+               spin_lock_irq(&assigned_dev->intx_lock);
                disable_irq_nosync(irq);
                assigned_dev->host_irq_disabled = true;
-               spin_unlock(&assigned_dev->intx_lock);
+               spin_unlock_irq(&assigned_dev->intx_lock);
        }
 
-       kvm_set_irq(assigned_dev->kvm, assigned_dev->irq_source_id,
-                   assigned_dev->guest_irq, 1);
+       kvm_assigned_dev_raise_guest_irq(assigned_dev,
+                                        assigned_dev->guest_irq);
 
        return IRQ_HANDLED;
 }
 
+#ifdef __KVM_HAVE_MSI
+static irqreturn_t kvm_assigned_dev_thread_msi(int irq, void *dev_id)
+{
+       struct kvm_assigned_dev_kernel *assigned_dev = dev_id;
+
+       kvm_assigned_dev_raise_guest_irq(assigned_dev,
+                                        assigned_dev->guest_irq);
+
+       return IRQ_HANDLED;
+}
+#endif
+
 #ifdef __KVM_HAVE_MSIX
 static irqreturn_t kvm_assigned_dev_thread_msix(int irq, void *dev_id)
 {
@@ -83,8 +125,7 @@ static irqreturn_t kvm_assigned_dev_thread_msix(int irq, void *dev_id)
 
        if (index >= 0) {
                vector = assigned_dev->guest_msix_entries[index].vector;
-               kvm_set_irq(assigned_dev->kvm, assigned_dev->irq_source_id,
-                           vector, 1);
+               kvm_assigned_dev_raise_guest_irq(assigned_dev, vector);
        }
 
        return IRQ_HANDLED;
@@ -100,15 +141,31 @@ static void kvm_assigned_dev_ack_irq(struct kvm_irq_ack_notifier *kian)
 
        kvm_set_irq(dev->kvm, dev->irq_source_id, dev->guest_irq, 0);
 
-       /* The guest irq may be shared so this ack may be
-        * from another device.
-        */
-       spin_lock(&dev->intx_lock);
-       if (dev->host_irq_disabled) {
-               enable_irq(dev->host_irq);
-               dev->host_irq_disabled = false;
+       spin_lock(&dev->intx_mask_lock);
+
+       if (!(dev->flags & KVM_DEV_ASSIGN_MASK_INTX)) {
+               bool reassert = false;
+
+               spin_lock_irq(&dev->intx_lock);
+               /*
+                * The guest IRQ may be shared so this ack can come from an
+                * IRQ for another guest device.
+                */
+               if (dev->host_irq_disabled) {
+                       if (!(dev->flags & KVM_DEV_ASSIGN_PCI_2_3))
+                               enable_irq(dev->host_irq);
+                       else if (!pci_check_and_unmask_intx(dev->dev))
+                               reassert = true;
+                       dev->host_irq_disabled = reassert;
+               }
+               spin_unlock_irq(&dev->intx_lock);
+
+               if (reassert)
+                       kvm_set_irq(dev->kvm, dev->irq_source_id,
+                                   dev->guest_irq, 1);
        }
-       spin_unlock(&dev->intx_lock);
+
+       spin_unlock(&dev->intx_mask_lock);
 }
 
 static void deassign_guest_irq(struct kvm *kvm,
@@ -156,7 +213,15 @@ static void deassign_host_irq(struct kvm *kvm,
                pci_disable_msix(assigned_dev->dev);
        } else {
                /* Deal with MSI and INTx */
-               disable_irq(assigned_dev->host_irq);
+               if ((assigned_dev->irq_requested_type &
+                    KVM_DEV_IRQ_HOST_INTX) &&
+                   (assigned_dev->flags & KVM_DEV_ASSIGN_PCI_2_3)) {
+                       spin_lock_irq(&assigned_dev->intx_lock);
+                       pci_intx(assigned_dev->dev, false);
+                       spin_unlock_irq(&assigned_dev->intx_lock);
+                       synchronize_irq(assigned_dev->host_irq);
+               } else
+                       disable_irq(assigned_dev->host_irq);
 
                free_irq(assigned_dev->host_irq, assigned_dev);
 
@@ -237,15 +302,34 @@ void kvm_free_all_assigned_devices(struct kvm *kvm)
 static int assigned_device_enable_host_intx(struct kvm *kvm,
                                            struct kvm_assigned_dev_kernel *dev)
 {
+       irq_handler_t irq_handler;
+       unsigned long flags;
+
        dev->host_irq = dev->dev->irq;
-       /* Even though this is PCI, we don't want to use shared
-        * interrupts. Sharing host devices with guest-assigned devices
-        * on the same interrupt line is not a happy situation: there
-        * are going to be long delays in accepting, acking, etc.
+
+       /*
+        * We can only share the IRQ line with other host devices if we are
+        * able to disable the IRQ source at device-level - independently of
+        * the guest driver. Otherwise host devices may suffer from unbounded
+        * IRQ latencies when the guest keeps the line asserted.
         */
-       if (request_threaded_irq(dev->host_irq, NULL, kvm_assigned_dev_thread,
-                                IRQF_ONESHOT, dev->irq_name, dev))
+       if (dev->flags & KVM_DEV_ASSIGN_PCI_2_3) {
+               irq_handler = kvm_assigned_dev_intx;
+               flags = IRQF_SHARED;
+       } else {
+               irq_handler = NULL;
+               flags = IRQF_ONESHOT;
+       }
+       if (request_threaded_irq(dev->host_irq, irq_handler,
+                                kvm_assigned_dev_thread_intx, flags,
+                                dev->irq_name, dev))
                return -EIO;
+
+       if (dev->flags & KVM_DEV_ASSIGN_PCI_2_3) {
+               spin_lock_irq(&dev->intx_lock);
+               pci_intx(dev->dev, true);
+               spin_unlock_irq(&dev->intx_lock);
+       }
        return 0;
 }
 
@@ -262,8 +346,9 @@ static int assigned_device_enable_host_msi(struct kvm *kvm,
        }
 
        dev->host_irq = dev->dev->irq;
-       if (request_threaded_irq(dev->host_irq, NULL, kvm_assigned_dev_thread,
-                                0, dev->irq_name, dev)) {
+       if (request_threaded_irq(dev->host_irq, NULL,
+                                kvm_assigned_dev_thread_msi, 0,
+                                dev->irq_name, dev)) {
                pci_disable_msi(dev->dev);
                return -EIO;
        }
@@ -321,7 +406,6 @@ static int assigned_device_enable_guest_msi(struct kvm *kvm,
 {
        dev->guest_irq = irq->guest_irq;
        dev->ack_notifier.gsi = -1;
-       dev->host_irq_disabled = false;
        return 0;
 }
 #endif
@@ -333,7 +417,6 @@ static int assigned_device_enable_guest_msix(struct kvm *kvm,
 {
        dev->guest_irq = irq->guest_irq;
        dev->ack_notifier.gsi = -1;
-       dev->host_irq_disabled = false;
        return 0;
 }
 #endif
@@ -367,6 +450,7 @@ static int assign_host_irq(struct kvm *kvm,
        default:
                r = -EINVAL;
        }
+       dev->host_irq_disabled = false;
 
        if (!r)
                dev->irq_requested_type |= host_irq_type;
@@ -468,6 +552,7 @@ static int kvm_vm_ioctl_deassign_dev_irq(struct kvm *kvm,
 {
        int r = -ENODEV;
        struct kvm_assigned_dev_kernel *match;
+       unsigned long irq_type;
 
        mutex_lock(&kvm->lock);
 
@@ -476,7 +561,9 @@ static int kvm_vm_ioctl_deassign_dev_irq(struct kvm *kvm,
        if (!match)
                goto out;
 
-       r = kvm_deassign_irq(kvm, match, assigned_irq->flags);
+       irq_type = assigned_irq->flags & (KVM_DEV_IRQ_HOST_MASK |
+                                         KVM_DEV_IRQ_GUEST_MASK);
+       r = kvm_deassign_irq(kvm, match, irq_type);
 out:
        mutex_unlock(&kvm->lock);
        return r;
@@ -609,6 +696,10 @@ static int kvm_vm_ioctl_assign_device(struct kvm *kvm,
        if (!match->pci_saved_state)
                printk(KERN_DEBUG "%s: Couldn't store %s saved state\n",
                       __func__, dev_name(&dev->dev));
+
+       if (!pci_intx_mask_supported(dev))
+               assigned_dev->flags &= ~KVM_DEV_ASSIGN_PCI_2_3;
+
        match->assigned_dev_id = assigned_dev->assigned_dev_id;
        match->host_segnr = assigned_dev->segnr;
        match->host_busnr = assigned_dev->busnr;
@@ -616,6 +707,7 @@ static int kvm_vm_ioctl_assign_device(struct kvm *kvm,
        match->flags = assigned_dev->flags;
        match->dev = dev;
        spin_lock_init(&match->intx_lock);
+       spin_lock_init(&match->intx_mask_lock);
        match->irq_source_id = -1;
        match->kvm = kvm;
        match->ack_notifier.irq_acked = kvm_assigned_dev_ack_irq;
@@ -761,6 +853,55 @@ msix_entry_out:
 }
 #endif
 
+static int kvm_vm_ioctl_set_pci_irq_mask(struct kvm *kvm,
+               struct kvm_assigned_pci_dev *assigned_dev)
+{
+       int r = 0;
+       struct kvm_assigned_dev_kernel *match;
+
+       mutex_lock(&kvm->lock);
+
+       match = kvm_find_assigned_dev(&kvm->arch.assigned_dev_head,
+                                     assigned_dev->assigned_dev_id);
+       if (!match) {
+               r = -ENODEV;
+               goto out;
+       }
+
+       spin_lock(&match->intx_mask_lock);
+
+       match->flags &= ~KVM_DEV_ASSIGN_MASK_INTX;
+       match->flags |= assigned_dev->flags & KVM_DEV_ASSIGN_MASK_INTX;
+
+       if (match->irq_requested_type & KVM_DEV_IRQ_GUEST_INTX) {
+               if (assigned_dev->flags & KVM_DEV_ASSIGN_MASK_INTX) {
+                       kvm_set_irq(match->kvm, match->irq_source_id,
+                                   match->guest_irq, 0);
+                       /*
+                        * Masking at hardware-level is performed on demand,
+                        * i.e. when an IRQ actually arrives at the host.
+                        */
+               } else if (!(assigned_dev->flags & KVM_DEV_ASSIGN_PCI_2_3)) {
+                       /*
+                        * Unmask the IRQ line if required. Unmasking at
+                        * device level will be performed by user space.
+                        */
+                       spin_lock_irq(&match->intx_lock);
+                       if (match->host_irq_disabled) {
+                               enable_irq(match->host_irq);
+                               match->host_irq_disabled = false;
+                       }
+                       spin_unlock_irq(&match->intx_lock);
+               }
+       }
+
+       spin_unlock(&match->intx_mask_lock);
+
+out:
+       mutex_unlock(&kvm->lock);
+       return r;
+}
+
 long kvm_vm_ioctl_assigned_device(struct kvm *kvm, unsigned ioctl,
                                  unsigned long arg)
 {
@@ -868,6 +1009,15 @@ long kvm_vm_ioctl_assigned_device(struct kvm *kvm, unsigned ioctl,
                break;
        }
 #endif
+       case KVM_ASSIGN_SET_INTX_MASK: {
+               struct kvm_assigned_pci_dev assigned_dev;
+
+               r = -EFAULT;
+               if (copy_from_user(&assigned_dev, argp, sizeof assigned_dev))
+                       goto out;
+               r = kvm_vm_ioctl_set_pci_irq_mask(kvm, &assigned_dev);
+               break;
+       }
        default:
                r = -ENOTTY;
                break;
@@ -875,4 +1025,3 @@ long kvm_vm_ioctl_assigned_device(struct kvm *kvm, unsigned ioctl,
 out:
        return r;
 }
-
index a91f980..42b7393 100644 (file)
@@ -203,7 +203,7 @@ static bool make_all_cpus_request(struct kvm *kvm, unsigned int req)
 
 void kvm_flush_remote_tlbs(struct kvm *kvm)
 {
-       int dirty_count = kvm->tlbs_dirty;
+       long dirty_count = kvm->tlbs_dirty;
 
        smp_mb();
        if (make_all_cpus_request(kvm, KVM_REQ_TLB_FLUSH))
@@ -289,15 +289,15 @@ static void kvm_mmu_notifier_invalidate_page(struct mmu_notifier *mn,
         */
        idx = srcu_read_lock(&kvm->srcu);
        spin_lock(&kvm->mmu_lock);
+
        kvm->mmu_notifier_seq++;
        need_tlb_flush = kvm_unmap_hva(kvm, address) | kvm->tlbs_dirty;
-       spin_unlock(&kvm->mmu_lock);
-       srcu_read_unlock(&kvm->srcu, idx);
-
        /* we've to flush the tlb before the pages can be freed */
        if (need_tlb_flush)
                kvm_flush_remote_tlbs(kvm);
 
+       spin_unlock(&kvm->mmu_lock);
+       srcu_read_unlock(&kvm->srcu, idx);
 }
 
 static void kvm_mmu_notifier_change_pte(struct mmu_notifier *mn,
@@ -335,12 +335,12 @@ static void kvm_mmu_notifier_invalidate_range_start(struct mmu_notifier *mn,
        for (; start < end; start += PAGE_SIZE)
                need_tlb_flush |= kvm_unmap_hva(kvm, start);
        need_tlb_flush |= kvm->tlbs_dirty;
-       spin_unlock(&kvm->mmu_lock);
-       srcu_read_unlock(&kvm->srcu, idx);
-
        /* we've to flush the tlb before the pages can be freed */
        if (need_tlb_flush)
                kvm_flush_remote_tlbs(kvm);
+
+       spin_unlock(&kvm->mmu_lock);
+       srcu_read_unlock(&kvm->srcu, idx);
 }
 
 static void kvm_mmu_notifier_invalidate_range_end(struct mmu_notifier *mn,
@@ -357,11 +357,11 @@ static void kvm_mmu_notifier_invalidate_range_end(struct mmu_notifier *mn,
         * been freed.
         */
        kvm->mmu_notifier_seq++;
+       smp_wmb();
        /*
         * The above sequence increase must be visible before the
-        * below count decrease but both values are read by the kvm
-        * page fault under mmu_lock spinlock so we don't need to add
-        * a smb_wmb() here in between the two.
+        * below count decrease, which is ensured by the smp_wmb above
+        * in conjunction with the smp_rmb in mmu_notifier_retry().
         */
        kvm->mmu_notifier_count--;
        spin_unlock(&kvm->mmu_lock);
@@ -378,13 +378,14 @@ static int kvm_mmu_notifier_clear_flush_young(struct mmu_notifier *mn,
 
        idx = srcu_read_lock(&kvm->srcu);
        spin_lock(&kvm->mmu_lock);
-       young = kvm_age_hva(kvm, address);
-       spin_unlock(&kvm->mmu_lock);
-       srcu_read_unlock(&kvm->srcu, idx);
 
+       young = kvm_age_hva(kvm, address);
        if (young)
                kvm_flush_remote_tlbs(kvm);
 
+       spin_unlock(&kvm->mmu_lock);
+       srcu_read_unlock(&kvm->srcu, idx);
+
        return young;
 }
 
@@ -449,7 +450,7 @@ static void kvm_init_memslots_id(struct kvm *kvm)
                slots->id_to_index[i] = slots->memslots[i].id = i;
 }
 
-static struct kvm *kvm_create_vm(void)
+static struct kvm *kvm_create_vm(unsigned long type)
 {
        int r, i;
        struct kvm *kvm = kvm_arch_alloc_vm();
@@ -457,7 +458,7 @@ static struct kvm *kvm_create_vm(void)
        if (!kvm)
                return ERR_PTR(-ENOMEM);
 
-       r = kvm_arch_init_vm(kvm);
+       r = kvm_arch_init_vm(kvm, type);
        if (r)
                goto out_err_nodisable;
 
@@ -535,21 +536,13 @@ static void kvm_destroy_dirty_bitmap(struct kvm_memory_slot *memslot)
 static void kvm_free_physmem_slot(struct kvm_memory_slot *free,
                                  struct kvm_memory_slot *dont)
 {
-       int i;
-
        if (!dont || free->rmap != dont->rmap)
                vfree(free->rmap);
 
        if (!dont || free->dirty_bitmap != dont->dirty_bitmap)
                kvm_destroy_dirty_bitmap(free);
 
-
-       for (i = 0; i < KVM_NR_PAGE_SIZES - 1; ++i) {
-               if (!dont || free->lpage_info[i] != dont->lpage_info[i]) {
-                       vfree(free->lpage_info[i]);
-                       free->lpage_info[i] = NULL;
-               }
-       }
+       kvm_arch_free_memslot(free, dont);
 
        free->npages = 0;
        free->rmap = NULL;
@@ -616,7 +609,6 @@ static int kvm_vm_release(struct inode *inode, struct file *filp)
        return 0;
 }
 
-#ifndef CONFIG_S390
 /*
  * Allocation size is twice as large as the actual dirty bitmap size.
  * This makes it possible to do double buffering: see x86's
@@ -624,6 +616,7 @@ static int kvm_vm_release(struct inode *inode, struct file *filp)
  */
 static int kvm_create_dirty_bitmap(struct kvm_memory_slot *memslot)
 {
+#ifndef CONFIG_S390
        unsigned long dirty_bytes = 2 * kvm_dirty_bitmap_bytes(memslot);
 
        if (dirty_bytes > PAGE_SIZE)
@@ -636,21 +629,8 @@ static int kvm_create_dirty_bitmap(struct kvm_memory_slot *memslot)
 
        memslot->dirty_bitmap_head = memslot->dirty_bitmap;
        memslot->nr_dirty_pages = 0;
-       return 0;
-}
 #endif /* !CONFIG_S390 */
-
-static struct kvm_memory_slot *
-search_memslots(struct kvm_memslots *slots, gfn_t gfn)
-{
-       struct kvm_memory_slot *memslot;
-
-       kvm_for_each_memslot(memslot, slots)
-               if (gfn >= memslot->base_gfn &&
-                     gfn < memslot->base_gfn + memslot->npages)
-                       return memslot;
-
-       return NULL;
+       return 0;
 }
 
 static int cmp_memslot(const void *slot1, const void *slot2)
@@ -778,69 +758,24 @@ int __kvm_set_memory_region(struct kvm *kvm,
        r = -ENOMEM;
 
        /* Allocate if a slot is being created */
+       if (npages && !old.npages) {
+               new.user_alloc = user_alloc;
+               new.userspace_addr = mem->userspace_addr;
 #ifndef CONFIG_S390
-       if (npages && !new.rmap) {
                new.rmap = vzalloc(npages * sizeof(*new.rmap));
-
                if (!new.rmap)
                        goto out_free;
-
-               new.user_alloc = user_alloc;
-               new.userspace_addr = mem->userspace_addr;
-       }
-       if (!npages)
-               goto skip_lpage;
-
-       for (i = 0; i < KVM_NR_PAGE_SIZES - 1; ++i) {
-               unsigned long ugfn;
-               unsigned long j;
-               int lpages;
-               int level = i + 2;
-
-               /* Avoid unused variable warning if no large pages */
-               (void)level;
-
-               if (new.lpage_info[i])
-                       continue;
-
-               lpages = 1 + ((base_gfn + npages - 1)
-                            >> KVM_HPAGE_GFN_SHIFT(level));
-               lpages -= base_gfn >> KVM_HPAGE_GFN_SHIFT(level);
-
-               new.lpage_info[i] = vzalloc(lpages * sizeof(*new.lpage_info[i]));
-
-               if (!new.lpage_info[i])
+#endif /* not defined CONFIG_S390 */
+               if (kvm_arch_create_memslot(&new, npages))
                        goto out_free;
-
-               if (base_gfn & (KVM_PAGES_PER_HPAGE(level) - 1))
-                       new.lpage_info[i][0].write_count = 1;
-               if ((base_gfn+npages) & (KVM_PAGES_PER_HPAGE(level) - 1))
-                       new.lpage_info[i][lpages - 1].write_count = 1;
-               ugfn = new.userspace_addr >> PAGE_SHIFT;
-               /*
-                * If the gfn and userspace address are not aligned wrt each
-                * other, or if explicitly asked to, disable large page
-                * support for this slot
-                */
-               if ((base_gfn ^ ugfn) & (KVM_PAGES_PER_HPAGE(level) - 1) ||
-                   !largepages_enabled)
-                       for (j = 0; j < lpages; ++j)
-                               new.lpage_info[i][j].write_count = 1;
        }
 
-skip_lpage:
-
        /* Allocate page dirty bitmap if needed */
        if ((new.flags & KVM_MEM_LOG_DIRTY_PAGES) && !new.dirty_bitmap) {
                if (kvm_create_dirty_bitmap(&new) < 0)
                        goto out_free;
                /* destroy any largepage mappings for dirty tracking */
        }
-#else  /* not defined CONFIG_S390 */
-       new.user_alloc = user_alloc;
-       if (user_alloc)
-               new.userspace_addr = mem->userspace_addr;
-#endif /* not defined CONFIG_S390 */
 
        if (!npages) {
                struct kvm_memory_slot *slot;
@@ -890,8 +825,7 @@ skip_lpage:
        if (!npages) {
                new.rmap = NULL;
                new.dirty_bitmap = NULL;
-               for (i = 0; i < KVM_NR_PAGE_SIZES - 1; ++i)
-                       new.lpage_info[i] = NULL;
+               memset(&new.arch, 0, sizeof(new.arch));
        }
 
        update_memslots(slots, &new);
@@ -978,6 +912,11 @@ out:
        return r;
 }
 
+bool kvm_largepages_enabled(void)
+{
+       return largepages_enabled;
+}
+
 void kvm_disable_largepages(void)
 {
        largepages_enabled = false;
@@ -1031,12 +970,6 @@ int kvm_is_error_hva(unsigned long addr)
 }
 EXPORT_SYMBOL_GPL(kvm_is_error_hva);
 
-static struct kvm_memory_slot *__gfn_to_memslot(struct kvm_memslots *slots,
-                                               gfn_t gfn)
-{
-       return search_memslots(slots, gfn);
-}
-
 struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, gfn_t gfn)
 {
        return __gfn_to_memslot(kvm_memslots(kvm), gfn);
@@ -1459,7 +1392,7 @@ int kvm_gfn_to_hva_cache_init(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
 
        ghc->gpa = gpa;
        ghc->generation = slots->generation;
-       ghc->memslot = __gfn_to_memslot(slots, gfn);
+       ghc->memslot = gfn_to_memslot(kvm, gfn);
        ghc->hva = gfn_to_hva_many(ghc->memslot, gfn, NULL);
        if (!kvm_is_error_hva(ghc->hva))
                ghc->hva += offset;
@@ -1657,7 +1590,7 @@ static int kvm_vcpu_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
                page = virt_to_page(vcpu->kvm->coalesced_mmio_ring);
 #endif
        else
-               return VM_FAULT_SIGBUS;
+               return kvm_arch_vcpu_fault(vcpu, vmf);
        get_page(page);
        vmf->page = page;
        return 0;
@@ -1718,6 +1651,10 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, u32 id)
                goto vcpu_destroy;
 
        mutex_lock(&kvm->lock);
+       if (!kvm_vcpu_compatible(vcpu)) {
+               r = -EINVAL;
+               goto unlock_vcpu_destroy;
+       }
        if (atomic_read(&kvm->online_vcpus) == KVM_MAX_VCPUS) {
                r = -EINVAL;
                goto unlock_vcpu_destroy;
@@ -2198,12 +2135,12 @@ static struct file_operations kvm_vm_fops = {
        .llseek         = noop_llseek,
 };
 
-static int kvm_dev_ioctl_create_vm(void)
+static int kvm_dev_ioctl_create_vm(unsigned long type)
 {
        int r;
        struct kvm *kvm;
 
-       kvm = kvm_create_vm();
+       kvm = kvm_create_vm(type);
        if (IS_ERR(kvm))
                return PTR_ERR(kvm);
 #ifdef KVM_COALESCED_MMIO_PAGE_OFFSET
@@ -2254,10 +2191,7 @@ static long kvm_dev_ioctl(struct file *filp,
                r = KVM_API_VERSION;
                break;
        case KVM_CREATE_VM:
-               r = -EINVAL;
-               if (arg)
-                       goto out;
-               r = kvm_dev_ioctl_create_vm();
+               r = kvm_dev_ioctl_create_vm(arg);
                break;
        case KVM_CHECK_EXTENSION:
                r = kvm_dev_ioctl_check_extension_generic(arg);